@jbpark/live-editor 4.4.0 → 4.6.0
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.
- package/README.ko.md +4 -1
- package/README.md +7 -3
- package/dist/{boundary-B17cepvm.js → boundary-BLB80tyw.js} +8 -5
- package/dist/boundary-BLB80tyw.js.map +1 -0
- package/dist/cache-B0-XcIxJ.js.map +1 -1
- package/dist/{compile-DDfk5P25.js → compile-Dxas-D05.js} +3 -3
- package/dist/compile-Dxas-D05.js.map +1 -0
- package/dist/{constants-h1JAgOeW.js → constants-DU17Tdwo.js} +3 -3
- package/dist/constants-DU17Tdwo.js.map +1 -0
- package/dist/{context-DB5kW3qe.js → context-B8MzP7_p.js} +11 -5
- package/dist/context-B8MzP7_p.js.map +1 -0
- package/dist/{core-CRsAGpei.js → core-Bgfek364.js} +2 -2
- package/dist/core-Bgfek364.js.map +1 -0
- package/dist/{detect-typescript-CCj9ALXc.js → detect-typescript-Dr_oLniM.js} +2 -2
- package/dist/detect-typescript-Dr_oLniM.js.map +1 -0
- package/dist/dnd/index.d.ts +1 -1
- package/dist/dnd/index.js +1 -1
- package/dist/{dnd-BE5ZizqX.js → dnd-UoJILA75.js} +973 -885
- package/dist/dnd-UoJILA75.js.map +1 -0
- package/dist/{document-BDn_f08_.js → document-CGbe6bSV.js} +7739 -7736
- package/dist/document-CGbe6bSV.js.map +1 -0
- package/dist/editor/index.js +2 -2
- package/dist/{editor-DQ8Q--qR.js → editor-CMElfHer.js} +2 -2
- package/dist/editor-CMElfHer.js.map +1 -0
- package/dist/editor-caches-ClMvdcQF.js.map +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-DWhxQEom.js → error-CN_GCnXB.js} +13 -6
- package/dist/error-CN_GCnXB.js.map +1 -0
- package/dist/{index-Dgh1JTX3.d.ts → index-C69Lv-jR.d.ts} +72 -69
- package/dist/{index-C4SGQ3Ci.d.ts → index-CRwEhJ7w.d.ts} +4 -1
- package/dist/{index-f7ijuNTa.d.ts → index-DKYUxi-E.d.ts} +115 -155
- package/dist/index-DrWtSKXu.d.ts +11 -0
- package/dist/index.d.ts +18 -18
- package/dist/index.js +12 -8
- package/dist/index.js.map +1 -1
- package/dist/{ast-dYb78955.js → items-B6OXxcLG.js} +588 -718
- package/dist/items-B6OXxcLG.js.map +1 -0
- package/dist/messages-CSrMI4Rm.js +133 -0
- package/dist/messages-CSrMI4Rm.js.map +1 -0
- package/dist/messages-IBPs4TkZ.d.ts +130 -0
- package/dist/preview/index.js +2 -2
- package/dist/{preview-BnaCEFsF.js → preview-CtyG5UbH.js} +6 -4
- package/dist/preview-CtyG5UbH.js.map +1 -0
- package/dist/provider/index.d.ts +3 -8
- package/dist/provider/index.js +3 -2
- package/dist/{sections-CBVMO8Jl.js → sections-BYWOBISr.js} +9 -4
- package/dist/sections-BYWOBISr.js.map +1 -0
- package/dist/states-Ci1AvoQ9.js.map +1 -1
- package/dist/style.css +505 -21
- package/dist/{use-dynamic-tailwind-Bcipc1hL.js → use-dynamic-tailwind-BP1toJkW.js} +66 -40
- package/dist/use-dynamic-tailwind-BP1toJkW.js.map +1 -0
- package/dist/utils/ast/index.d.ts +3 -2
- package/dist/utils/ast/index.js +150 -3
- package/dist/utils/ast/index.js.map +1 -0
- package/dist/utils/index.d.ts +30 -13
- package/dist/utils/index.js +26 -6
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/tailwind/index.js.map +1 -1
- package/dist/validate-DB59Z_Nx.d.ts +100 -0
- package/dist/validate-iLo8IONY.js +64 -0
- package/dist/validate-iLo8IONY.js.map +1 -0
- package/package.json +3 -3
- package/dist/ast-dYb78955.js.map +0 -1
- package/dist/boundary-B17cepvm.js.map +0 -1
- package/dist/compile-DDfk5P25.js.map +0 -1
- package/dist/constants-h1JAgOeW.js.map +0 -1
- package/dist/context-DB5kW3qe.js.map +0 -1
- package/dist/core-CRsAGpei.js.map +0 -1
- package/dist/detect-typescript-CCj9ALXc.js.map +0 -1
- package/dist/dnd-BE5ZizqX.js.map +0 -1
- package/dist/document-BDn_f08_.js.map +0 -1
- package/dist/editor-DQ8Q--qR.js.map +0 -1
- package/dist/error-DWhxQEom.js.map +0 -1
- package/dist/preview-BnaCEFsF.js.map +0 -1
- package/dist/sections-CBVMO8Jl.js.map +0 -1
- package/dist/use-dynamic-tailwind-Bcipc1hL.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dnd-UoJILA75.js","names":["LiveError","CSS","Renderer","Children","CSS","t","CoreEditor","Children","Panel","PropertyPanel","Dnd","Renderer","DndImpl"],"sources":["../src/components/dnd/palette/palette-drag.ts","../src/components/dnd/canvas/droppable.tsx","../src/components/dnd/canvas/inspector-highlight.tsx","../src/components/dnd/palette/draggable.tsx","../src/components/dnd/canvas/section-fallback-context.ts","../src/components/dnd/canvas/section-fallback.tsx","../src/components/dnd/canvas/renderer.tsx","../src/components/dnd/canvas/sortable.tsx","../src/components/dnd/canvas/overlay.tsx","../src/components/dnd/edit-options.ts","../src/components/dnd/inspector.ts","../src/components/dnd/layout-context.ts","../src/components/dnd/panel-binding.ts","../src/components/dnd/panel/bulk-actions-bar.tsx","../src/components/dnd/panel/node.tsx","../src/components/dnd/panel/use-structural-selection.ts","../src/components/dnd/panel/use-dnd-children.ts","../src/components/dnd/panel/children.tsx","../src/components/dnd/panel/field-kind.ts","../src/components/dnd/panel/sortable-items.tsx","../src/components/dnd/panel/use-dnd-items.ts","../src/components/dnd/panel/items.tsx","../src/components/dnd/panel/field.tsx","../src/components/dnd/panel/field-group.tsx","../src/components/dnd/panel/panel.tsx","../src/components/dnd/layout.tsx","../src/components/dnd/state/use-delete-flow.ts","../src/components/dnd/state/use-dnd-keyboard.ts","../src/components/dnd/state/use-inspector-state.ts","../src/components/dnd/state/use-section-document.ts","../src/components/dnd/dnd.tsx","../src/components/dnd/index.ts"],"sourcesContent":["import type { Section } from '~/types';\n\nconst PALETTE_SECTION = 'palette-section';\n\n// The data a palette section carries while it's dragged. Written by\n// `Live.Dnd.DraggableItem` and read back on drop, in the drag overlay, by\n// the drop highlights and in screen-reader announcements, all through\n// `paletteSectionOf`.\nexport const paletteDragData = (section: Section) => ({\n type: PALETTE_SECTION,\n section,\n});\n\n// The palette section being dragged, or `undefined` when the drag is\n// something else, such as a canvas section.\nexport const paletteSectionOf = (\n data: { current?: unknown } | undefined,\n): Section | undefined => {\n const current = data?.current as\n { type?: unknown; section?: Section } | undefined;\n\n return current?.type === PALETTE_SECTION ? current.section : undefined;\n};\n","import { useDroppable } from '@dnd-kit/core';\nimport { Typography } from '@jbpark/ui-kit';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport { paletteSectionOf } from '../palette/palette-drag';\n\nconst Droppable = ({\n children,\n className,\n}: React.ComponentPropsWithRef<'div'>) => {\n const { setNodeRef, isOver, active } = useDroppable({\n id: 'sortable-area',\n });\n\n const { setNodeRef: setBottomRef, isOver: isBottomOver } = useDroppable({\n id: 'sortable-area-bottom',\n });\n\n const isPaletteSectionDragging = !!paletteSectionOf(active?.data);\n const shouldHighlight = isOver && isPaletteSectionDragging;\n const shouldHighlightBottom = isBottomOver && isPaletteSectionDragging;\n const messages = useLiveMessages();\n\n return (\n <div\n ref={setNodeRef}\n className={cn(\n 'min-h-full',\n 'border-2 border-dashed p-1',\n shouldHighlight ? 'border-blue-300 bg-blue-50' : 'border-gray-200',\n className,\n )}\n >\n {children}\n {isPaletteSectionDragging && (\n <div\n ref={setBottomRef}\n className={cn(\n 'mt-2 min-h-24',\n 'rounded-lg border-2 border-dashed',\n 'transition-all duration-200',\n 'flex items-center justify-center',\n shouldHighlightBottom\n ? 'border-blue-400 bg-blue-100'\n : 'border-gray-300 bg-gray-50',\n )}\n >\n <Typography.Text className=\"text-sm text-gray-500\">\n {shouldHighlightBottom\n ? messages.canvas.dropHere\n : messages.canvas.dropAtBottom}\n </Typography.Text>\n </div>\n )}\n </div>\n );\n};\n\nexport default Droppable;\n","import { useLayoutEffect, useRef } from 'react';\n\n// The outline drawn over the element under the pointer, or the one a panel\n// field edits. Rendered inside the canvas's scroll container, so it sits at\n// the canvas's level: whatever covers the canvas, such as the mobile panel\n// Drawer or a host's modal, covers the outline too, and it never shows\n// outside the canvas. `rect` is in viewport coordinates and is converted to\n// the container's, scroll included.\nconst InspectorHighlight = ({ rect }: { rect: DOMRect | null }) => {\n const ref = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const box = ref.current;\n const container = box?.closest<HTMLElement>('[data-frame-container]');\n\n if (!box || !rect || !container) {\n return;\n }\n\n const outer = container.getBoundingClientRect();\n\n box.style.left = `${rect.left - outer.left - container.clientLeft + container.scrollLeft}px`;\n box.style.top = `${rect.top - outer.top - container.clientTop + container.scrollTop}px`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n }, [rect]);\n\n return rect ? (\n <div\n ref={ref}\n aria-hidden\n data-dnd-inspector-highlight\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n outline: '2px solid #3b82f6',\n outlineOffset: -1,\n background: 'rgba(59, 130, 246, 0.12)',\n // Above the sections and their toolbars (up to `z-60`), below the\n // element picker's button and the stale banner (`z-70`).\n zIndex: 65,\n }}\n />\n ) : null;\n};\n\nexport default InspectorHighlight;\n","import { useDraggable } from '@dnd-kit/core';\nimport { Card } from '@jbpark/ui-kit';\n\nimport type { Section } from '~/types';\nimport { cn } from '~/utils/cn';\n\nimport { paletteDragData } from './palette-drag';\n\nexport interface DraggableItemDragState {\n ref: (node: HTMLElement | null) => void;\n dragProps: React.HTMLAttributes<HTMLElement>;\n isDragging: boolean;\n}\n\nexport interface DraggableItemProps {\n item: Section;\n children: (drag: DraggableItemDragState) => React.ReactNode;\n}\n\n// Makes a palette item draggable, with the drag data the canvas expects on\n// drop (`paletteDragData`). `Live.Dnd.DraggableItem`; the built-in palette\n// uses it too.\nconst DraggableItem = ({ item, children }: DraggableItemProps) => {\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({\n id: item.id,\n data: paletteDragData(item),\n });\n\n return children({\n ref: setNodeRef,\n dragProps: { ...listeners, ...attributes },\n isDragging,\n });\n};\n\n// The built-in palette card, used by the palette and the drag overlay.\nexport interface DefaultDraggableItemProps {\n item: Section;\n onAdd?: (item: Section) => void;\n // Add on a single tap instead of a double-click. On desktop a click could\n // be a drag that didn't start, so a double-click adds. On mobile there's\n // nothing to drag onto behind the Drawer, and a double-tap doesn't reliably\n // fire `dblclick`, so a tap adds.\n tapToAdd?: boolean;\n}\n\nexport const DefaultDraggableItem = ({\n item,\n onAdd,\n tapToAdd = false,\n}: DefaultDraggableItemProps) => (\n <DraggableItem item={item}>\n {({ ref, dragProps, isDragging }) => (\n <Card\n ref={ref}\n style={{ opacity: isDragging ? 0.5 : 1 }}\n {...dragProps}\n className={cn(\n 'cursor-grab',\n // A visible ring for keyboard focus only, instead of no outline at\n // all: the card is reachable with Tab (#435).\n 'outline-none focus-visible:ring-2 focus-visible:ring-blue-500',\n 'hover:border-blue-300 hover:shadow-md',\n isDragging && 'opacity-50',\n )}\n onClick={tapToAdd && onAdd ? () => onAdd(item) : undefined}\n onDoubleClick={onAdd ? () => onAdd(item) : undefined}\n // The card is a `role=\"button\"`: Enter adds it, the keyboard\n // counterpart of the double-click above. Space stays with dnd-kit,\n // which picks the card up (#435).\n onKeyDown={event => {\n dragProps.onKeyDown?.(event);\n\n if (\n onAdd &&\n event.key === 'Enter' &&\n event.target === event.currentTarget &&\n !event.defaultPrevented\n ) {\n event.preventDefault();\n onAdd(item);\n }\n }}\n >\n {item.name}\n </Card>\n )}\n </DraggableItem>\n);\n\nexport default DraggableItem;\n","import { createContext } from 'react';\n\nimport type { Section } from '~/types';\n\nexport interface DndSectionFallbackArgs {\n section: Section;\n // `compile`: the section's code failed to compile. `runtime`: it threw\n // while rendering. `forced`: `shouldForceSectionFallback` returned true, so\n // it was never compiled.\n reason: 'compile' | 'runtime' | 'forced';\n // The compiler or runtime message. `undefined` for `forced`.\n message?: string;\n}\n\n// Return a node to show in the section's place, or `undefined` for the\n// built-in error box.\nexport type DndRenderSectionFallback = (\n args: DndSectionFallbackArgs,\n) => React.ReactNode | undefined;\n\n// Read only by `SectionFallback`, which renders only for a failed section,\n// so a new inline function each render never re-renders a working section\n// (#97).\nexport const SectionFallbackContext = createContext<\n DndRenderSectionFallback | undefined\n>(undefined);\n","import { useContext } from 'react';\n\nimport ErrorBoundary from '~/components/error/boundary';\n\nimport {\n type DndRenderSectionFallback,\n type DndSectionFallbackArgs,\n SectionFallbackContext,\n} from './section-fallback-context';\n\ninterface ConsumerFallbackProps {\n render: DndRenderSectionFallback;\n args: DndSectionFallbackArgs;\n builtin: React.ReactElement;\n}\n\n// Its own component so the consumer's function runs inside the guard below:\n// a throw from the call itself, not only from what it returns, is caught.\nconst ConsumerFallback = ({ render, args, builtin }: ConsumerFallbackProps) => {\n const node = render(args);\n\n return node === undefined ? builtin : <>{node}</>;\n};\n\ninterface Props {\n args: DndSectionFallbackArgs;\n // What renders when no consumer fallback is set, when it returns\n // `undefined`, or when it throws.\n builtin: React.ReactElement;\n}\n\nconst SectionFallback = ({ args, builtin }: Props) => {\n const render = useContext(SectionFallbackContext);\n\n if (!render) {\n return builtin;\n }\n\n // A broken fallback must not break the canvas: revert to the built-in\n // error for this section only.\n return (\n <ErrorBoundary fallback={() => builtin}>\n <ConsumerFallback render={render} args={args} builtin={builtin} />\n </ErrorBoundary>\n );\n};\n\nexport default SectionFallback;\n","import { memo } from 'react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport ErrorBoundary from '~/components/error/boundary';\nimport LiveError from '~/components/error/error';\nimport Frame, { type FrameProps } from '~/components/frame';\nimport { useCompiledModule } from '~/components/preview/use-compiled-module';\nimport { useDynamicTailwind } from '~/components/preview/use-dynamic-tailwind';\n\nimport SectionFallback from './section-fallback';\n\ninterface Props {\n preview: string;\n // The section for `renderSectionFallback`, as strings: a `Section` object\n // is new on every document change and would break the memo below.\n sectionId?: string;\n sectionName?: string;\n sectionCode?: string;\n // Skip compiling and render the fallback (`shouldForceSectionFallback`).\n forceFallback?: boolean;\n modules?: Record<string, unknown>;\n headers?: Record<string, boolean>;\n frame?: FrameProps;\n dynamicTailwind?: boolean;\n provider?: (children: React.ReactNode) => React.ReactNode;\n}\n\n// One canvas section: compiles its preview and renders it in its frame.\n// Memoized: an unchanged section gets the same `preview` string, so React\n// skips it entirely (#97).\nconst Renderer = ({\n preview,\n sectionId = '',\n sectionName = '',\n sectionCode = preview,\n forceFallback = false,\n headers,\n modules,\n frame,\n dynamicTailwind = false,\n provider,\n}: Props) => {\n // A forced section compiles empty code, so none of its code runs.\n const module = useCompiledModule(forceFallback ? '' : preview, modules);\n const section = { id: sectionId, name: sectionName, code: sectionCode };\n const messages = useLiveMessages();\n\n // The section's Tailwind classes, compiled into a `<style>` rendered next\n // to its content. A shadow root has no stylesheet of its own, and only\n // inherited CSS crosses into it (`frame/shadow.tsx`).\n const { ref: wrapperRef, css: dynamicCSS } = useDynamicTailwind(\n preview,\n dynamicTailwind && !forceFallback,\n );\n\n const renderProvider = (component: React.ReactNode) => {\n return provider ? provider(component) : component;\n };\n\n // A section with no component shows its fallback in place of the frame,\n // as `Live.Preview` does for a compile error.\n if (forceFallback) {\n return (\n <SectionFallback\n args={{ section, reason: 'forced' }}\n builtin={\n <LiveError\n message={messages.errors.sectionNotRendered}\n title={messages.errors.sectionUnavailable}\n />\n }\n />\n );\n }\n\n if (module?.error) {\n return (\n <SectionFallback\n args={{ section, reason: 'compile', message: module.error }}\n builtin={\n <LiveError message={module.error} title={messages.errors.compile} />\n }\n />\n );\n }\n\n const Component = module?.exports?.default;\n\n if (!Component) {\n return null;\n }\n\n return (\n <Frame {...frame} autoHeight>\n {container => (\n <div\n ref={wrapperRef}\n className=\"w-full overflow-x-hidden\"\n data-editor-mode\n >\n {/*\n Keeps a render error in this section, so it can't unmount the\n editor (#246). Inside the frame, so a passing error while typing\n doesn't rebuild the iframe. The next edit gives a new `preview`,\n which resets it.\n\n No `Error.Guard`, unlike `Live.Preview`: it listens on `window`,\n so one per section would make every section show any section's\n error. Errors also don't go to `ErrorContext`, which holds one\n string for the whole tree.\n */}\n <ErrorBoundary\n resetKeys={[preview]}\n fallback={(message, reset) => (\n <SectionFallback\n args={{ section, reason: 'runtime', message }}\n builtin={\n <LiveError\n message={message}\n onReset={reset}\n title={messages.errors.rendering}\n />\n }\n />\n )}\n >\n {renderProvider(\n <>\n <Component\n headers={headers}\n container={container}\n //\n />\n {dynamicTailwind && dynamicCSS && <style>{dynamicCSS}</style>}\n </>,\n )}\n </ErrorBoundary>\n </div>\n )}\n </Frame>\n );\n};\n\n// Compares `frame` by value, since it's usually written inline and is a new\n// object every render (#348): arrays by their entries, objects (`style`)\n// shallowly, anything else by identity, so a new `onLoaded` still\n// re-renders.\nconst sameValue = (a: unknown, b: unknown): boolean => {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((item, i) => Object.is(item, b[i]));\n }\n\n if (\n a &&\n b &&\n typeof a === 'object' &&\n typeof b === 'object' &&\n Object.getPrototypeOf(a) === Object.prototype &&\n Object.getPrototypeOf(b) === Object.prototype\n ) {\n const aKeys = Object.keys(a);\n\n return (\n aKeys.length === Object.keys(b).length &&\n aKeys.every(key =>\n Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n ),\n )\n );\n }\n\n return false;\n};\n\nconst sameFrame = (a?: FrameProps, b?: FrameProps): boolean => {\n if (a === b) {\n return true;\n }\n\n if (!a || !b) {\n return false;\n }\n\n const keys = new Set([...Object.keys(a), ...Object.keys(b)]);\n\n return [...keys].every(key =>\n sameValue(a[key as keyof FrameProps], b[key as keyof FrameProps]),\n );\n};\n\n// Every other prop is compared by identity, as `memo` does by default.\nconst arePropsEqual = (prev: Props, next: Props): boolean => {\n const keys = new Set([...Object.keys(prev), ...Object.keys(next)]);\n\n return [...keys].every(key =>\n key === 'frame'\n ? sameFrame(prev.frame, next.frame)\n : Object.is(prev[key as keyof Props], next[key as keyof Props]),\n );\n};\n\nexport default memo(Renderer, arePropsEqual);\n","import { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { Button, Space } from '@jbpark/ui-kit';\nimport { ChevronDown, ChevronUp, Copy, Trash } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport { paletteSectionOf } from '../palette/palette-drag';\n\ninterface Props {\n id: string;\n name?: string;\n children: React.ReactNode;\n selected?: boolean;\n onClick?: () => void;\n onDelete?: (id: string) => void;\n onCopy?: (id: string) => void;\n // The move buttons on the selected section, the same move as the panel's\n // (#505). Each is disabled where the section can't go further.\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n canMoveUp?: boolean;\n canMoveDown?: boolean;\n // Registers the focusable wrapper, so the canvas can move focus to it.\n nodeRef?: (node: HTMLElement | null) => void;\n // Arrow keys and Home/End on a focused section, outside a drag (#435).\n onNavigate?: (to: SectionNavigation) => void;\n // Delete or Backspace on a focused section (#435).\n onDeleteKey?: () => void;\n // The element picker is on (#432): the section can't be dragged, and the\n // pointer over it reports positions instead of selecting it.\n inspecting?: boolean;\n onInspectMove?: (\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n ) => void;\n onInspectPick?: (\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n ) => void;\n onInspectLeave?: () => void;\n}\n\nexport type SectionNavigation = 'previous' | 'next' | 'first' | 'last';\n\nconst NAVIGATION_KEYS: Record<string, SectionNavigation> = {\n ArrowUp: 'previous',\n ArrowDown: 'next',\n Home: 'first',\n End: 'last',\n};\n\nconst Sortable = ({\n id,\n children,\n selected,\n onClick,\n onDelete: _onDelete,\n onCopy: _onCopy,\n onMoveUp,\n onMoveDown,\n canMoveUp = false,\n canMoveDown = false,\n nodeRef,\n onNavigate,\n onDeleteKey,\n inspecting = false,\n onInspectMove,\n onInspectPick,\n onInspectLeave,\n}: Props) => {\n const {\n attributes,\n listeners,\n setNodeRef,\n setActivatorNodeRef,\n transform,\n transition,\n isDragging,\n isOver,\n active,\n } = useSortable({ id, disabled: inspecting });\n const messages = useLiveMessages();\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n cursor: inspecting ? 'crosshair' : 'grab',\n };\n\n const isPaletteSectionOver = isOver && !!paletteSectionOf(active?.data);\n\n // The wrapper is a `role=\"button\"`, so Enter selects it the way a click\n // does. Only when the key lands on the wrapper itself, not on its copy and\n // delete buttons, and not while a drag is on (Enter drops one then) (#435).\n //\n // The same rule covers the other keys handled here. Keys pressed inside a\n // section's own inputs never count: those sit in the section's frame, or\n // retarget to its shadow host, so the event target isn't the wrapper.\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n listeners?.onKeyDown?.(e);\n\n if (e.target !== e.currentTarget || active || e.defaultPrevented) {\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault();\n onClick?.();\n\n return;\n }\n\n const to = NAVIGATION_KEYS[e.key];\n\n if (to && onNavigate) {\n // Otherwise the arrow keys also scroll the canvas.\n e.preventDefault();\n onNavigate(to);\n\n return;\n }\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && onDeleteKey) {\n e.preventDefault();\n onDeleteKey();\n }\n };\n\n // The same element is the activator, so Space on a toolbar button presses\n // that button instead of picking the section up.\n const setRefs = (node: HTMLDivElement | null) => {\n setNodeRef(node);\n setActivatorNodeRef(node);\n nodeRef?.(node);\n };\n\n const onDelete = (e: React.MouseEvent) => {\n e.stopPropagation();\n _onDelete?.(id);\n };\n\n const onCopy = (e: React.MouseEvent) => {\n e.stopPropagation();\n _onCopy?.(id);\n };\n\n // Stops the click from reaching the wrapper, which would select it again.\n const press = (action?: () => void) => (e: React.MouseEvent) => {\n e.stopPropagation();\n action?.();\n };\n\n return (\n <div\n ref={setRefs}\n style={style}\n {...attributes}\n {...listeners}\n onKeyDown={onKeyDown}\n onClick={onClick}\n className={cn(\n 'relative',\n selected && 'z-10 outline-2 outline-offset-2 outline-blue-500',\n isPaletteSectionOver && 'border-t-4 border-t-green-500',\n //\n )}\n >\n <div\n className={cn(\n 'absolute inset-0 z-50',\n //\n )}\n onPointerMove={\n inspecting\n ? e =>\n onInspectMove?.(\n e.currentTarget.parentElement!,\n e.currentTarget,\n e.clientX,\n e.clientY,\n )\n : undefined\n }\n onPointerLeave={inspecting ? onInspectLeave : undefined}\n onClick={\n inspecting\n ? e => {\n // The pick selects the section itself.\n e.stopPropagation();\n onInspectPick?.(\n e.currentTarget.parentElement!,\n e.currentTarget,\n e.clientX,\n e.clientY,\n );\n }\n : undefined\n }\n />\n {children}\n {selected && (\n <Space\n className={cn(\n 'absolute top-1 right-1 z-60',\n //\n )}\n >\n {onMoveUp && (\n <Button\n icon={<ChevronUp />}\n disabled={!canMoveUp}\n onClick={press(onMoveUp)}\n aria-label={messages.section.moveUp}\n />\n )}\n {onMoveDown && (\n <Button\n icon={<ChevronDown />}\n disabled={!canMoveDown}\n onClick={press(onMoveDown)}\n aria-label={messages.section.moveDown}\n />\n )}\n <Button\n icon={<Copy />}\n onClick={onCopy}\n aria-label={messages.section.duplicate}\n />\n <Button\n danger\n icon={<Trash />}\n onClick={onDelete}\n aria-label={messages.section.delete}\n />\n </Space>\n )}\n </div>\n );\n};\n\nexport default Sortable;\n","import { useDndContext } from '@dnd-kit/core';\n\nimport type { FrameProps } from '~/components/frame';\nimport type { Section } from '~/types';\nimport { generateSection } from '~/utils/sections';\n\nimport { DefaultDraggableItem } from '../palette/draggable';\nimport { paletteSectionOf } from '../palette/palette-drag';\nimport Renderer from './renderer';\nimport Sortable from './sortable';\n\ninterface Props {\n sections: Section[];\n isForced?: (section: Section) => boolean;\n renderProps: {\n fullCode: string;\n containerId?: string;\n modules: Record<string, unknown>;\n frame?: FrameProps;\n dynamicTailwind?: boolean;\n };\n}\n\nconst Overlay = ({ sections, isForced, renderProps }: Props) => {\n const { active } = useDndContext();\n\n if (!active) {\n return null;\n }\n\n const paletteSection = paletteSectionOf(active.data);\n\n if (paletteSection) {\n return <DefaultDraggableItem item={paletteSection} />;\n }\n\n const section = sections.find(s => s.id === active.id);\n\n if (section) {\n const preview = generateSection(section.code, renderProps.fullCode, {\n containerId: renderProps.containerId,\n });\n\n return (\n <Sortable id={section.id} name={section.name}>\n <Renderer\n preview={preview}\n sectionId={section.id}\n sectionName={section.name}\n sectionCode={section.code}\n forceFallback={isForced?.(section) ?? false}\n modules={renderProps.modules}\n frame={renderProps.frame}\n dynamicTailwind={renderProps.dynamicTailwind}\n />\n </Sortable>\n );\n }\n\n return null;\n};\n\nexport default Overlay;\n","import { createContext, useContext } from 'react';\n\nimport { Toast } from '@jbpark/ui-kit';\n\nimport type { BindingOptions } from '~/utils/ast/types';\nimport type { UpdateFailure } from '~/utils/ast/update';\n\nimport type { FieldProps } from './panel/field';\n\n// An edit the editor didn't apply. `title` and `description` are what the\n// built-in toast shows, so a host can show them its own way.\nexport type DndEditError =\n | {\n // `update()` rejected a field edit. `failure.reason` says why, most\n // often a `property` or `label` that doesn't match the markup.\n type: 'update';\n id: string;\n label: string;\n property: string;\n failure: UpdateFailure | undefined;\n title: string;\n description?: string;\n }\n | {\n // The selected section's source, or an `items` value inside it, did\n // not parse. Nothing in it can be edited from the panel until it does.\n type: 'parse';\n target: 'section' | 'items';\n error?: unknown;\n title: string;\n description?: string;\n }\n | {\n // An edit was refused because the document doesn't parse; the canvas\n // and panel show the last version that did (#433). Reported when an\n // edit is attempted, not when the source stops parsing.\n type: 'parse';\n target: 'document';\n reason: 'parse-error';\n error: unknown;\n title: string;\n description?: string;\n }\n | {\n // The document has no element with the container id, so it has no\n // sections and nothing added from the palette can land. Reported once\n // each time a document reaches this state, not on every edit (#449).\n type: 'parse';\n target: 'document';\n reason: 'container-not-found';\n containerId: string;\n title: string;\n description?: string;\n }\n | {\n // An array edit could not be applied without losing source (a spread,\n // a hole, unsupported syntax). The source was left unchanged.\n type: 'items';\n title: string;\n description?: string;\n };\n\n// Called before the built-in control for every field — top-level, nested\n// object keys and array item properties alike. Return a node to render it\n// instead, `null` to render nothing, or `undefined` to keep `builtin`.\n// `builtin` is the control that would have rendered, so a renderer can wrap\n// it rather than replace it; don't render `<Live.Dnd.Field>` from here, since\n// that calls this function again.\nexport type DndRenderField = (\n props: FieldProps,\n builtin: React.ReactElement,\n) => React.ReactNode | undefined;\n\ninterface DndEditOptions {\n renderField?: DndRenderField;\n reportError: (error: DndEditError) => void;\n // `Live.Dnd`'s `bindings` and `bindingKeys`, for the editors that read\n // elements out of a value of their own, such as `useDndItems` (#509,\n // #513).\n bindingOptions?: BindingOptions;\n}\n\nexport const toastEditError = (error: DndEditError) => {\n Toast.error(\n error.title,\n error.description ? { description: error.description } : undefined,\n );\n};\n\n// The edit options every `Field` reads, wherever it renders: nested, inside\n// `Items` or `Children`, or in a custom panel. The default lets `Field` and\n// `useDndItems` work outside `Live.Dnd`, reporting through the toast.\nexport const DndEditOptionsContext = createContext<DndEditOptions>({\n reportError: toastEditError,\n});\n\nexport const useDndEditOptions = () => useContext(DndEditOptionsContext);\n","import { createContext, useContext } from 'react';\n\nimport { DATA_ATTR } from '~/constants';\n\n// What `Live.Dnd` reports when an element is picked in the canvas preview:\n// the element's `data-id`, the key its fields carry in `useDndPanel()`, and\n// the section it belongs to (#432).\nexport interface DndNodePick {\n id: string;\n sectionId: string;\n}\n\n// The element picker. While `active`, pointing at a section in the canvas\n// outlines the element under the pointer, and clicking selects that section\n// and reports the element. Section dragging is off for as long as it's on.\nexport interface DndInspector {\n active: boolean;\n activate: () => void;\n deactivate: () => void;\n toggle: () => void;\n // The last element picked, or `null`. Cleared when the selection moves to\n // another section.\n picked: DndNodePick | null;\n // Outlines the element with this `data-id` in the selected section's\n // preview, the way the picker outlines the element under the pointer.\n // `null` removes the outline. The built-in panel calls it for the field\n // under the pointer or focus, so a field shows which element it edits\n // (#514).\n highlight: (id: string | null) => void;\n}\n\nexport const DndInspectorContext = createContext<DndInspector | null>(null);\n\nexport const useDndInspector = (): DndInspector => {\n const inspector = useContext(DndInspectorContext);\n\n if (!inspector) {\n throw new Error('useDndInspector() must be used inside <Live.Dnd>.');\n }\n\n return inspector;\n};\n\n// A shadow root's `elementsFromPoint` lists the host page's elements under\n// the point too, the canvas overlay among them, so a nested lookup keeps only\n// its own tree's.\nconst outside = (root: Document | ShadowRoot) => (element: Element) =>\n element.getRootNode() !== root;\n\n// The deepest element at a point, looking into iframes and shadow roots on\n// the way down. Every canvas section sits under a transparent overlay that\n// takes the pointer, so the hit test has to skip it and go through to the\n// preview: in the host document for a section rendered in place, then inside\n// the iframe document or shadow root for the other frame modes.\nconst deepestAt = (\n root: Document | ShadowRoot,\n x: number,\n y: number,\n skip: (element: Element) => boolean,\n): Element | null => {\n const element = root\n .elementsFromPoint(x, y)\n .find(candidate => !skip(candidate));\n\n if (!element) {\n return null;\n }\n\n if (element instanceof HTMLIFrameElement) {\n const document = element.contentDocument;\n\n if (!document) {\n return element;\n }\n\n const rect = element.getBoundingClientRect();\n\n return (\n deepestAt(document, x - rect.left, y - rect.top, outside(document)) ??\n element\n );\n }\n\n if (element.shadowRoot && element.shadowRoot !== root) {\n return (\n deepestAt(element.shadowRoot, x, y, outside(element.shadowRoot)) ??\n element\n );\n }\n\n return element;\n};\n\nconst hasId = (element: Element) => Boolean(element.getAttribute(DATA_ATTR.ID));\n\n// The picked element inside `section`, as the nearest element at or above the\n// point that carries a non-empty `data-id`. `null` outside the section, or\n// when nothing there carries an id.\nexport const pickElement = (\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n): Element | null => {\n let element = deepestAt(\n section.ownerDocument,\n x,\n y,\n candidate =>\n candidate === overlay ||\n candidate === section ||\n !section.contains(candidate),\n );\n\n // Stops at the section's wrapper, so an id on the host page around the\n // canvas is never picked.\n while (element && element !== section && !hasId(element)) {\n element =\n element.parentElement ??\n // Past a shadow root, carry on from its host.\n (element.parentNode as ShadowRoot | null)?.host ??\n null;\n }\n\n return element === section ? null : element;\n};\n\n// The element carrying `data-id=\"id\"` in `section`'s preview, looking into\n// its iframe or shadow root for the frame modes that have one. `null` when\n// the section doesn't render it.\nexport const findElementById = (\n section: HTMLElement,\n id: string,\n): Element | null => {\n const selector = `[${DATA_ATTR.ID}=\"${CSS.escape(id)}\"]`;\n const roots: ParentNode[] = [section];\n\n for (const root of roots) {\n const found = root.querySelector(selector);\n\n if (found) {\n return found;\n }\n\n root.querySelectorAll('iframe').forEach(frame => {\n if (frame.contentDocument) {\n roots.push(frame.contentDocument);\n }\n });\n root.querySelectorAll('*').forEach(element => {\n if (element.shadowRoot) {\n roots.push(element.shadowRoot);\n }\n });\n }\n\n return null;\n};\n\n// The picked element's box in the host viewport, adding the offset of each\n// iframe it's nested in.\nexport const viewportRect = (element: Element): DOMRect => {\n const rect = element.getBoundingClientRect();\n let x = rect.left;\n let y = rect.top;\n let frame = element.ownerDocument.defaultView?.frameElement ?? null;\n\n while (frame) {\n const frameRect = frame.getBoundingClientRect();\n\n x += frameRect.left;\n y += frameRect.top;\n frame = frame.ownerDocument.defaultView?.frameElement ?? null;\n }\n\n return new DOMRect(x, y, rect.width, rect.height);\n};\n","import { createContext, useContext } from 'react';\n\nimport type { DndPalette, DndPanel } from './types';\n\n// The state a custom layout needs: where things go, not what they contain.\nexport interface DndLayout {\n // Whether the screen is at a mobile breakpoint, where the built-in layout\n // stacks the canvas and a tap on a palette item adds it.\n isMobile: boolean;\n // `null` when nothing is selected. The built-in layout uses it to open the\n // properties Drawer on mobile, where the panel has nowhere else to go.\n selectedId: string | null;\n clearSelection: () => void;\n // The palette Drawer's open state. Dnd owns it because adding an item\n // closes the Drawer; a layout only opens it.\n paletteOpen: boolean;\n setPaletteOpen: (open: boolean) => void;\n // Why the document can't be edited right now, or `null`. `'parse-error'`\n // while the source doesn't parse: the canvas shows the last version that\n // did, read-only (#433). `'container-not-found'` when it has no container\n // element, so it has no sections (#449).\n documentError: 'parse-error' | 'container-not-found' | null;\n}\n\n// Everything `Live.Dnd` passes to its children, read through the three\n// hooks below, so each component depends only on the part it uses.\n// `canvas` is a node, not data: `Live.Dnd.Canvas` places it, and nothing\n// else can produce it.\ninterface DndRegions extends DndLayout {\n palette: DndPalette;\n panel: DndPanel;\n canvas: React.ReactNode;\n}\n\nexport const DndRegionContext = createContext<DndRegions | null>(null);\n\n// Internal. `subject` names the caller as written, such as\n// `<Live.Dnd.Palette />`, for the error thrown outside `Live.Dnd`.\nexport const useDndRegions = (subject: string): DndRegions => {\n const regions = useContext(DndRegionContext);\n\n if (!regions) {\n throw new Error(`${subject} must be used inside <Live.Dnd>.`);\n }\n\n return regions;\n};\n\n// The palette's items and the callback that adds one to the canvas. With\n// `Live.Dnd.DraggableItem` for dragging, that's all a palette needs.\nexport const useDndPalette = (): DndPalette =>\n useDndRegions('useDndPalette()').palette;\n\n// The selected section, its editable bindings, and the callbacks that\n// commit edits: everything the built-in panel uses.\nexport const useDndPanel = (): DndPanel => useDndRegions('useDndPanel()').panel;\n\n// The layout state.\nexport const useDndLayout = (): DndLayout => useDndRegions('useDndLayout()');\n","import { RESERVED_BINDING_PROPERTIES } from '~/constants';\nimport {\n getCurrentValue,\n getStructuredValue,\n readNodeBindings,\n} from '~/utils/ast/binding';\nimport {\n type BindingItem,\n type BindingOption,\n type BindingRenderLeaf,\n type BindingRenderMap,\n type BindingType,\n type BindingWidget,\n type DataAttrNode,\n} from '~/utils/ast/types';\nimport { canLosslesslyEvaluateSource } from '~/utils/ast/value';\n\n// Commits one field by its element's `data-id`. Used by `DndPanel` and\n// `Field` (#308).\nexport interface PanelNodeChange {\n (params: {\n id: string;\n label: string;\n property: string;\n value: unknown;\n }): void;\n}\n\n// Several `PanelNodeChange`s as one edit, applied in order, all or none: if\n// one is refused, nothing is committed and the error names it (#425).\n// Calling `PanelNodeChange` several times instead makes one change per call\n// and keeps the earlier ones when a later one fails. An empty array does\n// nothing.\nexport interface PanelNodesChange {\n (changes: Parameters<PanelNodeChange>[0][]): void;\n}\n\n// One editable binding of the selected section: what a custom panel needs\n// to render its own control, with an `onChange` that commits the edit.\nexport interface PanelBinding {\n // The element's `data-id`, stable across edits.\n id: string;\n // Human-readable label from the binding definition.\n label: string;\n // The bound prop/attribute name (e.g. `children`, `src`, `color`).\n property: string;\n // The declared type. Switch on it to pick a control: an input for\n // `string` or `url`, a text area for `jsx` or `richtext`, a checkbox for\n // `boolean`, and so on. `undefined` means a plain string.\n type?: BindingType;\n // The control the binding asks for, such as `{ type: 'slider', step: 5 }`,\n // always in object form. Switch on `widget.type`, any string. The built-in\n // panel ignores it. Constraints are the fields below, not part of this.\n widget?: BindingWidget;\n // A fixed set of choices, for a select.\n options?: BindingOption[];\n // For `object` and `array` bindings: the types of the nested keys or\n // items, which the built-in panel uses for their fields.\n render?: BindingRenderMap;\n // Constraints, as `validateBindingValue` checks them. `min` and `max`\n // apply to the number a `type: 'number'` binding's `value` holds.\n min?: number;\n max?: number;\n pattern?: string;\n required?: boolean;\n // The binding's own keys, such as `group` or `tab`, kept apart so they\n // can't collide with a field added later. Absent when there are none\n // (#234).\n meta?: Record<string, unknown>;\n // The current value as its JS type: a number for `number`, a boolean for\n // `boolean`, an object or array for `object` and `array`, otherwise a\n // string (#238).\n value: unknown;\n // The source text behind `value`, for what a JS value can't hold: `jsx`\n // and `richtext`, or an expression to edit as text.\n rawValue: string;\n // `false` when editing the value would mean rebuilding it and losing an\n // expression, spread, hole or reference. The array and JSX editors apply\n // their own, narrower checks.\n canEditValue?: boolean;\n // `false` when the element doesn't have the attribute. Absent otherwise,\n // and always for content (`innerText`, `innerHTML`, `children`).\n // `onChange(undefined)` removes the attribute and `onChange(value)` adds it,\n // so a panel can draw an on/off control from this. `prop=\"\"` counts as\n // present (#426).\n present?: boolean;\n // The element the binding belongs to: its tag name as written and its own\n // text, trimmed (`''` when it has none). The built-in panel heads each\n // element's fields with these, to tell apart bindings with the same label\n // (#514). Absent for an array item's property.\n element?: PanelBindingElement;\n // Commits a new value the same way the built-in panel does, errors\n // included. Pass the value as its JS type; it's written according to the\n // declared `type`.\n onChange: (value: unknown) => void;\n}\n\nexport interface PanelBindingElement {\n tagName: string;\n text: string;\n}\n\n// A `PanelBinding` without `onChange`. Reading a node can be cached;\n// `onChange` must come from the current render, so it's added separately\n// (#336).\nexport type PanelBindingData = Omit<PanelBinding, 'onChange'>;\n\n// One data-bound element and its panel bindings.\nexport interface PanelBindingSource {\n // `data-id` of the element every binding below belongs to.\n id: string;\n // `'element'` when the tag has no name.\n tagName: string;\n bindings: PanelBindingData[];\n}\n\nconst readAttribute = (node: DataAttrNode, name: string) =>\n node.dataAttributes.find(attribute => attribute.name === name)?.value;\n\nconst canEditBindingValue = (node: DataAttrNode, binding: BindingItem) => {\n // The editor owns these attributes; `update()` refuses them too (#429).\n if (RESERVED_BINDING_PROPERTIES.includes(binding.property)) {\n return false;\n }\n\n if (\n binding.property === 'children' ||\n binding.property === 'innerText' ||\n binding.property === 'innerHTML' ||\n binding.property === 'items' ||\n binding.property === 'data' ||\n binding.type === 'array' ||\n binding.type === 'jsx' ||\n binding.type === 'richtext'\n ) {\n return true;\n }\n\n const attribute = node.attributes.find(\n candidate => candidate.name === binding.property,\n );\n\n // Not in the source yet: nothing to lose, and a value adds it (#426).\n if (!attribute) {\n return true;\n }\n\n return (\n attribute.isStringLiteral === true ||\n canLosslesslyEvaluateSource(attribute?.value ?? '')\n );\n};\n\n// Every field a binding declares. The return type makes leaving one out a\n// type error, so a field added to `BindingItem` reaches every panel and\n// nested editor at once (#340, #383).\nexport const toBindingFields = (\n binding: BindingItem,\n): { [K in keyof Required<BindingItem>]: BindingItem[K] } => ({\n label: binding.label,\n property: binding.property,\n type: binding.type,\n widget: binding.widget,\n options: binding.options,\n render: binding.render,\n min: binding.min,\n max: binding.max,\n pattern: binding.pattern,\n required: binding.required,\n meta: binding.meta,\n});\n\n// The binding for a nested key of an `object` or `array` value. A\n// render-map leaf brings its own fields; `label` and `property` default to\n// the key. A nested map, or no entry, gives an untyped field that passes\n// its sub-map down.\nexport const resolveRenderEntry = (\n render: BindingRenderMap | undefined,\n key: string,\n): BindingItem => {\n const entry = render?.[key];\n\n if (entry && 'type' in entry) {\n const leaf = entry as BindingRenderLeaf;\n\n return {\n ...leaf,\n label: leaf.label ?? key,\n property: leaf.property ?? key,\n };\n }\n\n return { label: key, property: key, render: entry as BindingRenderMap };\n};\n\n// Properties that are the element's content rather than one of its\n// attributes, so there's nothing to be absent.\nconst CONTENT_PROPERTIES = new Set(['innerText', 'innerHTML', 'children']);\n\nconst isAttributeAbsent = (node: DataAttrNode, binding: BindingItem) =>\n !CONTENT_PROPERTIES.has(binding.property) &&\n !node.attributes.some(candidate => candidate.name === binding.property);\n\nconst toPanelBindingData = (\n node: DataAttrNode,\n id: string,\n binding: BindingItem,\n): PanelBindingData => ({\n ...toBindingFields(binding),\n id,\n value: getStructuredValue(node, binding.property, binding.type),\n rawValue: getCurrentValue(node, binding.property),\n ...(!canEditBindingValue(node, binding) && { canEditValue: false }),\n ...(isAttributeAbsent(node, binding) && { present: false }),\n element: {\n tagName: node.tagName || 'element',\n text: node.textContent.replace(/\\s+/g, ' ').trim(),\n },\n});\n\n// An extracted element's panel bindings, without `onChange`. `null` when it\n// isn't editable: no `data-id`, or no bindings. Uses the bindings `extract()`\n// already resolved (#509, #513), so it's cheap enough for every element.\nexport const resolvePanelBindings = (\n node: DataAttrNode,\n): PanelBindingSource | null => {\n const id = readAttribute(node, 'data-id');\n\n if (!id) {\n return null;\n }\n\n const parsed = readNodeBindings(node);\n\n if (!parsed.length) {\n return null;\n }\n\n return {\n id,\n tagName: node.tagName || 'element',\n bindings: parsed.map(binding => toPanelBindingData(node, id, binding)),\n };\n};\n\n// Adds `onChange` to bindings read by `resolvePanelBindings`. Call it during\n// render, not inside a memo: `commit` belongs to the current document, and an\n// old one would write older source over newer (#336).\nexport const withPanelCommit = (\n bindings: PanelBindingData[],\n commit: PanelNodeChange | undefined,\n): PanelBinding[] =>\n bindings.map(binding => ({\n ...binding,\n onChange: (value: unknown) =>\n commit?.({\n id: binding.id,\n label: binding.label,\n property: binding.property,\n value,\n }),\n }));\n","import { Button } from '@jbpark/ui-kit';\nimport { ArrowDown, ArrowUp, Copy, X } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\n\ninterface BulkActionsBarProps {\n count: number;\n disabled?: boolean;\n onDuplicate: () => void;\n onMoveUp: () => void;\n onMoveDown: () => void;\n onDelete: () => void;\n onClear: () => void;\n}\n\nconst BulkActionsBar = ({\n count,\n disabled = false,\n onDuplicate,\n onMoveUp,\n onMoveDown,\n onDelete,\n onClear,\n}: BulkActionsBarProps) => {\n const messages = useLiveMessages();\n\n if (count === 0) {\n return null;\n }\n\n return (\n <div\n className=\"flex items-center justify-between rounded border\n border-blue-200 bg-blue-50 p-2\"\n >\n <div className=\"text-xs font-medium text-blue-700\">\n {messages.selection.count(count)}\n </div>\n <div className=\"flex items-center space-x-1\">\n <Button\n size=\"small\"\n icon={<Copy />}\n title={messages.selection.duplicate}\n disabled={disabled}\n onClick={onDuplicate}\n />\n <Button\n size=\"small\"\n icon={<ArrowUp />}\n title={messages.selection.moveUp}\n disabled={disabled}\n onClick={onMoveUp}\n />\n <Button\n size=\"small\"\n icon={<ArrowDown />}\n title={messages.selection.moveDown}\n disabled={disabled}\n onClick={onMoveDown}\n />\n <Button\n danger\n size=\"small\"\n icon={<X />}\n title={messages.selection.delete}\n disabled={disabled}\n onClick={onDelete}\n />\n <Button size=\"small\" onClick={onClear}>\n {messages.selection.clear}\n </Button>\n </div>\n </div>\n );\n};\n\nexport default BulkActionsBar;\n","import type { DataAttrNode } from '~/utils/ast/types';\n\nimport {\n type PanelNodeChange,\n resolvePanelBindings,\n withPanelCommit,\n} from '../panel-binding';\nimport Field from './field';\n\nexport interface FieldEditorProps {\n data: DataAttrNode;\n onChange?: PanelNodeChange;\n}\n\nconst Node = ({ data, onChange }: FieldEditorProps) => {\n const source = resolvePanelBindings(data);\n\n if (!source) {\n return null;\n }\n\n // Keyed by `property`, not `label`, which two bindings can share (#318).\n return (\n <div className=\"space-y-2 rounded\">\n <div className=\"space-y-1\">\n {withPanelCommit(source.bindings, onChange).map(binding => (\n <div key={`${binding.id}-${binding.property}`} className=\"space-y-1\">\n <label className=\"block text-xs font-semibold text-gray-700\">\n {binding.label}\n <span className=\"ml-1 text-gray-400\">({binding.property})</span>\n </label>\n <Field binding={binding} onNodeChange={onChange} />\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Node;\n","import { useState } from 'react';\n\nimport { useMultiSelect } from '@jbpark/use-hooks';\n\nimport type { ChildrenAction } from '~/utils/ast/children';\nimport { moveSelectedIndices } from '~/utils/selection';\n\n// The structural commands both list editors issue (#342). Children sends them\n// to the AST layer as-is; Items translates them to array element positions.\nexport type StructuralCommand = ChildrenAction;\n\n// Where the selection stands after a command succeeds. Commands that leave\n// every existing position in place keep it; a bulk move carries the block to\n// its new positions; anything else shifts positions under the selection, so\n// it is cleared rather than left pointing at different items (#285).\nexport const selectionAfter = (\n command: StructuralCommand,\n selected: ReadonlySet<number>,\n count: number,\n): Set<number> => {\n switch (command.type) {\n case 'append':\n case 'duplicate':\n // Both add at the end, so no existing item moves.\n return new Set(selected);\n case 'move-selected':\n return moveSelectedIndices(\n Array.from({ length: count }, (_, index) => index),\n new Set(command.indices),\n command.direction,\n ).indices;\n default:\n return new Set();\n }\n};\n\ninterface Pending {\n // Recognizes the source this command produced, as opposed to one that\n // came from somewhere else (another field, undo, an external edit).\n matches: (revision: string) => boolean;\n selection: Set<number>;\n}\n\nexport interface RecordOptions {\n // Apply the selection now as well, for a caller that already knows the\n // command succeeded. Otherwise it applies when the source arrives.\n now?: boolean;\n}\n\n// Positional multi-selection for a list whose source can change under it.\n// `revision` identifies the current source. When it changes to the source a\n// recorded command produced, that command's selection applies; when it\n// changes for any other reason, the selection is cleared, since positions in\n// an unrelated source no longer name the same items. A refused command\n// produces no new source, so it changes nothing.\nexport const useStructuralSelection = (count: number, revision: string) => {\n const selection = useMultiSelect(count);\n const [seen, setSeen] = useState(revision);\n const [pending, setPending] = useState<Pending | null>(null);\n\n // Adjusted during render rather than in an effect, so a frame with the\n // previous source's selection never paints.\n if (revision !== seen) {\n setSeen(revision);\n setPending(null);\n\n if (pending?.matches(revision) && pending.selection.size > 0) {\n selection.replace(pending.selection);\n } else {\n selection.clear();\n }\n }\n\n const record = (\n next: Set<number>,\n matches: Pending['matches'],\n { now = false }: RecordOptions = {},\n ) => {\n setPending({ matches, selection: next });\n\n if (!now) {\n return;\n }\n\n // `clear` also drops the shift-range anchor, which `replace` keeps.\n if (next.size > 0) {\n selection.replace(next);\n } else {\n selection.clear();\n }\n };\n\n return { selection, record };\n};\n","import { useMemo } from 'react';\n\nimport {\n type ChildrenAction,\n type ChildrenEdit,\n getChildrenSignatures,\n} from '~/utils/ast/children';\nimport { type DataAttrNode } from '~/utils/ast/types';\nimport { moveSelectedIndices } from '~/utils/selection';\n\nimport {\n selectionAfter,\n useStructuralSelection,\n} from './use-structural-selection';\n\nexport interface DndChildrenOptions {\n onChange?: (value: string) => void;\n}\n\n// The signature list a successful command produces, as far as it can be\n// known up front: a reorder is a permutation of the current signatures, and\n// an append or duplicate leaves them all in place as a prefix. Lets the\n// selection tell this command's result apart from an unrelated edit.\nconst producedBy = (\n expected: string[],\n action: ChildrenAction,\n): ((revision: string) => boolean) => {\n if (action.type === 'move-selected') {\n const moved = JSON.stringify(\n moveSelectedIndices(expected, new Set(action.indices), action.direction)\n .items,\n );\n\n return revision => revision === moved;\n }\n\n const added =\n action.type === 'append'\n ? 1\n : action.type === 'duplicate'\n ? action.indices.length\n : 0;\n\n return revision => {\n const next = JSON.parse(revision) as string[];\n\n return (\n next.length === expected.length + added &&\n expected.every((signature, index) => next[index] === signature)\n );\n };\n};\n\n// What the built-in Children editor runs on. Sends each command as the\n// `children` value through `onChange`, where `update` applies it, and\n// keeps the selection by `useStructuralSelection`'s rule.\nexport const useDndChildren = (\n items: DataAttrNode[],\n { onChange }: DndChildrenOptions = {},\n) => {\n const expected = useMemo(() => getChildrenSignatures(items), [items]);\n const revision = JSON.stringify(expected);\n const { selection, record } = useStructuralSelection(items.length, revision);\n\n // The outcome is only known when new source arrives, so the selection is\n // recorded here and applied then. A rejected edit produces no new source\n // and leaves the selection as it was.\n const commit = (action: ChildrenAction) => {\n const edit: ChildrenEdit = { kind: 'children-edit', expected, action };\n const next = selectionAfter(action, selection.selected, items.length);\n\n if (next.size > 0) {\n record(next, producedBy(expected, action));\n }\n\n onChange?.(JSON.stringify(edit));\n };\n\n return {\n items,\n selection,\n actions: {\n move: (from: number, to: number) => commit({ type: 'move', from, to }),\n remove: (index: number) => commit({ type: 'remove', indices: [index] }),\n add: () => commit({ type: 'append' }),\n duplicateSelected: () =>\n commit({ type: 'duplicate', indices: [...selection.selected] }),\n moveSelected: (direction: 'up' | 'down') =>\n commit({\n type: 'move-selected',\n indices: [...selection.selected],\n direction,\n }),\n removeSelected: () =>\n commit({ type: 'remove', indices: [...selection.selected] }),\n },\n };\n};\n\nexport type DndChildren = ReturnType<typeof useDndChildren>;\n","import { useMemo } from 'react';\n\nimport { Button, Checkbox } from '@jbpark/ui-kit';\nimport { ArrowDown, ArrowUp, Plus, X } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { findEditableChildren } from '~/utils/ast/binding';\nimport { type DataAttrNode } from '~/utils/ast/types';\n\nimport type { PanelNodeChange } from '../panel-binding';\nimport BulkActionsBar from './bulk-actions-bar';\nimport Node from './node';\nimport { useDndChildren } from './use-dnd-children';\n\ninterface Props {\n value: DataAttrNode[];\n onChange?: (value: string) => void;\n onNodeChange?: PanelNodeChange;\n}\n\nconst Children = ({ value, onChange, onNodeChange }: Props) => {\n const items = useMemo(() => (Array.isArray(value) ? value : []), [value]);\n\n const { selection, actions } = useDndChildren(items, { onChange });\n const messages = useLiveMessages();\n\n const editableChildrenMap = useMemo(() => {\n const map = new Map<number, DataAttrNode[]>();\n items.forEach((item, index) => {\n const editableNodes = findEditableChildren(item);\n if (editableNodes.length > 0) {\n map.set(index, editableNodes);\n }\n });\n return map;\n }, [items]);\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm font-semibold text-green-700\">\n {messages.children.heading(items.length)}\n </div>\n <Button\n size=\"small\"\n color=\"green\"\n icon={<Plus />}\n onClick={actions.add}\n >\n {messages.children.add}\n </Button>\n </div>\n\n <BulkActionsBar\n count={selection.selected.size}\n onDuplicate={actions.duplicateSelected}\n onMoveUp={() => actions.moveSelected('up')}\n onMoveDown={() => actions.moveSelected('down')}\n onDelete={actions.removeSelected}\n onClear={selection.clear}\n />\n\n {items.map((item, itemIndex) => (\n <div\n key={item.id || itemIndex}\n className=\"space-y-2 rounded border border-green-200 bg-green-50 p-3\"\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-2\">\n <div\n onClick={e => selection.toggle(itemIndex, e.shiftKey)}\n className=\"inline-flex\"\n >\n <Checkbox\n checked={selection.isSelected(itemIndex)}\n onChange={() => {}}\n />\n </div>\n <div className=\"text-xs font-medium text-green-800\">\n {messages.children.child(\n itemIndex + 1,\n item.tagName || 'fragment',\n )}\n </div>\n </div>\n\n <div className=\"flex space-x-1\">\n <Button\n size=\"small\"\n icon={<ArrowUp />}\n aria-label={messages.children.moveUp}\n disabled={itemIndex === 0}\n onClick={() => actions.move(itemIndex, itemIndex - 1)}\n />\n <Button\n size=\"small\"\n icon={<ArrowDown />}\n aria-label={messages.children.moveDown}\n disabled={itemIndex === items.length - 1}\n onClick={() => actions.move(itemIndex, itemIndex + 1)}\n />\n <Button\n aria-label={messages.children.delete}\n title={messages.children.delete}\n danger\n size=\"small\"\n icon={<X />}\n onClick={() => actions.remove(itemIndex)}\n />\n </div>\n </div>\n\n {editableChildrenMap.has(itemIndex) && (\n <div className=\"space-y-2\">\n <div className=\"text-xs font-medium text-green-700\">\n {messages.children.editableBindings}\n </div>\n {editableChildrenMap.get(itemIndex)!.map((editableNode, idx) => {\n const nodeId = editableNode.dataAttributes.find(\n a => a.name === 'data-id',\n )?.value;\n\n return (\n <div\n key={`editable-${nodeId || idx}`}\n data-node-id={nodeId}\n className=\"rounded border border-green-100 bg-white p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400\"\n >\n <div className=\"mb-1 text-xs text-green-600\">\n {editableNode.tagName}\n </div>\n <Node data={editableNode} onChange={onNodeChange} />\n </div>\n );\n })}\n </div>\n )}\n\n {!!item.children && !editableChildrenMap.has(itemIndex) && (\n <div className=\"space-y-1\">\n <div className=\"text-xs font-medium text-green-700\">\n {messages.children.childNodes}\n </div>\n {item.children.map((node, nodeIndex) => (\n <div\n key={`node-${itemIndex}-${nodeIndex}`}\n className=\"ml-2 rounded border border-green-100 bg-white p-2\"\n >\n <Node data={node} onChange={onNodeChange} />\n </div>\n ))}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n};\n\nexport default Children;\n","import { BINDING_PROP } from '~/constants';\n\nimport type { PanelBinding } from '../panel-binding';\n\n// Which built-in control `Field` renders for a binding. Exported so a\n// custom panel can ask the same question, most often whether a binding\n// needs a structural editor.\nexport type FieldKind =\n // `canEditValue: false` — shown as preserved source, not editable.\n | 'readonly'\n // An array literal (`items`/`data` or `type: 'array'`) — the Items editor,\n // or `useDndItems` for your own markup.\n | 'items'\n // Element children given as extracted nodes — the Children editor, or\n // `useDndChildren` for your own markup.\n | 'children'\n | 'richtext'\n | 'jsx'\n | 'html'\n // A plain object value — one nested field per key.\n | 'object'\n | 'boolean'\n | 'select'\n | 'color'\n | 'date'\n | 'url'\n | 'number'\n | 'text';\n\nexport type FieldKindBinding = Pick<\n PanelBinding,\n 'property' | 'type' | 'value' | 'options' | 'canEditValue'\n>;\n\nconst isColorProperty = (property: string): boolean =>\n property.toLowerCase().includes('color');\n\n// The first match wins. Describes the built-in control only: `renderField`\n// runs first and can replace it.\nexport const getFieldKind = (binding: FieldKindBinding): FieldKind => {\n const { property, type, value } = binding;\n\n if (binding.canEditValue === false) {\n return 'readonly';\n }\n\n if (property === 'items' || property === 'data' || type === 'array') {\n return 'items';\n }\n\n if (type === 'richtext') {\n return 'richtext';\n }\n\n if (property === BINDING_PROP.INNER_HTML) {\n return 'html';\n }\n\n if (type === 'jsx') {\n return 'jsx';\n }\n\n if (property === 'children' && Array.isArray(value)) {\n return 'children';\n }\n\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n return 'object';\n }\n\n if (type === 'boolean' || typeof value === 'boolean') {\n return 'boolean';\n }\n\n if (binding.options && Array.isArray(binding.options)) {\n return 'select';\n }\n\n if (type === 'color' || isColorProperty(property)) {\n return 'color';\n }\n\n if (type === 'date') {\n return 'date';\n }\n\n if (type === 'url') {\n return 'url';\n }\n\n if (type === 'number' || typeof value === 'number') {\n return 'number';\n }\n\n return 'text';\n};\n\n// True for the two kinds whose value holds further data-bound elements, so a\n// flat input can't edit them: route these to `Field` or to the matching hook.\nexport const isStructuralFieldKind = (\n kind: FieldKind,\n): kind is 'items' | 'children' => kind === 'items' || kind === 'children';\n","import {\n type Announcements,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n closestCenter,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n restrictToParentElement,\n restrictToVerticalAxis,\n} from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { ChevronDown, ChevronRight, GripVertical } from 'lucide-react';\n\nimport {\n type LiveMessages,\n useLiveMessages,\n} from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport type { DndItemsItem } from './use-dnd-items';\n\n// The default announcements would read out the items' generated ids.\nconst label = (\n messages: LiveMessages,\n items: DndItemsItem[],\n id: string | number,\n) => {\n const index = items.findIndex(item => item.id === id);\n\n // Every id dnd-kit reports is one of `items`; the id itself is only a\n // last resort.\n return index >= 0 ? messages.items.item(index + 1) : String(id);\n};\n\n// Drag sorting for the built-in Items editor (#436). It has a context of its\n// own, so a drag here never reaches the canvas's section sorting. Moves go\n// through `actions.move`, the same edit the up/down buttons make.\n//\n// A mouse drag starts after a few pixels of movement. A touch drag starts\n// after a long press, so a short tap still scrolls the panel. The handle is\n// a button, so the keyboard can pick an item up with Space or Enter and move\n// it with the arrow keys.\nexport const SortableItems = ({\n items,\n disabled,\n onMove,\n children,\n}: {\n items: DndItemsItem[];\n disabled?: boolean;\n onMove: (item: DndItemsItem, toIndex: number) => void;\n children: (item: DndItemsItem) => React.ReactNode;\n}) => {\n const sensors = useSensors(\n useSensor(MouseSensor, { activationConstraint: { distance: 4 } }),\n useSensor(TouchSensor, {\n activationConstraint: { delay: 250, tolerance: 5 },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const onDragEnd = ({ active, over }: DragEndEvent) => {\n const from = items.find(item => item.id === active.id);\n const to = items.find(item => item.id === over?.id);\n\n if (from && to && from !== to) {\n onMove(from, to.index);\n }\n };\n\n const messages = useLiveMessages();\n const { announcements: say } = messages;\n const name = (id: string | number) => label(messages, items, id);\n\n const announcements: Announcements = {\n onDragStart: ({ active }) => say.pickedUp(name(active.id)),\n onDragOver: ({ active, over }) =>\n over ? say.itemOver(name(active.id), name(over.id)) : undefined,\n onDragEnd: ({ active, over }) =>\n over\n ? say.itemMoved(name(active.id), name(over.id))\n : say.dropped(name(active.id)),\n onDragCancel: ({ active }) => say.cancelled(name(active.id)),\n };\n\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n modifiers={[restrictToVerticalAxis, restrictToParentElement]}\n accessibility={{ announcements }}\n onDragEnd={onDragEnd}\n >\n <SortableContext\n items={items.map(item => item.id)}\n strategy={verticalListSortingStrategy}\n disabled={disabled}\n >\n <div className=\"space-y-4\">{items.map(children)}</div>\n </SortableContext>\n </DndContext>\n );\n};\n\n// One item in the Items editor: a header with a drag handle, the selection\n// checkbox and a toggle that shows or hides the item's fields.\nexport const ItemCard = ({\n id,\n title,\n disabled,\n expanded,\n onToggle,\n checkbox,\n controls,\n className,\n children,\n}: {\n id: string;\n title: string;\n disabled?: boolean;\n expanded: boolean;\n onToggle: () => void;\n checkbox: React.ReactNode;\n controls: React.ReactNode;\n className?: string;\n children: React.ReactNode;\n}) => {\n const messages = useLiveMessages();\n const {\n attributes,\n listeners,\n setNodeRef,\n setActivatorNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id, disabled });\n\n return (\n <div\n ref={setNodeRef}\n style={{ transform: CSS.Translate.toString(transform), transition }}\n className={cn(className, isDragging && 'relative z-10 shadow-md')}\n >\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center space-x-1\">\n <button\n type=\"button\"\n ref={setActivatorNodeRef}\n {...attributes}\n {...listeners}\n aria-label={messages.items.reorder(title)}\n disabled={disabled}\n className=\"cursor-grab rounded p-0.5 text-gray-400\n hover:text-gray-700 disabled:cursor-not-allowed\n disabled:opacity-40\"\n >\n <GripVertical size={14} />\n </button>\n {checkbox}\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={onToggle}\n className=\"inline-flex items-center space-x-1 rounded px-1 text-xs\n font-medium\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n <span>{title}</span>\n </button>\n </div>\n {controls}\n </div>\n {expanded && children}\n </div>\n );\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport * as t from '@babel/types';\nimport type { useMultiSelect } from '@jbpark/use-hooks';\nimport { nanoid } from 'nanoid';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { canStructurallyEditArray } from '~/utils/ast/array-source';\nimport { findEditableChildren } from '~/utils/ast/binding';\nimport { extract } from '~/utils/ast/extract';\nimport {\n appendArrayItem,\n duplicateArrayItems,\n moveArrayItem,\n moveArrayItems,\n removeArrayItems,\n updateArrayItemProperty,\n updateArrayItemValue,\n} from '~/utils/ast/items';\nimport {\n type BindingOptions,\n type BindingRenderMap,\n type DataAttrNode,\n} from '~/utils/ast/types';\nimport { parseValue } from '~/utils/ast/value';\nimport {\n canLosslesslyEvaluateSource,\n extractNodeValue,\n extractObjectProperties,\n parseArrayExpression,\n} from '~/utils/ast/value';\nimport { moveSelectedIndices } from '~/utils/selection';\n\nimport { useDndEditOptions } from '../edit-options';\nimport {\n type PanelBinding,\n type PanelNodeChange,\n resolvePanelBindings,\n resolveRenderEntry,\n toBindingFields,\n withPanelCommit,\n} from '../panel-binding';\nimport {\n selectionAfter,\n useStructuralSelection,\n} from './use-structural-selection';\n\n// A data-bound element inside a JSX-valued item property. `bindings`\n// doesn't list these, because `extract()` doesn't read into attribute\n// values, so this hook extracts the property's JSX itself (#308).\nexport interface DndItemsNestedElement {\n // The element's `data-id`, which is what commits address it by.\n id: string;\n tagName: string;\n bindings: PanelBinding[];\n}\n\nexport interface DndItemsNestedGroup {\n // The item property holding this JSX (e.g. `children`, `label`).\n property: string;\n elements: DndItemsNestedElement[];\n // Set instead of `elements` when the JSX has no bindings: a `jsx` binding\n // for editing the property's source (#298).\n fallback?: PanelBinding;\n}\n\nexport interface DndItemsItem {\n // Stays the same while the hook can tell the item survived an edit, so\n // React keys follow an item that moves, is copied or is deleted.\n id: string;\n // Position among the visible items of this kind, which is what selection\n // indices refer to.\n index: number;\n // Position in the array's elements, which is what every `~/utils/ast`\n // item function addresses. Differs from `index` when the array mixes\n // objects and primitives.\n elementIndex: number;\n // An object item's plain (non-JSX) properties, already resolved through\n // the binding `render` map.\n properties: PanelBinding[];\n // An object item's JSX-valued properties.\n nested: DndItemsNestedGroup[];\n // A primitive item's own value. Absent on object items.\n value?: PanelBinding;\n}\n\nexport interface DndItemsActions {\n // Appends a copy of the first item of the current `kind`, since a new\n // item's shape comes from its siblings. On an empty array it fails with\n // the error toast, so offer it only when `items` isn't empty, as the\n // built-in panel does (#316).\n add: () => void;\n move: (elementIndex: number, toIndex: number) => void;\n // Refuses to remove the last item, so the array stays editable.\n remove: (elementIndex: number) => void;\n duplicateSelected: () => void;\n moveSelected: (direction: 'up' | 'down') => void;\n removeSelected: () => void;\n}\n\n// Which items show their fields. Keyed by `DndItemsItem.id`, so an item\n// keeps its state when it moves, a sibling changes, or another item is\n// added or removed. Every item starts expanded, including one added later.\n// The hook only holds the state; drawing a collapsed item is the panel's job.\nexport interface DndItemsExpansion {\n // The ids of the current items that are expanded, in item order.\n expandedIds: string[];\n isExpanded: (id: string) => boolean;\n toggle: (id: string) => void;\n // Expands exactly these items and collapses the rest. Pass every id to\n // expand all, or `[]` to collapse all.\n setExpanded: (ids: string[]) => void;\n}\n\nexport interface DndItems {\n // Which kind the array is being edited as. The panel shows one kind at a\n // time; an array holding both is treated as objects, and the primitives\n // stay untouched rather than being dropped.\n kind: 'object' | 'primitive';\n items: DndItemsItem[];\n // `@jbpark/use-hooks`' multi-select state, re-exposed as-is: `selected`,\n // `toggle`, `isSelected`, `clear`, `replace`. Its indices are item\n // `index` values, not `elementIndex` — the actions below translate.\n selection: ReturnType<typeof useMultiSelect>;\n expansion: DndItemsExpansion;\n actions: DndItemsActions;\n // Whether the current source can be moved, copied, removed or appended\n // without losing syntax. Value/property edits can remain available when\n // this is false. Every action revalidates the source before committing.\n canEditStructure: boolean;\n // The source didn't parse as an array expression. `items` is empty; the\n // built-in panel also raises a toast.\n parseError: boolean;\n}\n\nexport interface DndItemsOptions {\n render?: BindingRenderMap;\n // Commits the new array source after an edit.\n onChange?: (value: string) => void;\n // Commits an edit to a nested element by its own `data-id` (#308).\n onNodeChange?: PanelNodeChange;\n}\n\ninterface RawObjectItem {\n id: string;\n index: number;\n elementIndex: number;\n source: string;\n editableProperties: ReturnType<typeof extractObjectProperties>;\n jsxBindings: Record<string, DataAttrNode[]>;\n jsxFallbacks: Record<string, string>;\n}\n\ninterface RawPrimitiveItem {\n id: string;\n index: number;\n elementIndex: number;\n source: string;\n value: string | number | boolean | null;\n type: ReturnType<typeof extractNodeValue>['type'];\n}\n\n// What an edit reads: this render's array, or the one a same-tick commit\n// left behind (#451), with the item identity and selection that go with it.\ninterface Snapshot {\n value: string;\n items: Array<RawObjectItem | RawPrimitiveItem>;\n ids: string[];\n selected: Set<number>;\n}\n\ninterface PendingCommit {\n // The render `value` the commit was built on.\n from: string;\n value: string;\n ids: string[];\n selected: Set<number>;\n}\n\nconst createPendingCommit = () => {\n let current: PendingCommit | null = null;\n\n return {\n read: () => current,\n write: (next: PendingCommit) => {\n current = next;\n },\n clear: () => {\n current = null;\n },\n };\n};\n\ninterface ItemIdentityState {\n value: string;\n kind: DndItems['kind'];\n ids: string[];\n signatures: string[];\n}\n\n// Pulls the data-bound elements out of one JSX-valued property. A container\n// declaring `children` wins outright: it owns the elements below it, so\n// listing them separately would offer the same edit twice.\nconst bindingsInJSX = (\n source: string,\n bindingOptions: BindingOptions | undefined,\n): DataAttrNode[] => {\n const nodes = extract(source, bindingOptions);\n const container = nodes.find(n =>\n n.bindings?.some(b => b.property === 'children'),\n );\n\n if (container) {\n return [container];\n }\n\n const bindings: DataAttrNode[] = [];\n\n nodes.forEach(n => {\n if (\n n.bindings &&\n n.bindings.length > 0 &&\n n.dataAttributes.some(a => a.name === 'data-id')\n ) {\n bindings.push(n);\n }\n\n bindings.push(...findEditableChildren(n));\n });\n\n return bindings;\n};\n\n// Parses the array. Kept apart from building the bindings, so the parse is\n// memoized on the source while the callbacks stay current every render.\nconst parseSource = (value: string, bindingOptions?: BindingOptions) => {\n const ast = parseArrayExpression(value);\n\n if (!ast) {\n return { objectItems: [], primitiveItems: [], parseError: true };\n }\n\n const objectItems: RawObjectItem[] = [];\n const primitiveItems: RawPrimitiveItem[] = [];\n ast.elements.forEach((element, elementIndex) => {\n if (!t.isExpression(element)) {\n return;\n }\n\n if (!t.isObjectExpression(element)) {\n const extracted = extractNodeValue(element);\n\n primitiveItems.push({\n id: nanoid(6),\n index: primitiveItems.length,\n elementIndex,\n source: value.slice(element.start!, element.end!),\n value: extracted.value,\n type: extracted.type,\n });\n return;\n }\n\n const jsxBindings: Record<string, DataAttrNode[]> = {};\n const jsxFallbacks: Record<string, string> = {};\n\n element.properties.forEach(prop => {\n if (\n !t.isObjectProperty(prop) ||\n !t.isIdentifier(prop.key) ||\n !(t.isJSXElement(prop.value) || t.isJSXFragment(prop.value))\n ) {\n return;\n }\n\n const propertyName = prop.key.name;\n\n try {\n const found = bindingsInJSX(\n value.slice(prop.value.start!, prop.value.end!),\n bindingOptions,\n );\n\n if (found.length > 0) {\n jsxBindings[propertyName] = found;\n } else {\n jsxFallbacks[propertyName] = value.slice(\n prop.value.start!,\n prop.value.end!,\n );\n }\n } catch (error) {\n console.error(\n `Failed to parse JSX in property '${propertyName}':`,\n error,\n );\n }\n });\n\n const editableProperties = extractObjectProperties(element);\n\n for (const property of Object.values(editableProperties)) {\n if (property.type === 'array' || property.type === 'object') {\n property.value = value.slice(\n property.astNode.start!,\n property.astNode.end!,\n );\n }\n }\n\n objectItems.push({\n id: nanoid(6),\n index: objectItems.length,\n elementIndex,\n source: value.slice(element.start!, element.end!),\n editableProperties,\n jsxBindings,\n jsxFallbacks,\n });\n });\n\n return { objectItems, primitiveItems, parseError: false };\n};\n\nconst createIdentityState = (\n value: string,\n kind: DndItems['kind'],\n items: Array<RawObjectItem | RawPrimitiveItem>,\n ids: string[] = items.map(item => item.id),\n): ItemIdentityState => ({\n value,\n kind,\n ids,\n signatures: items.map(item => item.source),\n});\n\nconst reconcileIdentityState = (\n current: ItemIdentityState | null,\n value: string,\n kind: DndItems['kind'],\n items: Array<RawObjectItem | RawPrimitiveItem>,\n): ItemIdentityState => {\n if (\n current &&\n current.value === value &&\n current.kind === kind &&\n current.ids.length === items.length\n ) {\n return current;\n }\n\n if (!current || current.kind !== kind) {\n return createIdentityState(value, kind, items);\n }\n\n const previousCounts = new Map<string, number>();\n const nextCounts = new Map<string, number>();\n\n current.signatures.forEach(signature => {\n previousCounts.set(signature, (previousCounts.get(signature) ?? 0) + 1);\n });\n items.forEach(item => {\n nextCounts.set(item.source, (nextCounts.get(item.source) ?? 0) + 1);\n });\n\n const ids = items.map(item => {\n const previousIndex = current.signatures.indexOf(item.source);\n\n return previousIndex >= 0 &&\n previousCounts.get(item.source) === 1 &&\n nextCounts.get(item.source) === 1\n ? current.ids[previousIndex]!\n : item.id;\n });\n\n return createIdentityState(value, kind, items, ids);\n};\n\nconst moveId = (ids: string[], from: number, to: number) => {\n const next = [...ids];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved!);\n\n return next;\n};\n\nconst removeIds = (ids: string[], indices: Set<number>) => {\n return ids.filter((_, index) => !indices.has(index));\n};\n\n// What the built-in Items editor runs on, for a custom panel's own markup.\n// It finds the nested data-bound elements in each item, applies the\n// `render` map, maps visible positions to array positions for every edit,\n// and keeps the selection right after a move or delete (#285). Fields come\n// back as `PanelBinding`s, so `Live.Dnd.Field` can render them.\nexport const useDndItems = (\n value: string,\n { render, onChange, onNodeChange }: DndItemsOptions = {},\n): DndItems => {\n const { reportError, bindingOptions } = useDndEditOptions();\n const messages = useLiveMessages();\n const { objectItems, primitiveItems, parseError } = useMemo(\n () => parseSource(value, bindingOptions),\n [value, bindingOptions],\n );\n const canEditStructure = useMemo(\n () => canStructurallyEditArray(value),\n [value],\n );\n\n // Read through refs, so the effect below reports each parse failure once,\n // even when the host passes a new `onEditError` or new messages.\n const reportErrorRef = useRef(reportError);\n const messagesRef = useRef(messages);\n\n useEffect(() => {\n reportErrorRef.current = reportError;\n messagesRef.current = messages;\n });\n\n useEffect(() => {\n if (parseError) {\n reportErrorRef.current({\n type: 'parse',\n target: 'items',\n title: messagesRef.current.editErrors.itemsParseFailed,\n description: messagesRef.current.editErrors.checkConsole,\n });\n }\n }, [parseError]);\n\n const kind =\n primitiveItems.length > 0 && objectItems.length === 0\n ? 'primitive'\n : 'object';\n const isPrimitive = kind === 'primitive';\n const rawItems = isPrimitive ? primitiveItems : objectItems;\n const [identityState, setIdentityState] = useState(() =>\n createIdentityState(value, kind, rawItems),\n );\n const identity = useMemo(\n () => reconcileIdentityState(identityState, value, kind, rawItems),\n [identityState, kind, rawItems, value],\n );\n\n // Collapsed rather than expanded ids, so an item this hook hasn't seen\n // yet, such as one just added, starts expanded. Ids are never reused, so\n // one left behind by a removed item can't collapse another.\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n\n const { selection, record } = useStructuralSelection(\n isPrimitive ? primitiveItems.length : objectItems.length,\n value,\n );\n\n // The array the last commit produced, with its item ids and selection,\n // and the render `value` it was built on. Edits read `latest()`, so a\n // second edit in the same tick builds on the first instead of undoing it\n // (#451). Cleared after each render, when the new `value` takes over, as\n // in `useSectionDocument` (#450).\n //\n // Held in `useState`, not a ref: the bindings built during render close\n // over `latest()`, and the React compiler treats that as reading a ref in\n // render.\n const [pending] = useState(createPendingCommit);\n\n useEffect(() => {\n pending.clear();\n });\n\n const latest = (): Snapshot => {\n const last = pending.read();\n\n if (last?.from !== value) {\n return {\n value,\n items: rawItems,\n ids: identity.ids,\n selected: selection.selected,\n };\n }\n\n const parsed = parseSource(last.value);\n\n return {\n value: last.value,\n items: isPrimitive ? parsed.primitiveItems : parsed.objectItems,\n ids: last.ids,\n selected: last.selected,\n };\n };\n\n // Where the item this render showed at `elementIndex` is in `snapshot`,\n // followed by identity so an edit lands on the same item after a\n // same-tick move. `null` when a same-tick edit removed it; `undefined`\n // when this render has no such item, so the caller keeps the position it\n // was given.\n const locate = (snapshot: Snapshot, elementIndex: number) => {\n const shown = rawItems.find(item => item.elementIndex === elementIndex);\n\n if (!shown) {\n return undefined;\n }\n\n const index = snapshot.ids.indexOf(identity.ids[shown.index]!);\n\n return index >= 0 ? snapshot.items[index] : null;\n };\n\n // `null` means the edit failed. Otherwise the selection becomes\n // `nextSelection` now, and again when this source comes back as `value`;\n // any other new `value` clears it (`useStructuralSelection`).\n const commit = (\n snapshot: Snapshot,\n next: string | null,\n nextIds: string[] | undefined,\n nextSelection: Set<number>,\n ) => {\n if (next === null) {\n reportError({\n type: 'items',\n title: messages.editErrors.itemUpdateFailed,\n description: messages.editErrors.itemUpdateFailedDetail,\n });\n\n return false;\n }\n\n const parsed = parseSource(next);\n const nextItems =\n kind === 'primitive' ? parsed.primitiveItems : parsed.objectItems;\n const ids = nextIds ?? snapshot.ids;\n\n pending.write({\n from: value,\n value: next,\n ids,\n selected: nextSelection,\n });\n setIdentityState(createIdentityState(next, kind, nextItems, ids));\n record(nextSelection, revision => revision === next, { now: true });\n onChange?.(next);\n\n return true;\n };\n\n // Selection indices count visible items; the AST functions take array\n // positions. Converting keeps hidden items from being lost.\n const elementIndicesOf = (snapshot: Snapshot, indices: Set<number>) =>\n new Set(\n snapshot.items\n .filter(item => indices.has(item.index))\n .map(item => item.elementIndex),\n );\n\n const updateProperty = (\n elementIndex: number,\n propertyKey: string,\n next: unknown,\n ) => {\n const snapshot = latest();\n const item = locate(snapshot, elementIndex);\n\n if (item === null) {\n return;\n }\n\n // A value edit moves nothing, so the selection stands.\n commit(\n snapshot,\n updateArrayItemProperty(\n snapshot.value,\n item?.elementIndex ?? elementIndex,\n propertyKey,\n next,\n render,\n ),\n undefined,\n new Set(snapshot.selected),\n );\n };\n\n const updateValue = (elementIndex: number, next: unknown) => {\n const snapshot = latest();\n const item = locate(snapshot, elementIndex);\n\n if (item === null) {\n return;\n }\n\n commit(\n snapshot,\n updateArrayItemValue(\n snapshot.value,\n item?.elementIndex ?? elementIndex,\n next,\n ),\n undefined,\n new Set(snapshot.selected),\n );\n };\n\n const actions: DndItemsActions = {\n add: () => {\n const snapshot = latest();\n const next = appendArrayItem(snapshot.value, kind);\n\n commit(\n snapshot,\n next,\n next ? [...snapshot.ids, nanoid(6)] : undefined,\n selectionAfter(\n { type: 'append' },\n snapshot.selected,\n snapshot.items.length,\n ),\n );\n },\n\n move: (elementIndex, toIndex) => {\n const snapshot = latest();\n const from = locate(snapshot, elementIndex);\n const target = snapshot.items.find(item => item.index === toIndex);\n\n if (!from || !target) {\n return;\n }\n\n // A move shifts positions, so clear the selection rather than leave it\n // on other items (#285).\n commit(\n snapshot,\n moveArrayItem(snapshot.value, from.elementIndex, target.elementIndex),\n moveId(snapshot.ids, from.index, target.index),\n new Set(),\n );\n },\n\n remove: elementIndex => {\n const snapshot = latest();\n const removed = locate(snapshot, elementIndex);\n\n if (removed === null) {\n return;\n }\n\n // A removal shifts later positions too, so clear the selection.\n commit(\n snapshot,\n removeArrayItems(\n snapshot.value,\n new Set([removed?.elementIndex ?? elementIndex]),\n kind,\n ),\n removed ? removeIds(snapshot.ids, new Set([removed.index])) : undefined,\n new Set(),\n );\n },\n\n duplicateSelected: () => {\n const snapshot = latest();\n const selected = elementIndicesOf(snapshot, snapshot.selected);\n const next = duplicateArrayItems(snapshot.value, selected);\n const copied = snapshot.items\n .filter(item => selected.has(item.elementIndex))\n .sort((a, b) => a.elementIndex - b.elementIndex)\n .map(() => nanoid(6));\n\n commit(\n snapshot,\n next,\n next ? [...snapshot.ids, ...copied] : undefined,\n selectionAfter(\n { type: 'duplicate', indices: [...snapshot.selected] },\n snapshot.selected,\n snapshot.items.length,\n ),\n );\n },\n\n moveSelected: direction => {\n const snapshot = latest();\n const nextIdentity = moveSelectedIndices(\n snapshot.ids,\n snapshot.selected,\n direction,\n );\n const result = moveArrayItems(\n snapshot.value,\n elementIndicesOf(snapshot, snapshot.selected),\n direction,\n );\n\n if (!result) {\n commit(snapshot, null, undefined, snapshot.selected);\n return;\n }\n\n // Translate the moved source positions back into the visible kind.\n const parsed = parseArrayExpression(result.code);\n const visible =\n parsed?.elements.flatMap((node, index) =>\n t.isExpression(node) && t.isObjectExpression(node) === !isPrimitive\n ? [index]\n : [],\n ) ?? [];\n // The moved block, mapped back from element positions: in a mixed\n // array a step can pass a hidden element, so this is not the same as\n // shifting the visible indices.\n commit(\n snapshot,\n result.code,\n nextIdentity.items,\n new Set(\n visible.flatMap((position, index) =>\n result.indices.has(position) ? [index] : [],\n ),\n ),\n );\n },\n\n removeSelected: () => {\n const snapshot = latest();\n\n commit(\n snapshot,\n removeArrayItems(\n snapshot.value,\n elementIndicesOf(snapshot, snapshot.selected),\n kind,\n ),\n removeIds(snapshot.ids, snapshot.selected),\n new Set(),\n );\n },\n };\n\n // Built every render, outside the memo, because they close over\n // `onChange` and `onNodeChange`. A cheap walk with no parsing.\n const items: DndItemsItem[] = isPrimitive\n ? primitiveItems.map(item => ({\n id: identity.ids[item.index] ?? item.id,\n index: item.index,\n elementIndex: item.elementIndex,\n properties: [],\n nested: [],\n value: {\n id: `primitive-${item.id}`,\n label: `item-${item.index}`,\n property: item.type,\n value: item.value ?? '',\n rawValue:\n item.type === 'unknown' ? item.source : String(item.value ?? ''),\n canEditValue: canLosslesslyEvaluateSource(item.source),\n onChange: next => updateValue(item.elementIndex, next),\n },\n }))\n : objectItems.map(item => {\n const id = identity.ids[item.index] ?? item.id;\n const properties: PanelBinding[] = Object.entries(\n item.editableProperties,\n ).map(([key, prop]) => {\n const binding = resolveRenderEntry(render, key);\n const propertySource = value.slice(\n prop.astNode.start!,\n prop.astNode.end!,\n );\n\n return {\n ...toBindingFields(binding),\n id: `item-${id}-${key}`,\n // Over the leaf's own `meta`, so the property's real type wins\n // over an authored `valueType`.\n meta: { ...binding.meta, valueType: prop.type },\n value: parseValue(String(prop.value)),\n rawValue:\n prop.type === 'unknown' ? propertySource : String(prop.value),\n canEditValue: canLosslesslyEvaluateSource(propertySource),\n onChange: next => updateProperty(item.elementIndex, key, next),\n };\n });\n\n const nested: DndItemsNestedGroup[] = [\n ...Object.entries(item.jsxBindings).map(([property, nodes]) => ({\n property,\n elements: nodes.flatMap(node => {\n const source = resolvePanelBindings(node);\n\n if (!source) {\n return [];\n }\n\n return [\n {\n id: source.id,\n tagName: source.tagName,\n bindings: withPanelCommit(source.bindings, onNodeChange),\n },\n ];\n }),\n })),\n ...Object.entries(item.jsxFallbacks).map(([property, code]) => ({\n property,\n elements: [],\n fallback: {\n id: `item-${id}-${property}-jsx`,\n label: property,\n property,\n type: 'jsx' as const,\n value: code,\n rawValue: code,\n canEditValue: true,\n onChange: (next: unknown) =>\n updateProperty(item.elementIndex, property, next),\n },\n })),\n ];\n\n return {\n id,\n index: item.index,\n elementIndex: item.elementIndex,\n properties,\n nested,\n };\n });\n\n const expansion: DndItemsExpansion = {\n expandedIds: items.flatMap(item =>\n collapsed.has(item.id) ? [] : [item.id],\n ),\n isExpanded: id => !collapsed.has(id),\n toggle: id =>\n setCollapsed(previous => {\n const next = new Set(previous);\n\n if (!next.delete(id)) {\n next.add(id);\n }\n\n return next;\n }),\n setExpanded: ids => {\n const expanded = new Set(ids);\n\n setCollapsed(\n new Set(\n items.flatMap(item => (expanded.has(item.id) ? [] : [item.id])),\n ),\n );\n },\n };\n\n return {\n kind,\n items,\n selection,\n expansion,\n actions,\n canEditStructure,\n parseError,\n };\n};\n","import { Button, Checkbox } from '@jbpark/ui-kit';\nimport { ArrowDown, ArrowUp, Plus, X } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { BindingRenderMap } from '~/utils/ast/types';\n\nimport type { PanelNodeChange } from '../panel-binding';\nimport BulkActionsBar from './bulk-actions-bar';\nimport Field from './field';\nimport { ItemCard, SortableItems } from './sortable-items';\nimport {\n type DndItemsItem,\n type DndItemsNestedGroup,\n useDndItems,\n} from './use-dnd-items';\n\ninterface Props {\n value: string;\n render?: BindingRenderMap;\n onChange?: (value: string) => void;\n onChildChange?: PanelNodeChange;\n}\n\n// The data-bound elements found inside one JSX-valued property, or the\n// raw-source fallback when that property declared no binding at all (#298).\nconst NestedGroup = ({\n group,\n onNodeChange,\n}: {\n group: DndItemsNestedGroup;\n onNodeChange?: PanelNodeChange;\n}) => {\n if (group.fallback) {\n return (\n <div className=\"space-y-2\">\n <div className=\"text-xs font-medium text-blue-700\">\n {group.property}\n </div>\n <Field binding={group.fallback} onNodeChange={onNodeChange} />\n </div>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"text-xs font-medium text-blue-700\">\n {group.property} Bindings ({group.elements.length}):\n </div>\n {group.elements.map(element => (\n <div\n key={`${group.property}-${element.id}`}\n data-node-id={element.id}\n className=\"rounded border border-blue-100 bg-blue-50 p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400\"\n >\n <div className=\"mb-1 text-xs text-blue-600\">\n <{element.tagName}>\n </div>\n <div className=\"space-y-2 rounded\">\n <div className=\"space-y-1\">\n {element.bindings.map(binding => (\n <div\n key={`${binding.property}-${binding.label}`}\n className=\"space-y-1\"\n >\n <label className=\"block text-xs font-semibold text-gray-700\">\n {binding.label}\n <span className=\"ml-1 text-gray-400\">\n ({binding.property})\n </span>\n </label>\n <Field binding={binding} onNodeChange={onNodeChange} />\n </div>\n ))}\n </div>\n </div>\n </div>\n ))}\n </div>\n );\n};\n\n// The built-in Items editor: markup over `useDndItems`, which does all the\n// reading and writing.\nconst Items = ({ value, render, onChange, onChildChange }: Props) => {\n const messages = useLiveMessages();\n const {\n kind,\n items,\n selection,\n expansion,\n actions,\n canEditStructure,\n parseError,\n } = useDndItems(value, {\n render,\n onChange,\n onNodeChange: onChildChange,\n });\n\n const header = (\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm font-semibold\">\n {messages.items.heading(items.length)}\n </div>\n {/* Add copies an existing item, so it is offered only once there is\n one to copy — see the empty-list notice below (#316). */}\n {items.length > 0 && canEditStructure && (\n <Button\n size=\"small\"\n icon={<Plus />}\n variant=\"solid\"\n color=\"green\"\n onClick={actions.add}\n >\n {messages.items.add}\n </Button>\n )}\n </div>\n );\n\n if (parseError) {\n return (\n <div className=\"space-y-4\">\n {header}\n <div\n className=\"rounded border border-dashed border-red-200 p-3 text-xs\n text-red-600\"\n >\n {messages.items.unreadable}\n </div>\n </div>\n );\n }\n\n // No items to copy a shape from. The editor never empties an array, so\n // the source itself has `[]`, or only holes and spreads.\n if (items.length === 0) {\n return (\n <div className=\"space-y-4\">\n {header}\n <div\n className=\"rounded border border-dashed border-gray-200 p-3 text-xs\n text-gray-500\"\n >\n {messages.items.empty}\n </div>\n </div>\n );\n }\n\n const bulkBar = (\n <BulkActionsBar\n count={selection.selected.size}\n disabled={!canEditStructure}\n onDuplicate={actions.duplicateSelected}\n onMoveUp={() => actions.moveSelected('up')}\n onMoveDown={() => actions.moveSelected('down')}\n onDelete={actions.removeSelected}\n onClear={selection.clear}\n />\n );\n\n const itemControls = (item: DndItemsItem) => (\n <div className=\"flex space-x-1\">\n <Button\n size=\"small\"\n icon={<ArrowUp />}\n aria-label={messages.items.moveUp}\n disabled={!canEditStructure || item.index === 0}\n onClick={() => actions.move(item.elementIndex, item.index - 1)}\n />\n <Button\n size=\"small\"\n icon={<ArrowDown />}\n aria-label={messages.items.moveDown}\n disabled={!canEditStructure || item.index === items.length - 1}\n onClick={() => actions.move(item.elementIndex, item.index + 1)}\n />\n <Button\n danger\n size=\"small\"\n icon={<X />}\n aria-label={messages.items.delete}\n disabled={!canEditStructure || items.length <= 1}\n onClick={() => actions.remove(item.elementIndex)}\n />\n </div>\n );\n\n const itemCheckbox = (item: DndItemsItem) => (\n <div\n onClick={e =>\n canEditStructure && selection.toggle(item.index, e.shiftKey)\n }\n className=\"inline-flex\"\n >\n <Checkbox\n checked={selection.isSelected(item.index)}\n disabled={!canEditStructure}\n onChange={() => {}}\n />\n </div>\n );\n\n const objectBody = (item: DndItemsItem) => (\n <>\n <div className=\"space-y-2\">\n {item.properties.map(binding => (\n <div key={`${item.id}-${binding.property}-${binding.label}`}>\n <div className=\"flex flex-col space-y-2\">\n <label className=\"w-20 shrink-0 text-xs font-medium\">\n {binding.label}\n </label>\n <Field binding={binding} onNodeChange={onChildChange} />\n </div>\n <span className=\"text-right text-xs text-gray-500\">\n ({String(binding.meta?.valueType)})\n </span>\n </div>\n ))}\n </div>\n <div className=\"space-y-3 border-t pt-2\">\n {item.nested.length ? (\n item.nested.map(group => (\n <NestedGroup\n key={group.property}\n group={group}\n onNodeChange={onChildChange}\n />\n ))\n ) : (\n <div className=\"text-xs text-gray-500\">\n <span aria-hidden=\"true\">✓</span> {messages.items.noNestedBindings}\n </div>\n )}\n </div>\n </>\n );\n\n const allExpanded = expansion.expandedIds.length === items.length;\n\n return (\n <div className=\"space-y-4\">\n {header}\n\n {items.length > 1 && (\n <div className=\"flex justify-end\">\n <Button\n size=\"small\"\n variant=\"text\"\n onClick={() =>\n expansion.setExpanded(\n allExpanded ? [] : items.map(item => item.id),\n )\n }\n >\n {allExpanded\n ? messages.items.collapseAll\n : messages.items.expandAll}\n </Button>\n </div>\n )}\n\n {bulkBar}\n\n {!canEditStructure && (\n <div\n className=\"rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700\"\n >\n {messages.items.structureLocked}\n </div>\n )}\n\n <SortableItems\n items={items}\n disabled={!canEditStructure}\n onMove={(item, toIndex) => actions.move(item.elementIndex, toIndex)}\n >\n {item => (\n <ItemCard\n key={item.id}\n id={item.id}\n title={messages.items.item(item.index + 1)}\n disabled={!canEditStructure}\n expanded={expansion.isExpanded(item.id)}\n onToggle={() => expansion.toggle(item.id)}\n checkbox={itemCheckbox(item)}\n controls={itemControls(item)}\n className={\n kind === 'primitive'\n ? 'space-y-2 rounded border border-gray-100 bg-gray-50 p-2'\n : 'space-y-3 rounded border bg-gray-50 p-3'\n }\n >\n {kind === 'primitive' ? (\n <Field binding={item.value!} onNodeChange={onChildChange} />\n ) : (\n objectBody(item)\n )}\n </ItemCard>\n )}\n </SortableItems>\n </div>\n );\n};\n\nexport default Items;\n","import {\n type ComponentProps,\n type FocusEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport {\n Checkbox,\n ColorPicker,\n DatePicker,\n Input,\n RichTextEditor,\n Select,\n} from '@jbpark/ui-kit';\nimport { useDebounce } from '@jbpark/use-hooks';\nimport type {\n EditorSelection,\n EditorView,\n ViewUpdate,\n} from '@uiw/react-codemirror';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport CoreEditor from '~/components/editor/core';\nimport { type DataAttrNode } from '~/utils/ast/types';\nimport { validateBindingValue } from '~/utils/ast/validate';\nimport { parseValue } from '~/utils/ast/value';\n\nimport { useDndEditOptions } from '../edit-options';\nimport type { PanelBinding, PanelNodeChange } from '../panel-binding';\nimport { resolveRenderEntry, toBindingFields } from '../panel-binding';\nimport Children from './children';\nimport { getFieldKind } from './field-kind';\nimport Items from './items';\n\n// Props of `Live.Dnd.Field`, the built-in control for one binding. A custom\n// panel can use it for any binding, most usefully `items` and `children`,\n// whose editors find nested elements. Renders the control only; supply\n// your own label.\nexport interface FieldProps {\n binding: PanelBinding;\n // Commits edits to elements other than `binding`'s own, which the Items\n // and Children editors make. Pass `useDndPanel().onNodeChange`; without it,\n // edits inside those values aren't saved (#308).\n onNodeChange?: PanelNodeChange;\n}\n\nconst normalizeToHex = (value: string): string => {\n const trimmed = value.trim();\n\n if (/^#([0-9A-Fa-f]{3}){1,2}$/.test(trimmed)) {\n return trimmed;\n }\n return '#000000';\n};\n\nconst parseDateValue = (value: string): Date | undefined => {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value.trim());\n\n if (!match) {\n return undefined;\n }\n\n const [, year, month, day] = match;\n const date = new Date(Number(year), Number(month) - 1, Number(day));\n\n return Number.isNaN(date.getTime()) ? undefined : date;\n};\n\nconst formatDateValue = (date: Date): string => {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${year}-${month}-${day}`;\n};\n\n// The color picker reports every drag frame, and each commit re-parses and\n// recompiles (#130). So the commit waits this long after the last change,\n// while `liveValue` updates the swatch every frame.\nconst COLOR_COMMIT_DELAY = 75;\n\n// The formatting controls for a small sidebar field, not every preset.\nconst RICHTEXT_TOOLBAR: ComponentProps<typeof RichTextEditor>['toolbar'] = [\n 'bold',\n 'italic',\n 'underline',\n 'bulletList',\n 'orderedList',\n 'link',\n];\n\ninterface ColorPickerFieldProps {\n value: string;\n onChange: (value: string) => void;\n}\n\ninterface JSXEditorFieldProps {\n value: string;\n isHTML: boolean;\n onSave: (value: string) => void;\n}\n\n// Keeps focus and selection when CodeMirror recreates its view, which\n// `@uiw/react-codemirror` does when a moved item's effects reconnect under\n// Strict Effects (#359).\nconst JSXEditorField = ({ value, isHTML, onSave }: JSXEditorFieldProps) => {\n const selectionRef = useRef<EditorSelection | null>(null);\n const focusedRef = useRef(false);\n\n const handleUpdate = useCallback((update: ViewUpdate) => {\n selectionRef.current = update.state.selection;\n }, []);\n\n const handleCreateEditor = useCallback((view: EditorView) => {\n if (selectionRef.current) {\n view.dispatch({ selection: selectionRef.current });\n }\n\n if (focusedRef.current) {\n view.focus();\n }\n }, []);\n\n const handleFocus = useCallback(() => {\n focusedRef.current = true;\n }, []);\n\n const handleBlur = useCallback((event: FocusEvent<HTMLDivElement>) => {\n if (\n event.relatedTarget &&\n !event.currentTarget.contains(event.relatedTarget as Node)\n ) {\n focusedRef.current = false;\n }\n }, []);\n\n return (\n <div onFocusCapture={handleFocus} onBlurCapture={handleBlur}>\n <CoreEditor\n value={value}\n height=\"150px\"\n fragment={!isHTML}\n raw={isHTML}\n onSave={onSave}\n onUpdate={handleUpdate}\n onCreateEditor={handleCreateEditor}\n />\n </div>\n );\n};\n\nconst ColorPickerField = ({ value, onChange }: ColorPickerFieldProps) => {\n const [liveValue, setLiveValue] = useState(value);\n // The last `value` seen, to notice a change from outside during render.\n const [prevValue, setPrevValue] = useState(value);\n const lastCommittedRef = useRef(value);\n\n // Follow a change from outside, such as undo or another field. Done\n // during render, so the old color never paints.\n if (value !== prevValue) {\n setPrevValue(value);\n setLiveValue(value);\n }\n\n // `commit` reads this from handlers and timers only, so an effect is\n // enough.\n useEffect(() => {\n lastCommittedRef.current = value;\n }, [value]);\n\n const commit = (next: string) => {\n if (next === lastCommittedRef.current) {\n return;\n }\n lastCommittedRef.current = next;\n onChange(next);\n };\n\n const debouncedCommit = useDebounce(() => commit(liveValue), {\n delay: COLOR_COMMIT_DELAY,\n autoInvoke: false,\n });\n\n return (\n <ColorPicker\n showText\n value={liveValue}\n onChange={next => {\n setLiveValue(next);\n debouncedCommit();\n }}\n onOpenChange={open => {\n // Commit at once when the picker closes, so an unmount can't drop\n // the last color.\n if (!open) {\n commit(liveValue);\n }\n }}\n />\n );\n};\n\n// `mb-0` matters: `dist/style.css` has no CSS reset, so without it a `<p>`\n// keeps the browser's bottom margin and the fields below jump when the\n// error appears (#409).\nconst FieldError = ({ message }: { message: string | null }) =>\n message ? <p className=\"mt-1 mb-0 text-xs text-red-500\">{message}</p> : null;\n\nconst BuiltinField = ({ binding, onNodeChange }: FieldProps) => {\n const messages = useLiveMessages();\n const validationOptions = { messages: messages.validation };\n // `value` is the JS value; `rawValue` is the source text, for the text\n // controls and the source editors (#238).\n const { id, value, rawValue, onChange } = binding;\n\n const [validationError, setValidationError] = useState<string | null>(null);\n\n // What the user is typing, for the inputs that commit on blur (url,\n // number, text area). Reset during render when `rawValue` changes from outside,\n // such as undo, so the old text isn't committed on blur (#284).\n const [text, setText] = useState(rawValue);\n const [prevRawValue, setPrevRawValue] = useState(rawValue);\n\n if (rawValue !== prevRawValue) {\n setPrevRawValue(rawValue);\n setText(rawValue);\n }\n\n const kind = getFieldKind(binding);\n\n if (kind === 'readonly') {\n return (\n <div\n className=\"space-y-1 rounded border border-dashed border-amber-200 p-3\n text-xs text-amber-700\"\n >\n <div>{messages.panel.expressionPreserved}</div>\n <code className=\"block overflow-x-auto text-amber-800\">{rawValue}</code>\n <div>{messages.panel.useCodeEditor}</div>\n </div>\n );\n }\n\n // Skips a commit that doesn't change anything, comparing a string with\n // `rawValue` and anything else with `value`.\n const commitIfChanged = (next: unknown) => {\n const current = typeof next === 'string' ? rawValue : value;\n\n if (next !== current) {\n onChange(next);\n }\n };\n\n if (kind === 'items') {\n return (\n <Items\n value={rawValue}\n render={binding.render}\n onChange={onChange}\n onChildChange={onNodeChange}\n />\n );\n }\n\n if (kind === 'richtext') {\n return (\n <RichTextEditor\n value={rawValue}\n toolbar={RICHTEXT_TOOLBAR}\n onChange={commitIfChanged}\n />\n );\n }\n\n if (kind === 'html' || kind === 'jsx') {\n return (\n <JSXEditorField\n value={rawValue}\n isHTML={kind === 'html'}\n onSave={commitIfChanged}\n />\n );\n }\n\n if (kind === 'children') {\n return (\n <Children\n value={value as DataAttrNode[]}\n onChange={onChange}\n onNodeChange={onNodeChange}\n />\n );\n }\n\n if (kind === 'object') {\n const objectValue = value as Record<string, unknown>;\n\n return (\n <div className=\"space-y-2 rounded border border-gray-200 bg-gray-50 p-2\">\n {Object.entries(objectValue).map(([key, val]) => {\n const nested = resolveRenderEntry(binding.render, key);\n\n return (\n <div key={key} className=\"space-y-1\">\n <label className=\"block text-xs font-medium text-gray-600\">\n {nested.label}\n </label>\n <Field\n binding={{\n ...toBindingFields(nested),\n id,\n value: val,\n rawValue:\n typeof val === 'object' && val !== null\n ? JSON.stringify(val)\n : String(val),\n onChange: next => {\n onChange({ ...objectValue, [key]: next });\n },\n }}\n onNodeChange={onNodeChange}\n />\n </div>\n );\n })}\n </div>\n );\n }\n\n if (kind === 'boolean') {\n return (\n <Checkbox\n checked={value === true || value === 'true'}\n onChange={checked => {\n onChange(checked);\n }}\n />\n );\n }\n\n const stringValue = rawValue;\n\n if (kind === 'select') {\n return (\n <Select\n value={stringValue}\n options={binding.options ?? []}\n onChange={commitIfChanged}\n />\n );\n }\n\n if (kind === 'color') {\n return (\n <ColorPickerField\n value={normalizeToHex(stringValue)}\n onChange={commitIfChanged}\n />\n );\n }\n\n if (kind === 'date') {\n return (\n <div>\n <DatePicker\n value={parseDateValue(stringValue)}\n onChange={date => {\n const next = date ? formatDateValue(date) : '';\n const result = validateBindingValue(\n binding,\n next,\n validationOptions,\n );\n\n if (!result.valid) {\n setValidationError(result.message ?? messages.panel.invalidValue);\n return;\n }\n\n setValidationError(null);\n\n commitIfChanged(next);\n }}\n />\n <FieldError message={validationError} />\n </div>\n );\n }\n\n if (kind === 'url') {\n return (\n <div>\n <Input\n type=\"url\"\n value={text}\n onChange={e => setText(e.target.value)}\n placeholder={messages.panel.urlPlaceholder}\n onBlur={e => {\n const next = e.target.value.trim();\n const result = validateBindingValue(\n binding,\n next,\n validationOptions,\n );\n\n if (!result.valid) {\n setValidationError(result.message ?? messages.panel.invalidValue);\n return;\n }\n\n setValidationError(null);\n\n commitIfChanged(next);\n }}\n />\n <FieldError message={validationError} />\n </div>\n );\n }\n\n if (kind === 'number') {\n return (\n <div>\n <Input\n type=\"number\"\n value={text}\n onChange={e => setText(e.target.value)}\n placeholder={messages.panel.numberPlaceholder}\n onBlur={e => {\n const raw = e.target.value.trim();\n // Commit a number, not a numeric string, as `update` and\n // `validateBindingValue` expect. Text that isn't a number is\n // committed as is rather than as `NaN`.\n const next: unknown =\n raw !== '' && !Number.isNaN(Number(raw)) ? Number(raw) : raw;\n const result = validateBindingValue(\n binding,\n next,\n validationOptions,\n );\n\n if (!result.valid) {\n setValidationError(result.message ?? messages.panel.invalidValue);\n return;\n }\n\n setValidationError(null);\n\n commitIfChanged(next);\n }}\n />\n <FieldError message={validationError} />\n </div>\n );\n }\n\n return (\n <div>\n <Input.TextArea\n value={text}\n onChange={e => setText(e.target.value)}\n placeholder={messages.panel.textPlaceholder}\n onBlur={e => {\n const raw = e.target.value.trim();\n // An untyped field reads the text as a value, so `42` commits as a\n // number. A declared type keeps the text as typed.\n const next: unknown = binding.type ? raw : parseValue(raw);\n const result = validateBindingValue(binding, next, validationOptions);\n\n if (!result.valid) {\n setValidationError(result.message ?? messages.panel.invalidValue);\n return;\n }\n\n setValidationError(null);\n\n commitIfChanged(next);\n }}\n />\n <FieldError message={validationError} />\n </div>\n );\n};\n\n// `Live.Dnd.Field`: the host's `renderField` first, then the built-in\n// control. Nested object keys and item properties render `Field` too, so\n// `renderField` reaches every field.\nconst Field = (props: FieldProps) => {\n const { renderField } = useDndEditOptions();\n const builtin = <BuiltinField {...props} />;\n\n if (!renderField) {\n return builtin;\n }\n\n const custom = renderField(props, builtin);\n\n return custom === undefined ? builtin : <>{custom}</>;\n};\n\nexport default Field;\n","import type { PanelBinding, PanelNodeChange } from '../panel-binding';\nimport Field from './field';\n\ninterface Props {\n bindings: PanelBinding[];\n onNodeChange?: PanelNodeChange;\n}\n\n// The fields of one element, from `PanelBinding`s. `Node` draws the same\n// for an extracted node, as the Children editor has.\nconst FieldGroup = ({ bindings, onNodeChange }: Props) => (\n <div className=\"space-y-2 rounded\">\n <div className=\"space-y-1\">\n {bindings.map(binding => (\n <div key={`${binding.property}-${binding.label}`} className=\"space-y-1\">\n <label className=\"block text-xs font-semibold text-gray-700\">\n {binding.label}\n <span className=\"ml-1 text-gray-400\">({binding.property})</span>\n </label>\n <Field binding={binding} onNodeChange={onNodeChange} />\n </div>\n ))}\n </div>\n </div>\n);\n\nexport default FieldGroup;\n","import { useContext, useEffect, useRef, useState } from 'react';\n\nimport { Button, Typography } from '@jbpark/ui-kit';\nimport { ChevronDown, ChevronUp, Trash } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { Section } from '~/types';\nimport { cn } from '~/utils/cn';\n\nimport { DndInspectorContext } from '../inspector';\nimport type { PanelBinding, PanelNodeChange } from '../panel-binding';\nimport FieldGroup from './field-group';\n\n// Props of the built-in property panel, which `Live.Dnd.Panel` renders from\n// `useDndPanel()`. They match that hook's fields, so the built-in panel and\n// a custom one use the same data (#237). Without `onNodeChange`, edits\n// inside `items` and `children` values aren't saved (#308).\nexport interface PanelProps {\n item?: Section;\n onDelete?: (id: string) => void;\n // Move the section. On mobile the panel covers the canvas, so these\n // replace dragging there.\n onMoveUp?: () => void;\n onMoveDown?: () => void;\n canMoveUp?: boolean;\n canMoveDown?: boolean;\n // `item`'s editable fields, the same `bindings` a custom panel gets\n // (#237).\n bindings: PanelBinding[];\n onNodeChange?: PanelNodeChange;\n // The document doesn't parse, so these fields are from the last version\n // that did and edits are refused (#433).\n readOnly?: boolean;\n}\n\n// Groups the flat `bindings` by element `id`, keeping their order, for one\n// box per element. Not memoized: `bindings` is new every render (#336),\n// and the walk is cheap.\nconst groupBindingsById = (bindings: PanelBinding[]): PanelBinding[][] => {\n const groups = new Map<string, PanelBinding[]>();\n\n for (const binding of bindings) {\n const group = groups.get(binding.id);\n\n if (group) {\n group.push(binding);\n } else {\n groups.set(binding.id, [binding]);\n }\n }\n\n return [...groups.values()];\n};\n\n// How a group's header names its element: the tag name, and its text when it\n// has some. Also the group's accessible name.\nconst describeElement = (binding: PanelBinding) => {\n const { tagName = 'element', text = '' } = binding.element ?? {};\n\n return { tagName, text, label: text ? `${tagName} \"${text}\"` : tagName };\n};\n\n// The element a panel event happened in: the nearest group or nested\n// element marked with `data-node-id`.\nconst nodeIdOf = (target: EventTarget | null) =>\n (target instanceof Element &&\n target.closest('[data-node-id]')?.getAttribute('data-node-id')) ||\n null;\n\nconst Panel = ({\n item,\n onDelete,\n onMoveUp,\n onMoveDown,\n canMoveUp = false,\n canMoveDown = false,\n bindings,\n onNodeChange,\n readOnly = false,\n}: PanelProps) => {\n const messages = useLiveMessages();\n const groups = groupBindingsById(bindings);\n const rootRef = useRef<HTMLDivElement>(null);\n // Read without the throwing hook: this panel also renders outside\n // `Live.Dnd`, read-only, where there's no picker.\n const inspector = useContext(DndInspectorContext);\n const picked = inspector?.picked ?? null;\n const pickedId = picked?.id;\n const highlight = inspector?.highlight;\n // The element under the pointer wins over the focused one, so moving the\n // pointer over another group shows that one while typing in a field.\n const [hoveredId, setHoveredId] = useState<string | null>(null);\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const targetId = hoveredId ?? focusedId;\n\n // Outlines on the canvas the element the field under the pointer or focus\n // edits, so fields that share a label can be told apart (#514).\n useEffect(() => {\n if (!highlight) {\n return;\n }\n\n highlight(targetId);\n\n return () => highlight(null);\n }, [highlight, targetId]);\n\n // Brings the fields of an element picked in the preview into view and\n // marks them, whether they're a top-level group or nested in an Items or\n // Children editor (#432). A collapsed array item hides its nested fields,\n // so there's nothing to scroll to then.\n useEffect(() => {\n const root = rootRef.current;\n\n if (!root || !pickedId) {\n return;\n }\n\n const target = root.querySelector(\n `[data-node-id=\"${CSS.escape(pickedId)}\"]`,\n );\n\n if (!target) {\n return;\n }\n\n target.setAttribute('data-picked', '');\n\n // Fields above the target can still grow for a moment after it renders\n // (a rich-text editor mounting, for one), pushing it back out of view.\n // So keep it in view for the first few hundred milliseconds.\n const until = performance.now() + 600;\n let frame = 0;\n\n const keepInView = () => {\n const box = target.getBoundingClientRect();\n const view = root.getBoundingClientRect();\n\n if (box.top < view.top || box.bottom > view.bottom) {\n target.scrollIntoView?.({ block: 'nearest' });\n }\n\n if (performance.now() < until) {\n frame = requestAnimationFrame(keepInView);\n }\n };\n\n keepInView();\n\n return () => {\n cancelAnimationFrame(frame);\n target.removeAttribute('data-picked');\n };\n }, [pickedId, groups.length]);\n\n if (!item) {\n return (\n <Typography.Paragraph\n className={cn(\n 'p-4 text-sm text-gray-500',\n //\n )}\n >\n {messages.panel.selectSection}\n </Typography.Paragraph>\n );\n }\n\n return (\n <div\n ref={rootRef}\n onPointerOver={e => setHoveredId(nodeIdOf(e.target))}\n onPointerLeave={() => setHoveredId(null)}\n onFocus={e => setFocusedId(nodeIdOf(e.target))}\n onBlur={e => {\n if (!e.currentTarget.contains(e.relatedTarget)) {\n setFocusedId(null);\n }\n }}\n className={cn(\n 'h-full space-y-4 p-4',\n 'overflow-x-hidden overflow-y-auto',\n //\n )}\n >\n <div className=\"flex items-center justify-between\">\n <Typography.Title className=\"text-lg font-semibold\">\n {item.name}\n </Typography.Title>\n <div className=\"flex items-center gap-1\">\n {onMoveUp && (\n <Button\n icon={<ChevronUp />}\n disabled={!canMoveUp}\n onClick={onMoveUp}\n aria-label={messages.section.moveUp}\n />\n )}\n {onMoveDown && (\n <Button\n icon={<ChevronDown />}\n disabled={!canMoveDown}\n onClick={onMoveDown}\n aria-label={messages.section.moveDown}\n />\n )}\n {onDelete && (\n <Button\n danger\n icon={<Trash />}\n onClick={() => onDelete(item.id)}\n aria-label={messages.section.delete}\n />\n )}\n </div>\n </div>\n {readOnly && (\n <Typography.Text role=\"status\" className=\"block text-xs text-amber-700\">\n {messages.panel.readOnly}\n </Typography.Text>\n )}\n {!groups.length && (\n <Typography.Text className=\"text-xs text-gray-400\">\n {messages.panel.noEditableElements}\n </Typography.Text>\n )}\n {groups.map(group => {\n const element = describeElement(group[0]!);\n\n return (\n <div\n key={group[0]!.id}\n data-node-id={group[0]!.id}\n role=\"group\"\n aria-label={element.label}\n className=\"rounded data-[picked]:ring-2 data-[picked]:ring-blue-400\n data-[picked]:ring-offset-2\"\n >\n {/* Only needed once fields of more than one element share the\n panel; a single element reads the same as before (#514). */}\n {groups.length > 1 && (\n <div\n className=\"mb-2 flex min-w-0 items-baseline gap-1.5 border-b\n border-gray-100 pb-1 text-xs\"\n >\n <code className=\"shrink-0 text-gray-500\">\n {element.tagName}\n </code>\n {element.text && (\n <span className=\"truncate text-gray-400\">{element.text}</span>\n )}\n </div>\n )}\n <FieldGroup bindings={group} onNodeChange={onNodeChange} />\n </div>\n );\n })}\n </div>\n );\n};\n\nexport default Panel;\n","import { Button, Drawer, Space, Splitter } from '@jbpark/ui-kit';\nimport { Crosshair, LayoutGrid } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport { useDndInspector } from './inspector';\nimport { useDndRegions } from './layout-context';\nimport { DefaultDraggableItem } from './palette/draggable';\nimport PropertyPanel from './panel';\n\n// A region's props: everything a `div` takes except `children`, which comes\n// from context. `className` is merged over the defaults, so yours wins.\nexport type DndRegionProps = Omit<\n React.ComponentPropsWithRef<'div'>,\n 'children'\n>;\n\n// The built-in palette and panel without their region wrapper, for the\n// mobile Drawers, which are already the scroll container.\nconst PaletteItems = ({ subject }: { subject: string }) => {\n const {\n palette: { items, onAdd },\n isMobile,\n } = useDndRegions(subject);\n\n return (\n <Space orientation=\"vertical\" align=\"start\">\n {items.map(item => (\n <DefaultDraggableItem\n key={item.id}\n item={item}\n onAdd={onAdd}\n tapToAdd={isMobile}\n />\n ))}\n </Space>\n );\n};\n\nconst PanelFields = ({ subject }: { subject: string }) => {\n const {\n panel: {\n item,\n onDelete,\n onMoveUp,\n onMoveDown,\n canMoveUp,\n canMoveDown,\n bindings,\n onNodeChange,\n readOnly,\n },\n } = useDndRegions(subject);\n\n return (\n <PropertyPanel\n item={item}\n onDelete={onDelete}\n onMoveUp={onMoveUp}\n onMoveDown={onMoveDown}\n canMoveUp={canMoveUp}\n canMoveDown={canMoveDown}\n bindings={bindings}\n onNodeChange={onNodeChange}\n readOnly={readOnly}\n />\n );\n};\n\n// The built-in palette in its scroll container. To replace it, put your\n// own component in `Layout`'s `palette` slot or anywhere in `Live.Dnd`'s\n// children, and read `useDndPalette()`.\nexport const Palette = ({ className, ...restProps }: DndRegionProps) => (\n <div\n className={cn(\n 'h-full overflow-y-auto bg-gray-50 p-4',\n className,\n //\n )}\n {...restProps}\n >\n <PaletteItems subject=\"<Live.Dnd.Palette>\" />\n </div>\n);\n\n// The canvas in its scroll container, which each section's iframe sizes\n// itself against (`data-frame-container`), with the styles that keep a\n// section's CSS out of the editor. Needs a parent with a fixed height.\n// Render it exactly once: the drop area and sortable list inside use fixed\n// ids.\nexport const Canvas = ({ className, style, ...restProps }: DndRegionProps) => {\n const { canvas, documentError } = useDndRegions('<Live.Dnd.Canvas>');\n const inspector = useDndInspector();\n const messages = useLiveMessages();\n\n return (\n <div\n className={cn(\n 'relative h-full w-full overflow-y-auto',\n className,\n //\n )}\n data-frame-container\n style={{\n isolation: 'isolate',\n contain: 'layout style',\n transform: 'translateZ(0)',\n ...style,\n }}\n {...restProps}\n >\n {canvas}\n {/* The element picker's switch (#432). Pinned to the bottom-left of\n the scroll area, clear of the selected section's own buttons at its\n top-right and of the mobile palette button at the bottom-right. */}\n {!documentError && (\n <div className=\"pointer-events-none sticky bottom-0 z-70 h-0\">\n <div className=\"pointer-events-auto absolute bottom-3 left-3\">\n <Button\n icon={<Crosshair />}\n color=\"primary\"\n variant={inspector.active ? 'solid' : 'outlined'}\n aria-pressed={inspector.active}\n aria-label={messages.canvas.pickElement}\n title={\n inspector.active\n ? messages.canvas.pickElementActive\n : messages.canvas.pickElement\n }\n onClick={inspector.toggle}\n />\n </div>\n </div>\n )}\n </div>\n );\n};\n\n// The built-in property panel. Replace it like `Palette`, through\n// `Layout`'s `panel` slot or `Live.Dnd`'s children, reading `useDndPanel()`.\nexport const Panel = ({ className, ...restProps }: DndRegionProps) => (\n <div\n className={cn(\n 'h-full',\n className,\n //\n )}\n {...restProps}\n >\n <PanelFields subject=\"<Live.Dnd.Panel>\" />\n </div>\n);\n\nexport interface DndLayoutProps {\n // Your own palette or panel in place of the built-in one, keeping the\n // rest of the layout. A slot is placed as is and brings its own\n // container. Read `useDndPalette()` / `useDndPanel()` in it.\n palette?: React.ReactNode;\n panel?: React.ReactNode;\n}\n\n// What `Live.Dnd` renders without children: a three-pane Splitter on\n// desktop, and on mobile the canvas with a button and Drawers.\nexport const Layout = ({ palette, panel }: DndLayoutProps) => {\n const { isMobile, selectedId, clearSelection, paletteOpen, setPaletteOpen } =\n useDndRegions('<Live.Dnd.Layout>');\n const messages = useLiveMessages();\n\n return (\n <>\n {isMobile ? (\n <Canvas />\n ) : (\n <Splitter withHandle orientation=\"horizontal\">\n <Splitter.Panel\n defaultSize=\"20%\"\n minSize=\"15%\"\n maxSize=\"35%\"\n collapsible\n >\n {palette ?? <Palette />}\n </Splitter.Panel>\n <Splitter.Panel defaultSize=\"60%\">\n <Canvas />\n </Splitter.Panel>\n <Splitter.Panel\n defaultSize=\"20%\"\n minSize=\"15%\"\n maxSize=\"35%\"\n collapsible\n >\n {panel ?? <Panel />}\n </Splitter.Panel>\n </Splitter>\n )}\n <Button\n type=\"primary\"\n shape=\"circle\"\n icon={<LayoutGrid />}\n aria-label={messages.canvas.palette}\n className=\"fixed right-4 bottom-4 z-20 md:hidden\"\n onClick={() => setPaletteOpen(true)}\n />\n {/* A slot goes in as-is; the built-ins go in without their region\n wrapper, since the Drawer is already the scroll container and the\n palette's gray background belongs to the desktop pane. */}\n <Drawer\n open={isMobile && paletteOpen}\n onClose={() => setPaletteOpen(false)}\n direction=\"bottom\"\n size=\"large\"\n title={messages.canvas.palette}\n >\n {palette ?? <PaletteItems subject=\"<Live.Dnd.Layout>\" />}\n </Drawer>\n <Drawer\n open={isMobile && Boolean(selectedId)}\n onClose={clearSelection}\n direction=\"bottom\"\n size=\"large\"\n title={messages.canvas.properties}\n >\n {panel ?? <PanelFields subject=\"<Live.Dnd.Layout>\" />}\n </Drawer>\n </>\n );\n};\n\nexport default Layout;\n","import { useEffect, useRef } from 'react';\n\nimport type { Section } from '~/types';\n\ninterface Options {\n sections: Section[];\n remove: (id: string) => void;\n onBeforeDelete?: (section: Section) => boolean | Promise<boolean>;\n}\n\n// Returns the function that deletes a section, from the canvas, the panel\n// or a custom panel's `onDelete`. It asks `onBeforeDelete` first, when\n// there is one. Its optional `onDeleted` runs only once the section is\n// gone (#435).\nexport const useDeleteFlow = ({\n sections,\n remove,\n onBeforeDelete,\n}: Options) => {\n // Read through a ref after an async `onBeforeDelete`: the document can\n // change while a confirmation is open, and an old `remove` would commit\n // against the old one.\n const removeRef = useRef(remove);\n\n useEffect(() => {\n removeRef.current = remove;\n });\n\n return (id: string, onDeleted?: () => void) => {\n const section = sections.find(candidate => candidate.id === id);\n\n if (!onBeforeDelete || !section) {\n remove(id);\n onDeleted?.();\n\n return;\n }\n\n const decide = (allowed: boolean) => {\n if (allowed) {\n removeRef.current(id);\n onDeleted?.();\n }\n };\n\n try {\n const answer = onBeforeDelete(section);\n\n if (typeof answer === 'boolean') {\n decide(answer);\n\n return;\n }\n\n answer.then(decide, error => {\n console.error('onBeforeDelete rejected; the section was kept', error);\n });\n } catch (error) {\n console.error('onBeforeDelete threw; the section was kept', error);\n }\n };\n};\n","import { useEffect, useState } from 'react';\n\nimport {\n type Announcements,\n KeyboardSensor,\n PointerSensor,\n type ScreenReaderInstructions,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport { sortableKeyboardCoordinates } from '@dnd-kit/sortable';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { Section } from '~/types';\n\nimport type { SectionNavigation } from '../canvas/sortable';\nimport { paletteSectionOf } from '../palette/palette-drag';\n\n// Enter is left out of `start` so it can select the focused section (#435).\nconst KEYBOARD_CODES = {\n start: ['Space'],\n cancel: ['Escape'],\n end: ['Space', 'Enter'],\n};\n\n// Section wrappers by id, with one stable ref callback per id so React\n// doesn't detach and reattach every wrapper on each render. Held in a\n// `useState` box and only read from handlers and effects.\nconst createNodeRegistry = () => {\n const nodes = new Map<string, HTMLElement>();\n const callbacks = new Map<string, (node: HTMLElement | null) => void>();\n\n return {\n get: (id: string) => nodes.get(id),\n register: (id: string) => {\n let callback = callbacks.get(id);\n\n if (!callback) {\n callback = node => {\n if (node) {\n nodes.set(id, node);\n } else {\n // A wrapper only detaches when its section leaves the canvas\n // (sections are keyed by id), so its callback can go too.\n nodes.delete(id);\n callbacks.delete(id);\n }\n };\n callbacks.set(id, callback);\n }\n\n return callback;\n },\n };\n};\n\nexport type SectionNodes = ReturnType<typeof createNodeRegistry>;\n\ninterface Options {\n sections: Section[];\n selectedId: string | null;\n selectedIndex: number;\n selectOnly: (id: string) => void;\n move: (id: string | null, direction: 'up' | 'down') => void;\n requestDelete: (id: string, onDeleted?: () => void) => void;\n}\n\n// Everything the keyboard does on the canvas (#435): dnd-kit's sensors and\n// what it announces, moving focus and selection between sections, Delete on\n// a focused section, and keeping focus put when a move button disables\n// itself (#505).\nexport const useDndKeyboard = ({\n sections,\n selectedId,\n selectedIndex,\n selectOnly,\n move,\n requestDelete,\n}: Options) => {\n const { announcements: say } = useLiveMessages();\n\n // Space picks a focused section up, the arrow keys move it, and Space or\n // Enter drops it (Escape cancels). Enter doesn't pick up, unlike dnd-kit's\n // default: a focused section is a `role=\"button\"`, and Enter selects it\n // like a click (see `Sortable`).\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 10,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n keyboardCodes: KEYBOARD_CODES,\n }),\n );\n\n // dnd-kit announces drags by id, which here is a generated `data-id`.\n const nameOf = (id: string | number, data?: { current?: unknown }) => {\n return (\n paletteSectionOf(data)?.name ??\n sections.find(section => section.id === id)?.name ??\n say.section\n );\n };\n\n const positionOf = (id: string | number) =>\n sections.findIndex(section => section.id === id) + 1;\n\n const announcements: Announcements = {\n onDragStart: ({ active }) => say.pickedUp(nameOf(active.id, active.data)),\n onDragOver: ({ active, over }) =>\n over && positionOf(over.id) > 0\n ? say.movedTo(\n nameOf(active.id, active.data),\n positionOf(over.id),\n sections.length,\n )\n : say.notOver(nameOf(active.id, active.data)),\n onDragEnd: ({ active, over }) =>\n over && positionOf(over.id) > 0\n ? say.droppedAt(\n nameOf(active.id, active.data),\n positionOf(over.id),\n sections.length,\n )\n : say.dropped(nameOf(active.id, active.data)),\n onDragCancel: ({ active }) => say.cancelled(nameOf(active.id, active.data)),\n };\n\n const screenReaderInstructions: ScreenReaderInstructions = {\n draggable: say.instructions,\n };\n\n // The focusable wrapper of each section, so the keyboard can move focus\n // between them.\n const [sectionNodes] = useState(createNodeRegistry);\n\n // `focus()` also scrolls the section into view.\n const focusSection = (id: string) => sectionNodes.get(id)?.focus();\n\n // Arrow keys and Home/End move focus to another section and select it, so\n // the panel follows. Outside a drag only: during one, dnd-kit owns them.\n const onNavigate = (fromId: string, to: SectionNavigation) => {\n const from = sections.findIndex(section => section.id === fromId);\n const index =\n to === 'first'\n ? 0\n : to === 'last'\n ? sections.length - 1\n : from + (to === 'next' ? 1 : -1);\n const target = sections[index];\n\n if (from < 0 || !target || target.id === fromId) {\n return;\n }\n\n selectOnly(target.id);\n focusSection(target.id);\n };\n\n // Delete on a focused section. Focus goes to the section that takes its\n // place (or the one before it, for the last), so it isn't dropped on the\n // page body.\n const onDeleteKey = (id: string) => {\n const index = sections.findIndex(section => section.id === id);\n const neighbor = sections[index + 1] ?? sections[index - 1];\n\n requestDelete(id, () => {\n if (neighbor) {\n focusSection(neighbor.id);\n }\n });\n };\n\n // A move to the first or last place disables the button just pressed, and\n // focus on a disabled button falls back to the document. Focusing the\n // section keeps a keyboard user where they were (#505).\n const onMoveButton = (id: string, direction: 'up' | 'down') => {\n const to =\n sections.findIndex(section => section.id === id) +\n (direction === 'up' ? -1 : 1);\n\n move(id, direction);\n\n if (to === 0 || to === sections.length - 1) {\n focusSection(id);\n }\n };\n\n // Keeps the selected section on screen when it moves out of view without\n // the keyboard taking it there: a move from the panel, or a copy that lands\n // below the fold. After the next frame, once the new order is laid out.\n useEffect(() => {\n if (selectedId === null) {\n return;\n }\n\n const frame = requestAnimationFrame(() => {\n sectionNodes.get(selectedId)?.scrollIntoView?.({ block: 'nearest' });\n });\n\n return () => cancelAnimationFrame(frame);\n }, [sectionNodes, selectedId, selectedIndex]);\n\n return {\n sensors,\n announcements,\n screenReaderInstructions,\n sectionNodes,\n onNavigate,\n onDeleteKey,\n onMoveButton,\n };\n};\n","import { useCallback, useEffect, useState } from 'react';\n\nimport { DATA_ATTR } from '~/constants';\n\nimport {\n type DndInspector,\n type DndNodePick,\n findElementById,\n pickElement,\n viewportRect,\n} from '../inspector';\nimport type { SectionNodes } from './use-dnd-keyboard';\n\ninterface Options {\n selectedId: string | null;\n selectOnly: (id: string) => void;\n sectionNodes: SectionNodes;\n onNodePick?: (pick: DndNodePick) => void;\n}\n\n// The element picker (#432) and the outline a panel field draws on its\n// element (#514). Returns the `useDndInspector()` value, the handlers a\n// section's overlay calls while picking, and the box to outline, if any.\nexport const useInspectorState = ({\n selectedId,\n selectOnly,\n sectionNodes,\n onNodePick,\n}: Options) => {\n // `picked` follows the selection: picking selects the element's section,\n // and selecting another section clears it.\n const [inspecting, setInspecting] = useState(false);\n const [picked, setPicked] = useState<DndNodePick | null>(null);\n const [hoverRect, setHoverRect] = useState<DOMRect | null>(null);\n // The element a panel field points at (`inspector.highlight`), and its box\n // in the viewport while it's on screen.\n const [fieldTarget, setFieldTarget] = useState<string | null>(null);\n const [fieldRect, setFieldRect] = useState<DOMRect | null>(null);\n\n if (picked && picked.sectionId !== selectedId) {\n setPicked(null);\n }\n\n const stopInspecting = useCallback(() => {\n setInspecting(false);\n setHoverRect(null);\n }, []);\n\n useEffect(() => {\n if (!inspecting) {\n return;\n }\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n stopInspecting();\n }\n };\n\n window.addEventListener('keydown', onKeyDown);\n\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [inspecting, stopInspecting]);\n\n // Follows the element a panel field points at, through canvas scrolls and\n // resizes, measuring its box again in viewport coordinates.\n useEffect(() => {\n const section = selectedId === null ? null : sectionNodes.get(selectedId);\n\n if (!fieldTarget || !section) {\n return;\n }\n\n let frame = 0;\n\n const measure = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => {\n const element = findElementById(section, fieldTarget);\n\n setFieldRect(element ? viewportRect(element) : null);\n });\n };\n\n measure();\n window.addEventListener('scroll', measure, true);\n window.addEventListener('resize', measure);\n\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener('scroll', measure, true);\n window.removeEventListener('resize', measure);\n };\n }, [fieldTarget, selectedId, sectionNodes]);\n\n const inspector: DndInspector = {\n active: inspecting,\n activate: () => setInspecting(true),\n deactivate: stopInspecting,\n toggle: () => (inspecting ? stopInspecting() : setInspecting(true)),\n picked,\n highlight: setFieldTarget,\n };\n\n const onInspectMove = (\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n ) => {\n const element = pickElement(section, overlay, x, y);\n\n setHoverRect(element ? viewportRect(element) : null);\n };\n\n const onInspectPick = (\n sectionId: string,\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n ) => {\n const id = pickElement(section, overlay, x, y)?.getAttribute(DATA_ATTR.ID);\n\n if (!id) {\n return;\n }\n\n const pick = { id, sectionId };\n\n selectOnly(sectionId);\n setPicked(pick);\n stopInspecting();\n onNodePick?.(pick);\n };\n\n return {\n inspector,\n inspecting,\n onInspectMove,\n onInspectPick,\n onInspectLeave: () => setHoverRect(null),\n // The picker's hover box while picking, otherwise the field's element.\n // `fieldRect` is only read while a field points somewhere, so a stale\n // box from the last target never shows.\n highlightRect: inspecting ? hoverRect : fieldTarget ? fieldRect : null,\n };\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { arrayMove } from '@dnd-kit/sortable';\n\nimport type { Section } from '~/types';\nimport {\n type DocumentProblem,\n type SectionOptions,\n} from '~/utils/ast/document';\nimport { fillSectionIds, inspectDocument } from '~/utils/ast/document';\nimport { replaceIds } from '~/utils/ast/tree';\nimport {\n createSectionPreviewCache,\n extractSections,\n replaceSections,\n} from '~/utils/sections';\n\nimport { usePreview } from '../../context/states';\n\nexport interface SectionDocument {\n sections: Section[];\n previews: string[];\n selectedId: string | null;\n selectedSection?: Section;\n selectedIndex: number;\n select: (id: string) => void;\n // Selects `id` without toggling, unlike `select`. Keyboard navigation uses\n // it, since landing on a section must not deselect it (#435).\n selectOnly: (id: string) => void;\n clearSelection: () => void;\n add: (section: Pick<Section, 'name' | 'code'>, atIndex?: number) => void;\n remove: (id: string) => void;\n copy: (id: string) => void;\n move: (id: string | null, direction: 'up' | 'down') => void;\n reorder: (activeId: string, overId: string) => void;\n patch: (next: Partial<Section> & { id: string }) => void;\n // The section as the latest commit left it, or `undefined` when nothing\n // has been committed since this render (or that commit removed it). Lets\n // an edit inside a section build on a commit from the same tick (#450).\n getCommittedSection: (id: string) => Section | undefined;\n // Why `value` isn't a usable document, or `null` when it is (#433, #449).\n problem: DocumentProblem | null;\n // True while `value` doesn't parse and `sections`/`previews` are from the\n // last version that did. Every mutation is then refused through\n // `onBlockedEdit`, because their source ranges belong to that version\n // (#433).\n stale: boolean;\n}\n\nexport interface SectionDocumentOptions extends SectionOptions {\n // Called instead of committing when a mutation is refused because the\n // document doesn't parse. Pass a stable function.\n onBlockedEdit?: (problem: DocumentProblem) => void;\n}\n\n// Remembers the last document that parsed, per container id. Kept in\n// `useState` and written from the derivation below; it never decides what\n// renders by itself.\nconst createLastParsed = () => {\n let last: { containerId?: string; document: string } | null = null;\n\n return {\n read: (containerId?: string) =>\n last && last.containerId === containerId ? last.document : undefined,\n write: (containerId: string | undefined, document: string) => {\n last = { containerId, document };\n },\n };\n};\n\n// The document side of `Live.Dnd`: reads the sections out of the code,\n// tracks the selected one, and commits every section operation through one\n// `commit` (#245).\nexport const useSectionDocument = (\n value: string,\n onChange?: (value: string) => void,\n {\n containerId,\n sectionNameFallback,\n onBlockedEdit,\n }: SectionDocumentOptions = {},\n): SectionDocument => {\n const { setCode } = usePreview();\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n // Every read of sections goes through here, so a section without\n // `data-name` gets the same name everywhere (#448).\n const readSections = useCallback(\n (code: string) =>\n extractSections(code, { containerId, sectionNameFallback }),\n [containerId, sectionNameFallback],\n );\n\n // Gives every section a unique `data-id`, so `selectedId` follows its\n // section through an insert, copy, move or delete (#245). The filled ids\n // reach the source only with the next commit: opening a document never\n // rewrites it.\n const document = useMemo(\n () => fillSectionIds(value, undefined, { containerId }),\n [containerId, value],\n );\n\n // What the canvas and panel show: `document`, or while it doesn't parse,\n // the last version that did, read-only (#433). This keeps them from\n // emptying on every keystroke in the code editor. A missing container shows\n // the problem instead (#449).\n const [lastParsed] = useState(createLastParsed);\n const view = useMemo(() => {\n const inspection = inspectDocument(document, { containerId });\n\n if (inspection.ok) {\n lastParsed.write(containerId, document);\n\n return { document, problem: null, stale: false };\n }\n\n const { ok: _ok, ...problem } = inspection;\n const last =\n problem.reason === 'parse-error'\n ? lastParsed.read(containerId)\n : undefined;\n\n return { document: last ?? document, problem, stale: last !== undefined };\n }, [containerId, document, lastParsed]);\n\n const sections = useMemo(\n () => readSections(view.document),\n [readSections, view.document],\n );\n\n // One preview cache per hook instance, which reuses the previews of\n // sections that didn't change (#131). Held in `useState` because it keeps\n // state between renders, which `useMemo` can't.\n const [previewCache] = useState(() => createSectionPreviewCache());\n const previews = useMemo(\n () => previewCache.compute(view.document, sections, { containerId }),\n [containerId, previewCache, sections, view.document],\n );\n\n const selectedIndex = sections.findIndex(s => s.id === selectedId);\n const selectedSection =\n selectedIndex >= 0 ? sections[selectedIndex] : undefined;\n\n // The document the last commit produced, and the render document it was\n // built on. Mutations read through `latestDocument()`, so a second commit\n // in the same tick builds on the first instead of undoing it (#450).\n //\n // Cleared after each render, when the new `value` takes over, including\n // when the host didn't accept the commit. The `from` check covers the time\n // between that render and this effect.\n const pendingRef = useRef<{ from: string; code: string } | null>(null);\n\n useEffect(() => {\n pendingRef.current = null;\n });\n\n const latestDocument = useCallback(() => {\n const pending = pendingRef.current;\n\n return pending?.from === document ? pending.code : document;\n }, [document]);\n\n // Re-reading an unchanged document is a parse-cache hit, not a new parse.\n const latestSections = useCallback(\n () => readSections(latestDocument()),\n [latestDocument, readSections],\n );\n\n // The one place a list of sections becomes a new document, sent to the\n // host's `onChange` and the provider. Ids and names are read again from the\n // result, so only `code` is taken. `fillSectionIds` gives an id to a\n // section added without one, such as a palette template. Returns the new\n // sections so a caller can select one by its real id.\n const commit = useCallback(\n (nextSections: { code: string }[]): Section[] => {\n const nextCode = fillSectionIds(\n replaceSections(\n latestDocument(),\n nextSections.map(s => s.code),\n { containerId },\n ),\n undefined,\n { containerId },\n );\n\n pendingRef.current = { from: document, code: nextCode };\n onChange?.(nextCode);\n setCode(nextCode);\n\n return readSections(nextCode);\n },\n [containerId, document, latestDocument, onChange, readSections, setCode],\n );\n\n const getCommittedSection = useCallback(\n (id: string) => {\n const pending = pendingRef.current;\n\n if (pending?.from !== document) {\n return undefined;\n }\n\n return readSections(pending.code).find(s => s.id === id);\n },\n [document, readSections],\n );\n\n // Every mutation starts here. It refuses, and reports through\n // `onBlockedEdit`, while the document is stale.\n const { problem, stale } = view;\n const refuse = useCallback(() => {\n if (!stale || !problem) {\n return false;\n }\n\n onBlockedEdit?.(problem);\n\n return true;\n }, [onBlockedEdit, problem, stale]);\n\n const select = useCallback((id: string) => {\n setSelectedId(prev => (prev === id ? null : id));\n }, []);\n\n const selectOnly = useCallback((id: string) => setSelectedId(id), []);\n\n const clearSelection = useCallback(() => setSelectedId(null), []);\n\n const add = useCallback(\n (section: Pick<Section, 'name' | 'code'>, atIndex?: number) => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n const next = { code: section.code };\n\n commit(\n atIndex === undefined || atIndex < 0\n ? [...current, next]\n : [...current.slice(0, atIndex), next, ...current.slice(atIndex)],\n );\n },\n [commit, refuse, latestSections],\n );\n\n const remove = useCallback(\n (id: string) => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n\n // Removes by position, so a duplicated id could never delete two\n // sections.\n const index = current.findIndex(s => s.id === id);\n\n if (index < 0) {\n return;\n }\n\n // Clear the selection only when the selected section is the one\n // deleted.\n if (id === selectedId) {\n setSelectedId(null);\n }\n\n commit(current.filter((_, i) => i !== index));\n },\n [commit, refuse, latestSections, selectedId],\n );\n\n const copy = useCallback(\n (id: string) => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n\n const index = current.findIndex(s => s.id === id);\n const source = current[index];\n\n if (!source) {\n return;\n }\n\n // New `data-id`s for the copy, its own included, so it's a distinct\n // section.\n const committed = commit([\n ...current.slice(0, index + 1),\n { code: replaceIds(source.code) },\n ...current.slice(index + 1),\n ]);\n\n // Select the copy by the id the committed document gave it (#245).\n setSelectedId(committed[index + 1]?.id ?? null);\n },\n [commit, refuse, latestSections],\n );\n\n const move = useCallback(\n (id: string | null, direction: 'up' | 'down') => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n\n const index = current.findIndex(s => s.id === id);\n const targetIndex = direction === 'up' ? index - 1 : index + 1;\n\n if (index < 0 || targetIndex < 0 || targetIndex >= current.length) {\n return;\n }\n\n // The selection follows the section, since its id moves with it.\n commit(arrayMove(current, index, targetIndex));\n },\n [commit, refuse, latestSections],\n );\n\n const reorder = useCallback(\n (activeId: string, overId: string) => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n\n const prevIndex = current.findIndex(s => s.id === activeId);\n const nextIndex = current.findIndex(s => s.id === overId);\n\n if (prevIndex < 0 || nextIndex < 0 || prevIndex === nextIndex) {\n return;\n }\n\n commit(arrayMove(current, prevIndex, nextIndex));\n },\n [commit, refuse, latestSections],\n );\n\n const patch = useCallback(\n (next: Partial<Section> & { id: string }) => {\n if (refuse()) {\n return;\n }\n\n const current = latestSections();\n\n commit(current.map(s => (s.id === next.id ? { ...s, ...next } : s)));\n },\n [commit, refuse, latestSections],\n );\n\n return {\n sections,\n previews,\n selectedId,\n selectedSection,\n selectedIndex,\n select,\n selectOnly,\n clearSelection,\n add,\n remove,\n copy,\n move,\n reorder,\n patch,\n getCommittedSection,\n problem,\n stale,\n };\n};\n","import {\n Children,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport {\n DndContext,\n type DragEndEvent,\n DragOverlay,\n type Modifier,\n closestCenter,\n} from '@dnd-kit/core';\nimport { restrictToVerticalAxis } from '@dnd-kit/modifiers';\nimport {\n SortableContext,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\nimport { Space, Typography } from '@jbpark/ui-kit';\nimport { useResponsiveSize } from '@jbpark/use-hooks';\n\nimport { PALETTE_SECTIONS } from '~/constants';\nimport type { Section } from '~/types';\nimport { type DocumentProblem } from '~/utils/ast/document';\nimport { extract } from '~/utils/ast/extract';\nimport { fillIdsFrom } from '~/utils/ast/tree';\nimport { type BindingOptions, type DataAttrNode } from '~/utils/ast/types';\nimport { updateAll } from '~/utils/ast/update';\nimport type { UpdateFailure } from '~/utils/ast/update';\n\nimport { cn } from '../../utils/cn';\nimport { preloadScripts } from '../../utils/scripts';\nimport { type LiveMessages, useLiveMessages } from '../context/messages';\nimport { usePreview } from '../context/states';\nimport { useStableModules } from '../preview/use-stable-modules';\nimport Droppable from './canvas/droppable';\nimport InspectorHighlight from './canvas/inspector-highlight';\nimport Overlay from './canvas/overlay';\nimport Renderer from './canvas/renderer';\nimport { SectionFallbackContext } from './canvas/section-fallback-context';\nimport Sortable from './canvas/sortable';\nimport {\n type DndEditError,\n DndEditOptionsContext,\n toastEditError,\n} from './edit-options';\nimport { DndInspectorContext } from './inspector';\nimport Layout from './layout';\nimport { DndRegionContext } from './layout-context';\nimport { paletteSectionOf } from './palette/palette-drag';\nimport {\n type PanelBinding,\n type PanelNodeChange,\n resolvePanelBindings,\n withPanelCommit,\n} from './panel-binding';\nimport { useDeleteFlow } from './state/use-delete-flow';\nimport { useDndKeyboard } from './state/use-dnd-keyboard';\nimport { useInspectorState } from './state/use-inspector-state';\nimport { useSectionDocument } from './state/use-section-document';\nimport type { DndPalette, DndPanel, Props } from './types';\n\n// Turns an `update` failure into the edit error's title and description.\n// The description names the cause, which is usually in the element's\n// `data-binding` rather than in the value just typed (#270).\nconst describeUpdateFailure = (\n failure: UpdateFailure | undefined,\n label: string,\n { editErrors: m }: LiveMessages,\n): { title: string; description?: string } => {\n switch (failure?.reason) {\n case 'attribute-not-found':\n return {\n title: m.updateFailed(label),\n description: m.attributeNotFound(failure.property),\n };\n case 'binding-not-declared':\n return {\n title: m.updateFailed(label),\n description: m.bindingNotDeclared({\n label,\n property: failure.property,\n }),\n };\n case 'duplicate-binding':\n return {\n title: m.updateFailed(label),\n description: m.duplicateBinding({\n count: failure.count,\n label,\n property: failure.property,\n }),\n };\n case 'reserved-property':\n return {\n title: m.cannotEdit(label),\n description: m.reservedProperty(failure.property),\n };\n case 'required-property':\n return {\n title: m.cannotRemove(label),\n description: m.requiredProperty(failure.property),\n };\n case 'no-binding':\n return { title: m.updateFailed(label), description: m.noBinding };\n case 'element-not-found':\n return { title: m.updateFailed(label), description: m.elementNotFound };\n case 'self-closing':\n return {\n title: m.cannotEdit(label),\n description: m.selfClosing(failure.property),\n };\n case 'unsupported-syntax':\n return {\n title: m.cannotEdit(label),\n description: m.unsupportedSyntax(failure.property),\n };\n case 'parse-error':\n return {\n title: m.updateFailed(label),\n description:\n failure.error instanceof Error\n ? failure.error.message\n : m.checkConsole,\n };\n default:\n return { title: m.updateFailed(label) };\n }\n};\n\n// An edit refused because the document doesn't parse (#433).\nconst blockedEditError = (\n error: unknown,\n { editErrors: m }: LiveMessages,\n): DndEditError => ({\n type: 'parse',\n target: 'document',\n reason: 'parse-error',\n error,\n title: m.syntaxError,\n description: m.syntaxErrorDetail,\n});\n\nconst conditionalModifiers: Modifier = args => {\n const { active } = args;\n\n if (paletteSectionOf(active?.data)) {\n return args.transform;\n }\n\n return restrictToVerticalAxis(args);\n};\n\n// One shared empty object. A new `{}` on every render would be a new\n// `modules` prop for every section, which breaks `Renderer`'s memo and\n// recompiles every section on every edit (#97, #348).\nconst NO_MODULES: Record<string, unknown> = {};\n\nconst Dnd = ({\n value: _value,\n props,\n modules: _modules = NO_MODULES,\n onChange: _onChange,\n className,\n items = [],\n frame,\n dynamicTailwind = false,\n provider,\n renderField,\n onEditError,\n renderSectionFallback,\n shouldForceSectionFallback,\n onBeforeDelete,\n sectionNameFallback,\n containerId,\n bindings: bindingRegistry,\n bindingKeys,\n onNodePick,\n children,\n ...restProps\n}: Props) => {\n const modules = useStableModules(_modules);\n const [mobilePaletteOpen, setMobilePaletteOpen] = useState(false);\n\n const { breakpoint } = useResponsiveSize();\n const isMobile = breakpoint.current === 'xs' || breakpoint.current === 'sm';\n\n // Only read here, for `value` below. `useSectionDocument` writes it.\n const { code } = usePreview();\n\n // A throwing predicate is treated as \"not forced\" rather than taking the\n // whole editor down with it.\n const isForced = (section: Section) => {\n try {\n return shouldForceSectionFallback?.(section) === true;\n } catch (error) {\n console.error('shouldForceSectionFallback threw', error);\n\n return false;\n }\n };\n\n // The host's `value` when it passes one (controlled), otherwise the\n // provider's code. An empty string counts as a value, as in `Live.Preview`.\n const value = _value === undefined ? code : _value;\n\n const messages = useLiveMessages();\n const reportError = onEditError ?? toastEditError;\n\n // Read through refs, so the effects below report each failure once, even\n // when the host passes a new `onEditError` or new messages every render.\n const reportErrorRef = useRef(reportError);\n const messagesRef = useRef(messages);\n\n useEffect(() => {\n reportErrorRef.current = reportError;\n messagesRef.current = messages;\n });\n\n // Reports an edit refused because the source doesn't parse. A source that\n // stops parsing isn't reported by itself: that happens on most keystrokes,\n // and the canvas already says so (#433).\n const onBlockedEdit = useCallback((problem: DocumentProblem) => {\n if (problem.reason === 'parse-error') {\n reportErrorRef.current(\n blockedEditError(problem.error, messagesRef.current),\n );\n }\n }, []);\n\n const {\n sections,\n previews,\n selectedId,\n selectedSection,\n selectedIndex,\n select,\n selectOnly,\n clearSelection,\n add: addSection,\n remove,\n copy: onCopy,\n move: moveSection,\n reorder,\n patch,\n getCommittedSection,\n problem,\n stale,\n } = useSectionDocument(value, _onChange, {\n containerId,\n sectionNameFallback,\n onBlockedEdit,\n });\n\n // The container id the document is missing, or `null`.\n const missingContainer =\n problem?.reason === 'container-not-found' ? problem.containerId : null;\n\n const onDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n if (!over) {\n return;\n }\n\n const section = paletteSectionOf(active.data);\n\n if (section) {\n const atBottom =\n over.id === 'sortable-area' || over.id === 'sortable-area-bottom';\n\n addSection(\n section,\n atBottom ? undefined : sections.findIndex(s => s.id === over.id),\n );\n return;\n }\n\n if (active.id !== over.id && sections.some(s => s.id === active.id)) {\n reorder(String(active.id), String(over.id));\n }\n };\n\n const onSelect = (id: string) => select(id);\n\n const requestDelete = useDeleteFlow({ sections, remove, onBeforeDelete });\n\n const onDelete = (id: string) => requestDelete(id);\n\n const {\n sensors,\n announcements,\n screenReaderInstructions,\n sectionNodes,\n onNavigate,\n onDeleteKey,\n onMoveButton,\n } = useDndKeyboard({\n sections,\n selectedId,\n selectedIndex,\n selectOnly,\n move: moveSection,\n requestDelete,\n });\n\n const {\n inspector,\n inspecting,\n onInspectMove,\n onInspectPick,\n onInspectLeave,\n highlightRect,\n } = useInspectorState({ selectedId, selectOnly, sectionNodes, onNodePick });\n\n const onChange = (next: Partial<Section>) => {\n if (!next.id) {\n return;\n }\n\n patch(next as Partial<Section> & { id: string });\n };\n\n // One object for everything below, renewed only when a map changes, so\n // memos that depend on it don't re-run every render (#513).\n const bindingOptions = useMemo<BindingOptions>(\n () => ({ bindings: bindingRegistry, bindingKeys }),\n [bindingRegistry, bindingKeys],\n );\n // The selected section's elements, parsed again only when its code or id\n // changes.\n const selectedCode = selectedSection?.code;\n const selectedSectionId = selectedSection?.id;\n const { fields, updatedCode, parseError } = useMemo(() => {\n if (!selectedCode) {\n return {\n fields: [] as DataAttrNode[],\n updatedCode: '',\n parseError: null,\n };\n }\n\n try {\n // The same ids the canvas preview fills this section with, so an\n // element's `data-id` there matches its fields here (#432).\n const updated = fillIdsFrom(selectedCode, selectedSectionId ?? '');\n // Every element, the `<section>` itself included, so a binding on the\n // section is editable too (#429).\n const allNodes = extract(updated, bindingOptions);\n\n return {\n fields: allNodes,\n updatedCode: updated !== selectedCode ? updated : selectedCode,\n parseError: null,\n };\n } catch (e) {\n console.warn('⚠️ Parsing error', e);\n return {\n fields: [] as DataAttrNode[],\n updatedCode: '',\n parseError: { error: e },\n };\n }\n }, [selectedCode, selectedSectionId, bindingOptions]);\n\n // Keyed on the missing id alone, so it fires when a document reaches this\n // state and not again for every edit that leaves it there.\n useEffect(() => {\n if (missingContainer !== null) {\n reportErrorRef.current({\n type: 'parse',\n target: 'document',\n reason: 'container-not-found',\n containerId: missingContainer,\n title:\n messagesRef.current.editErrors.missingContainer(missingContainer),\n description:\n messagesRef.current.editErrors.missingContainerDetail(\n missingContainer,\n ),\n });\n }\n }, [missingContainer]);\n\n useEffect(() => {\n if (parseError) {\n reportErrorRef.current({\n type: 'parse',\n target: 'section',\n error: parseError.error,\n title: messagesRef.current.editErrors.sectionParseFailed,\n description: messagesRef.current.editErrors.checkConsole,\n });\n }\n }, [parseError]);\n\n // The one commit path for panel edits. A single edit is a batch of one\n // (#425).\n const commitChanges = (changes: Parameters<PanelNodeChange>[0][]) => {\n if (changes.length === 0) {\n return;\n }\n\n // The fields show the last version that parsed while the source doesn't,\n // and their ids point into that version, not the current source (#433).\n if (stale && problem?.reason === 'parse-error') {\n reportError(blockedEditError(problem.error, messages));\n return;\n }\n\n // If an earlier commit in this same tick changed this section, build on\n // its result: starting from this render's `updatedCode` would undo it\n // (#450). Otherwise use `updatedCode`, which has the filled ids the\n // bindings point at.\n const committed =\n selectedSection && getCommittedSection(selectedSection.id)?.code;\n const base =\n committed && committed !== selectedCode ? committed : updatedCode;\n const result = updateAll(\n base,\n changes.map(({ id, label, property, value: changeValue }) => ({\n dataId: id,\n label,\n property,\n value: changeValue,\n })),\n bindingOptions,\n );\n\n if (!result.success) {\n const { id, label, property } = changes[result.index]!;\n\n reportError({\n type: 'update',\n id,\n label,\n property,\n failure: result.failure,\n ...describeUpdateFailure(result.failure, label, messages),\n });\n return;\n }\n\n if (selectedSection) {\n onChange({ ...selectedSection, code: result.code });\n }\n };\n\n const onFieldChange: PanelNodeChange = change => commitChanges([change]);\n\n // One entry per bound property, from `fields` alone. Don't add `onChange`\n // here: a callback must come from the current render, and this memo can\n // outlive it (#336).\n const bindingFields = useMemo(\n () => fields.flatMap(node => resolvePanelBindings(node)?.bindings ?? []),\n [fields],\n );\n\n // Adds each binding's `onChange`, made fresh every render so a commit uses\n // the current section and code. It's a cheap walk with no parsing.\n const bindings: PanelBinding[] = withPanelCommit(\n bindingFields,\n onFieldChange,\n );\n\n useEffect(() => {\n if (frame?.scripts?.length) {\n preloadScripts(frame.scripts);\n }\n }, [frame?.scripts]);\n\n // Data, not components: the built-in palette and panel read these through\n // `useDndPalette()` and `useDndPanel()`, the same way a custom one does\n // (#237).\n const palette: DndPalette = {\n items: items?.length ? items : PALETTE_SECTIONS,\n onAdd: (section: Section) => {\n addSection(section);\n setMobilePaletteOpen(false);\n },\n };\n\n const panel: DndPanel = {\n item: selectedSection,\n onChange,\n onDelete,\n onMoveUp: () => moveSection(selectedId, 'up'),\n onMoveDown: () => moveSection(selectedId, 'down'),\n canMoveUp: selectedIndex > 0,\n canMoveDown: selectedIndex >= 0 && selectedIndex < sections.length - 1,\n bindings,\n onNodeChange: onFieldChange,\n onNodesChange: commitChanges,\n readOnly: stale,\n bindingOptions,\n };\n\n // The canvas content. Its frame container belongs to `Live.Dnd.Canvas`, so\n // a custom layout can't leave it out.\n const canvas = (\n <>\n {stale && (\n <div\n role=\"status\"\n className={cn(\n 'sticky top-0 z-70',\n 'border-b border-amber-200 bg-amber-50 px-3 py-2',\n 'text-sm text-amber-900',\n )}\n >\n {messages.canvas.stale}\n </div>\n )}\n <Droppable\n className={cn(\n !sections.length && 'h-full',\n //\n )}\n >\n {!sections.length ? (\n <div\n className={cn(\n 'flex items-center justify-center',\n 'h-full',\n 'text-gray-500',\n )}\n >\n {problem?.reason === 'parse-error' ? (\n <Space orientation=\"vertical\" align=\"center\">\n <Typography.Paragraph>\n {messages.canvas.syntaxError}\n </Typography.Paragraph>\n <Typography.Text>\n {messages.canvas.syntaxErrorDetail}\n </Typography.Text>\n </Space>\n ) : missingContainer !== null ? (\n <Space orientation=\"vertical\" align=\"center\">\n <Typography.Paragraph>\n {messages.canvas.missingContainer(missingContainer)}\n </Typography.Paragraph>\n <Typography.Text>\n {messages.canvas.missingContainerDetail(missingContainer)}\n </Typography.Text>\n </Space>\n ) : (\n <Space orientation=\"vertical\" align=\"center\">\n <Typography.Paragraph>\n {messages.canvas.empty}\n </Typography.Paragraph>\n <Typography.Text>\n {isMobile\n ? messages.canvas.emptyHintTouch\n : messages.canvas.emptyHintDrag}\n </Typography.Text>\n </Space>\n )}\n </div>\n ) : (\n <SortableContext\n items={sections.map(s => s.id)}\n strategy={verticalListSortingStrategy}\n >\n {sections.map((section, index) => (\n <Sortable\n key={section.id}\n id={section.id}\n name={section.name}\n selected={selectedId === section.id}\n onClick={() => onSelect(section.id)}\n onDelete={onDelete}\n onCopy={onCopy}\n onMoveUp={() => onMoveButton(section.id, 'up')}\n onMoveDown={() => onMoveButton(section.id, 'down')}\n canMoveUp={index > 0}\n canMoveDown={index < sections.length - 1}\n nodeRef={sectionNodes.register(section.id)}\n onNavigate={to => onNavigate(section.id, to)}\n onDeleteKey={() => onDeleteKey(section.id)}\n inspecting={inspecting}\n onInspectMove={onInspectMove}\n onInspectPick={(...args) => onInspectPick(section.id, ...args)}\n onInspectLeave={onInspectLeave}\n >\n <Renderer\n preview={previews[index]!}\n sectionId={section.id}\n sectionName={section.name}\n sectionCode={section.code}\n forceFallback={isForced(section)}\n modules={modules}\n frame={frame}\n dynamicTailwind={dynamicTailwind}\n provider={provider}\n {...props}\n />\n </Sortable>\n ))}\n </SortableContext>\n )}\n </Droppable>\n <InspectorHighlight rect={highlightRect} />\n </>\n );\n\n return (\n <SectionFallbackContext.Provider value={renderSectionFallback}>\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n accessibility={{\n announcements,\n screenReaderInstructions,\n }}\n modifiers={[\n conditionalModifiers,\n //\n ]}\n onDragEnd={onDragEnd}\n >\n <div\n className={cn(\n 'relative flex h-full w-full',\n className,\n //\n )}\n {...restProps}\n >\n {/* Not memoized: `palette`, `panel` and `canvas` are new every\n render anyway. */}\n <DndEditOptionsContext.Provider\n value={{ renderField, reportError, bindingOptions }}\n >\n <DndRegionContext.Provider\n value={{\n palette,\n panel,\n canvas,\n isMobile,\n selectedId,\n clearSelection,\n paletteOpen: mobilePaletteOpen,\n setPaletteOpen: setMobilePaletteOpen,\n documentError: problem?.reason ?? null,\n }}\n >\n {/* The built-in layout when `children` renders nothing, such\n as only a JSX comment or a `{cond && <MyLayout />}` that is\n false. An editor with no regions would look broken. */}\n <DndInspectorContext.Provider value={inspector}>\n {Children.toArray(children).length ? children : <Layout />}\n </DndInspectorContext.Provider>\n </DndRegionContext.Provider>\n </DndEditOptionsContext.Provider>\n </div>\n <DragOverlay>\n <Overlay\n sections={sections}\n isForced={isForced}\n renderProps={{\n fullCode: value,\n modules,\n frame,\n dynamicTailwind,\n ...props,\n // After the spread, so a preview prop with the same name can't\n // point the overlay at a different container.\n containerId,\n }}\n />\n </DragOverlay>\n </DndContext>\n </SectionFallbackContext.Provider>\n );\n};\n\nexport default Dnd;\n","import type {\n DndRenderSectionFallback,\n DndSectionFallbackArgs,\n} from './canvas/section-fallback-context';\nimport DndImpl from './dnd';\nimport type { DndEditError, DndRenderField } from './edit-options';\nimport {\n type DndInspector,\n type DndNodePick,\n useDndInspector,\n} from './inspector';\nimport {\n Canvas,\n type DndLayoutProps,\n type DndRegionProps,\n Layout,\n Palette,\n Panel,\n} from './layout';\nimport {\n type DndLayout,\n useDndLayout,\n useDndPalette,\n useDndPanel,\n} from './layout-context';\nimport DraggableItem, {\n type DraggableItemDragState,\n type DraggableItemProps,\n} from './palette/draggable';\nimport type {\n PanelBinding,\n PanelNodeChange,\n PanelNodesChange,\n} from './panel-binding';\nimport Field, { type FieldProps } from './panel/field';\nimport {\n type DndChildren,\n type DndChildrenOptions,\n useDndChildren,\n} from './panel/use-dnd-children';\nimport {\n type DndItems,\n type DndItemsActions,\n type DndItemsExpansion,\n type DndItemsItem,\n type DndItemsNestedElement,\n type DndItemsNestedGroup,\n type DndItemsOptions,\n useDndItems,\n} from './panel/use-dnd-items';\nimport type { DndPalette, DndPanel, Props } from './types';\n\ntype DndComponent = typeof DndImpl & {\n // Makes a palette item draggable and hands back `ref`, `dragProps` and\n // `isDragging`, so a custom palette only decides how the item looks.\n DraggableItem: typeof DraggableItem;\n // The built-in control for one binding, so a custom panel can use it for\n // some bindings and its own controls for others. Takes a `PanelBinding`\n // and `onNodeChange`, both from `useDndPanel()`. Most useful for `items`\n // and `children`, whose editors reach nested elements that `bindings`\n // doesn't list. Renders the control only, without a label.\n Field: typeof Field;\n // The three built-in regions, each in the container it needs. Place them\n // in `Live.Dnd`'s `children` in any arrangement, with your own components\n // in place of any of them except `Canvas`, which can't be replaced. Render\n // `Canvas` exactly once.\n Palette: typeof Palette;\n Canvas: typeof Canvas;\n Panel: typeof Panel;\n // The built-in arrangement, which `Live.Dnd` renders without children: a\n // three-pane Splitter on desktop, and on mobile the canvas with a button\n // and Drawers. Use it to wrap the editor (a toolbar above it, say) or to\n // replace one region through its `palette` or `panel` slot.\n Layout: typeof Layout;\n};\n\nconst Dnd = DndImpl as DndComponent;\n\nDnd.DraggableItem = DraggableItem;\nDnd.Field = Field;\nDnd.Palette = Palette;\nDnd.Canvas = Canvas;\nDnd.Panel = Panel;\nDnd.Layout = Layout;\n\nexport { DraggableItem, Field };\nexport { Palette, Canvas, Panel, Layout };\n// The data behind each region, for components in `Live.Dnd`'s children:\n// the palette's items and `onAdd`, the panel's section, bindings and\n// commits, and the layout state the mobile Drawers run on, which a custom\n// layout replaces.\nexport { useDndPalette, useDndPanel, useDndLayout };\n// The element picker: turn it on, and clicking an element in the canvas\n// preview selects its section and reports the element's `data-id` (#432).\nexport { useDndInspector };\n// What the built-in Children editor runs on, for your own markup. It works\n// on the children as extracted nodes; read their fields with the two\n// functions below.\nexport { useDndChildren };\nexport type { DndChildren, DndChildrenOptions };\n// What the built-in Items editor runs on, for your own markup. Its items'\n// fields are `PanelBinding`s, so `Field` can render any of them.\nexport { useDndItems };\n// The two steps behind `useDndPanel().bindings`, for elements the panel\n// doesn't list, such as the children `useDndChildren` returns.\n// `resolvePanelBindings` reads the bindings; `withPanelCommit` adds\n// `onNodeChange`. The result is `PanelBinding`s for `Field`.\nexport { resolvePanelBindings, withPanelCommit } from './panel-binding';\nexport type {\n PanelBindingData,\n PanelBindingElement,\n PanelBindingSource,\n} from './panel-binding';\n// How `Field` picks its built-in control, for a custom panel that sends\n// some bindings (often `items` and `children`) to `Field` or a hook.\nexport { getFieldKind, isStructuralFieldKind } from './panel/field-kind';\nexport type { FieldKind, FieldKindBinding } from './panel/field-kind';\n\n// The earlier names of these hooks and types, kept as deprecated aliases\n// until the next major: `useItemsEditor` → `useDndItems`,\n// `useChildrenEditor` → `useDndChildren`, `ItemsEditor*` → `DndItems*`,\n// `ChildrenEditor*` → `DndChildren*`.\n/** @deprecated Renamed to `useDndItems`. */\nexport const useItemsEditor = useDndItems;\n/** @deprecated Renamed to `useDndChildren`. */\nexport const useChildrenEditor = useDndChildren;\n/** @deprecated Renamed to `DndItems`. */\nexport type ItemsEditor = DndItems;\n/** @deprecated Renamed to `DndItemsActions`. */\nexport type ItemsEditorActions = DndItemsActions;\n/** @deprecated Renamed to `DndItemsItem`. */\nexport type ItemsEditorItem = DndItemsItem;\n/** @deprecated Renamed to `DndItemsNestedElement`. */\nexport type ItemsEditorNestedElement = DndItemsNestedElement;\n/** @deprecated Renamed to `DndItemsNestedGroup`. */\nexport type ItemsEditorNestedGroup = DndItemsNestedGroup;\n/** @deprecated Renamed to `DndItemsOptions`. */\nexport type ItemsEditorOptions = DndItemsOptions;\n/** @deprecated Renamed to `DndChildren`. */\nexport type ChildrenEditor = DndChildren;\n/** @deprecated Renamed to `DndChildrenOptions`. */\nexport type ChildrenEditorOptions = DndChildrenOptions;\nexport type {\n Props,\n DndPalette,\n DndPanel,\n DndLayout,\n DndInspector,\n DndNodePick,\n DndLayoutProps,\n DndRegionProps,\n PanelBinding,\n PanelNodeChange,\n PanelNodesChange,\n FieldProps,\n DndEditError,\n DndRenderField,\n DndRenderSectionFallback,\n DndSectionFallbackArgs,\n DndItems,\n DndItemsActions,\n DndItemsExpansion,\n DndItemsItem,\n DndItemsNestedElement,\n DndItemsNestedGroup,\n DndItemsOptions,\n DraggableItemProps,\n DraggableItemDragState,\n};\nexport default Dnd;\n"],"mappings":"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"}
|