import {
GridTableIcon,
LayoutThreeColumnIcon,
LayoutThreeRowIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { NumberField } from "@/components/ui/number-field";
import {
GRID_MIN,
GRID_MAX,
DEFAULT_GRID_CONFIG,
} from "@/guides/grid";
import { usePreviewStore } from "@/preview/preview-store";
import { clampRound } from "@/utils/math";
import { cn } from "@/utils/ui";
import type { GuideDefinition } from "@/guides/types";
function GridLines({
rows,
cols,
color,
}: {
rows: number;
cols: number;
color: string;
}) {
const verticals = Array.from(
{ length: cols - 1 },
(_, i) => ((i + 1) / cols) * 100,
);
const horizontals = Array.from(
{ length: rows - 1 },
(_, i) => ((i + 1) / rows) * 100,
);
return (
<>
{verticals.map((pct) => (
))}
{horizontals.map((pct) => (
))}
>
);
}
function GridGuidePreview() {
return (
);
}
function GridGuideOverlay() {
const { rows, cols } = usePreviewStore((s) => s.gridConfig);
return (
);
}
function GridGuideOptions() {
const rows = usePreviewStore((s) => s.gridConfig.rows);
const cols = usePreviewStore((s) => s.gridConfig.cols);
const setGridConfig = usePreviewStore((s) => s.setGridConfig);
const clampGridValue = (value: number) =>
clampRound({ value, min: GRID_MIN, max: GRID_MAX });
return (
}
value={rows}
min={GRID_MIN}
max={GRID_MAX}
isDefault={rows === DEFAULT_GRID_CONFIG.rows}
onReset={() => setGridConfig({ rows: DEFAULT_GRID_CONFIG.rows })}
onScrub={(value) => setGridConfig({ rows: clampGridValue(value) })}
onChange={(event) => {
const parsed = Number.parseInt(event.target.value, 10);
if (!Number.isNaN(parsed))
setGridConfig({ rows: clampGridValue(parsed) });
}}
className="flex-1"
/>
}
value={cols}
min={GRID_MIN}
max={GRID_MAX}
isDefault={cols === DEFAULT_GRID_CONFIG.cols}
onReset={() => setGridConfig({ cols: DEFAULT_GRID_CONFIG.cols })}
onScrub={(value) => setGridConfig({ cols: clampGridValue(value) })}
onChange={(event) => {
const parsed = Number.parseInt(event.target.value, 10);
if (!Number.isNaN(parsed))
setGridConfig({ cols: clampGridValue(parsed) });
}}
className="flex-1"
/>
);
}
export const gridGuide = {
id: "grid",
label: "Grid",
renderPreview: () => ,
renderTriggerIcon: () => ,
renderOverlay: () => ,
renderOptions: () => ,
} as const satisfies GuideDefinition;