@nextlyhq/plugin-page-builder 0.0.2-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/admin/index.ts","../../src/admin/controls/registerDefaultControls.tsx","../../src/admin/controls/ColorControl.tsx","../../src/admin/icons.tsx","../../src/admin/controls/primitives.tsx","../../src/admin/controls/MediaControl.tsx","../../src/admin/controls/SpacingControl.tsx","../../src/admin/EditorSurface.tsx","../../src/admin/store/EditorProvider.tsx","../../src/admin/store/editorStore.ts","../../src/admin/canvas/CanvasNode.tsx","../../src/admin/logic/dragSensors.ts","../../src/admin/canvas/CanvasQueryLoop.tsx","../../src/admin/api/collectionsApi.ts","../../src/admin/canvas/DropZone.tsx","../../src/admin/canvas/IframeCanvas.tsx","../../src/core/responsive.ts","../../src/admin/canvas/Canvas.tsx","../../src/admin/logic/dragLabel.ts","../../src/admin/logic/dropRules.ts","../../src/admin/logic/locate.ts","../../src/admin/logic/dropPlan.ts","../../src/admin/panels/BlockLibrary.tsx","../../src/admin/panels/Inspector.tsx","../../src/admin/content/contentFields.ts","../../src/admin/logic/queryLoop.ts","../../src/admin/panels/inspectorTabs.ts","../../src/admin/panels/QueryLoopSettings.tsx","../../src/admin/SaveShell.tsx","../../src/admin/api/adminFetch.ts","../../src/admin/PageBuilderEditView.tsx","../../src/admin/PageBuilderField.tsx","../../src/admin/PageBuilderModeToggle.tsx","../../src/admin/PageBuilderToggle.tsx"],"sourcesContent":["/**\n * \"./admin\" entry — registers the plugin's React admin components (D19/D60). Importing\n * this module (via the host's generated import map, or eagerly) makes the string-path\n * components resolvable by the admin shell.\n */\nimport {\n registerComponents,\n registerKnownPlugin,\n} from \"@nextlyhq/plugin-sdk/admin\";\n\nimport { registerDefaultControls } from \"./controls/registerDefaultControls\";\nimport { PageBuilderEditView } from \"./PageBuilderEditView\";\nimport { PageBuilderField } from \"./PageBuilderField\";\nimport { PageBuilderModeToggle } from \"./PageBuilderModeToggle\";\nimport { PageBuilderToggle } from \"./PageBuilderToggle\";\n\n// Register the built-in inspector controls into the (open) control registry on load.\nregisterDefaultControls();\n\nconst EDIT_VIEW_PATH =\n \"@nextlyhq/plugin-page-builder/admin#PageBuilderEditView\";\n// Must match FIELD_COMPONENT_PATH exported from the \".\" entry (pageBuilderField).\nconst FIELD_PATH = \"@nextlyhq/plugin-page-builder/admin#PageBuilderField\";\n// Schema-builder slot component (contributes.admin.schemaBuilderSlot).\nconst TOGGLE_PATH = \"@nextlyhq/plugin-page-builder/admin#PageBuilderToggle\";\n// Entry-form toolbar slot component (contributes.admin.entryFormToolbarSlot).\nconst MODE_TOGGLE_PATH =\n \"@nextlyhq/plugin-page-builder/admin#PageBuilderModeToggle\";\nconst COMPONENTS = {\n [EDIT_VIEW_PATH]: PageBuilderEditView,\n [FIELD_PATH]: PageBuilderField,\n [TOGGLE_PATH]: PageBuilderToggle,\n [MODE_TOGGLE_PATH]: PageBuilderModeToggle,\n};\n\n// Eager registration on module load.\nregisterComponents(COMPONENTS);\n\n// Lazy fallback: the host can trigger registration on demand by package prefix.\nregisterKnownPlugin(\"@nextlyhq/plugin-page-builder\", () => {\n registerComponents(COMPONENTS);\n return Promise.resolve();\n});\n\nexport { PageBuilderEditView };\nexport { PageBuilderField };\nexport { PageBuilderToggle };\nexport { PageBuilderModeToggle };\nexport type { CustomEditViewProps } from \"./types\";\n","\"use client\";\n\n/**\n * Registers the built-in inspector controls into the (open) control registry and exposes\n * `renderControl`, the generic dispatch the inspector uses to turn a control `type` +\n * ControlProps into a rendered React node. Third parties register novel controls the same\n * way — no core edit needed (spec §7). Registration is idempotent.\n */\nimport { createElement, type ReactNode } from \"react\";\n\nimport { defaultControlRegistry } from \"../../core/registry\";\n\nimport { ColorControl } from \"./ColorControl\";\nimport { MediaControl } from \"./MediaControl\";\nimport {\n AlignControl,\n BooleanControl,\n DimensionControl,\n LinkControl,\n NumberControl,\n SelectControl,\n TextControl,\n TextareaControl,\n} from \"./primitives\";\nimport { SpacingControl } from \"./SpacingControl\";\nimport type { ControlComponent, ControlProps } from \"./types\";\n\nconst CONTROLS: Record<string, ControlComponent> = {\n text: TextControl,\n textarea: TextareaControl,\n number: NumberControl,\n boolean: BooleanControl,\n select: SelectControl,\n align: AlignControl,\n dimension: DimensionControl,\n link: LinkControl,\n spacing: SpacingControl,\n color: ColorControl,\n media: MediaControl,\n};\n\nlet registered = false;\n\nexport function registerDefaultControls(): void {\n if (registered) return;\n registered = true;\n for (const [type, Component] of Object.entries(CONTROLS)) {\n defaultControlRegistry.register({ type, Component });\n }\n}\n\n/** Render a control by type. Falls back to a plain text control for unknown types. */\nexport function renderControl(type: string, props: ControlProps): ReactNode {\n const def = defaultControlRegistry.get(type);\n const Component =\n (def?.Component as ControlComponent | undefined) ?? TextControl;\n return createElement(Component, props);\n}\n","\"use client\";\n\n/**\n * Color control (spec §8). @nextlyhq/ui ships no color picker, so this is a compact one:\n * a native <input type=\"color\">, a hex text field, a clear button, and — when a token\n * palette is provided — clickable token swatches. A raw color is stored as a string; a\n * token is stored as `{ token }` so the style compiler emits `var(--nx-<token>)`.\n */\nimport { Input } from \"@nextlyhq/ui\";\n\nimport type { TokenRef } from \"../../core/types\";\nimport { X } from \"../icons\";\n\nimport { ControlRow } from \"./primitives\";\nimport type { ControlProps } from \"./types\";\n\nfunction isToken(v: unknown): v is TokenRef {\n return typeof v === \"object\" && v !== null && \"token\" in v;\n}\n\nexport function ColorControl({ value, onChange, label, tokens }: ControlProps) {\n const token = isToken(value) ? value.token : undefined;\n const hex = typeof value === \"string\" ? value : \"\";\n return (\n <ControlRow label={label}>\n <div className=\"nx-pb-color-row\">\n <input\n type=\"color\"\n className=\"nx-pb-color-swatch\"\n aria-label={`${label ?? \"color\"} picker`}\n value={/^#[0-9a-fA-F]{6}$/.test(hex) ? hex : \"#000000\"}\n onChange={e => onChange(e.target.value)}\n />\n <Input\n value={token ? `token:${token}` : hex}\n placeholder=\"#000000\"\n onChange={e => onChange(e.target.value)}\n style={{ flex: 1 }}\n />\n {value !== undefined ? (\n <button\n type=\"button\"\n className=\"nx-pb-icon-btn\"\n aria-label=\"Clear color\"\n onClick={() => onChange(undefined)}\n style={{ padding: \"6px 8px\" }}\n >\n <X size={14} aria-hidden />\n </button>\n ) : null}\n </div>\n {tokens && tokens.length > 0 ? (\n <div className=\"nx-pb-color-tokens\">\n {tokens.map(t => (\n <button\n key={t.name}\n type=\"button\"\n className=\"nx-pb-color-token\"\n data-active={token === t.name || undefined}\n title={t.label}\n aria-label={t.label}\n onClick={() => onChange({ token: t.name })}\n style={{ background: t.preview }}\n />\n ))}\n </div>\n ) : null}\n </ControlRow>\n );\n}\n","\"use client\";\n\n/**\n * Explicit lucide icon map for the editor chrome. We map by NAME (an explicit object, not\n * `import * as`) so the admin bundle only pulls the icons we actually use. Block definitions\n * already carry a lucide icon name in `def.icon` (e.g. \"Heading\", \"Image\"); `blockIcon`\n * resolves that to a component, falling back to a neutral square.\n */\nimport {\n ArrowDown,\n ArrowUp,\n ChevronDown,\n ChevronRight,\n Copy,\n GripVertical,\n Heading,\n Image,\n LayoutGrid,\n Link2,\n Monitor,\n MousePointerClick,\n Plus,\n Repeat,\n Search,\n Smartphone,\n Square,\n Tablet,\n Trash2,\n Type,\n Video,\n X,\n type LucideIcon,\n} from \"lucide-react\";\n\nconst BLOCK_ICONS: Record<string, LucideIcon> = {\n Heading,\n Image,\n LayoutGrid,\n MousePointerClick,\n Repeat,\n Square,\n Type,\n Video,\n};\n\n/** Resolve a block definition's `icon` name to a lucide component. */\nexport function blockIcon(name: string | undefined): LucideIcon {\n return (name && BLOCK_ICONS[name]) || Square;\n}\n\nexport {\n ArrowDown,\n ArrowUp,\n ChevronDown,\n ChevronRight,\n Copy,\n GripVertical,\n Link2,\n Monitor,\n Plus,\n Search,\n Smartphone,\n Tablet,\n Trash2,\n X,\n};\n","\"use client\";\n\n/**\n * Small controlled inputs used by both the Content and Style inspector tabs. Each is a\n * thin wrapper over @nextlyhq/ui primitives conforming to ControlProps. Kept in one file\n * because they are tiny and share the ControlRow label chrome.\n */\nimport {\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Textarea,\n} from \"@nextlyhq/ui\";\nimport { type ReactNode, useId } from \"react\";\n\nimport type { ControlProps } from \"./types\";\n\nconst UNITS = [\"px\", \"%\", \"rem\", \"em\", \"vw\", \"vh\"];\n\nexport function ControlRow({\n label,\n htmlFor,\n children,\n}: {\n label?: string;\n htmlFor?: string;\n children: ReactNode;\n}): ReactNode {\n return (\n <div style={{ display: \"grid\", gap: 4, marginBottom: 10 }}>\n {label ? (\n <Label htmlFor={htmlFor} className=\"nx-pb-control-label\">\n {label}\n </Label>\n ) : null}\n {children}\n </div>\n );\n}\n\nconst str = (v: unknown): string => (typeof v === \"string\" ? v : \"\");\n\nexport function TextControl({ value, onChange, label, field }: ControlProps) {\n const id = useId();\n return (\n <ControlRow label={label} htmlFor={id}>\n <Input\n id={id}\n value={str(value)}\n placeholder={field?.placeholder}\n onChange={e => onChange(e.target.value)}\n />\n </ControlRow>\n );\n}\n\nexport function TextareaControl({\n value,\n onChange,\n label,\n field,\n}: ControlProps) {\n const id = useId();\n return (\n <ControlRow label={label} htmlFor={id}>\n <Textarea\n id={id}\n rows={3}\n value={str(value)}\n placeholder={field?.placeholder}\n onChange={e => onChange(e.target.value)}\n />\n </ControlRow>\n );\n}\n\nexport function NumberControl({ value, onChange, label }: ControlProps) {\n const id = useId();\n return (\n <ControlRow label={label} htmlFor={id}>\n <Input\n id={id}\n type=\"number\"\n value={typeof value === \"number\" ? value : str(value)}\n onChange={e =>\n onChange(e.target.value === \"\" ? undefined : Number(e.target.value))\n }\n />\n </ControlRow>\n );\n}\n\nexport function BooleanControl({ value, onChange, label }: ControlProps) {\n const id = useId();\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 10,\n }}\n >\n <Label htmlFor={id} className=\"nx-pb-control-label\">\n {label}\n </Label>\n <Switch\n id={id}\n checked={value === true}\n onCheckedChange={checked => onChange(checked)}\n />\n </div>\n );\n}\n\nexport function SelectControl({ value, onChange, label, field }: ControlProps) {\n const options = field?.options ?? [];\n return (\n <ControlRow label={label}>\n <Select value={str(value)} onValueChange={v => onChange(v)}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select…\" />\n </SelectTrigger>\n <SelectContent>\n {options.map(o => (\n <SelectItem key={o.value} value={o.value}>\n {o.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </ControlRow>\n );\n}\n\nconst ALIGN = [\n { value: \"left\", label: \"Left\" },\n { value: \"center\", label: \"Center\" },\n { value: \"right\", label: \"Right\" },\n { value: \"justify\", label: \"Justify\" },\n];\n\nexport function AlignControl({ value, onChange, label }: ControlProps) {\n return (\n <ControlRow label={label}>\n <div className=\"nx-pb-choice\" role=\"group\" aria-label={label}>\n {ALIGN.map(a => (\n <button\n key={a.value}\n type=\"button\"\n className=\"nx-pb-choice-btn\"\n aria-pressed={value === a.value}\n onClick={() => onChange(value === a.value ? undefined : a.value)}\n >\n {a.label}\n </button>\n ))}\n </div>\n </ControlRow>\n );\n}\n\n/** Splits a CSS length like \"12px\" into number + unit for editing. */\nfunction splitLength(v: unknown): { n: string; unit: string } {\n const s = str(v).trim();\n const m = /^(-?\\d*\\.?\\d+)(px|%|rem|em|vw|vh)?$/.exec(s);\n if (!m) return { n: \"\", unit: \"px\" };\n return { n: m[1], unit: m[2] ?? \"px\" };\n}\n\nexport function DimensionControl({ value, onChange, label }: ControlProps) {\n const { n, unit } = splitLength(value);\n const emit = (nextN: string, nextUnit: string) =>\n onChange(nextN === \"\" ? undefined : `${nextN}${nextUnit}`);\n return (\n <ControlRow label={label}>\n <div style={{ display: \"flex\", gap: 4 }}>\n <Input\n type=\"number\"\n value={n}\n style={{ flex: 1 }}\n onChange={e => emit(e.target.value, unit)}\n />\n <Select value={unit} onValueChange={u => emit(n, u)}>\n <SelectTrigger style={{ width: 80 }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {UNITS.map(u => (\n <SelectItem key={u} value={u}>\n {u}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </ControlRow>\n );\n}\n\nexport function LinkControl({ value, onChange, label }: ControlProps) {\n const v = (value ?? {}) as { href?: string; target?: string };\n const id = useId();\n return (\n <ControlRow label={label} htmlFor={id}>\n <Input\n id={id}\n value={str(v.href)}\n placeholder=\"https://…\"\n onChange={e => onChange({ ...v, href: e.target.value })}\n />\n <label\n className=\"nx-pb-control-label\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n marginTop: 4,\n }}\n >\n <input\n type=\"checkbox\"\n checked={v.target === \"_blank\"}\n onChange={e =>\n onChange({ ...v, target: e.target.checked ? \"_blank\" : undefined })\n }\n />\n Open in new tab\n </label>\n </ControlRow>\n );\n}\n","\"use client\";\n\n/**\n * Media control (spec §9). Reuses the admin's MediaPickerDialog (public export) to choose\n * a library asset; on select it stores `{ mediaId, url, alt, width, height }` so the canvas\n * previews via `url` directly and the render path can re-resolve by `mediaId` through the\n * dataProvider. A manual URL + alt (accessibility) remain available as a fallback.\n */\nimport { MediaPickerDialog, type Media } from \"@nextlyhq/admin\";\nimport { Button, Input } from \"@nextlyhq/ui\";\nimport { useState } from \"react\";\n\nimport { ControlRow } from \"./primitives\";\nimport type { ControlProps } from \"./types\";\n\nexport interface MediaValue {\n mediaId?: string;\n url?: string;\n alt?: string;\n width?: number;\n height?: number;\n}\n\nconst str = (v: unknown): string => (typeof v === \"string\" ? v : \"\");\n\nexport function MediaControl({ value, onChange, label }: ControlProps) {\n const v = (value ?? {}) as MediaValue;\n const [open, setOpen] = useState(false);\n\n const onSelect = (media: Media[]) => {\n const m = media[0];\n if (m) {\n onChange({\n mediaId: m.id,\n url: m.url,\n alt: m.altText ?? \"\",\n width: m.width ?? undefined,\n height: m.height ?? undefined,\n });\n }\n setOpen(false);\n };\n\n return (\n <ControlRow label={label}>\n {v.url ? (\n <img\n src={v.url}\n alt={v.alt ?? \"\"}\n style={{\n maxWidth: \"100%\",\n maxHeight: 120,\n borderRadius: \"var(--radius)\",\n border: \"1px solid hsl(var(--border))\",\n marginBottom: 6,\n }}\n />\n ) : null}\n <div style={{ display: \"flex\", gap: 6, marginBottom: 4 }}>\n <Button variant=\"outline\" onClick={() => setOpen(true)}>\n {v.url ? \"Replace\" : \"Choose from library\"}\n </Button>\n {v.url ? (\n <Button variant=\"ghost\" onClick={() => onChange(undefined)}>\n Remove\n </Button>\n ) : null}\n </div>\n <Input\n value={str(v.url)}\n placeholder=\"…or paste an image URL\"\n aria-label={`${label ?? \"media\"} url`}\n onChange={e => onChange({ ...v, url: e.target.value })}\n />\n <Input\n value={str(v.alt)}\n placeholder=\"Alt text (describe the image)\"\n aria-label={`${label ?? \"media\"} alt text`}\n style={{ marginTop: 4 }}\n onChange={e => onChange({ ...v, alt: e.target.value })}\n />\n <MediaPickerDialog\n mode=\"single\"\n open={open}\n onOpenChange={setOpen}\n onSelect={onSelect}\n accept=\"image/*\"\n title=\"Select media\"\n />\n </ControlRow>\n );\n}\n","\"use client\";\n\n/**\n * Edits a BoxSides value (padding/margin) as four px inputs (top/right/bottom/left), with a\n * link toggle that edits all four sides together (Elementor-style). Emits a BoxSides object;\n * empty sides are omitted so the compiler skips them.\n */\nimport { Input } from \"@nextlyhq/ui\";\nimport { useState } from \"react\";\n\nimport type { BoxSides } from \"../../core/types\";\nimport { Link2 } from \"../icons\";\n\nimport { ControlRow } from \"./primitives\";\nimport type { ControlProps } from \"./types\";\n\ntype Side = keyof BoxSides;\nconst SIDES: { key: Side; label: string }[] = [\n { key: \"top\", label: \"T\" },\n { key: \"right\", label: \"R\" },\n { key: \"bottom\", label: \"B\" },\n { key: \"left\", label: \"L\" },\n];\n\nfunction num(v: string | undefined): string {\n if (!v) return \"\";\n const m = /^(-?\\d*\\.?\\d+)/.exec(v);\n return m ? m[1] : \"\";\n}\n\nexport function SpacingControl({ value, onChange, label }: ControlProps) {\n const sides = (value ?? {}) as BoxSides;\n const [linked, setLinked] = useState(false);\n\n const emit = (side: Side, raw: string) => {\n // Linked: write the same value to every side at once.\n if (linked) {\n if (raw === \"\") return onChange(undefined);\n const all = `${raw}px`;\n return onChange({ top: all, right: all, bottom: all, left: all });\n }\n const next: BoxSides = { ...sides };\n if (raw === \"\") delete next[side];\n else next[side] = `${raw}px`;\n onChange(Object.keys(next).length ? next : undefined);\n };\n\n return (\n <ControlRow label={label}>\n <div className=\"nx-pb-box\">\n {SIDES.map(s => (\n <div key={s.key} className=\"nx-pb-box-side\">\n <Input\n type=\"number\"\n aria-label={`${label ?? \"spacing\"} ${s.key}`}\n value={num(sides[s.key])}\n onChange={e => emit(s.key, e.target.value)}\n />\n <span>{s.label}</span>\n </div>\n ))}\n <button\n type=\"button\"\n className=\"nx-pb-box-link\"\n aria-label=\"Link all sides\"\n aria-pressed={linked}\n title=\"Edit all sides together\"\n onClick={() => setLinked(l => !l)}\n >\n <Link2 size={15} aria-hidden />\n </button>\n </div>\n </ControlRow>\n );\n}\n","\"use client\";\n\n/**\n * The 3-pane editor surface (spec §9): left block library | center iframe canvas | right\n * inspector, with a breakpoint switcher. A single DragDropProvider spans all panes so a\n * library source can drop into the canvas and canvas nodes can reorder; between-item drop\n * zones show exactly where a block lands, and a DragOverlay chip follows the cursor. Drops\n * are planned by the pure `planDrop`. Keyboard users add via the library's Insert buttons\n * and reorder via the inspector — no pointer required.\n */\nimport { DragDropProvider, DragOverlay } from \"@dnd-kit/react\";\nimport { type LucideIcon } from \"lucide-react\";\n\nimport { defaultBlockRegistry } from \"../core/registry\";\n\nimport { Canvas } from \"./canvas/Canvas\";\nimport { Monitor, Smartphone, Tablet } from \"./icons\";\nimport { dragLabel } from \"./logic/dragLabel\";\nimport { planDrop } from \"./logic/dropPlan\";\nimport { BlockLibrary } from \"./panels/BlockLibrary\";\nimport { Inspector } from \"./panels/Inspector\";\nimport { useEditor } from \"./store/EditorProvider\";\n\nconst BREAKPOINTS: { id: string; label: string; Icon: LucideIcon }[] = [\n { id: \"base\", label: \"Desktop\", Icon: Monitor },\n { id: \"tablet\", label: \"Tablet\", Icon: Tablet },\n { id: \"mobile\", label: \"Mobile\", Icon: Smartphone },\n];\n\nexport function EditorSurface() {\n const { state, dispatch } = useEditor();\n const root = state.document.root;\n\n const onDragEnd = (event: {\n operation: {\n source: { id: string | number; data?: unknown } | null;\n target: { id: string | number; data?: unknown } | null;\n };\n canceled: boolean;\n }) => {\n if (event.canceled) return;\n const { source, target } = event.operation;\n if (!source || !target) return;\n const action = planDrop(\n source.data ?? {},\n target.data ?? {},\n root,\n defaultBlockRegistry\n );\n if (action) dispatch(action);\n };\n\n return (\n <DragDropProvider onDragEnd={onDragEnd}>\n <div className=\"nx-pb-editor\">\n <div className=\"nx-pb-toolbar\">\n <div className=\"nx-pb-seg\" role=\"group\" aria-label=\"Preview device\">\n {BREAKPOINTS.map(({ id, label, Icon }) => (\n <button\n key={id}\n type=\"button\"\n className=\"nx-pb-seg-btn\"\n aria-pressed={state.activeBreakpoint === id}\n aria-label={label}\n onClick={() =>\n dispatch({ type: \"SET_BREAKPOINT\", breakpoint: id })\n }\n >\n <Icon size={15} aria-hidden />\n {label}\n </button>\n ))}\n </div>\n </div>\n <div className=\"nx-pb-body\">\n <aside className=\"nx-pb-pane nx-pb-pane--left\">\n <BlockLibrary />\n </aside>\n <main className=\"nx-pb-pane--center\">\n <Canvas />\n </main>\n <aside className=\"nx-pb-pane nx-pb-pane--right\">\n <Inspector />\n </aside>\n </div>\n </div>\n\n <DragOverlay>\n {source => (\n <div\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n padding: \"6px 12px\",\n borderRadius: \"var(--radius)\",\n background: \"hsl(var(--primary))\",\n color: \"hsl(var(--primary-foreground))\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: \"0 8px 24px rgb(0 0 0 / 0.25)\",\n pointerEvents: \"none\",\n whiteSpace: \"nowrap\",\n }}\n >\n <span aria-hidden>⠿</span>\n {dragLabel(source?.data ?? {}, root, defaultBlockRegistry)}\n </div>\n )}\n </DragOverlay>\n </DragDropProvider>\n );\n}\n","\"use client\";\n\n/**\n * Editor context + reducer wiring (spec §9). Provides the store to the canvas,\n * inspector, and save shell, and debounces a localStorage draft per entry so a crash\n * doesn't lose work. `useEditor()` is the access hook.\n */\nimport {\n createContext,\n useContext,\n useEffect,\n useReducer,\n useRef,\n type Dispatch,\n type ReactNode,\n} from \"react\";\n\nimport type { BlockDocument } from \"../../core/types\";\n\nimport {\n editorReducer,\n initialState,\n type EditorAction,\n type EditorState,\n} from \"./editorStore\";\n\ninterface EditorContextValue {\n state: EditorState;\n dispatch: Dispatch<EditorAction>;\n}\n\nconst EditorContext = createContext<EditorContextValue | null>(null);\n\nexport function useEditor(): EditorContextValue {\n const ctx = useContext(EditorContext);\n if (!ctx) throw new Error(\"useEditor must be used inside <EditorProvider>\");\n return ctx;\n}\n\nexport function draftKeyFor(\n collectionSlug: string,\n entryId: string | undefined\n): string {\n return `nx-pb-draft:${collectionSlug}:${entryId ?? \"new\"}`;\n}\n\nexport function EditorProvider({\n document: doc,\n draftKey,\n onDocumentChange,\n children,\n}: {\n document: BlockDocument;\n draftKey: string;\n /**\n * Fired whenever the document changes (skipping the initial mount) — used by the\n * field mount (`PageBuilderField`) to sync into the host react-hook-form. The full\n * Edit-view leaves this unset and persists via `SaveShell`.\n */\n onDocumentChange?: (document: BlockDocument) => void;\n children: ReactNode;\n}) {\n const [state, dispatch] = useReducer(editorReducer, doc, initialState);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const firstRender = useRef(true);\n\n // Hold the latest callback in a ref so the sync effect depends ONLY on the document.\n // Callers (e.g. PageBuilderField) commonly pass an inline arrow — depending on its\n // identity would re-run the effect every render and, via the host form's onChange,\n // loop infinitely (\"Maximum update depth exceeded\").\n const onDocumentChangeRef = useRef(onDocumentChange);\n onDocumentChangeRef.current = onDocumentChange;\n\n // Push document changes to a host form (field mount), not on the initial mount.\n useEffect(() => {\n if (firstRender.current) {\n firstRender.current = false;\n return;\n }\n onDocumentChangeRef.current?.(state.document);\n }, [state.document]);\n\n // Debounced draft autosave (only while there are unsaved changes).\n useEffect(() => {\n if (!state.dirty) return;\n if (timer.current) clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n try {\n localStorage.setItem(draftKey, JSON.stringify(state.document));\n } catch {\n /* quota / unavailable — ignore */\n }\n }, 800);\n return () => {\n if (timer.current) clearTimeout(timer.current);\n };\n }, [state.document, state.dirty, draftKey]);\n\n return (\n <EditorContext.Provider value={{ state, dispatch }}>\n {children}\n </EditorContext.Provider>\n );\n}\n","/**\n * The editor's pure reducer (spec §9). Operates on a BlockDocument via the isomorphic\n * core tree ops, with bounded undo/redo history. Defaults for new nodes come from the\n * block registry — never a hard-coded list.\n */\nimport { defaultBlockRegistry } from \"../../core/registry\";\nimport {\n duplicateNode,\n findNode,\n insertNode,\n makeNode,\n moveNode,\n removeNode,\n updateNode,\n} from \"../../core/tree\";\nimport type {\n BlockDocument,\n BlockNode,\n Binding,\n StyleValues,\n} from \"../../core/types\";\n\nconst HISTORY_LIMIT = 50;\nconst BASE_BREAKPOINT = \"base\";\n\nexport interface EditorState {\n document: BlockDocument;\n selectedId: string | null;\n activeBreakpoint: string;\n past: BlockDocument[];\n future: BlockDocument[];\n dirty: boolean;\n}\n\nexport function initialState(document: BlockDocument): EditorState {\n return {\n document,\n selectedId: null,\n activeBreakpoint: BASE_BREAKPOINT,\n past: [],\n future: [],\n dirty: false,\n };\n}\n\nexport type EditorAction =\n | { type: \"SELECT\"; id: string | null }\n | { type: \"SET_BREAKPOINT\"; breakpoint: string }\n | {\n type: \"ADD\";\n parentId: string;\n slot: string;\n nodeType: string;\n index: number;\n }\n | { type: \"MOVE\"; id: string; parentId: string; slot: string; index: number }\n | { type: \"REMOVE\"; id: string }\n | { type: \"DUPLICATE\"; id: string }\n | { type: \"UPDATE_PROPS\"; id: string; props: Record<string, unknown> }\n | {\n type: \"UPDATE_STYLE\";\n id: string;\n breakpoint: string;\n style: StyleValues;\n /** Which state to write — normal (default) or hover. */\n styleState?: \"normal\" | \"hover\";\n }\n | { type: \"SET_BINDING\"; id: string; prop: string; binding: Binding | null }\n | { type: \"SET_CUSTOM_CLASS\"; id: string; customClass: string }\n | { type: \"REPLACE\"; document: BlockDocument }\n | { type: \"MARK_SAVED\" }\n | { type: \"UNDO\" }\n | { type: \"REDO\" };\n\n/** Keep a selection only if the id still resolves in the given document. */\nfunction keepValidSelection(\n document: BlockDocument,\n selectedId: string | null\n): string | null {\n if (!selectedId) return null;\n return findNode(document.root, selectedId) ? selectedId : null;\n}\n\n/** Build a fresh node for `type` from the registry's declared defaults. */\nexport function createNodeFromType(nodeType: string): BlockNode {\n const def = defaultBlockRegistry.get(nodeType);\n const props = def ? structuredClone(def.defaultProps) : {};\n const style = def?.defaultStyle\n ? structuredClone(def.defaultStyle)\n : undefined;\n const slots = def?.isContainer ? { default: [] } : undefined;\n return makeNode(nodeType, props, style, slots);\n}\n\n/** Commit a new root: push current onto history (bounded), clear redo, mark dirty. */\nfunction commit(\n state: EditorState,\n root: BlockNode,\n selectedId = state.selectedId\n): EditorState {\n const past = [...state.past, state.document].slice(-HISTORY_LIMIT);\n return {\n ...state,\n document: { ...state.document, root },\n past,\n future: [],\n dirty: true,\n selectedId,\n };\n}\n\nexport function editorReducer(\n state: EditorState,\n action: EditorAction\n): EditorState {\n const root = state.document.root;\n\n switch (action.type) {\n case \"SELECT\":\n return { ...state, selectedId: action.id };\n\n case \"SET_BREAKPOINT\":\n return { ...state, activeBreakpoint: action.breakpoint };\n\n case \"ADD\": {\n const node = createNodeFromType(action.nodeType);\n return commit(\n state,\n insertNode(root, action.parentId, action.slot, node, action.index),\n node.id\n );\n }\n\n case \"MOVE\":\n return commit(\n state,\n moveNode(root, action.id, action.parentId, action.slot, action.index)\n );\n\n case \"REMOVE\": {\n const next = removeNode(root, action.id);\n return { ...commit(state, next), selectedId: null };\n }\n\n case \"DUPLICATE\":\n return commit(state, duplicateNode(root, action.id));\n\n case \"UPDATE_PROPS\": {\n const node = findNode(root, action.id);\n const props = { ...(node?.props ?? {}), ...action.props };\n return commit(state, updateNode(root, action.id, { props }));\n }\n\n case \"UPDATE_STYLE\": {\n const node = findNode(root, action.id);\n const key = action.styleState === \"hover\" ? \"styleHover\" : \"style\";\n const style = { ...(node?.[key] ?? {}) };\n style[action.breakpoint] = {\n ...(style[action.breakpoint] ?? {}),\n ...action.style,\n };\n return commit(state, updateNode(root, action.id, { [key]: style }));\n }\n\n case \"SET_BINDING\": {\n const node = findNode(root, action.id);\n const bindings = { ...(node?.bindings ?? {}) };\n if (action.binding) bindings[action.prop] = action.binding;\n else delete bindings[action.prop];\n return commit(state, updateNode(root, action.id, { bindings }));\n }\n\n case \"SET_CUSTOM_CLASS\": {\n const customClass = action.customClass.trim() || undefined;\n return commit(state, updateNode(root, action.id, { customClass }));\n }\n\n case \"REPLACE\":\n return {\n ...initialState(action.document),\n activeBreakpoint: state.activeBreakpoint,\n };\n\n case \"MARK_SAVED\":\n return { ...state, dirty: false };\n\n case \"UNDO\": {\n if (!state.past.length) return state;\n const prev = state.past[state.past.length - 1];\n return {\n ...state,\n document: prev,\n selectedId: keepValidSelection(prev, state.selectedId),\n past: state.past.slice(0, -1),\n future: [state.document, ...state.future],\n dirty: true,\n };\n }\n\n case \"REDO\": {\n if (!state.future.length) return state;\n const next = state.future[0];\n return {\n ...state,\n document: next,\n selectedId: keepValidSelection(next, state.selectedId),\n past: [...state.past, state.document],\n future: state.future.slice(1),\n dirty: true,\n };\n }\n\n default:\n return state;\n }\n}\n","\"use client\";\n\n/**\n * Canvas rendering of the block tree (spec §9). Renders the SAME production block output\n * as the frontend (pixel parity), then augments each block element with a stable\n * `data-nx-id`, click-to-select, the selection class, per-block error isolation, and a\n * @dnd-kit draggable handle so it can be picked up.\n *\n * Drop targeting is parity-safe:\n * - In normal block flow (containers, query-loop template) zero-height DropZones are\n * interleaved between children — they add no layout box, so the output matches the\n * frontend exactly.\n * - Inside a GRID a between-child <div> would become an extra grid item and break the\n * columns, so grid children render directly; each grid cell is an \"insert-before\"\n * droppable and the grid itself is an \"append\" droppable (highlight, no layout box).\n *\n * The root container renders via `CanvasNode`; descendants render via `DraggableNode`.\n */\nimport { useDraggable, useDroppable } from \"@dnd-kit/react\";\nimport {\n cloneElement,\n isValidElement,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport { defaultBlockRegistry } from \"../../core/registry\";\nimport { nodeClass } from \"../../core/style-compiler\";\nimport type { BlockNode } from \"../../core/types\";\nimport { BlockErrorBoundary } from \"../../render/ErrorBoundary\";\nimport { QUERY_LOOP_TYPE } from \"../../render/query/types\";\nimport { dragSensors } from \"../logic/dragSensors\";\nimport { useEditor } from \"../store/EditorProvider\";\n\nimport { QueryLoopSamplePreview } from \"./CanvasQueryLoop\";\nimport { DropZone } from \"./DropZone\";\n\nconst BLOCK_TYPE = \"nx-block\";\n\n/** Visual stand-in shown on the canvas for a block whose render() is empty (e.g. an\n * Image with no source), so it stays visible and selectable at author time. */\nconst placeholderStyle = {\n padding: \"14px 16px\",\n fontSize: 13,\n color: \"#6b7280\",\n border: \"1px dashed #cbd5e1\",\n borderRadius: 6,\n textAlign: \"center\" as const,\n background: \"#f8fafc\",\n};\n\n/** Containers whose children lay out horizontally — no interleaved DropZones (parity). */\nfunction isHorizontal(node: BlockNode): boolean {\n return node.type === \"core/grid\";\n}\n\ntype RefCb = (el: Element | null) => void;\nfunction mergeRefs(...refs: (RefCb | undefined)[]): RefCb {\n return el => {\n for (const r of refs) r?.(el);\n };\n}\n\nfunction classFor(\n node: BlockNode,\n selected: boolean,\n extra: (string | false | undefined)[] = []\n): string {\n return [\n nodeClass(node.id),\n node.customClass,\n selected && \"nx-pb-selected\",\n ...extra,\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\n/** Render a slot's children with drop targets (parity-safe per container type). */\nfunction renderSlot(node: BlockNode, slotName: string): ReactNode {\n const children = node.slots?.[slotName] ?? [];\n if (children.length === 0) {\n return (\n <DropZone\n key=\"dz-empty\"\n parentId={node.id}\n slot={slotName}\n index={0}\n empty\n />\n );\n }\n\n // Grid: render children directly (each an insert-before droppable). No between-divs.\n if (isHorizontal(node)) {\n return children.map((child, i) => (\n <DraggableNode\n key={child.id}\n node={child}\n parentId={node.id}\n slot={slotName}\n index={i}\n dropBeforeIndex={i}\n />\n ));\n }\n\n // Block flow: interleave zero-height DropZones (no layout impact → pixel parity).\n const out: ReactNode[] = [];\n children.forEach((child, i) => {\n out.push(\n <DropZone key={`dz-${i}`} parentId={node.id} slot={slotName} index={i} />\n );\n out.push(\n <DraggableNode\n key={child.id}\n node={child}\n parentId={node.id}\n slot={slotName}\n index={i}\n />\n );\n });\n out.push(\n <DropZone\n key={`dz-${children.length}`}\n parentId={node.id}\n slot={slotName}\n index={children.length}\n />\n );\n return out;\n}\n\nfunction buildSlots(node: BlockNode): Record<string, ReactNode> {\n const slots: Record<string, ReactNode> = {};\n if (node.slots) {\n for (const name of Object.keys(node.slots)) {\n slots[name] = renderSlot(node, name);\n }\n }\n return slots;\n}\n\n/** Root renderer — the page container, not itself draggable. */\nexport function CanvasNode({ node }: { node: BlockNode }): ReactNode {\n const { state } = useEditor();\n const def = defaultBlockRegistry.get(node.type);\n const selected = state.selectedId === node.id;\n const className = classFor(node, selected);\n\n if (!def) {\n return (\n <div\n data-nx-id={node.id}\n data-nx-unknown={node.type}\n className={className}\n />\n );\n }\n\n const element = def.render({\n props: node.props,\n node,\n slots: buildSlots(node),\n className,\n });\n if (!isValidElement(element)) {\n return (\n <div className={className} data-nx-id={node.id} style={placeholderStyle}>\n {def.label} — click to configure\n </div>\n );\n }\n return cloneElement(element as ReactElement<Record<string, unknown>>, {\n \"data-nx-id\": node.id,\n });\n}\n\n/** A draggable descendant node, optionally an insert-before / append drop target. */\nfunction DraggableNode({\n node,\n parentId,\n slot,\n index,\n dropBeforeIndex,\n}: {\n node: BlockNode;\n parentId: string;\n slot: string;\n index: number;\n /** When set (grid child), this element is also an \"insert before\" drop target. */\n dropBeforeIndex?: number;\n}): ReactNode {\n const { state } = useEditor();\n const def = defaultBlockRegistry.get(node.type);\n const selected = state.selectedId === node.id;\n\n const { ref: dragRef, isDragging } = useDraggable({\n id: node.id,\n type: BLOCK_TYPE,\n data: { kind: \"node\", nodeId: node.id, parentId, slot, index },\n sensors: dragSensors,\n });\n\n // Grid child: \"insert before me\" target.\n const before = useDroppable({\n id: `before:${node.id}`,\n type: BLOCK_TYPE,\n accept: BLOCK_TYPE,\n disabled: dropBeforeIndex == null,\n data: { kind: \"dropzone\", parentId, slot, index: dropBeforeIndex ?? 0 },\n });\n\n // Grid itself: \"append\" target for its own default slot.\n const grid = isHorizontal(node);\n const appendIndex = node.slots?.default?.length ?? 0;\n const append = useDroppable({\n id: `append:${node.id}`,\n type: BLOCK_TYPE,\n accept: BLOCK_TYPE,\n disabled: !grid,\n data: {\n kind: \"dropzone\",\n parentId: node.id,\n slot: \"default\",\n index: appendIndex,\n },\n });\n\n const className = classFor(node, selected, [\n isDragging && \"nx-pb-dragging\",\n before.isDropTarget && \"nx-pb-drop-before\",\n append.isDropTarget && \"nx-pb-drop-append\",\n ]);\n\n const ref = mergeRefs(dragRef, before.ref, grid ? append.ref : undefined);\n\n if (!def) {\n return (\n <div\n ref={ref}\n data-nx-id={node.id}\n data-nx-unknown={node.type}\n className={className}\n />\n );\n }\n\n const element = def.render({\n props: node.props,\n node,\n slots: buildSlots(node),\n className,\n });\n if (!isValidElement(element)) {\n return (\n <div\n ref={ref}\n className={className}\n data-nx-id={node.id}\n style={placeholderStyle}\n >\n {def.label} — click to configure\n </div>\n );\n }\n\n // The Query Loop keeps its editable template, and we APPEND a read-only sample-data\n // preview after it so the author sees how the template maps to real entries (spec §5).\n const el = element as ReactElement<Record<string, unknown>>;\n const augmented =\n node.type === QUERY_LOOP_TYPE\n ? cloneElement(\n el,\n { \"data-nx-id\": node.id, ref },\n (el.props as { children?: ReactNode }).children,\n <QueryLoopSamplePreview key=\"__nx-sample\" node={node} />\n )\n : cloneElement(el, { \"data-nx-id\": node.id, ref });\n\n return (\n <BlockErrorBoundary\n fallback={\n <div\n ref={ref}\n data-nx-id={node.id}\n className={className}\n style={{\n padding: 8,\n fontSize: 12,\n color: \"#b91c1c\",\n border: \"1px dashed #fca5a5\",\n borderRadius: 6,\n }}\n >\n {def.label} failed to render.\n </div>\n }\n >\n {augmented}\n </BlockErrorBoundary>\n );\n}\n","/**\n * Shared @dnd-kit sensor config for the editor. A 4px distance activation constraint means\n * a click (or a click that jitters a pixel or two) never starts a drag — it stays a\n * selection — while a deliberate drag still works. This is the fix for \"drags eat clicks\".\n * We keep the KeyboardSensor so overriding a draggable's sensors doesn't drop keyboard drag.\n */\nimport {\n KeyboardSensor,\n PointerActivationConstraints,\n PointerSensor,\n type Sensors,\n} from \"@dnd-kit/dom\";\n\nexport const dragSensors: Sensors = [\n PointerSensor.configure({\n activationConstraints: [\n new PointerActivationConstraints.Distance({ value: 4 }),\n ],\n }),\n KeyboardSensor,\n];\n","\"use client\";\n\n/**\n * Design-time Query Loop sample preview (spec §5). Appended AFTER the loop's editable\n * template on the canvas (never replacing it, so selection/drag/dropzones keep working): it\n * fetches a few real sample rows for the loop's collection and renders them read-only via the\n * production `RenderNode` (bindings resolved), so the author sees how the template maps to real\n * data. It spans the full column width and ignores pointer events. Production rendering is\n * unchanged; this is editor-only and bounded to a few rows.\n */\nimport { useEffect, useState } from \"react\";\n\nimport { defaultBlockRegistry } from \"../../core/registry\";\nimport { DEFAULT_SLOT, type BlockNode } from \"../../core/types\";\nimport { loopGridStyle } from \"../../render/query/grid\";\nimport { RenderNode } from \"../../render/RenderNode\";\nimport { getSampleEntries } from \"../api/collectionsApi\";\n\nconst PREVIEW_ROWS = 4;\n\nexport function QueryLoopSamplePreview({ node }: { node: BlockNode }) {\n const collection =\n typeof node.props.collection === \"string\" ? node.props.collection : \"\";\n const sort =\n typeof node.props.sort === \"string\" ? node.props.sort : undefined;\n const where = node.props.where;\n const [rows, setRows] = useState<Record<string, unknown>[] | null>(null);\n const [error, setError] = useState(false);\n\n useEffect(() => {\n let alive = true;\n if (!collection) {\n setRows(null);\n return;\n }\n setError(false);\n getSampleEntries(collection, { limit: PREVIEW_ROWS, sort, where })\n .then(r => alive && setRows(r))\n .catch(() => alive && setError(true));\n return () => {\n alive = false;\n };\n }, [collection, sort, where]);\n\n // Nothing to preview when unconfigured (the template alone communicates the block).\n if (!collection) return null;\n\n const template = node.slots?.[DEFAULT_SLOT] ?? [];\n\n return (\n <div style={{ gridColumn: \"1 / -1\", pointerEvents: \"none\" }} aria-hidden>\n <div style={labelStyle}>\n {error\n ? \"Preview unavailable\"\n : rows == null\n ? \"Loading sample preview…\"\n : rows.length === 0\n ? \"No entries found\"\n : `Live preview — ${collection}`}\n </div>\n {rows && rows.length > 0 ? (\n <div style={loopGridStyle(node.props) ?? { display: \"grid\", gap: 12 }}>\n {rows.map((item, i) => (\n <div key={i} data-nx-loop-item={i}>\n {template.map(child => (\n <RenderNode\n key={child.id}\n node={child}\n registry={defaultBlockRegistry}\n item={item}\n />\n ))}\n </div>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\nconst labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\" as const,\n color: \"#94a3b8\",\n margin: \"10px 0 6px\",\n borderTop: \"1px dashed #cbd5e1\",\n paddingTop: 8,\n};\n","\"use client\";\n\n/**\n * Client-side discovery of collections, their field schema, and sample entries — used by\n * the Query Loop authoring UI (spec §5). The editor runs in the admin, so these hit the\n * admin REST surface (`/admin/api`, same-origin cookies). No public admin hook exposes the\n * schema/entries, so we call the endpoints directly. The response NORMALIZERS are pure and\n * unit-tested; the fetch wrappers stay thin.\n */\n\nconst BASE = \"/admin/api\";\n\nexport interface CollectionSummary {\n slug: string;\n label: string;\n}\n\nexport interface CollectionField {\n name: string;\n type: string;\n label: string;\n}\n\ntype Rec = Record<string, unknown>;\nconst asArray = (v: unknown): Rec[] => (Array.isArray(v) ? (v as Rec[]) : []);\nconst str = (v: unknown, fallback = \"\"): string =>\n typeof v === \"string\" ? v : fallback;\n\n/** `GET /admin/api/collections` → summaries, dropping admin-hidden + slugless entries. */\nexport function normalizeCollections(body: unknown): CollectionSummary[] {\n const items = asArray((body as Rec | null)?.items);\n const out: CollectionSummary[] = [];\n for (const c of items) {\n const admin = c.admin as Rec | undefined;\n if (admin?.hidden === true) continue;\n const slug = str(c.name) || str(c.slug);\n if (!slug) continue;\n const labels = c.labels as Rec | undefined;\n const label = str(c.label) || str(labels?.plural) || slug;\n out.push({ slug, label });\n }\n return out;\n}\n\n/** `GET /admin/api/collections/schema/{slug}` → simple field descriptors. */\nexport function normalizeFields(body: unknown): CollectionField[] {\n const fields = asArray((body as Rec | null)?.fields);\n const out: CollectionField[] = [];\n for (const f of fields) {\n const name = str(f.name);\n if (!name) continue;\n out.push({ name, type: str(f.type, \"text\"), label: str(f.label) || name });\n }\n return out;\n}\n\nasync function getJson(url: string): Promise<unknown> {\n const res = await fetch(url, {\n credentials: \"same-origin\",\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) throw new Error(`Request failed (${res.status})`);\n return res.json();\n}\n\nexport async function listCollections(): Promise<CollectionSummary[]> {\n return normalizeCollections(await getJson(`${BASE}/collections`));\n}\n\nexport async function getCollectionFields(\n slug: string\n): Promise<CollectionField[]> {\n if (!slug) return [];\n return normalizeFields(\n await getJson(`${BASE}/collections/schema/${encodeURIComponent(slug)}`)\n );\n}\n\nexport async function getSampleEntries(\n slug: string,\n opts: { limit?: number; sort?: string; where?: unknown } = {}\n): Promise<Record<string, unknown>[]> {\n if (!slug) return [];\n const params = new URLSearchParams();\n params.set(\"limit\", String(opts.limit ?? 5));\n params.set(\"depth\", \"1\");\n if (opts.sort) params.set(\"sort\", opts.sort);\n if (opts.where !== undefined && opts.where !== null) {\n params.set(\"where\", JSON.stringify(opts.where));\n }\n const body = (await getJson(\n `${BASE}/collections/${encodeURIComponent(slug)}/entries?${params.toString()}`\n )) as Record<string, unknown> | null;\n return asArray(body?.items);\n}\n","\"use client\";\n\n/**\n * A drop target between (or inside) a slot's children (spec §9). Each gap is its own\n * droppable, so the editor shows EXACTLY where a block will land: the targeted zone\n * lights up with a blue insertion line, and an empty container shows a \"Drop here\"\n * placeholder. Zones only claim space while a drag is in progress, so the canvas stays\n * clean at rest.\n */\nimport { useDragDropMonitor, useDroppable } from \"@dnd-kit/react\";\nimport { useState, type ReactNode } from \"react\";\n\nconst BLOCK_TYPE = \"nx-block\";\n\nexport function DropZone({\n parentId,\n slot,\n index,\n empty = false,\n}: {\n parentId: string;\n slot: string;\n index: number;\n empty?: boolean;\n}): ReactNode {\n const [dragging, setDragging] = useState(false);\n useDragDropMonitor({\n onDragStart() {\n setDragging(true);\n },\n onDragEnd() {\n setDragging(false);\n },\n });\n\n const { ref, isDropTarget } = useDroppable({\n id: `dz:${parentId}:${slot}:${index}`,\n type: BLOCK_TYPE,\n accept: BLOCK_TYPE,\n data: { kind: \"dropzone\", parentId, slot, index },\n });\n\n if (empty) {\n return (\n <div\n ref={ref}\n className=\"nx-pb-dropzone-empty\"\n data-active={isDropTarget || undefined}\n >\n Drop a block here\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className=\"nx-pb-dropzone\"\n data-drag={dragging || undefined}\n data-active={isDropTarget || undefined}\n />\n );\n}\n","\"use client\";\n\n/**\n * Iframe canvas (spec §9). Renders the block tree inside an <iframe> via a portal so the\n * preview lives in its own document at a real device width — responsive overrides are\n * actually visible, and page CSS is isolated from the admin shell. The compiled page CSS\n * + a small editor-overlay stylesheet are injected into the iframe <head>.\n */\nimport { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { BREAKPOINT_WIDTHS } from \"../../core/responsive\";\nimport {\n compileDocumentCss,\n compileTokensCss,\n} from \"../../core/style-compiler\";\nimport { useEditor } from \"../store/EditorProvider\";\n\nconst OVERLAY_CSS = [\n \"body{margin:0;font-family:system-ui,-apple-system,sans-serif}\",\n // Blocks are grabbable; hovering hints the boundary (Elementor-like).\n \"[data-nx-id]{cursor:grab}\",\n \"[data-nx-id]:active{cursor:grabbing}\",\n \"[data-nx-id]:hover{outline:1px dashed #a5b4fc;outline-offset:-1px}\",\n // Selected block: solid ring + a small grip badge (top-left) as a grab cue.\n \".nx-pb-selected,[data-nx-id].nx-pb-selected:hover{outline:2px solid #6366f1;outline-offset:-2px;position:relative}\",\n \".nx-pb-selected::before{content:'\\\\283F';position:absolute;top:-2px;left:-2px;transform:translateY(-100%);font-size:12px;line-height:1;padding:2px 5px;background:#6366f1;color:#fff;border-radius:4px 4px 0 0;pointer-events:none;z-index:2}\",\n \".nx-pb-dragging{opacity:.4}\",\n \".nx-pb-empty{color:#9ca3af;padding:32px;text-align:center;font-size:14px}\",\n // Between-item drop zones: collapsed at rest, a hint while dragging, a bold blue\n // insertion bar when they are the active drop target.\n \".nx-pb-dropzone{height:0;border-radius:3px;transition:height .1s ease,background .1s ease}\",\n \".nx-pb-dropzone[data-drag]{height:6px;margin:3px 0;background:rgba(99,102,241,.12)}\",\n \".nx-pb-dropzone[data-active]{height:6px;margin:4px 0;background:#4f46e5;box-shadow:0 0 0 4px rgba(79,70,229,.15)}\",\n // Empty-container placeholder.\n \".nx-pb-dropzone-empty{border:2px dashed #c7d2fe;border-radius:8px;padding:20px 12px;margin:6px;text-align:center;color:#6366f1;font-size:13px;background:#f8f9ff}\",\n \".nx-pb-dropzone-empty[data-active]{border-color:#4f46e5;background:#eef2ff;color:#4338ca}\",\n // Grid drop targets (layout-safe: inset shadow / outline, no box).\n \".nx-pb-drop-before{box-shadow:inset 3px 0 0 #4f46e5}\",\n \".nx-pb-drop-append{outline:2px dashed #4f46e5;outline-offset:-2px}\",\n].join(\"\");\n\nexport function IframeCanvas({ children }: { children: ReactNode }) {\n const { state, dispatch } = useEditor();\n const ref = useRef<HTMLIFrameElement>(null);\n const [body, setBody] = useState<HTMLElement | null>(null);\n // Desktop/base is FLUID (fills the pane); only tablet/mobile use a fixed device width.\n // A fixed desktop frame (1280px) clips behind the panels when the pane is narrower.\n const width =\n state.activeBreakpoint === \"base\"\n ? 0\n : BREAKPOINT_WIDTHS[state.activeBreakpoint] || 0;\n\n // Attach to the iframe document once it exists (onLoad or already-complete).\n const attach = () => {\n const doc = ref.current?.contentDocument;\n if (doc?.body) setBody(doc.body);\n };\n useEffect(() => {\n attach();\n }, []);\n\n // Keep the compiled page CSS in sync with the document.\n useEffect(() => {\n const doc = ref.current?.contentDocument;\n if (!doc?.head) return;\n let overlay = doc.getElementById(\"nx-pb-overlay\");\n if (!overlay) {\n overlay = doc.createElement(\"style\");\n overlay.id = \"nx-pb-overlay\";\n overlay.textContent = OVERLAY_CSS;\n doc.head.appendChild(overlay);\n }\n let pageStyle = doc.getElementById(\n \"nx-pb-style\"\n ) as HTMLStyleElement | null;\n if (!pageStyle) {\n pageStyle = doc.createElement(\"style\");\n pageStyle.id = \"nx-pb-style\";\n doc.head.appendChild(pageStyle);\n }\n pageStyle.textContent =\n compileTokensCss(\"nx-pb-page\") +\n \"\\n\" +\n compileDocumentCss(state.document);\n }, [state.document, body]);\n\n // Selection via a native delegated listener ON THE IFRAME DOCUMENT. React's synthetic\n // events don't cross the portal→iframe boundary, so onClick handlers inside the canvas\n // fire unreliably; a native listener on the iframe document does not have that problem.\n // Clicking empty space (no [data-nx-id] ancestor) deselects.\n useEffect(() => {\n const doc = ref.current?.contentDocument;\n if (!doc) return;\n const onClick = (e: MouseEvent) => {\n const target = e.target as Element | null;\n const el = target?.closest?.(\"[data-nx-id]\") ?? null;\n dispatch({ type: \"SELECT\", id: el?.getAttribute(\"data-nx-id\") ?? null });\n };\n doc.addEventListener(\"click\", onClick);\n return () => doc.removeEventListener(\"click\", onClick);\n }, [body, dispatch]);\n\n return (\n <div\n style={{\n display: \"flex\",\n // \"safe center\" centers the device frame but falls back to the start edge when it\n // would overflow — so a narrow pane scrolls from the left instead of clipping it.\n justifyContent: \"safe center\",\n height: \"100%\",\n background: \"hsl(var(--muted))\",\n overflow: \"auto\",\n padding: width ? 16 : 0,\n }}\n >\n <iframe\n ref={ref}\n title=\"Page preview\"\n onLoad={attach}\n style={{\n border: \"none\",\n background: \"#fff\",\n height: \"100%\",\n width: width ? `${width}px` : \"100%\",\n // A fixed device width must NOT be capped to the pane — the canvas scrolls\n // instead, so the preview stays a faithful WYSIWYG at that width.\n maxWidth: width ? \"none\" : \"100%\",\n flexShrink: 0,\n boxShadow: width ? \"0 0 0 1px #e5e7eb\" : \"none\",\n borderRadius: width ? 8 : 0,\n }}\n />\n {body\n ? createPortal(<div className=\"nx-pb-page\">{children}</div>, body)\n : null}\n </div>\n );\n}\n","/**\n * Breakpoint-aware read/write over ResponsiveStyle (spec §8). Pure + immutable so the\n * inspector can drive edits and the reducer stays testable. Breakpoint keys are data\n * (project-configurable) — these helpers treat any string key generically.\n */\nimport type { ResponsiveStyle, StyleValues } from \"./types\";\n\n/** Editor preview widths per breakpoint (px). \"base\" = full width (0 → 100%). */\n/**\n * Editor preview widths per breakpoint (px). \"base\" is a fixed, representative desktop\n * width (not fluid) so the canvas is a faithful WYSIWYG: the editor renders content at a\n * definite width and the published page matches at that same width — width-dependent\n * layout (max-width, centering, %) can't be pixel-matched between a fluid page and a\n * narrower editor pane otherwise.\n */\nexport const BREAKPOINT_WIDTHS: Record<string, number> = {\n base: 1280,\n tablet: 768,\n mobile: 375,\n};\n\nexport function readStyleValue(\n style: ResponsiveStyle | undefined,\n styleKey: string,\n breakpoint: string\n): unknown {\n return style?.[breakpoint]?.[styleKey as keyof StyleValues];\n}\n\n/**\n * Return a new ResponsiveStyle with `styleKey` set (or removed, when value is\n * undefined/\"\") at `breakpoint`. Never mutates the input.\n */\nexport function writeStyleValue(\n style: ResponsiveStyle | undefined,\n styleKey: string,\n breakpoint: string,\n value: unknown\n): ResponsiveStyle {\n const next: ResponsiveStyle = { ...(style ?? {}) };\n const layer: StyleValues = { ...(next[breakpoint] ?? {}) };\n if (value === undefined || value === \"\") {\n delete layer[styleKey as keyof StyleValues];\n } else {\n (layer as Record<string, unknown>)[styleKey] = value;\n }\n next[breakpoint] = layer;\n return next;\n}\n","\"use client\";\n\n/**\n * The editor canvas (spec §9). Renders the block tree inside an iframe (IframeCanvas) for\n * real device-width responsive preview + style isolation. The root always renders through\n * CanvasNode so an empty page shows its \"Drop a block here\" zone. DnD is provided by the\n * DragDropProvider in EditorSurface.\n */\nimport { useEditor } from \"../store/EditorProvider\";\n\nimport { CanvasNode } from \"./CanvasNode\";\nimport { IframeCanvas } from \"./IframeCanvas\";\n\nexport function Canvas() {\n const { state } = useEditor();\n\n return (\n <IframeCanvas>\n <CanvasNode node={state.document.root} />\n </IframeCanvas>\n );\n}\n","/**\n * Resolve the human label for a drag source (spec §9). A library source knows its block\n * type directly; a node source only carries its id, so we look the node up in the current\n * document and read its definition's label. Pure → unit-tested.\n */\nimport type { BlockRegistry } from \"../../core/registry\";\nimport { findNode } from \"../../core/tree\";\nimport type { BlockNode } from \"../../core/types\";\n\nimport type { DragSource } from \"./dropPlan\";\n\nexport function dragLabel(\n data: DragSource,\n root: BlockNode,\n registry: BlockRegistry\n): string {\n if (data.kind === \"library\" && data.blockType) {\n return registry.get(data.blockType)?.label ?? data.blockType;\n }\n if (data.kind === \"node\" && data.nodeId) {\n const node = findNode(root, data.nodeId);\n const label = node ? registry.get(node.type)?.label : undefined;\n return label ?? \"Block\";\n }\n return \"Block\";\n}\n","/**\n * Pure drop-eligibility + insertion-index math for the canvas DnD (spec §9). Kept free of\n * React/@dnd-kit so it is unit-testable and reused by both the pointer and keyboard\n * sensors. `canDrop` enforces the two structural invariants: only containers accept\n * children, and a slot's `allowedBlocks` (when present) restricts the child types.\n */\nimport type { BlockRegistry } from \"../../core/registry\";\n\nexport interface DropCheck {\n ok: boolean;\n reason?:\n | \"unknown-parent\"\n | \"not-a-container\"\n | \"unknown-slot\"\n | \"not-allowed-in-slot\";\n}\n\nexport function canDrop(\n parentType: string,\n slotName: string,\n childType: string,\n registry: BlockRegistry\n): DropCheck {\n const parent = registry.get(parentType);\n if (!parent) return { ok: false, reason: \"unknown-parent\" };\n if (!parent.isContainer) return { ok: false, reason: \"not-a-container\" };\n const slot = (parent.slots ?? []).find(s => s.name === slotName);\n if (!slot) return { ok: false, reason: \"unknown-slot\" };\n if (slot.allowedBlocks && !slot.allowedBlocks.includes(childType)) {\n return { ok: false, reason: \"not-allowed-in-slot\" };\n }\n return { ok: true };\n}\n\n/**\n * Index at which a dragged block should be inserted, given the sibling rects (in\n * document/pointer space) and the pointer's Y. Inserts before the first sibling whose\n * vertical midpoint is below the pointer; appends when the pointer is past all of them.\n */\nexport function insertionIndex(\n rects: { top: number; height: number }[],\n pointerY: number\n): number {\n for (let i = 0; i < rects.length; i++) {\n const mid = rects[i].top + rects[i].height / 2;\n if (pointerY < mid) return i;\n }\n return rects.length;\n}\n","/**\n * Locate a node's position within the tree (spec §9). Pure + unit-tested so the inspector\n * reorder controls and the DnD drop handler agree on where a node lives. Returns the\n * parent id, the slot name, the child index, and the sibling count — everything a MOVE\n * dispatch needs — or null for the root / a missing id.\n */\nimport type { BlockNode } from \"../../core/types\";\n\nexport interface NodeLocation {\n parentId: string;\n slot: string;\n index: number;\n count: number;\n}\n\nexport function locateNode(root: BlockNode, id: string): NodeLocation | null {\n const stack: BlockNode[] = [root];\n while (stack.length) {\n const node = stack.pop()!;\n if (node.slots) {\n for (const [slot, children] of Object.entries(node.slots)) {\n const index = children.findIndex(c => c.id === id);\n if (index !== -1) {\n return { parentId: node.id, slot, index, count: children.length };\n }\n stack.push(...children);\n }\n }\n }\n return null;\n}\n","/**\n * Pure drop planning for the canvas DnD (spec §9). Turns a drag source + a drop-zone\n * target into the exact editor action to dispatch — applying the drop rules, the cycle\n * guard, and the index adjustment a same-slot move needs (moveNode removes first, then\n * inserts, so a target index past the source shifts down by one). Kept React/@dnd-kit\n * free so the tricky index math is unit-tested.\n */\nimport type { BlockRegistry } from \"../../core/registry\";\nimport { findNode } from \"../../core/tree\";\nimport type { BlockNode } from \"../../core/types\";\n\nimport { canDrop } from \"./dropRules\";\nimport { locateNode } from \"./locate\";\n\nexport interface DragSource {\n kind?: \"library\" | \"node\";\n blockType?: string;\n nodeId?: string;\n}\n\nexport interface DropTarget {\n kind?: \"dropzone\";\n parentId?: string;\n slot?: string;\n /** Insert position: the dragged block becomes the `index`-th child (0..N). */\n index?: number;\n}\n\nexport type DropAction =\n | {\n type: \"ADD\";\n parentId: string;\n slot: string;\n nodeType: string;\n index: number;\n }\n | { type: \"MOVE\"; id: string; parentId: string; slot: string; index: number };\n\nexport function planDrop(\n source: DragSource,\n target: DropTarget,\n root: BlockNode,\n registry: BlockRegistry\n): DropAction | null {\n if (\n target.kind !== \"dropzone\" ||\n target.parentId == null ||\n target.slot == null\n ) {\n return null;\n }\n const parent = findNode(root, target.parentId);\n if (!parent) return null;\n const index = target.index ?? 0;\n\n if (source.kind === \"library\" && source.blockType) {\n if (!canDrop(parent.type, target.slot, source.blockType, registry).ok)\n return null;\n return {\n type: \"ADD\",\n parentId: target.parentId,\n slot: target.slot,\n nodeType: source.blockType,\n index,\n };\n }\n\n if (source.kind === \"node\" && source.nodeId) {\n const moving = findNode(root, source.nodeId);\n if (!moving) return null;\n // Cannot drop a node into itself or one of its descendants.\n if (findNode(moving, target.parentId)) return null;\n if (!canDrop(parent.type, target.slot, moving.type, registry).ok)\n return null;\n\n let toIndex = index;\n const loc = locateNode(root, source.nodeId);\n if (loc && loc.parentId === target.parentId && loc.slot === target.slot) {\n // Dropping into a gap adjacent to the source is a no-op.\n if (index === loc.index || index === loc.index + 1) return null;\n // Removing the source first shifts later gaps down by one.\n if (index > loc.index) toIndex = index - 1;\n }\n return {\n type: \"MOVE\",\n id: source.nodeId,\n parentId: target.parentId,\n slot: target.slot,\n index: toIndex,\n };\n }\n\n return null;\n}\n","\"use client\";\n\n/**\n * The block library (spec §9). Lists every registered block grouped by category, with a\n * search box and collapsible categories. Each entry is BOTH a @dnd-kit draggable source\n * (drag into the canvas) AND an \"Insert\" button (click / keyboard-accessible path). Inserts\n * land in the selected container's default slot, else at the end of the page root.\n */\nimport { useDraggable } from \"@dnd-kit/react\";\nimport { useMemo, useState } from \"react\";\n\nimport { defaultBlockRegistry } from \"../../core/registry\";\nimport { findNode } from \"../../core/tree\";\nimport { DEFAULT_SLOT, type BlockDefinition } from \"../../core/types\";\nimport { blockIcon, ChevronDown, ChevronRight, Search } from \"../icons\";\nimport { dragSensors } from \"../logic/dragSensors\";\nimport { useEditor } from \"../store/EditorProvider\";\n\nconst CATEGORY_ORDER = [\"basic\", \"layout\", \"media\", \"dynamic\"];\n\nfunction LibraryItem({ def }: { def: BlockDefinition }) {\n const { state, dispatch } = useEditor();\n const { ref, isDragging } = useDraggable({\n id: `lib:${def.type}`,\n type: \"nx-block\",\n data: { kind: \"library\", blockType: def.type },\n sensors: dragSensors,\n });\n const Icon = blockIcon(def.icon);\n\n const insert = () => {\n const root = state.document.root;\n const selected = state.selectedId\n ? findNode(root, state.selectedId)\n : undefined;\n const container =\n selected && defaultBlockRegistry.get(selected.type)?.isContainer\n ? selected\n : root;\n const slot = DEFAULT_SLOT;\n const index = container.slots?.[slot]?.length ?? 0;\n dispatch({\n type: \"ADD\",\n parentId: container.id,\n slot,\n nodeType: def.type,\n index,\n });\n };\n\n return (\n <div\n ref={ref}\n className=\"nx-pb-lib-item\"\n data-dragging={isDragging || undefined}\n title={`Drag ${def.label} onto the canvas`}\n >\n <Icon aria-hidden />\n <span className=\"nx-pb-lib-item-label\">{def.label}</span>\n <button\n type=\"button\"\n className=\"nx-pb-lib-item-insert\"\n onClick={insert}\n aria-label={`Insert ${def.label}`}\n >\n Insert\n </button>\n </div>\n );\n}\n\nfunction Category({ name, defs }: { name: string; defs: BlockDefinition[] }) {\n const [open, setOpen] = useState(true);\n const Chevron = open ? ChevronDown : ChevronRight;\n return (\n <div className=\"nx-pb-lib-cat\">\n <button\n type=\"button\"\n className=\"nx-pb-lib-cat-btn\"\n aria-expanded={open}\n onClick={() => setOpen(o => !o)}\n >\n <Chevron aria-hidden />\n {name}\n </button>\n {open ? (\n <div className=\"nx-pb-lib-grid\">\n {defs.map(def => (\n <LibraryItem key={def.type} def={def} />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n\nexport function BlockLibrary() {\n const [query, setQuery] = useState(\"\");\n\n const categories = useMemo(() => {\n const q = query.trim().toLowerCase();\n const byCategory = new Map<string, BlockDefinition[]>();\n for (const def of defaultBlockRegistry.all()) {\n if (q && !def.label.toLowerCase().includes(q)) continue;\n const list = byCategory.get(def.category) ?? [];\n list.push(def);\n byCategory.set(def.category, list);\n }\n return [...byCategory.keys()]\n .sort((a, b) => CATEGORY_ORDER.indexOf(a) - CATEGORY_ORDER.indexOf(b))\n .map(name => ({ name, defs: byCategory.get(name)! }));\n }, [query]);\n\n return (\n <div>\n <div className=\"nx-pb-pane-header\">Blocks</div>\n <div className=\"nx-pb-lib-search\">\n <Search aria-hidden />\n <input\n type=\"search\"\n value={query}\n placeholder=\"Search blocks\"\n aria-label=\"Search blocks\"\n onChange={e => setQuery(e.target.value)}\n />\n </div>\n {categories.length === 0 ? (\n <div className=\"nx-pb-lib-empty\">No blocks match “{query}”.</div>\n ) : (\n categories.map(({ name, defs }) => (\n // Remount per query so a filtered category always shows expanded.\n <Category\n key={`${name}:${query ? \"q\" : \"\"}`}\n name={name}\n defs={defs}\n />\n ))\n )}\n </div>\n );\n}\n","\"use client\";\n\n/**\n * The inspector (spec §9). A polished, three-tab settings panel generated from the\n * selected block's definition:\n * - Content — `def.contentFields` via the plugin control set (with per-field \"bind\"\n * toggles for Query Loop data).\n * - Style — `def.styleControls`, with a Normal / Hover state switch (hover writes\n * `node.styleHover`) and the active device breakpoint (from the toolbar) shown inline.\n * - Advanced — reorder, custom class, duplicate / delete.\n */\nimport {\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@nextlyhq/ui\";\nimport { useEffect, useState } from \"react\";\n\nimport { getPath } from \"../../core/bindings\";\nimport { defaultBlockRegistry } from \"../../core/registry\";\nimport { readStyleValue } from \"../../core/responsive\";\nimport { findNode } from \"../../core/tree\";\nimport type { Binding, BlockNode, ControlRef } from \"../../core/types\";\nimport { QUERY_LOOP_TYPE } from \"../../render/query/types\";\nimport {\n getCollectionFields,\n getSampleEntries,\n type CollectionField,\n} from \"../api/collectionsApi\";\nimport {\n narrowContentFields,\n type ContentField,\n} from \"../content/contentFields\";\nimport {\n registerDefaultControls,\n renderControl,\n} from \"../controls/registerDefaultControls\";\nimport { ArrowDown, ArrowUp, blockIcon, Copy, Trash2 } from \"../icons\";\nimport { locateNode } from \"../logic/locate\";\nimport { findEnclosingLoop } from \"../logic/queryLoop\";\nimport { useEditor } from \"../store/EditorProvider\";\n\nimport { firstPopulatedTab } from \"./inspectorTabs\";\nimport { QueryLoopSettings } from \"./QueryLoopSettings\";\n\nconst NONE = \"__none__\";\n\nregisterDefaultControls();\n\nconst BASE = \"base\";\ntype Tab = \"content\" | \"style\" | \"advanced\";\ntype StyleState = \"normal\" | \"hover\";\n\n// ---------------------------------------------------------------------------\n// Small presentational helpers\n// ---------------------------------------------------------------------------\n\nfunction SectionLabel({ children }: { children: React.ReactNode }) {\n return <div className=\"nx-pb-section-label\">{children}</div>;\n}\n\nfunction Empty({ children }: { children: React.ReactNode }) {\n return <p className=\"nx-pb-empty\">{children}</p>;\n}\n\nfunction Segmented<T extends string>({\n value,\n options,\n onChange,\n ariaLabel,\n}: {\n value: T;\n options: { value: T; label: string }[];\n onChange: (v: T) => void;\n ariaLabel?: string;\n}) {\n return (\n <div className=\"nx-pb-seg\" role=\"group\" aria-label={ariaLabel}>\n {options.map(o => (\n <button\n key={o.value}\n type=\"button\"\n className=\"nx-pb-seg-btn\"\n aria-pressed={value === o.value}\n onClick={() => onChange(o.value)}\n >\n {o.label}\n </button>\n ))}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Tabs\n// ---------------------------------------------------------------------------\n\n/** A short, safe preview string for a resolved binding value. */\nfunction previewText(v: unknown): string {\n if (v == null) return \"—\";\n let s: string;\n if (typeof v === \"string\") s = v;\n else if (typeof v === \"number\" || typeof v === \"boolean\") s = String(v);\n else s = JSON.stringify(v) ?? \"—\";\n return s.length > 40 ? `${s.slice(0, 40)}…` : s;\n}\n\n/**\n * Binding editor for a bindable field. Inside a Query Loop we discover the loop collection's\n * fields and show a field DROPDOWN plus a live value from a sample entry; outside a loop (or\n * if discovery fails) we fall back to a raw path input.\n */\nfunction BindingPathEditor({\n node,\n field,\n binding,\n}: {\n node: BlockNode;\n field: ContentField;\n binding: Binding;\n}) {\n const { state, dispatch } = useEditor();\n const loop = findEnclosingLoop(state.document.root, node.id);\n const collection =\n loop && typeof loop.props.collection === \"string\"\n ? loop.props.collection\n : \"\";\n const [fields, setFields] = useState<CollectionField[]>([]);\n const [sample, setSample] = useState<Record<string, unknown> | null>(null);\n\n const setPath = (path: string) =>\n dispatch({\n type: \"SET_BINDING\",\n id: node.id,\n prop: field.name,\n binding: { source: \"field\", path },\n });\n\n useEffect(() => {\n let alive = true;\n if (!collection) {\n setFields([]);\n setSample(null);\n return;\n }\n getCollectionFields(collection)\n .then(f => alive && setFields(f))\n .catch(() => alive && setFields([]));\n getSampleEntries(collection, { limit: 1 })\n .then(rows => alive && setSample(rows[0] ?? null))\n .catch(() => alive && setSample(null));\n return () => {\n alive = false;\n };\n }, [collection]);\n\n // No loop context / discovery unavailable → raw path input.\n if (!collection || fields.length === 0) {\n return (\n <>\n <Input\n value={binding.path}\n placeholder=\"field path, e.g. title or author.name\"\n aria-label={`${field.label} binding path`}\n onChange={e => setPath(e.target.value)}\n />\n <p className=\"nx-pb-empty\" style={{ marginTop: 2 }}>\n Resolves from the current Query Loop item.\n </p>\n </>\n );\n }\n\n return (\n <>\n <Select\n value={binding.path || NONE}\n onValueChange={v => setPath(v === NONE ? \"\" : v)}\n >\n <SelectTrigger aria-label={`${field.label} field`}>\n <SelectValue placeholder=\"Choose a field…\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>Choose a field…</SelectItem>\n {fields.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"nx-pb-empty\" style={{ marginTop: 2 }}>\n {binding.path ? (\n <>\n Preview:{\" \"}\n <strong>{previewText(getPath(sample ?? {}, binding.path))}</strong>\n </>\n ) : (\n \"Pick a field from the loop collection.\"\n )}\n </p>\n </>\n );\n}\n\nfunction BindableField({\n node,\n field,\n}: {\n node: BlockNode;\n field: ContentField;\n}) {\n const { dispatch } = useEditor();\n const bound = node.bindings?.[field.name];\n\n if (!field.bindable) {\n return renderControl(field.type, {\n label: field.label,\n field,\n value: node.props[field.name],\n onChange: value =>\n dispatch({\n type: \"UPDATE_PROPS\",\n id: node.id,\n props: { [field.name]: value },\n }),\n });\n }\n\n return (\n <div style={{ marginBottom: 10 }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 4,\n }}\n >\n <Label className=\"nx-pb-control-label\">{field.label}</Label>\n <label\n className=\"nx-pb-control-label\"\n style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}\n >\n Bind\n <Switch\n checked={!!bound}\n onCheckedChange={on =>\n dispatch({\n type: \"SET_BINDING\",\n id: node.id,\n prop: field.name,\n binding: on ? { source: \"field\", path: \"\" } : null,\n })\n }\n />\n </label>\n </div>\n {bound ? (\n <BindingPathEditor node={node} field={field} binding={bound} />\n ) : (\n renderControl(field.type, {\n field,\n value: node.props[field.name],\n onChange: value =>\n dispatch({\n type: \"UPDATE_PROPS\",\n id: node.id,\n props: { [field.name]: value },\n }),\n })\n )}\n </div>\n );\n}\n\nfunction ContentTab({ node }: { node: BlockNode }) {\n // The Query Loop authors through its own discovery-driven panel, not content fields.\n if (node.type === QUERY_LOOP_TYPE) {\n return <QueryLoopSettings node={node} />;\n }\n const def = defaultBlockRegistry.get(node.type);\n const fields = narrowContentFields(def?.contentFields);\n if (fields.length === 0) {\n return <Empty>This block has no content options.</Empty>;\n }\n return (\n <div>\n <SectionLabel>Content</SectionLabel>\n {fields.map(field => (\n <BindableField key={field.name} node={node} field={field} />\n ))}\n </div>\n );\n}\n\nfunction StyleTab({\n node,\n styleState,\n setStyleState,\n}: {\n node: BlockNode;\n styleState: StyleState;\n setStyleState: (v: StyleState) => void;\n}) {\n const { state, dispatch } = useEditor();\n const def = defaultBlockRegistry.get(node.type);\n const controls = def?.styleControls ?? [];\n const bp = state.activeBreakpoint;\n const tree = styleState === \"hover\" ? node.styleHover : node.style;\n\n if (controls.length === 0) {\n return <Empty>This block has no style options.</Empty>;\n }\n\n return (\n <div>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 12,\n }}\n >\n <Segmented<StyleState>\n value={styleState}\n onChange={setStyleState}\n ariaLabel=\"Style state\"\n options={[\n { value: \"normal\", label: \"Normal\" },\n { value: \"hover\", label: \"Hover\" },\n ]}\n />\n <span\n className=\"nx-pb-device-badge\"\n data-active={bp !== BASE || undefined}\n title=\"Editing styles for this device (change with the toolbar)\"\n >\n {bp === BASE ? \"Desktop\" : bp}\n </span>\n </div>\n\n {styleState === \"hover\" ? (\n <p className=\"nx-pb-empty\" style={{ margin: \"0 0 10px\" }}>\n Applied on <strong>:hover</strong>; empty values fall back to Normal.\n </p>\n ) : null}\n\n <SectionLabel>Style</SectionLabel>\n {controls.map((ref: ControlRef) => (\n <div key={`${ref.control}:${ref.styleKey}`}>\n {renderControl(ref.control, {\n label: ref.label,\n value: readStyleValue(tree, ref.styleKey, bp),\n onChange: value =>\n dispatch({\n type: \"UPDATE_STYLE\",\n id: node.id,\n breakpoint: bp,\n styleState,\n style: { [ref.styleKey]: value },\n }),\n })}\n </div>\n ))}\n </div>\n );\n}\n\nfunction AdvancedTab({ node }: { node: BlockNode }) {\n const { state, dispatch } = useEditor();\n const loc = locateNode(state.document.root, node.id);\n const move = (delta: number) => {\n if (!loc) return;\n const next = loc.index + delta;\n if (next < 0 || next >= loc.count) return;\n dispatch({\n type: \"MOVE\",\n id: node.id,\n parentId: loc.parentId,\n slot: loc.slot,\n index: next,\n });\n };\n return (\n <div style={{ display: \"grid\", gap: 14 }}>\n {loc ? (\n <div>\n <SectionLabel>Arrange</SectionLabel>\n <div style={{ display: \"flex\", gap: 6 }}>\n <button\n type=\"button\"\n className=\"nx-pb-icon-btn\"\n disabled={loc.index <= 0}\n aria-label=\"Move block up\"\n onClick={() => move(-1)}\n >\n <ArrowUp size={15} aria-hidden /> Up\n </button>\n <button\n type=\"button\"\n className=\"nx-pb-icon-btn\"\n disabled={loc.index >= loc.count - 1}\n aria-label=\"Move block down\"\n onClick={() => move(1)}\n >\n <ArrowDown size={15} aria-hidden /> Down\n </button>\n <button\n type=\"button\"\n className=\"nx-pb-icon-btn\"\n aria-label=\"Duplicate block\"\n onClick={() => dispatch({ type: \"DUPLICATE\", id: node.id })}\n >\n <Copy size={15} aria-hidden /> Duplicate\n </button>\n </div>\n </div>\n ) : null}\n\n <div>\n <SectionLabel>Custom CSS class</SectionLabel>\n {renderControl(\"text\", {\n value: node.customClass ?? \"\",\n onChange: value =>\n dispatch({\n type: \"SET_CUSTOM_CLASS\",\n id: node.id,\n customClass: typeof value === \"string\" ? value : \"\",\n }),\n })}\n </div>\n\n <div className=\"nx-pb-empty\">\n Type <code>{node.type}</code>\n </div>\n\n <button\n type=\"button\"\n className=\"nx-pb-icon-btn\"\n aria-label=\"Delete block\"\n style={{\n color: \"hsl(var(--destructive))\",\n borderColor: \"hsl(var(--destructive) / 0.4)\",\n }}\n onClick={() => dispatch({ type: \"REMOVE\", id: node.id })}\n >\n <Trash2 size={15} aria-hidden /> Delete block\n </button>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Inspector shell\n// ---------------------------------------------------------------------------\n\nexport function Inspector() {\n const { state } = useEditor();\n const [tab, setTab] = useState<Tab>(\"content\");\n const [styleState, setStyleState] = useState<StyleState>(\"normal\");\n const node = state.selectedId\n ? findNode(state.document.root, state.selectedId)\n : undefined;\n const def = node ? defaultBlockRegistry.get(node.type) : undefined;\n\n // On selection change, open a populated tab and reset Hover mode, so panel state from\n // the previously-selected block never leaks (spec §3.5). The Query Loop always has its\n // Content panel populated (the settings UI), so open there.\n useEffect(() => {\n const initial =\n node?.type === QUERY_LOOP_TYPE ? \"content\" : firstPopulatedTab(def);\n setTab(initial);\n setStyleState(\"normal\");\n }, [state.selectedId]);\n\n if (!node) {\n return (\n <>\n <div className=\"nx-pb-pane-header\">Settings</div>\n <div className=\"nx-pb-inspector-empty\">\n Select a block on the canvas to edit its content and style.\n </div>\n </>\n );\n }\n\n const Icon = blockIcon(def?.icon);\n\n return (\n <div className=\"nx-pb-inspector\">\n <div className=\"nx-pb-inspector-header\">\n <span className=\"nx-pb-block-icon\">\n <Icon size={16} aria-hidden />\n </span>\n <div>\n <div className=\"nx-pb-inspector-title\">{def?.label ?? node.type}</div>\n <div className=\"nx-pb-inspector-sub\">{def?.category ?? \"block\"}</div>\n </div>\n </div>\n <Tabs\n value={tab}\n onValueChange={v => setTab(v as Tab)}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flex: 1,\n minHeight: 0,\n }}\n >\n <TabsList style={{ margin: \"10px 12px 0\" }}>\n <TabsTrigger value=\"content\">Content</TabsTrigger>\n <TabsTrigger value=\"style\">Style</TabsTrigger>\n <TabsTrigger value=\"advanced\">Advanced</TabsTrigger>\n </TabsList>\n <div style={{ padding: 12, overflow: \"auto\", flex: 1 }}>\n <TabsContent value=\"content\">\n <ContentTab node={node} />\n </TabsContent>\n <TabsContent value=\"style\">\n <StyleTab\n node={node}\n styleState={styleState}\n setStyleState={setStyleState}\n />\n </TabsContent>\n <TabsContent value=\"advanced\">\n <AdvancedTab node={node} />\n </TabsContent>\n </div>\n </Tabs>\n </div>\n );\n}\n","/**\n * Plugin-owned Content-field schema (spec §9). A deliberately small schema — text,\n * textarea, select, number, boolean, link, media — so the inspector's Content tab is\n * self-contained and does not depend on the admin's (currently unexported) FieldRenderer.\n * A block declares `contentFields` as `unknown[]` in core; the admin narrows it here.\n * Reusing Nextly's own field renderers is a documented post-MVP door.\n */\nexport type ContentFieldType =\n | \"text\"\n | \"textarea\"\n | \"select\"\n | \"number\"\n | \"boolean\"\n | \"link\"\n | \"media\";\n\nexport interface ContentFieldOption {\n value: string;\n label: string;\n}\n\nexport interface ContentField {\n name: string;\n type: ContentFieldType;\n label: string;\n default?: unknown;\n options?: ContentFieldOption[];\n placeholder?: string;\n /** Marks a field as bindable to a Query Loop item (bind UI wired in M6). */\n bindable?: boolean;\n}\n\nconst TYPES = new Set<ContentFieldType>([\n \"text\",\n \"textarea\",\n \"select\",\n \"number\",\n \"boolean\",\n \"link\",\n \"media\",\n]);\n\nconst TYPE_DEFAULTS: Record<ContentFieldType, unknown> = {\n text: \"\",\n textarea: \"\",\n select: undefined,\n number: 0,\n boolean: false,\n link: undefined,\n media: undefined,\n};\n\n/** Narrow an untyped `def.contentFields` into validated ContentField entries. */\nexport function narrowContentFields(\n fields: unknown[] | undefined\n): ContentField[] {\n if (!Array.isArray(fields)) return [];\n const out: ContentField[] = [];\n for (const f of fields) {\n if (!f || typeof f !== \"object\") continue;\n const r = f as Record<string, unknown>;\n if (typeof r.name !== \"string\") continue;\n if (typeof r.type !== \"string\" || !TYPES.has(r.type as ContentFieldType)) {\n continue;\n }\n out.push({\n name: r.name,\n type: r.type as ContentFieldType,\n label: typeof r.label === \"string\" ? r.label : r.name,\n default: r.default,\n options: Array.isArray(r.options)\n ? (r.options as ContentFieldOption[])\n : undefined,\n placeholder:\n typeof r.placeholder === \"string\" ? r.placeholder : undefined,\n bindable: r.bindable === true,\n });\n }\n return out;\n}\n\n/** Build a `{ name: defaultValue }` object from a field list. */\nexport function contentDefaults(\n fields: ContentField[]\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const f of fields) {\n out[f.name] = f.default !== undefined ? f.default : TYPE_DEFAULTS[f.type];\n }\n return out;\n}\n","/**\n * Pure helpers for Query Loop authoring (spec §5). React/@dnd-kit free so the tree walk,\n * field derivation, and sort encoding stay unit-tested.\n */\nimport type { BlockNode } from \"../../core/types\";\nimport { QUERY_LOOP_TYPE } from \"../../render/query/types\";\n\n/** The nearest ancestor `core/query-loop` that contains `id` (excludes the node itself). */\nexport function findEnclosingLoop(\n root: BlockNode,\n id: string\n): BlockNode | undefined {\n let found: BlockNode | undefined;\n const visit = (node: BlockNode, loop: BlockNode | undefined): boolean => {\n if (node.id === id) {\n found = loop;\n return true;\n }\n const nextLoop = node.type === QUERY_LOOP_TYPE ? node : loop;\n if (node.slots) {\n for (const children of Object.values(node.slots)) {\n for (const child of children) {\n if (visit(child, nextLoop)) return true;\n }\n }\n }\n return false;\n };\n visit(root, undefined);\n return found;\n}\n\n/** Union of keys across sample rows, in stable sorted order. */\nexport function deriveFieldNames(rows: Record<string, unknown>[]): string[] {\n const keys = new Set<string>();\n for (const row of rows) {\n if (row && typeof row === \"object\") {\n for (const k of Object.keys(row)) keys.add(k);\n }\n }\n return [...keys].sort();\n}\n\nexport type SortDir = \"asc\" | \"desc\";\n\n/** Encode a field + direction into the API sort string (`-field` = desc). */\nexport function buildSort(field: string, dir: SortDir): string {\n if (!field) return \"\";\n return dir === \"desc\" ? `-${field}` : field;\n}\n\n/** Decode an API sort string back into field + direction. */\nexport function parseSort(sort: string): { field: string; dir: SortDir } {\n if (!sort) return { field: \"\", dir: \"asc\" };\n return sort.startsWith(\"-\")\n ? { field: sort.slice(1), dir: \"desc\" }\n : { field: sort, dir: \"asc\" };\n}\n","/**\n * Pick the inspector tab a freshly-selected block should open to, so no block ever opens\n * to an empty pane (spec §3.5). Content first, then Style, then Advanced.\n */\nimport type { BlockDefinition } from \"../../core/types\";\n\nexport type InspectorTab = \"content\" | \"style\" | \"advanced\";\n\nexport function firstPopulatedTab(\n def: BlockDefinition | undefined\n): InspectorTab {\n if ((def?.contentFields?.length ?? 0) > 0) return \"content\";\n if ((def?.styleControls?.length ?? 0) > 0) return \"style\";\n return \"advanced\";\n}\n","\"use client\";\n\n/**\n * Dedicated Query Loop authoring panel (spec §5). Replaces the generic Content tab for\n * `core/query-loop`: a collection DROPDOWN discovered from the admin, a sort field + asc/desc,\n * a limit, a column count, and one basic equals-filter — all discovered from the collection's\n * schema so the author never types a slug or field name from memory. Writes to `node.props`.\n */\nimport {\n Input,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@nextlyhq/ui\";\nimport { useEffect, useState } from \"react\";\n\nimport type { BlockNode } from \"../../core/types\";\nimport {\n getCollectionFields,\n listCollections,\n type CollectionField,\n type CollectionSummary,\n} from \"../api/collectionsApi\";\nimport { buildSort, parseSort, type SortDir } from \"../logic/queryLoop\";\nimport { useEditor } from \"../store/EditorProvider\";\n\nconst NONE = \"__none__\";\n\nfunction str(v: unknown): string {\n return typeof v === \"string\" ? v : \"\";\n}\n\nexport function QueryLoopSettings({ node }: { node: BlockNode }) {\n const { dispatch } = useEditor();\n const props = node.props;\n const collection = str(props.collection);\n\n const [collections, setCollections] = useState<CollectionSummary[]>([]);\n const [fields, setFields] = useState<CollectionField[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n const set = (patch: Record<string, unknown>) =>\n dispatch({ type: \"UPDATE_PROPS\", id: node.id, props: patch });\n\n useEffect(() => {\n let alive = true;\n listCollections()\n .then(c => alive && setCollections(c))\n .catch(e => alive && setError((e as Error).message));\n return () => {\n alive = false;\n };\n }, []);\n\n useEffect(() => {\n let alive = true;\n if (!collection) {\n setFields([]);\n return;\n }\n getCollectionFields(collection)\n .then(f => alive && setFields(f))\n .catch(() => alive && setFields([]));\n return () => {\n alive = false;\n };\n }, [collection]);\n\n const sort = parseSort(str(props.sort));\n const limit = typeof props.limit === \"number\" ? props.limit : 10;\n const columns = typeof props.columns === \"number\" ? props.columns : 1;\n const where = (props.where ?? {}) as Record<string, { equals?: unknown }>;\n const filterField = Object.keys(where)[0] ?? \"\";\n const filterValue = filterField ? str(where[filterField]?.equals) : \"\";\n\n const setSort = (field: string, dir: SortDir) =>\n set({ sort: buildSort(field === NONE ? \"\" : field, dir) });\n const setFilter = (field: string, value: string) => {\n if (!field || field === NONE || value === \"\")\n return set({ where: undefined });\n set({ where: { [field]: { equals: value } } });\n };\n\n return (\n <div style={{ display: \"grid\", gap: 12 }}>\n <div className=\"nx-pb-section-label\">Data source</div>\n\n <label className=\"nx-pb-control-label\">Collection</label>\n <Select\n value={collection || NONE}\n onValueChange={v => set({ collection: v === NONE ? \"\" : v })}\n >\n <SelectTrigger aria-label=\"Collection\">\n <SelectValue placeholder=\"Choose a collection…\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>Choose a collection…</SelectItem>\n {collections.map(c => (\n <SelectItem key={c.slug} value={c.slug}>\n {c.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {error ? (\n <p className=\"nx-pb-empty\" style={{ color: \"hsl(var(--destructive))\" }}>\n Couldn’t load collections: {error}\n </p>\n ) : null}\n\n <div className=\"nx-pb-section-label\">Order &amp; layout</div>\n\n <label className=\"nx-pb-control-label\">Sort by</label>\n <div style={{ display: \"flex\", gap: 6 }}>\n <Select\n value={sort.field || NONE}\n onValueChange={v => setSort(v, sort.dir)}\n >\n <SelectTrigger aria-label=\"Sort field\" style={{ flex: 1 }}>\n <SelectValue placeholder=\"Default\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>Default order</SelectItem>\n {fields.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Select\n value={sort.dir}\n onValueChange={v => setSort(sort.field, v as SortDir)}\n >\n <SelectTrigger aria-label=\"Sort direction\" style={{ width: 110 }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"asc\">Asc</SelectItem>\n <SelectItem value=\"desc\">Desc</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n <div style={{ display: \"flex\", gap: 6 }}>\n <label className=\"nx-pb-control-label\" style={{ flex: 1 }}>\n Items\n <Input\n type=\"number\"\n min={1}\n value={limit}\n aria-label=\"Limit\"\n onChange={e =>\n set({\n limit:\n e.target.value === \"\" ? undefined : Number(e.target.value),\n })\n }\n />\n </label>\n <label className=\"nx-pb-control-label\" style={{ flex: 1 }}>\n Columns\n <Input\n type=\"number\"\n min={1}\n max={12}\n value={columns}\n aria-label=\"Columns\"\n onChange={e =>\n set({\n columns: e.target.value === \"\" ? 1 : Number(e.target.value),\n })\n }\n />\n </label>\n </div>\n\n <div className=\"nx-pb-section-label\">Filter</div>\n <div style={{ display: \"flex\", gap: 6 }}>\n <Select\n value={filterField || NONE}\n onValueChange={v => setFilter(v, v === NONE ? \"\" : filterValue)}\n >\n <SelectTrigger aria-label=\"Filter field\" style={{ flex: 1 }}>\n <SelectValue placeholder=\"No filter\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>No filter</SelectItem>\n {fields.map(f => (\n <SelectItem key={f.name} value={f.name}>\n {f.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Input\n value={filterValue}\n placeholder=\"equals…\"\n aria-label=\"Filter value\"\n disabled={!filterField}\n style={{ flex: 1 }}\n onChange={e => setFilter(filterField, e.target.value)}\n />\n </div>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Page-settings header + self-persisting save bar (spec §9/§11). The custom Edit view\n * gets no save function, so this writes via the public admin REST client (adminFetch).\n * Create requires title + slug; Publish sets status; delete/cancel honor the callbacks.\n */\nimport { Button, Input, Label } from \"@nextlyhq/ui\";\nimport { useState } from \"react\";\n\nimport { deletePage, savePage } from \"./api/adminFetch\";\nimport { useEditor } from \"./store/EditorProvider\";\nimport type { CustomEditViewProps } from \"./types\";\n\nexport function SaveShell({ props }: { props: CustomEditViewProps }) {\n const { state, dispatch } = useEditor();\n const data = props.initialData ?? {};\n const str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n const [title, setTitle] = useState(str(data.title));\n const [slug, setSlug] = useState(str(data.slug));\n const customCss = str(data.customCss); // edited via a panel in a later milestone\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n async function save(status: \"draft\" | \"published\") {\n if (!title.trim() || !slug.trim()) {\n setError(\"Title and slug are required.\");\n return;\n }\n setBusy(true);\n setError(null);\n try {\n const entry = await savePage({\n id: props.entryId,\n title,\n slug,\n content: state.document,\n customCss,\n status,\n });\n dispatch({ type: \"MARK_SAVED\" });\n props.onSuccess?.(entry);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setBusy(false);\n }\n }\n\n async function remove() {\n if (!props.entryId) {\n props.onCancel?.();\n return;\n }\n setBusy(true);\n try {\n await deletePage(props.entryId);\n props.onDelete?.();\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <div\n style={{\n display: \"flex\",\n gap: 12,\n alignItems: \"flex-end\",\n flexWrap: \"wrap\",\n }}\n >\n <div>\n <Label htmlFor=\"nx-pb-title\">Title</Label>\n <Input\n id=\"nx-pb-title\"\n value={title}\n onChange={e => setTitle(e.target.value)}\n />\n </div>\n <div>\n <Label htmlFor=\"nx-pb-slug\">Slug</Label>\n <Input\n id=\"nx-pb-slug\"\n value={slug}\n onChange={e => setSlug(e.target.value)}\n />\n </div>\n <div style={{ display: \"flex\", gap: 8, marginLeft: \"auto\" }}>\n <Button\n variant=\"outline\"\n disabled={busy}\n onClick={() => void save(\"draft\")}\n >\n Save Draft\n </Button>\n <Button disabled={busy} onClick={() => void save(\"published\")}>\n Publish\n </Button>\n <Button variant=\"ghost\" disabled={busy} onClick={() => void remove()}>\n {props.entryId ? \"Delete\" : \"Cancel\"}\n </Button>\n </div>\n {error ? (\n <p\n style={{ color: \"hsl(var(--destructive))\", width: \"100%\", margin: 0 }}\n >\n {error}\n </p>\n ) : null}\n </div>\n );\n}\n","/**\n * Minimal admin REST client for the full editor (spec §11). The custom Edit view gets\n * no save function and `entryApi` is not a public export, so we persist via the public\n * admin REST surface with same-origin cookie auth. Base + envelope verified in\n * NOTES-platform.md: base `/admin/api`, mutation envelope `{ message, item }`.\n */\nimport type { BlockDocument } from \"../../core/types\";\n\nconst ENTRIES = \"/admin/api/collections/pages/entries\";\n\nexport interface SavePageInput {\n id?: string;\n title: string;\n slug: string;\n content: BlockDocument;\n customCss: string;\n status: \"draft\" | \"published\";\n}\n\nasync function handle(res: Response): Promise<Record<string, unknown>> {\n const body = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n if (!res.ok) {\n const message =\n (typeof body.error === \"string\" && body.error) ||\n (typeof body.message === \"string\" && body.message) ||\n `Request failed (${res.status})`;\n throw new Error(message);\n }\n // Mutation envelope is `{ message, item }`; fall back to the bare body.\n return (body.item as Record<string, unknown>) ?? body;\n}\n\n/** Create (POST) or update (PATCH) the page. Returns the saved entry. */\nexport async function savePage(\n input: SavePageInput\n): Promise<Record<string, unknown>> {\n const { id, ...payload } = input;\n const res = await fetch(id ? `${ENTRIES}/${id}` : ENTRIES, {\n method: id ? \"PATCH\" : \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n credentials: \"same-origin\",\n body: JSON.stringify(payload),\n });\n return handle(res);\n}\n\nexport async function deletePage(id: string): Promise<void> {\n const res = await fetch(`${ENTRIES}/${id}`, {\n method: \"DELETE\",\n credentials: \"same-origin\",\n });\n await handle(res);\n}\n","\"use client\";\n\n/**\n * The full-screen page editor, mounted as the `pages` collection Edit-view override.\n * Renders inside the admin content area. Loads the stored block tree (or an empty one),\n * wires the store + canvas + save shell.\n */\nimport { makeNode } from \"../core/tree\";\nimport type { BlockDocument } from \"../core/types\";\nimport \"../render/blocks\"; // register block renderers so the canvas + store defaults work\n\nimport { EditorSurface } from \"./EditorSurface\";\nimport { SaveShell } from \"./SaveShell\";\nimport { EditorProvider, draftKeyFor } from \"./store/EditorProvider\";\nimport type { CustomEditViewProps } from \"./types\";\n\nfunction emptyDoc(): BlockDocument {\n return {\n version: 1,\n root: makeNode(\"core/container\", {}, undefined, { default: [] }),\n };\n}\n\nexport function PageBuilderEditView(props: CustomEditViewProps) {\n const data = props.initialData ?? {};\n const doc = (data.content as BlockDocument | undefined) ?? emptyDoc();\n\n return (\n <EditorProvider\n document={doc}\n draftKey={draftKeyFor(props.collectionSlug, props.entryId)}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n <SaveShell props={props} />\n <EditorSurface />\n </div>\n </EditorProvider>\n );\n}\n","\"use client\";\n\n/**\n * The page-builder editor mounted as a custom collection/single field (spec §9/§11).\n * Nextly's FieldRenderer renders this via `admin.component` (D24) inside a PluginSlot,\n * passing react-hook-form `{ control, name }`. We bridge RHF ↔ the editor: `useController`\n * reads the stored BlockDocument, and `EditorProvider.onDocumentChange` pushes edits back\n * into the form so the HOST form's save persists them (no SaveShell here).\n */\nimport { useController, type Control } from \"react-hook-form\";\n\nimport { makeNode } from \"../core/tree\";\nimport type { BlockDocument } from \"../core/types\";\n\nimport { EditorSurface } from \"./EditorSurface\";\nimport { draftKeyFor, EditorProvider } from \"./store/EditorProvider\";\n\nexport interface PageBuilderFieldProps {\n /** Form path (react-hook-form) for this field. */\n name: string;\n /** react-hook-form control, injected by the host FieldRenderer. */\n control: Control;\n field?: { label?: string };\n}\n\nfunction emptyDoc(): BlockDocument {\n return {\n version: 1,\n root: makeNode(\"core/container\", {}, undefined, { default: [] }),\n };\n}\n\nfunction isDocument(v: unknown): v is BlockDocument {\n return (\n typeof v === \"object\" &&\n v !== null &&\n \"root\" in v &&\n typeof (v as { root?: unknown }).root === \"object\"\n );\n}\n\nexport function PageBuilderField({ name, control }: PageBuilderFieldProps) {\n const { field } = useController({ control, name });\n const doc = isDocument(field.value) ? field.value : emptyDoc();\n\n return (\n <EditorProvider\n document={doc}\n draftKey={draftKeyFor(\"field\", name)}\n onDocumentChange={next => field.onChange(next)}\n >\n <EditorSurface />\n </EditorProvider>\n );\n}\n","\"use client\";\n\n/**\n * Per-entry editor-mode toggle, contributed via\n * `contributes.admin.entryFormToolbarSlot` and rendered in the entry/single form\n * header toolbar. Presentational only — the admin owns react-hook-form and hands\n * this component `{ value, onChange }` for the mode field, so the plugin never\n * needs its own react-hook-form instance.\n *\n * `Normal` → the entity's own fields; `Page Builder` → the visual canvas (the\n * takeover layout hides the other fields). Renders nothing when the collection\n * has no page-builder field (no `controllerField`).\n */\nimport { Button } from \"@nextlyhq/ui\";\n\ninterface Props {\n controllerField?: string;\n value?: unknown;\n onChange?: (next: unknown) => void;\n}\n\nexport function PageBuilderModeToggle({\n controllerField,\n value,\n onChange,\n}: Props) {\n if (!controllerField) return null;\n const isBuilder = value === \"builder\";\n return (\n <div\n role=\"group\"\n aria-label=\"Editor mode\"\n className=\"inline-flex items-center gap-0.5 rounded-md border border-border p-0.5\"\n >\n <Button\n type=\"button\"\n size=\"sm\"\n variant={isBuilder ? \"ghost\" : \"default\"}\n aria-pressed={!isBuilder}\n onClick={() => onChange?.(\"default\")}\n >\n Normal\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={isBuilder ? \"default\" : \"ghost\"}\n aria-pressed={isBuilder}\n onClick={() => onChange?.(\"builder\")}\n >\n Page Builder\n </Button>\n </div>\n );\n}\n","\"use client\";\n\n/**\n * Schema-builder \"Use Page Builder\" toggle, contributed via\n * `contributes.admin.schemaBuilderSlot`. The admin renders it (generically, via\n * `SchemaBuilderSlots`) above the field list in the collection/single builders\n * and passes `{ fields, setFields, disabled, context }`.\n *\n * Turning it on appends the editor-choice fields — an `editormode` select + a\n * reserved `content` field of the plugin's first-class `page-builder` type\n * (shown only in builder mode). The UI builder normalizes field names to\n * lowercase and strips `admin.component`, so the canvas field is identified by\n * its `type` (not a component path) and renders via the plugin's registered\n * field-type → component mapping. Off removes both. Idempotent.\n */\nimport { Label, Switch } from \"@nextlyhq/ui\";\n\nimport {\n EDITOR_MODE_FIELD,\n PAGE_BUILDER_CONTENT_FIELD,\n PAGE_BUILDER_TYPE,\n} from \"../collections/pageBuilderEntry\";\n\ninterface BuilderField {\n id?: string;\n name?: string;\n type?: string;\n admin?: { component?: string } | null;\n}\n\n/** The canvas field — the first-class `page-builder` type, or the legacy json +\n * plugin-editor component form (defensive; UI-created uses the type). */\nfunction isCanvasField(f: BuilderField): boolean {\n if (f.type === PAGE_BUILDER_TYPE) return true;\n const component = f.admin?.component;\n return (\n typeof component === \"string\" && component.includes(\"plugin-page-builder\")\n );\n}\n\nfunction hasPageBuilderFields(fields: BuilderField[]): boolean {\n return (\n fields.some(f => f.name === EDITOR_MODE_FIELD) && fields.some(isCanvasField)\n );\n}\n\nfunction addPageBuilderFields<T extends BuilderField>(fields: T[]): T[] {\n if (hasPageBuilderFields(fields)) return fields;\n const editormode = {\n id: \"pb-editormode\",\n name: EDITOR_MODE_FIELD,\n label: \"Editor\",\n type: \"select\",\n validation: {},\n defaultValue: \"default\",\n options: [\n { value: \"default\", label: \"Default\" },\n { value: \"builder\", label: \"Page Builder\" },\n ],\n // Hidden: stores the per-entry mode but never shows as a field. The choice is\n // a toolbar toggle; it's also filtered out of the schema-builder field list.\n admin: { hidden: true },\n } as unknown as T;\n const content = {\n id: \"pb-content\",\n name: PAGE_BUILDER_CONTENT_FIELD,\n label: \"Page Builder\",\n type: PAGE_BUILDER_TYPE,\n validation: {},\n admin: { condition: { field: EDITOR_MODE_FIELD, equals: \"builder\" } },\n } as unknown as T;\n return [...fields, editormode, content];\n}\n\nfunction removePageBuilderFields<T extends BuilderField>(fields: T[]): T[] {\n return fields.filter(f => f.name !== EDITOR_MODE_FIELD && !isCanvasField(f));\n}\n\nexport interface PageBuilderToggleProps<T extends BuilderField> {\n fields: T[];\n setFields: (fields: T[]) => void;\n disabled?: boolean;\n context?: \"collection\" | \"single\";\n}\n\nexport function PageBuilderToggle<T extends BuilderField>({\n fields,\n setFields,\n disabled,\n}: PageBuilderToggleProps<T>) {\n const on = hasPageBuilderFields(fields);\n return (\n <div className=\"flex items-center gap-3 py-2\">\n <Switch\n checked={on}\n disabled={disabled}\n aria-label=\"Use Page Builder\"\n onCheckedChange={next =>\n setFields(\n next\n ? addPageBuilderFields(fields)\n : removePageBuilderFields(fields)\n )\n }\n />\n <Label className=\"cursor-pointer\">Use Page Builder</Label>\n <span className=\"text-xs text-muted-foreground\">\n Let entries choose a visual Page Builder canvas instead of the fields.\n </span>\n </div>\n );\n}\n"],"mappings":"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","names":["Input","jsx","jsxs","Input","Input","jsx","jsxs","str","Input","Input","useState","jsx","jsxs","useState","Input","jsx","useDroppable","useEffect","useState","str","jsx","jsxs","useState","useEffect","useState","jsx","jsx","jsxs","BLOCK_TYPE","useDroppable","useEffect","useRef","useState","jsx","jsxs","useRef","useState","useEffect","jsx","useDraggable","useState","jsx","jsxs","useDraggable","useState","Input","Label","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Switch","useEffect","useState","Input","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","useEffect","useState","jsx","jsxs","str","useState","useEffect","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Input","jsx","jsxs","NONE","BASE","useState","useEffect","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Label","Switch","jsx","jsxs","Button","Input","Label","useState","jsx","jsxs","str","useState","Label","Input","Button","jsx","jsxs","jsx","emptyDoc","Button","jsx","jsxs","Label","Switch","jsx","jsxs","Switch","Label"]}
@@ -0,0 +1,45 @@
1
+ // src/core/css-sanitize.ts
2
+ import * as csstree from "css-tree";
3
+ function isDangerousValue(val) {
4
+ const v = val.toLowerCase();
5
+ return v.includes("javascript:") || v.includes("vbscript:") || /expression\s*\(/.test(v) || /url\(\s*['"]?\s*data:/.test(v);
6
+ }
7
+ function sanitizeCustomCss(css, scopeClass) {
8
+ if (!css) return "";
9
+ const cleaned = css.replace(/<\/?(style|script)[^>]*>/gi, "");
10
+ let ast;
11
+ try {
12
+ ast = csstree.parse(cleaned);
13
+ } catch {
14
+ return "";
15
+ }
16
+ csstree.walk(ast, {
17
+ visit: "Atrule",
18
+ enter(node, item, list) {
19
+ const name = node.name.toLowerCase();
20
+ if (name !== "media" && name !== "supports") list.remove(item);
21
+ }
22
+ });
23
+ csstree.walk(ast, {
24
+ visit: "Declaration",
25
+ enter(node, item, list) {
26
+ const decl = node;
27
+ const value = csstree.generate(decl.value);
28
+ if (isDangerousValue(value) && list && item) list.remove(item);
29
+ }
30
+ });
31
+ csstree.walk(ast, {
32
+ visit: "Selector",
33
+ enter(node) {
34
+ const sel = node;
35
+ sel.children.prependData({ type: "Combinator", name: " " });
36
+ sel.children.prependData({ type: "ClassSelector", name: scopeClass });
37
+ }
38
+ });
39
+ return csstree.generate(ast);
40
+ }
41
+
42
+ export {
43
+ sanitizeCustomCss
44
+ };
45
+ //# sourceMappingURL=chunk-7VN7UNLK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/css-sanitize.ts"],"sourcesContent":["/**\n * Parser-backed page-level custom-CSS sanitizer + scoper (spec §8/§14). React-free.\n *\n * Fails closed: on a fatal parse error returns \"\". Strips raw markup, drops dangerous\n * at-rules (@import and anything but @media/@supports) and declarations\n * (javascript:/vbscript:/data:/expression()), then prefixes every selector with the\n * page scope class so custom CSS cannot leak onto the host site.\n */\nimport * as csstree from \"css-tree\";\nimport type { CssNode, List, ListItem } from \"css-tree\";\n\nfunction isDangerousValue(val: string): boolean {\n const v = val.toLowerCase();\n return (\n v.includes(\"javascript:\") ||\n v.includes(\"vbscript:\") ||\n /expression\\s*\\(/.test(v) ||\n /url\\(\\s*['\"]?\\s*data:/.test(v)\n );\n}\n\nexport function sanitizeCustomCss(css: string, scopeClass: string): string {\n if (!css) return \"\";\n\n // Defensively strip any raw <style>/<script> tags before parsing.\n const cleaned = css.replace(/<\\/?(style|script)[^>]*>/gi, \"\");\n\n let ast: CssNode;\n try {\n ast = csstree.parse(cleaned);\n } catch {\n return \"\";\n }\n\n // Drop dangerous at-rules (keep only @media / @supports).\n csstree.walk(ast, {\n visit: \"Atrule\",\n enter(node: CssNode, item: ListItem<CssNode>, list: List<CssNode>) {\n const name = (node as csstree.Atrule).name.toLowerCase();\n if (name !== \"media\" && name !== \"supports\") list.remove(item);\n },\n });\n\n // Drop declarations with dangerous values.\n csstree.walk(ast, {\n visit: \"Declaration\",\n enter(node: CssNode, item: ListItem<CssNode>, list: List<CssNode>) {\n const decl = node as csstree.Declaration;\n const value = csstree.generate(decl.value);\n if (isDangerousValue(value) && list && item) list.remove(item);\n },\n });\n\n // Scope every selector under the page root class.\n csstree.walk(ast, {\n visit: \"Selector\",\n enter(node: CssNode) {\n const sel = node as csstree.Selector;\n sel.children.prependData({ type: \"Combinator\", name: \" \" });\n sel.children.prependData({ type: \"ClassSelector\", name: scopeClass });\n },\n });\n\n return csstree.generate(ast);\n}\n"],"mappings":";AAQA,YAAY,aAAa;AAGzB,SAAS,iBAAiB,KAAsB;AAC9C,QAAM,IAAI,IAAI,YAAY;AAC1B,SACE,EAAE,SAAS,aAAa,KACxB,EAAE,SAAS,WAAW,KACtB,kBAAkB,KAAK,CAAC,KACxB,wBAAwB,KAAK,CAAC;AAElC;AAEO,SAAS,kBAAkB,KAAa,YAA4B;AACzE,MAAI,CAAC,IAAK,QAAO;AAGjB,QAAM,UAAU,IAAI,QAAQ,8BAA8B,EAAE;AAE5D,MAAI;AACJ,MAAI;AACF,UAAc,cAAM,OAAO;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AAGA,EAAQ,aAAK,KAAK;AAAA,IAChB,OAAO;AAAA,IACP,MAAM,MAAe,MAAyB,MAAqB;AACjE,YAAM,OAAQ,KAAwB,KAAK,YAAY;AACvD,UAAI,SAAS,WAAW,SAAS,WAAY,MAAK,OAAO,IAAI;AAAA,IAC/D;AAAA,EACF,CAAC;AAGD,EAAQ,aAAK,KAAK;AAAA,IAChB,OAAO;AAAA,IACP,MAAM,MAAe,MAAyB,MAAqB;AACjE,YAAM,OAAO;AACb,YAAM,QAAgB,iBAAS,KAAK,KAAK;AACzC,UAAI,iBAAiB,KAAK,KAAK,QAAQ,KAAM,MAAK,OAAO,IAAI;AAAA,IAC/D;AAAA,EACF,CAAC;AAGD,EAAQ,aAAK,KAAK;AAAA,IAChB,OAAO;AAAA,IACP,MAAM,MAAe;AACnB,YAAM,MAAM;AACZ,UAAI,SAAS,YAAY,EAAE,MAAM,cAAc,MAAM,IAAI,CAAC;AAC1D,UAAI,SAAS,YAAY,EAAE,MAAM,iBAAiB,MAAM,WAAW,CAAC;AAAA,IACtE;AAAA,EACF,CAAC;AAED,SAAe,iBAAS,GAAG;AAC7B;","names":[]}