@jbpark/live-editor 4.6.1 → 6.0.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.
Files changed (91) hide show
  1. package/README.ko.md +37 -35
  2. package/README.md +37 -35
  3. package/dist/{boundary-BLB80tyw.js → boundary-CySnDUs2.js} +5 -4
  4. package/dist/boundary-CySnDUs2.js.map +1 -0
  5. package/dist/{compile-Dxas-D05.js → compile-my0AjsCw.js} +8 -7
  6. package/dist/compile-my0AjsCw.js.map +1 -0
  7. package/dist/constants-st9gnJ5g.js +55 -0
  8. package/dist/constants-st9gnJ5g.js.map +1 -0
  9. package/dist/{context-B8MzP7_p.js → context-Bjq0CvBE.js} +3 -3
  10. package/dist/{context-B8MzP7_p.js.map → context-Bjq0CvBE.js.map} +1 -1
  11. package/dist/{core-Bgfek364.js → core-BNVuH8-l.js} +51 -14
  12. package/dist/core-BNVuH8-l.js.map +1 -0
  13. package/dist/{detect-typescript-Dr_oLniM.js → detect-typescript-CMF0FVKD.js} +2 -2
  14. package/dist/{detect-typescript-Dr_oLniM.js.map → detect-typescript-CMF0FVKD.js.map} +1 -1
  15. package/dist/dnd/index.d.ts +3 -2
  16. package/dist/dnd/index.js +3 -2
  17. package/dist/dnd-BvjEDo-x.js +4197 -0
  18. package/dist/dnd-BvjEDo-x.js.map +1 -0
  19. package/dist/document-BQhb7YR8.d.ts +17 -0
  20. package/dist/{document-CHO215iP.js → document-uHqw0mvr.js} +194 -109
  21. package/dist/document-uHqw0mvr.js.map +1 -0
  22. package/dist/edit-options-C_r9aCz4.d.ts +100 -0
  23. package/dist/editor/index.d.ts +1 -1
  24. package/dist/editor/index.js +2 -2
  25. package/dist/{editor-CMElfHer.js → editor-CvnzrM9J.js} +2 -2
  26. package/dist/{editor-CMElfHer.js.map → editor-CvnzrM9J.js.map} +1 -1
  27. package/dist/error/index.d.ts +1 -1
  28. package/dist/error/index.js +2 -2
  29. package/dist/{error-CN_GCnXB.js → error-CFzvnLCf.js} +18 -32
  30. package/dist/error-CFzvnLCf.js.map +1 -0
  31. package/dist/{index-DpDU1IAw.d.ts → index-92L7F440.d.ts} +2 -2
  32. package/dist/{index-DrWtSKXu.d.ts → index-BZpZwrxT.d.ts} +2 -2
  33. package/dist/index-C8h8TcIl.d.ts +15 -0
  34. package/dist/{index-13BDSrQc.d.ts → index-C93npmTU.d.ts} +4 -6
  35. package/dist/{index-DQkL37eL.d.ts → index-CqsS207F.d.ts} +6 -12
  36. package/dist/{index-CiWB0zFb.d.ts → index-DQcdHg_V.d.ts} +18 -136
  37. package/dist/{index-CRwEhJ7w.d.ts → index-DfIvkht8.d.ts} +3 -3
  38. package/dist/index.d.ts +12 -11
  39. package/dist/index.js +6 -6
  40. package/dist/index.js.map +1 -1
  41. package/dist/{messages-IBPs4TkZ.d.ts → messages-BpN3QIhj.d.ts} +8 -2
  42. package/dist/{messages-CSrMI4Rm.js → messages-DrINcRdG.js} +8 -2
  43. package/dist/messages-DrINcRdG.js.map +1 -0
  44. package/dist/preview/index.d.ts +2 -2
  45. package/dist/preview/index.js +2 -3
  46. package/dist/{preview-CtyG5UbH.js → preview-B05MkVIQ.js} +16 -13
  47. package/dist/preview-B05MkVIQ.js.map +1 -0
  48. package/dist/provider/index.d.ts +2 -2
  49. package/dist/provider/index.js +2 -2
  50. package/dist/{sections-jYuqS4KB.js → sections-DhH_aVf5.js} +4 -7
  51. package/dist/sections-DhH_aVf5.js.map +1 -0
  52. package/dist/style.css +809 -4950
  53. package/dist/{validate-DB59Z_Nx.d.ts → types-Czps1Txy.d.ts} +12 -28
  54. package/dist/ui-kit/index.d.ts +22 -0
  55. package/dist/{constants-DU17Tdwo.js → ui-kit/index.js} +147 -54
  56. package/dist/ui-kit/index.js.map +1 -0
  57. package/dist/ui-kit/style.css +5039 -0
  58. package/dist/update-2PJbwoS8.d.ts +68 -0
  59. package/dist/{items-BXXtMUNI.js → update-BuYQJqjq.js} +143 -392
  60. package/dist/update-BuYQJqjq.js.map +1 -0
  61. package/dist/{use-dynamic-tailwind-BP1toJkW.js → use-dynamic-tailwind-B3l1qZRW.js} +318 -287
  62. package/dist/use-dynamic-tailwind-B3l1qZRW.js.map +1 -0
  63. package/dist/use-field-state-iQGW0vc6.js +131 -0
  64. package/dist/use-field-state-iQGW0vc6.js.map +1 -0
  65. package/dist/utils/ast/index.d.ts +47 -4
  66. package/dist/utils/ast/index.js +4 -64
  67. package/dist/utils/ast/index.js.map +1 -1
  68. package/dist/utils/index.d.ts +13 -32
  69. package/dist/utils/index.js +4 -26
  70. package/dist/validate-CZz30Pnb.js +122 -0
  71. package/dist/validate-CZz30Pnb.js.map +1 -0
  72. package/dist/validate-CiA1LF6S.d.ts +33 -0
  73. package/package.json +20 -10
  74. package/dist/boundary-BLB80tyw.js.map +0 -1
  75. package/dist/compile-Dxas-D05.js.map +0 -1
  76. package/dist/constants-DU17Tdwo.js.map +0 -1
  77. package/dist/core-Bgfek364.js.map +0 -1
  78. package/dist/dnd-V8NAxd_R.js +0 -2755
  79. package/dist/dnd-V8NAxd_R.js.map +0 -1
  80. package/dist/document-CHO215iP.js.map +0 -1
  81. package/dist/document-DqRSCtsx.d.ts +0 -1614
  82. package/dist/error-CN_GCnXB.js.map +0 -1
  83. package/dist/index-C_PfR4X9.d.ts +0 -734
  84. package/dist/items-BXXtMUNI.js.map +0 -1
  85. package/dist/messages-CSrMI4Rm.js.map +0 -1
  86. package/dist/preview-CtyG5UbH.js.map +0 -1
  87. package/dist/sections-jYuqS4KB.js.map +0 -1
  88. package/dist/use-dynamic-tailwind-BP1toJkW.js.map +0 -1
  89. package/dist/utils/index.js.map +0 -1
  90. package/dist/validate-iLo8IONY.js +0 -64
  91. package/dist/validate-iLo8IONY.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dnd-BvjEDo-x.js","names":["styles","styles","styles","LiveError","styles","CSS","styles","Renderer","styles","styles","styles","styles","styles","styles","Children","styles","styles","CoreEditor","styles","CSS","t.isExpression","t.isObjectExpression","t.templateLiteral","t.templateElement","t.isJSXElement","t.isJSXFragment","t.stringLiteral","t.isObjectProperty","t.isIdentifier","t.isExpression","t.isJSXOpeningElement","t.isJSXAttribute","t.isJSXIdentifier","t.isStringLiteral","t.isJSXSpreadAttribute","t.isSpreadElement","t.isExpression","t.isObjectExpression","t.isObjectProperty","t.isIdentifier","t.isJSXElement","t.isJSXFragment","t.isExpression","t.isObjectExpression","styles","styles","Children","styles","Panel","styles","styles","styles","PropertyPanel","Dnd","canvasStyles","Renderer","layoutStyles","DndImpl"],"sources":["../src/constants/palette-sections.ts","../src/components/dnd/canvas/canvas.module.css","../src/components/dnd/layout.module.css","../src/components/dnd/canvas/canvas-notice.tsx","../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/button.module.css","../src/components/dnd/button.tsx","../src/components/dnd/canvas/section-handlers.ts","../src/components/dnd/canvas/sortable.tsx","../src/components/dnd/canvas/overlay.tsx","../src/components/dnd/toast.module.css","../src/components/dnd/toast.ts","../src/components/dnd/edit-options.ts","../src/components/dnd/inspector.ts","../src/components/dnd/drawer.module.css","../src/components/dnd/drawer.tsx","../src/components/dnd/layout-context.ts","../src/components/dnd/panel/panel.module.css","../src/components/dnd/panel/element-selection.ts","../src/components/dnd/panel-binding.ts","../src/components/dnd/panel/structure.module.css","../src/components/dnd/panel/row-controls.module.css","../src/components/dnd/panel/row-controls.tsx","../src/components/dnd/panel/selection/selection.module.css","../src/components/dnd/panel/selection/bulk-actions-bar.tsx","../src/components/dnd/panel/selection/select-all-checkbox.tsx","../src/components/dnd/panel/selection/selection-checkbox.tsx","../src/components/dnd/panel/selection/use-structural-selection.ts","../src/components/dnd/panel/children/use-dnd-children.ts","../src/components/dnd/panel/children/children.tsx","../src/components/dnd/panel/fields/color-field.tsx","../src/components/dnd/panel/fields/jsx-editor-field.tsx","../src/components/dnd/panel/fields/labeled-field.tsx","../src/components/dnd/panel/items/sortable-items.tsx","../src/utils/ast/array-source.ts","../src/utils/ast/items.ts","../src/components/dnd/panel/items/item-bindings.ts","../src/components/dnd/panel/items/item-identity.ts","../src/components/dnd/panel/items/items-source.ts","../src/components/dnd/panel/items/use-item-expansion.ts","../src/components/dnd/panel/items/use-dnd-items.ts","../src/components/dnd/panel/items/items.tsx","../src/components/dnd/panel/field.tsx","../src/components/dnd/panel/element-fields.tsx","../src/components/dnd/panel/panel.tsx","../src/components/dnd/split-panes.module.css","../src/components/dnd/split-panes.tsx","../src/components/dnd/layout.tsx","../src/components/dnd/state/edit-errors.ts","../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/state/use-section-editing.ts","../src/components/dnd/dnd.tsx","../src/components/dnd/index.ts"],"sourcesContent":["import type { Section } from '../types';\n\n// The sections `Live.Dnd`'s palette offers when the host passes no `items`.\n// Plain elements with Tailwind classes, so they need no imports or modules.\n// `@jbpark/live-editor/ui-kit` has the same sections built with ui-kit\n// (`uiKitPaletteSections`).\nexport const PALETTE_SECTIONS: Section[] = [\n {\n id: 'hero',\n name: 'Hero',\n code: `\n <section data-name=\"Hero\" className=\"text-center text-white\">\n <div\n data-id=\"\"\n data-binding={[\n {\n label: 'Background Style',\n property: 'style',\n type: 'object',\n // Types the keys inside the object value; a leaf takes the same\n // fields as a top-level binding.\n render: {\n backgroundColor: { type: 'color', label: 'Background Color' },\n gap: {\n type: 'number',\n label: 'Content Spacing',\n // Constraints the library validates with or without a\n // widget.\n min: 0,\n max: 40,\n // Presentation only: the built-in panel ignores it and\n // shows a number input; a custom panel can switch on\n // widget.type.\n widget: { type: 'slider', step: 4, unit: 'px' },\n },\n },\n // Not a library field, so it arrives as meta.group.\n group: 'layout',\n },\n ]}\n style={{ backgroundColor: '#6366f1', gap: 16 }}\n className=\"flex flex-col items-center px-5 py-15\"\n >\n <h1\n data-id=\"\"\n data-binding={[\n {\n label: 'Title',\n property: 'innerText',\n type: 'string',\n required: true,\n },\n ]}\n className=\"text-5xl font-bold\"\n >\n Welcome to Live Editor\n </h1>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', type: 'richtext' }]}\n className=\"text-xl\"\n >\n Build <strong>dynamic components</strong> with drag & drop\n </p>\n <a\n data-id=\"\"\n data-binding={[\n { label: 'Button Text', property: 'innerText' },\n { label: 'Button Link', property: 'href', type: 'url' },\n ]}\n href=\"https://github.com/pjb0811/live-editor\"\n className=\"rounded-md bg-white px-6 py-3 text-lg font-medium text-indigo-500 hover:bg-gray-50\"\n >\n 🚀 Get Started\n </a>\n </div>\n </section>\n `,\n },\n {\n id: 'features',\n name: 'Features',\n code: `\n <section data-name=\"Features\" className=\"px-5 py-10\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Feature Cards', property: 'children' }]}\n className=\"mx-auto flex max-w-7xl flex-wrap gap-6\"\n >\n <div className=\"min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Icon', property: 'innerText' }]}\n className=\"mb-3 text-5xl\"\n >\n 🚀\n </div>\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl text-gray-800\"\n >\n Feature 1\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-gray-600\"\n >\n Amazing feature description\n </p>\n </div>\n <div className=\"min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Icon', property: 'innerText' }]}\n className=\"mb-3 text-5xl\"\n >\n ⚡\n </div>\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl text-gray-800\"\n >\n Feature 2\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-gray-600\"\n >\n Another great feature\n </p>\n </div>\n <div className=\"min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Icon', property: 'innerText' }]}\n className=\"mb-3 text-5xl\"\n >\n ✨\n </div>\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl text-gray-800\"\n >\n Feature 3\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-gray-600\"\n >\n One more awesome thing\n </p>\n </div>\n </div>\n </section>\n `,\n },\n {\n id: 'about',\n name: 'About',\n code: `\n <section data-name=\"About\" className=\"mx-auto max-w-3xl px-5 py-10\">\n <h2\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-5 text-4xl font-semibold text-gray-800\"\n >\n About Live Editor\n </h2>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description 1', type: 'richtext' }]}\n className=\"mb-4 text-lg leading-relaxed text-gray-600\"\n >\n Live Editor is a powerful visual development tool that enables you to\n create stunning web interfaces through an intuitive drag-and-drop\n experience. Built with modern web technologies, it streamlines your\n workflow and accelerates development cycles.\n </p>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description 2', type: 'richtext' }]}\n className=\"text-lg leading-relaxed text-gray-600\"\n >\n Whether you&apos;re a seasoned developer or just starting out, Live\n Editor provides the flexibility and control you need to bring your\n creative vision to life. Focus on what matters most - building great\n products.\n </p>\n </section>\n `,\n },\n {\n id: 'cta',\n name: 'CTA',\n code: `\n <section data-name=\"CTA\" className=\"bg-gray-50 px-5 py-12 text-center\">\n <div className=\"mx-auto max-w-xl\">\n <h2\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-4 text-3xl font-semibold text-gray-800\"\n >\n Ready to get started?\n </h2>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"mb-6 text-lg text-gray-600\"\n >\n Start exploring what Live Editor can do for your projects\n </p>\n <div\n data-id=\"\"\n data-binding={[{ label: 'Buttons', property: 'children' }]}\n className=\"flex flex-wrap justify-center gap-4\"\n >\n <a\n data-id=\"\"\n data-binding={[{ label: 'Button 1 Text', property: 'innerText' }]}\n href=\"#\"\n className=\"rounded-md bg-indigo-500 px-8 py-3 text-base text-white hover:bg-indigo-600\"\n >\n View Documentation\n </a>\n <a\n data-id=\"\"\n data-binding={[{ label: 'Button 2 Text', property: 'innerText' }]}\n href=\"#\"\n className=\"rounded-md border-2 border-indigo-500 px-8 py-3 text-base text-indigo-500 hover:bg-indigo-50\"\n >\n View Examples\n </a>\n </div>\n </div>\n </section>\n `,\n },\n {\n id: 'getting-started',\n name: 'Getting Started',\n code: `\n <section data-name=\"Getting Started\" className=\"px-5 py-16\">\n <div className=\"mx-auto max-w-5xl\">\n <h2\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-12 text-center text-4xl font-bold text-gray-800\"\n >\n How to Get Started\n </h2>\n <div className=\"grid gap-8 md:grid-cols-3\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Card 1 Content', property: 'children' }]}\n className=\"rounded-lg border-2 border-gray-200 bg-white p-8\"\n >\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Card 1 Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl font-bold text-gray-800\"\n >\n Explore\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Card 1 Icon', property: 'innerText' }]}\n className=\"mb-6 text-4xl font-bold text-indigo-600\"\n >\n 📚\n </p>\n <ul className=\"mb-8 space-y-3 text-gray-600\">\n <li>✓ Read documentation</li>\n <li>✓ Browse examples</li>\n <li>✓ Try the demo</li>\n </ul>\n <a\n data-id=\"\"\n data-binding={[{ label: 'Card 1 Button', property: 'innerText' }]}\n href=\"#\"\n className=\"block rounded-md border-2 border-indigo-500 px-4 py-2 text-center text-indigo-500 hover:bg-indigo-50\"\n >\n View Docs\n </a>\n </div>\n <div\n data-id=\"\"\n data-binding={[{ label: 'Card 2 Content', property: 'children' }]}\n className=\"relative rounded-lg border-2 border-indigo-500 bg-white p-8\"\n >\n <div className=\"absolute -top-4 left-1/2 -translate-x-1/2 rounded-full bg-indigo-500 px-4 py-1 text-sm text-white\">\n Recommended\n </div>\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Card 2 Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl font-bold text-gray-800\"\n >\n Practice\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Card 2 Icon', property: 'innerText' }]}\n className=\"mb-6 text-4xl font-bold text-indigo-600\"\n >\n 💻\n </p>\n <ul className=\"mb-8 space-y-3 text-gray-600\">\n <li>✓ Interactive playground</li>\n <li>✓ Experiment freely</li>\n <li>✓ Build your own</li>\n </ul>\n <a\n data-id=\"\"\n data-binding={[{ label: 'Card 2 Button', property: 'innerText' }]}\n href=\"#\"\n className=\"block rounded-md bg-indigo-500 px-4 py-2 text-center text-white hover:bg-indigo-600\"\n >\n Start Building\n </a>\n </div>\n <div\n data-id=\"\"\n data-binding={[{ label: 'Card 3 Content', property: 'children' }]}\n className=\"rounded-lg border-2 border-gray-200 bg-white p-8\"\n >\n <h3\n data-id=\"\"\n data-binding={[{ label: 'Card 3 Title', property: 'innerText' }]}\n className=\"mb-2 text-2xl font-bold text-gray-800\"\n >\n Contribute\n </h3>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Card 3 Icon', property: 'innerText' }]}\n className=\"mb-6 text-4xl font-bold text-indigo-600\"\n >\n 🤝\n </p>\n <ul className=\"mb-8 space-y-3 text-gray-600\">\n <li>✓ Report issues</li>\n <li>✓ Suggest features</li>\n <li>✓ Submit pull requests</li>\n </ul>\n <a\n data-id=\"\"\n data-binding={[{ label: 'Card 3 Button', property: 'innerText' }]}\n href=\"#\"\n className=\"block rounded-md border-2 border-indigo-500 px-4 py-2 text-center text-indigo-500 hover:bg-indigo-50\"\n >\n View on GitHub\n </a>\n </div>\n </div>\n </div>\n </section>\n `,\n },\n {\n id: 'key-features',\n name: 'Key Features',\n code: `\n <section data-name=\"Key Features\" className=\"bg-indigo-50 px-5 py-16\">\n <div className=\"mx-auto max-w-6xl\">\n <h2\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-12 text-center text-4xl font-bold text-gray-800\"\n >\n Key Features\n </h2>\n <div className=\"grid gap-8 md:grid-cols-2\">\n <div className=\"rounded-lg bg-white p-8 shadow-md\">\n <div className=\"mb-4 text-4xl\">🎨</div>\n <h3 className=\"mb-4 text-2xl font-bold text-gray-800\">\n Visual Editing\n </h3>\n <p className=\"text-gray-600\">\n See your changes in real-time as you build. Live Editor provides\n instant visual feedback, making it easier to understand how code\n affects your interface.\n </p>\n </div>\n <div className=\"rounded-lg bg-white p-8 shadow-md\">\n <div className=\"mb-4 text-4xl\">🧩</div>\n <h3 className=\"mb-4 text-2xl font-bold text-gray-800\">\n Component-Based\n </h3>\n <p className=\"text-gray-600\">\n Build with reusable components that you can drag, drop, and\n customize. Learn modern development patterns while creating your\n interface.\n </p>\n </div>\n </div>\n </div>\n </section>\n `,\n },\n {\n id: 'stats',\n name: 'Stats',\n code: `\n <section data-name=\"Stats\" className=\"bg-indigo-600 px-5 py-16 text-white\">\n <div\n data-id=\"\"\n data-binding={[{ label: 'Stats Cards', property: 'children' }]}\n className=\"mx-auto flex max-w-6xl flex-wrap justify-center gap-10\"\n >\n <div className=\"min-w-50 flex-1 text-center\">\n <p\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-5xl font-bold\"\n >\n Open\n </p>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-indigo-200\"\n >\n Source Project\n </p>\n </div>\n <div className=\"min-w-50 flex-1 text-center\">\n <p\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-5xl font-bold\"\n >\n Free\n </p>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-indigo-200\"\n >\n For Everyone\n </p>\n </div>\n <div className=\"min-w-50 flex-1 text-center\">\n <p\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-5xl font-bold\"\n >\n Active\n </p>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-indigo-200\"\n >\n Community\n </p>\n </div>\n <div className=\"min-w-50 flex-1 text-center\">\n <p\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-2 text-5xl font-bold\"\n >\n Learn\n </p>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Description', property: 'innerText' }]}\n className=\"text-indigo-200\"\n >\n By Doing\n </p>\n </div>\n </div>\n </section>\n `,\n },\n {\n id: 'roadmap',\n name: 'Roadmap',\n code: `\n <section data-name=\"Roadmap\" className=\"px-5 py-16\">\n <div className=\"mx-auto max-w-3xl\">\n <h2\n data-id=\"\"\n data-binding={[\n { label: 'Title', property: 'innerText', required: true },\n ]}\n className=\"mb-8 text-center text-4xl font-bold text-gray-800\"\n >\n Roadmap\n </h2>\n <ol\n data-id=\"\"\n data-binding={[{ label: 'Milestones', property: 'children' }]}\n >\n <li className=\"flex items-center gap-4 border-b border-gray-100 py-4\">\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Accent',\n property: 'style',\n type: 'object',\n render: {\n backgroundColor: { type: 'color', label: 'Accent Color' },\n },\n },\n ]}\n style={{ backgroundColor: '#22c55e' }}\n className=\"size-3 shrink-0 rounded-full\"\n />\n <div className=\"min-w-0 flex-1\">\n <p\n data-id=\"\"\n data-binding={[\n { label: 'Title', property: 'innerText', required: true },\n ]}\n className=\"font-semibold text-gray-800\"\n >\n Visual editing\n </p>\n <p className=\"text-sm text-gray-500\">\n <time\n data-id=\"\"\n data-binding={[\n {\n label: 'Release Date',\n property: 'dateTime',\n type: 'date',\n required: true,\n },\n { label: 'Date Text', property: 'innerText' },\n ]}\n dateTime=\"2026-03-02\"\n >\n March 2, 2026\n </time>\n {' · '}\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Status',\n property: 'innerText',\n options: [\n { label: 'Planned', value: 'Planned' },\n { label: 'In Progress', value: 'In Progress' },\n { label: 'Shipped', value: 'Shipped' },\n ],\n },\n ]}\n >\n Shipped\n </span>\n </p>\n <progress\n data-id=\"\"\n data-binding={[\n {\n label: 'Progress',\n property: 'value',\n type: 'number',\n min: 0,\n max: 100,\n widget: { type: 'slider', step: 10, unit: '%' },\n },\n ]}\n value={100}\n max={100}\n className=\"mt-2 h-2 w-full\"\n />\n </div>\n <a\n data-id=\"\"\n data-binding={[\n { label: 'Link Text', property: 'innerText' },\n {\n label: 'Link URL',\n property: 'href',\n type: 'url',\n pattern: '^https://',\n // Not a library field, so it arrives as meta.hint.\n hint: 'Must use https',\n },\n ]}\n href=\"https://github.com\"\n className=\"text-sm text-indigo-500 hover:underline\"\n >\n Release notes\n </a>\n </li>\n <li className=\"flex items-center gap-4 border-b border-gray-100 py-4\">\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Accent',\n property: 'style',\n type: 'object',\n render: {\n backgroundColor: { type: 'color', label: 'Accent Color' },\n },\n },\n ]}\n style={{ backgroundColor: '#6366f1' }}\n className=\"size-3 shrink-0 rounded-full\"\n />\n <div className=\"min-w-0 flex-1\">\n <p\n data-id=\"\"\n data-binding={[\n { label: 'Title', property: 'innerText', required: true },\n ]}\n className=\"font-semibold text-gray-800\"\n >\n Custom panels\n </p>\n <p className=\"text-sm text-gray-500\">\n <time\n data-id=\"\"\n data-binding={[\n {\n label: 'Release Date',\n property: 'dateTime',\n type: 'date',\n required: true,\n },\n { label: 'Date Text', property: 'innerText' },\n ]}\n dateTime=\"2026-09-26\"\n >\n September 26, 2026\n </time>\n {' · '}\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Status',\n property: 'innerText',\n options: [\n { label: 'Planned', value: 'Planned' },\n { label: 'In Progress', value: 'In Progress' },\n { label: 'Shipped', value: 'Shipped' },\n ],\n },\n ]}\n >\n In Progress\n </span>\n </p>\n <progress\n data-id=\"\"\n data-binding={[\n {\n label: 'Progress',\n property: 'value',\n type: 'number',\n min: 0,\n max: 100,\n widget: { type: 'slider', step: 10, unit: '%' },\n },\n ]}\n value={60}\n max={100}\n className=\"mt-2 h-2 w-full\"\n />\n </div>\n <a\n data-id=\"\"\n data-binding={[\n { label: 'Link Text', property: 'innerText' },\n {\n label: 'Link URL',\n property: 'href',\n type: 'url',\n pattern: '^https://',\n // Not a library field, so it arrives as meta.hint.\n hint: 'Must use https',\n },\n ]}\n href=\"https://github.com\"\n className=\"text-sm text-indigo-500 hover:underline\"\n >\n Guide\n </a>\n </li>\n <li className=\"flex items-center gap-4 border-b border-gray-100 py-4\">\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Accent',\n property: 'style',\n type: 'object',\n render: {\n backgroundColor: { type: 'color', label: 'Accent Color' },\n },\n },\n ]}\n style={{ backgroundColor: '#f59e0b' }}\n className=\"size-3 shrink-0 rounded-full\"\n />\n <div className=\"min-w-0 flex-1\">\n <p\n data-id=\"\"\n data-binding={[\n { label: 'Title', property: 'innerText', required: true },\n ]}\n className=\"font-semibold text-gray-800\"\n >\n Collaboration\n </p>\n <p className=\"text-sm text-gray-500\">\n <time\n data-id=\"\"\n data-binding={[\n {\n label: 'Release Date',\n property: 'dateTime',\n type: 'date',\n required: true,\n },\n { label: 'Date Text', property: 'innerText' },\n ]}\n dateTime=\"2027-01-15\"\n >\n January 15, 2027\n </time>\n {' · '}\n <span\n data-id=\"\"\n data-binding={[\n {\n label: 'Status',\n property: 'innerText',\n options: [\n { label: 'Planned', value: 'Planned' },\n { label: 'In Progress', value: 'In Progress' },\n { label: 'Shipped', value: 'Shipped' },\n ],\n },\n ]}\n >\n Planned\n </span>\n </p>\n <progress\n data-id=\"\"\n data-binding={[\n {\n label: 'Progress',\n property: 'value',\n type: 'number',\n min: 0,\n max: 100,\n widget: { type: 'slider', step: 10, unit: '%' },\n },\n ]}\n value={0}\n max={100}\n className=\"mt-2 h-2 w-full\"\n />\n </div>\n <a\n data-id=\"\"\n data-binding={[\n { label: 'Link Text', property: 'innerText' },\n {\n label: 'Link URL',\n property: 'href',\n type: 'url',\n pattern: '^https://',\n // Not a library field, so it arrives as meta.hint.\n hint: 'Must use https',\n },\n ]}\n href=\"https://github.com\"\n className=\"text-sm text-indigo-500 hover:underline\"\n >\n Discussion\n </a>\n </li>\n </ol>\n <p className=\"mt-6 text-center text-sm text-gray-500\">\n Last updated{' '}\n <time\n data-id=\"\"\n data-binding={[\n {\n label: 'Updated On',\n property: 'dateTime',\n type: 'date',\n required: true,\n },\n { label: 'Updated Text', property: 'innerText' },\n ]}\n dateTime=\"2026-09-26\"\n >\n September 26, 2026\n </time>\n {' · '}\n <a\n data-id=\"\"\n data-binding={[\n { label: 'Link Text', property: 'innerText' },\n {\n label: 'Link URL',\n property: 'href',\n type: 'url',\n required: true,\n pattern: '^https://',\n },\n ]}\n href=\"https://github.com/pjb0811/live-editor/releases\"\n className=\"text-indigo-500 hover:underline\"\n >\n All releases\n </a>\n </p>\n </div>\n </section>\n `,\n },\n {\n id: 'faq',\n name: 'FAQ',\n code: `\n <section data-name=\"FAQ\" className=\"px-5 py-16\">\n <div className=\"mx-auto max-w-3xl\">\n <h2\n data-id=\"\"\n data-binding={[{ label: 'Title', property: 'innerText' }]}\n className=\"mb-12 text-center text-4xl font-bold text-gray-800\"\n >\n Frequently Asked Questions\n </h2>\n <div\n data-id=\"\"\n data-binding={[{ label: 'FAQ Items', property: 'children' }]}\n className=\"divide-y divide-gray-200\"\n >\n <details className=\"py-4\">\n <summary\n data-id=\"\"\n data-binding={[{ label: 'Question 1', property: 'innerText' }]}\n className=\"cursor-pointer text-lg font-semibold text-gray-800\"\n >\n What is Live Editor?\n </summary>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Answer 1', type: 'richtext' }]}\n className=\"mt-3 text-gray-600\"\n >\n Live Editor is an open-source tool for building web\n interfaces visually. It helps you learn web development by\n providing instant feedback as you build components.\n </p>\n </details>\n <details className=\"py-4\">\n <summary\n data-id=\"\"\n data-binding={[{ label: 'Question 2', property: 'innerText' }]}\n className=\"cursor-pointer text-lg font-semibold text-gray-800\"\n >\n Do I need coding experience?\n </summary>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Answer 2', type: 'richtext' }]}\n className=\"mt-3 text-gray-600\"\n >\n No! Live Editor is designed for all skill levels. Beginners\n can learn through visual editing, while experienced\n developers can work directly with code.\n </p>\n </details>\n <details className=\"py-4\">\n <summary\n data-id=\"\"\n data-binding={[{ label: 'Question 3', property: 'innerText' }]}\n className=\"cursor-pointer text-lg font-semibold text-gray-800\"\n >\n Is it really free?\n </summary>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Answer 3', type: 'richtext' }]}\n className=\"mt-3 text-gray-600\"\n >\n Yes, completely free! Live Editor is an open-source project\n with no hidden costs or premium tiers. All features are\n available to everyone.\n </p>\n </details>\n <details className=\"py-4\">\n <summary\n data-id=\"\"\n data-binding={[{ label: 'Question 4', property: 'innerText' }]}\n className=\"cursor-pointer text-lg font-semibold text-gray-800\"\n >\n How can I contribute?\n </summary>\n <p\n data-id=\"\"\n data-binding={[{ label: 'Answer 4', type: 'richtext' }]}\n className=\"mt-3 text-gray-600\"\n >\n You can contribute by reporting bugs, suggesting features,\n sharing your projects, or contributing code. Check our\n GitHub repository for more details.\n </p>\n </details>\n </div>\n </div>\n </section>\n `,\n },\n];\n","@layer components {\n .dropArea {\n box-sizing: border-box;\n min-height: 100%;\n padding: 0.25rem;\n border: 2px dashed var(--live-editor-color-border-subtle);\n }\n\n .fill {\n height: 100%;\n }\n\n .dropAreaOver {\n border-color: var(--live-editor-color-primary-border);\n background: var(--live-editor-color-primary-soft);\n }\n\n .dropBottom {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 6rem;\n margin-top: 0.5rem;\n border: 2px dashed var(--live-editor-color-border);\n border-radius: var(--live-editor-radius-lg);\n background: var(--live-editor-color-surface-muted);\n font-size: var(--live-editor-font-size-sm);\n color: var(--live-editor-color-text-muted);\n transition:\n background-color 0.2s,\n border-color 0.2s;\n }\n\n .dropBottomOver {\n border-color: var(--live-editor-color-focus);\n background: var(--live-editor-color-primary-soft);\n }\n\n .section {\n position: relative;\n }\n\n .sectionSelected {\n z-index: 10;\n outline: 2px solid var(--live-editor-color-focus);\n outline-offset: 2px;\n }\n\n .sectionDropTarget {\n border-top: 4px solid var(--live-editor-color-success);\n }\n\n /* Over the section's frame, so the frame never takes the pointer. */\n .sectionShield {\n position: absolute;\n inset: 0;\n z-index: 50;\n }\n\n .sectionToolbar {\n position: absolute;\n top: 0.25rem;\n right: 0.25rem;\n z-index: 60;\n display: flex;\n gap: 0.5rem;\n }\n\n .stale {\n position: sticky;\n top: 0;\n z-index: 70;\n padding: 0.5rem 0.75rem;\n border-bottom: 1px solid var(--live-editor-color-warning-border);\n background: var(--live-editor-color-warning-soft);\n font-size: var(--live-editor-font-size-sm);\n color: var(--live-editor-color-warning-text);\n }\n\n .empty {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: var(--live-editor-color-text-muted);\n }\n\n .notice {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5rem;\n text-align: center;\n\n & p {\n margin: 0;\n }\n }\n}\n","@layer components {\n .root {\n position: relative;\n display: flex;\n width: 100%;\n height: 100%;\n color: var(--live-editor-color-text);\n }\n\n .palette {\n box-sizing: border-box;\n height: 100%;\n padding: 1rem;\n overflow-y: auto;\n background: var(--live-editor-color-surface-muted);\n }\n\n .paletteItems {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n\n .canvas {\n position: relative;\n width: 100%;\n height: 100%;\n overflow-y: auto;\n }\n\n .panel {\n height: 100%;\n }\n\n /* Pins the element picker's switch to the bottom-left of the scroll area. */\n .pickerDock {\n position: sticky;\n bottom: 0;\n z-index: 70;\n height: 0;\n pointer-events: none;\n }\n\n .picker {\n position: absolute;\n bottom: 0.75rem;\n left: 0.75rem;\n pointer-events: auto;\n }\n\n .paletteButton {\n position: fixed;\n right: 1rem;\n bottom: 1rem;\n z-index: 20;\n\n @media (min-width: 768px) {\n display: none;\n }\n }\n\n .card {\n box-sizing: border-box;\n padding: 0.75rem 1rem;\n border: 1px solid var(--live-editor-color-border-subtle);\n border-radius: var(--live-editor-radius-lg);\n background: var(--live-editor-color-surface);\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n font-size: var(--live-editor-font-size-sm);\n cursor: grab;\n transition:\n border-color 0.15s,\n box-shadow 0.15s;\n\n &:hover {\n border-color: var(--live-editor-color-primary-border);\n box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);\n }\n\n /* A visible ring for keyboard focus only: the card is reachable with\n Tab (#435). */\n &:focus {\n outline: none;\n }\n\n &:focus-visible {\n outline: 2px solid var(--live-editor-color-focus);\n outline-offset: 2px;\n }\n }\n}\n","import styles from './canvas.module.css';\n\ninterface Props {\n title: React.ReactNode;\n detail: React.ReactNode;\n}\n\n// What an empty canvas says: why it is empty, and what to do about it.\nconst CanvasNotice = ({ title, detail }: Props) => (\n <div className={styles.notice}>\n <p>{title}</p>\n <span>{detail}</span>\n </div>\n);\n\nexport default CanvasNotice;\n","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';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport styles from './canvas.module.css';\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 styles.dropArea,\n shouldHighlight && styles.dropAreaOver,\n className,\n )}\n >\n {children}\n {isPaletteSectionDragging && (\n <div\n ref={setBottomRef}\n className={cn(\n styles.dropBottom,\n shouldHighlightBottom && styles.dropBottomOver,\n )}\n >\n {shouldHighlightBottom\n ? messages.canvas.dropHere\n : messages.canvas.dropAtBottom}\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';\n\nimport type { Section } from '~/types';\n\nimport styles from '../layout.module.css';\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.\ninterface 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 <div\n ref={ref}\n style={{ opacity: isDragging ? 0.5 : 1 }}\n {...dragProps}\n className={styles.card}\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 </div>\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 { renderStableComponent } from '~/components/preview/stable-component';\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 // Inside the frame, which may not have the editor's stylesheet.\n style={{ width: '100%', overflowX: '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 {/* Keeps the section's DOM when an edit leaves its hooks alone. */}\n {renderStableComponent(Component, preview, {\n headers,\n container,\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","/* A sublayer of `components`, so the styles a caller adds through\n `className` (in `components` itself) override these. */\n@layer components.primitives {\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.375rem;\n height: 2rem;\n margin: 0;\n padding: 0 0.75rem;\n border: 1px solid transparent;\n border-radius: var(--live-editor-radius-lg);\n font: inherit;\n font-size: var(--live-editor-font-size-sm);\n font-weight: 500;\n line-height: 1;\n white-space: nowrap;\n cursor: pointer;\n transition:\n background-color 0.15s,\n border-color 0.15s,\n color 0.15s;\n\n /* The tone each variant draws with. */\n --tone: var(--live-editor-color-text);\n --tone-soft: var(--live-editor-color-surface-muted);\n --tone-border: var(--live-editor-color-border);\n --tone-text: var(--live-editor-color-surface);\n\n &:focus-visible {\n outline: 2px solid var(--live-editor-color-focus);\n outline-offset: 2px;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n & svg {\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n }\n }\n\n .small {\n height: 1.5rem;\n padding: 0 0.5rem;\n font-size: var(--live-editor-font-size-xs);\n\n & svg {\n width: 0.75rem;\n height: 0.75rem;\n }\n }\n\n .iconOnly {\n width: 2rem;\n padding: 0;\n\n &.small {\n width: 1.5rem;\n }\n }\n\n .circle {\n border-radius: 9999px;\n }\n\n .primary {\n --tone: var(--live-editor-color-primary);\n --tone-soft: var(--live-editor-color-primary-soft);\n --tone-border: var(--live-editor-color-primary-border);\n --tone-text: var(--live-editor-color-primary-text);\n }\n\n .danger {\n --tone: var(--live-editor-color-danger);\n --tone-soft: var(--live-editor-color-danger-soft);\n --tone-border: var(--live-editor-color-danger);\n --tone-text: #ffffff;\n }\n\n .success {\n --tone: var(--live-editor-color-success);\n --tone-soft: var(--live-editor-color-surface-muted);\n --tone-border: var(--live-editor-color-success);\n --tone-text: #ffffff;\n }\n\n .outlined {\n border-color: var(--tone-border);\n background: var(--live-editor-color-surface);\n color: var(--tone);\n\n &:hover:not(:disabled) {\n background: var(--tone-soft);\n }\n }\n\n .solid {\n border-color: var(--tone);\n background: var(--tone);\n color: var(--tone-text);\n\n &:hover:not(:disabled) {\n filter: brightness(0.92);\n }\n }\n\n .text {\n background: transparent;\n color: var(--tone);\n\n &:hover:not(:disabled) {\n background: var(--tone-soft);\n }\n }\n}\n","import { cn } from '~/utils/cn';\n\nimport styles from './button.module.css';\n\ninterface ButtonProps extends Omit<\n React.ComponentPropsWithRef<'button'>,\n 'type'\n> {\n variant?: 'outlined' | 'solid' | 'text';\n tone?: 'neutral' | 'primary' | 'danger' | 'success';\n size?: 'small' | 'middle';\n shape?: 'default' | 'circle';\n // Drawn before `children`. A button with an icon and no children is\n // square, and needs an `aria-label`.\n icon?: React.ReactNode;\n}\n\n// The chrome's button. Always `type=\"button\"`, so it never submits a form\n// the editor sits in.\nconst Button = ({\n variant = 'outlined',\n tone = 'neutral',\n size = 'middle',\n shape = 'default',\n icon,\n className,\n children,\n ...restProps\n}: ButtonProps) => (\n <button\n type=\"button\"\n className={cn(\n styles.button,\n styles[variant],\n tone !== 'neutral' && styles[tone],\n size === 'small' && styles.small,\n shape === 'circle' && styles.circle,\n icon && !children && styles.iconOnly,\n className,\n )}\n {...restProps}\n >\n {icon}\n {children}\n </button>\n);\n\nexport default Button;\n","import { createContext, useContext } from 'react';\n\nexport type SectionNavigation = 'previous' | 'next' | 'first' | 'last';\n\n// What every canvas section shares: the element picker (#432) and keyboard\n// navigation (#435). Each handler takes the section's id.\nexport interface SectionHandlers {\n // The element picker is on: sections can't be dragged, and the pointer\n // over one 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 sectionId: string,\n section: HTMLElement,\n overlay: Element,\n x: number,\n y: number,\n ) => void;\n onInspectLeave: () => void;\n // Registers a section's focusable wrapper, so the canvas can move focus\n // to it.\n nodeRef: (sectionId: string) => (node: HTMLElement | null) => void;\n // Arrow keys and Home/End on a focused section, outside a drag.\n onNavigate: (sectionId: string, to: SectionNavigation) => void;\n // Delete or Backspace on a focused section.\n onDeleteKey: (sectionId: string) => void;\n}\n\n// Provided around the canvas only. The drag overlay's copy of a section\n// renders outside it, so it registers no node and handles no keys.\nexport const SectionHandlersContext = createContext<SectionHandlers | null>(\n null,\n);\n\nexport const useSectionHandlers = () => useContext(SectionHandlersContext);\n","import { useSortable } from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { ChevronDown, ChevronUp, Copy, Trash } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport styles from './canvas.module.css';\n\nimport Button from '../button';\nimport { paletteSectionOf } from '../palette/palette-drag';\nimport { type SectionNavigation, useSectionHandlers } from './section-handlers';\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}\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,\n onCopy,\n onMoveUp,\n onMoveDown,\n canMoveUp = false,\n canMoveDown = false,\n}: Props) => {\n // The picker and keyboard handlers, or `null` in the drag overlay.\n const handlers = useSectionHandlers();\n const inspecting = handlers?.inspecting ?? false;\n\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 && handlers) {\n // Otherwise the arrow keys also scroll the canvas.\n e.preventDefault();\n handlers.onNavigate(id, to);\n\n return;\n }\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && handlers) {\n e.preventDefault();\n handlers.onDeleteKey(id);\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 handlers?.nodeRef(id)(node);\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 styles.section,\n selected && styles.sectionSelected,\n isPaletteSectionOver && styles.sectionDropTarget,\n )}\n >\n <div\n className={styles.sectionShield}\n onPointerMove={\n inspecting\n ? e =>\n handlers?.onInspectMove(\n e.currentTarget.parentElement!,\n e.currentTarget,\n e.clientX,\n e.clientY,\n )\n : undefined\n }\n onPointerLeave={inspecting ? handlers?.onInspectLeave : undefined}\n onClick={\n inspecting\n ? e => {\n // The pick selects the section itself.\n e.stopPropagation();\n handlers?.onInspectPick(\n id,\n e.currentTarget.parentElement!,\n e.currentTarget,\n e.clientX,\n e.clientY,\n );\n }\n : undefined\n }\n />\n {children}\n {selected && (\n <div className={styles.sectionToolbar}>\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={press(() => onCopy?.(id))}\n aria-label={messages.section.duplicate}\n />\n <Button\n tone=\"danger\"\n icon={<Trash />}\n onClick={press(() => onDelete?.(id))}\n aria-label={messages.section.delete}\n />\n </div>\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","@layer components {\n .region {\n position: fixed;\n bottom: 1rem;\n left: 50%;\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n width: max-content;\n max-width: calc(100vw - 2rem);\n transform: translateX(-50%);\n }\n\n .toast {\n box-sizing: border-box;\n max-width: 24rem;\n padding: 0.75rem 1rem;\n border: 1px solid var(--live-editor-color-danger);\n border-left-width: 4px;\n border-radius: var(--live-editor-radius-lg);\n background: var(--live-editor-color-surface);\n box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);\n color: var(--live-editor-color-text);\n font-size: var(--live-editor-font-size-sm);\n cursor: pointer;\n }\n\n .title {\n font-weight: 600;\n color: var(--live-editor-color-danger);\n }\n\n .description {\n margin-top: 0.25rem;\n color: var(--live-editor-color-text-muted);\n }\n}\n","import styles from './toast.module.css';\n\nconst TOAST_DURATION = 6000;\n\nlet region: HTMLElement | null = null;\n\n// The fixed stack the toasts go in, made on first use. Plain DOM rather\n// than React, so a toast can show from anywhere, inside `Live.Dnd` or not.\nconst getRegion = () => {\n if (region?.isConnected) {\n return region;\n }\n\n region = document.createElement('div');\n region.className = styles.region!;\n document.body.append(region);\n\n return region;\n};\n\n// Shows an error with an optional description for a few seconds, announced\n// to screen readers. A click dismisses it early.\nexport const showErrorToast = (title: string, description?: string) => {\n if (typeof document === 'undefined') {\n return;\n }\n\n const toast = document.createElement('div');\n\n toast.className = styles.toast!;\n toast.setAttribute('role', 'alert');\n\n const heading = document.createElement('div');\n\n heading.className = styles.title!;\n heading.textContent = title;\n toast.append(heading);\n\n if (description) {\n const detail = document.createElement('div');\n\n detail.className = styles.description!;\n detail.textContent = description;\n toast.append(detail);\n }\n\n const remove = () => {\n window.clearTimeout(timer);\n toast.remove();\n };\n const timer = window.setTimeout(remove, TOAST_DURATION);\n\n toast.addEventListener('click', remove);\n getRegion().append(toast);\n};\n","import { createContext, useContext } from 'react';\n\nimport type { BindingOptions } from '~/utils/ast/types';\nimport type { UpdateFailure } from '~/utils/ast/update';\n\nimport type { FieldProps } from './panel/types';\nimport { showErrorToast } from './toast';\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 showErrorToast(error.title, error.description);\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","@layer components {\n .drawer {\n box-sizing: border-box;\n width: 100%;\n max-width: 100%;\n height: 80dvh;\n max-height: 80dvh;\n margin: auto 0 0;\n padding: 0;\n border: 0;\n border-radius: var(--live-editor-radius-lg) var(--live-editor-radius-lg) 0 0;\n background: var(--live-editor-color-surface);\n color: var(--live-editor-color-text);\n animation: slide-up 0.2s ease-out;\n\n &::backdrop {\n background: rgb(0 0 0 / 0.4);\n }\n }\n\n /* Fills the dialog, so a click outside it lands on the backdrop only. */\n .content {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n border-bottom: 1px solid var(--live-editor-color-border-subtle);\n }\n\n .title {\n margin: 0;\n font-size: var(--live-editor-font-size-lg);\n font-weight: 600;\n }\n\n .body {\n flex: 1;\n padding: 1rem;\n overflow-y: auto;\n }\n\n @keyframes slide-up {\n from {\n transform: translateY(100%);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .drawer {\n animation: none;\n }\n }\n}\n","import { useEffect, useId, useRef } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport styles from './drawer.module.css';\n\nimport Button from './button';\n\ninterface Props {\n open: boolean;\n title: React.ReactNode;\n closeLabel: string;\n onClose: () => void;\n children: React.ReactNode;\n}\n\n// A sheet that slides up from the bottom of the viewport, in a modal\n// `<dialog>`: focus moves into it and stays there, the page behind is\n// inert, and Escape or a click on the backdrop closes it. Its children\n// mount only while it is open.\nconst Drawer = ({ open, title, closeLabel, onClose, children }: Props) => {\n const titleId = useId();\n\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n\n if (!dialog || !open) {\n return;\n }\n\n // jsdom has no `showModal`.\n if (typeof dialog.showModal === 'function') {\n dialog.showModal();\n } else {\n dialog.setAttribute('open', '');\n }\n\n return () => {\n if (typeof dialog.close === 'function') {\n dialog.close();\n } else {\n dialog.removeAttribute('open');\n }\n };\n }, [open]);\n\n if (!open) {\n return null;\n }\n\n return (\n <dialog\n ref={dialogRef}\n className={styles.drawer}\n aria-labelledby={titleId}\n // Escape fires `cancel`; the dialog stays open until `open` changes.\n onCancel={e => {\n e.preventDefault();\n onClose();\n }}\n // A click on the dialog itself, not on its content, is on the\n // backdrop.\n onClick={e => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n }}\n >\n <div className={styles.content}>\n <div className={styles.header}>\n <h2 id={titleId} className={styles.title}>\n {title}\n </h2>\n <Button\n variant=\"text\"\n size=\"small\"\n icon={<X />}\n aria-label={closeLabel}\n onClick={onClose}\n />\n </div>\n <div className={styles.body}>{children}</div>\n </div>\n </dialog>\n );\n};\n\nexport default Drawer;\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","@layer components {\n .empty {\n margin: 0;\n padding: 1rem;\n font-size: var(--live-editor-font-size-sm);\n color: var(--live-editor-color-text-muted);\n }\n\n .panel {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n height: 100%;\n padding: 1rem;\n overflow-x: hidden;\n overflow-y: auto;\n color: var(--live-editor-color-text);\n }\n\n .header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n }\n\n .title {\n margin: 0;\n font-size: var(--live-editor-font-size-lg);\n font-weight: 600;\n }\n\n .actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n }\n\n .note {\n display: block;\n font-size: var(--live-editor-font-size-xs);\n color: var(--live-editor-color-text-subtle);\n }\n\n .readOnly {\n display: block;\n font-size: var(--live-editor-font-size-xs);\n color: var(--live-editor-color-warning-text);\n }\n\n .element {\n border-radius: var(--live-editor-radius);\n\n &[data-picked] {\n outline: 2px solid var(--live-editor-color-focus);\n outline-offset: 4px;\n }\n }\n\n .elementHeader {\n display: flex;\n align-items: baseline;\n gap: 0.375rem;\n min-width: 0;\n margin-bottom: 0.5rem;\n padding-bottom: 0.25rem;\n border-bottom: 1px solid var(--live-editor-color-border-subtle);\n font-size: var(--live-editor-font-size-xs);\n }\n\n .elementTag {\n flex-shrink: 0;\n font-family: var(--live-editor-font-mono);\n color: var(--live-editor-color-text-muted);\n }\n\n .elementText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--live-editor-color-text-subtle);\n }\n\n .bindings {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n\n .binding {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n }\n\n .bindingLabel {\n display: block;\n font-size: var(--live-editor-font-size-xs);\n font-weight: 600;\n color: var(--live-editor-color-text);\n }\n\n .bindingProperty {\n margin-left: 0.25rem;\n font-weight: 400;\n color: var(--live-editor-color-text-subtle);\n }\n}\n","import { type RefObject, createContext } from 'react';\n\n// The elements whose fields to mark, by `data-id`, and the scrolling box\n// that keeps a newly marked one in view. A set, so a mode that selects\n// several elements at once can mark them all (#643).\nexport interface ElementSelection {\n ids: ReadonlySet<string>;\n scrollRootRef?: RefObject<HTMLElement | null>;\n}\n\nexport const ElementSelectionContext = createContext<ElementSelection>({\n ids: new Set(),\n});\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. See\n // `BindingFieldSpec` for each.\n min?: number;\n max?: number;\n pattern?: string;\n patternMessage?: string;\n required?: boolean;\n minLength?: number;\n maxLength?: number;\n step?: number;\n minItems?: number;\n maxItems?: number;\n minDate?: string;\n maxDate?: string;\n protocols?: string[];\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 patternMessage: binding.patternMessage,\n required: binding.required,\n minLength: binding.minLength,\n maxLength: binding.maxLength,\n step: binding.step,\n minItems: binding.minItems,\n maxItems: binding.maxItems,\n minDate: binding.minDate,\n maxDate: binding.maxDate,\n protocols: binding.protocols,\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","/* The Items and Children editors. Each root sets the accent its rows and\n headings draw with. */\n@layer components {\n .items {\n --accent: var(--live-editor-color-primary);\n --accent-soft: var(--live-editor-color-primary-soft);\n --accent-border: var(--live-editor-color-primary-border);\n }\n\n .children {\n --accent: var(--live-editor-color-success);\n --accent-soft: var(--live-editor-color-surface-muted);\n --accent-border: var(--live-editor-color-border-subtle);\n }\n\n .stack,\n .stackLoose,\n .stackTight {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n\n .stackLoose {\n gap: 1rem;\n }\n\n .stackTight {\n gap: 0.25rem;\n }\n\n /* Wraps rather than overlaps when the panel is narrow. */\n .row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n }\n\n .rowStart {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n min-width: 0;\n }\n\n .heading {\n font-size: var(--live-editor-font-size-sm);\n font-weight: 600;\n color: var(--accent);\n }\n\n .label {\n font-size: var(--live-editor-font-size-xs);\n font-weight: 500;\n color: var(--accent);\n }\n\n .muted {\n font-size: var(--live-editor-font-size-xs);\n color: var(--live-editor-color-text-muted);\n }\n\n .notice,\n .noticeDanger,\n .noticeWarning {\n padding: 0.75rem;\n border: 1px dashed var(--live-editor-color-border-subtle);\n border-radius: var(--live-editor-radius);\n font-size: var(--live-editor-font-size-xs);\n color: var(--live-editor-color-text-muted);\n }\n\n .noticeDanger {\n border-color: var(--live-editor-color-danger);\n color: var(--live-editor-color-danger);\n }\n\n .noticeWarning {\n border-color: var(--live-editor-color-warning-border);\n color: var(--live-editor-color-warning-text);\n }\n\n /* One item or child. */\n .card {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.75rem;\n border: 1px solid var(--accent-border);\n border-radius: var(--live-editor-radius);\n background: var(--accent-soft);\n }\n\n .cardCompact {\n padding: 0.5rem;\n }\n\n .dragging {\n position: relative;\n z-index: 10;\n box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);\n }\n\n /* The fields of one element inside an item or child. */\n .element {\n padding: 0.5rem;\n border: 1px solid var(--accent-border);\n border-radius: var(--live-editor-radius);\n background: var(--live-editor-color-surface);\n\n &[data-picked] {\n outline: 2px solid var(--live-editor-color-focus);\n outline-offset: 2px;\n }\n }\n\n .indented {\n margin-left: 0.5rem;\n }\n\n .elementTag {\n margin-bottom: 0.25rem;\n font-size: var(--live-editor-font-size-xs);\n color: var(--accent);\n }\n\n .nested {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n padding-top: 0.5rem;\n border-top: 1px solid var(--accent-border);\n }\n\n .propertyLabel {\n font-size: var(--live-editor-font-size-xs);\n font-weight: 500;\n }\n\n .valueType {\n font-size: var(--live-editor-font-size-xs);\n color: var(--live-editor-color-text-muted);\n text-align: right;\n }\n\n .handle,\n .toggle {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n margin: 0;\n padding: 0.125rem;\n border: 0;\n border-radius: var(--live-editor-radius);\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n\n &:focus-visible {\n outline: 2px solid var(--live-editor-color-focus);\n }\n }\n\n .handle {\n cursor: grab;\n color: var(--live-editor-color-text-subtle);\n\n &:hover:not(:disabled) {\n color: var(--live-editor-color-text);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n }\n }\n\n .toggle {\n padding: 0 0.25rem;\n white-space: nowrap;\n font-size: var(--live-editor-font-size-xs);\n font-weight: 500;\n }\n}\n","@layer components {\n .controls {\n display: flex;\n gap: 0.25rem;\n }\n}\n","import { ArrowDown, ArrowUp, X } from 'lucide-react';\n\nimport styles from './row-controls.module.css';\n\nimport Button from '../button';\n\ninterface Props {\n // The row's position among `count` rows.\n index: number;\n count: number;\n labels: { moveUp: string; moveDown: string; delete: string };\n disabled?: boolean;\n deleteDisabled?: boolean;\n onMove: (toIndex: number) => void;\n onDelete: () => void;\n}\n\n// Move up, move down and delete for one Items or Children row.\nconst RowControls = ({\n index,\n count,\n labels,\n disabled = false,\n deleteDisabled = false,\n onMove,\n onDelete,\n}: Props) => (\n <div className={styles.controls}>\n <Button\n size=\"small\"\n icon={<ArrowUp />}\n aria-label={labels.moveUp}\n disabled={disabled || index === 0}\n onClick={() => onMove(index - 1)}\n />\n <Button\n size=\"small\"\n icon={<ArrowDown />}\n aria-label={labels.moveDown}\n disabled={disabled || index === count - 1}\n onClick={() => onMove(index + 1)}\n />\n <Button\n tone=\"danger\"\n size=\"small\"\n icon={<X />}\n aria-label={labels.delete}\n title={labels.delete}\n disabled={disabled || deleteDisabled}\n onClick={onDelete}\n />\n </div>\n);\n\nexport default RowControls;\n","@layer components {\n .bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n padding: 0.5rem;\n border: 1px solid var(--live-editor-color-primary-border);\n border-radius: var(--live-editor-radius);\n background: var(--live-editor-color-primary-soft);\n }\n\n .count {\n font-size: var(--live-editor-font-size-xs);\n font-weight: 500;\n color: var(--live-editor-color-primary);\n }\n\n .actions {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n }\n\n /* `appearance` is set because a host reset may turn it off. */\n .checkbox {\n appearance: auto;\n width: 1rem;\n height: 1rem;\n margin: 0;\n accent-color: var(--live-editor-color-primary);\n cursor: pointer;\n\n &:disabled {\n cursor: not-allowed;\n }\n }\n\n .selectAll {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n font-size: var(--live-editor-font-size-xs);\n cursor: pointer;\n }\n}\n","import { ArrowDown, ArrowUp, Copy, X } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\n\nimport styles from './selection.module.css';\n\nimport Button from '../../button';\n\ninterface BulkActionsBarProps {\n count: number;\n disabled?: boolean;\n // Each on top of `disabled`, for a limit on the item count.\n duplicateDisabled?: boolean;\n deleteDisabled?: 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 duplicateDisabled = false,\n deleteDisabled = 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 className={styles.bar}>\n <div className={styles.count}>{messages.selection.count(count)}</div>\n <div className={styles.actions}>\n <Button\n size=\"small\"\n icon={<Copy />}\n title={messages.selection.duplicate}\n disabled={disabled || duplicateDisabled}\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 tone=\"danger\"\n size=\"small\"\n icon={<X />}\n title={messages.selection.delete}\n disabled={disabled || deleteDisabled}\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 { useEffect, useRef } from 'react';\n\nimport { useLiveMessages } from '~/components/context/messages';\n\nimport styles from './selection.module.css';\n\ninterface Props {\n total: number;\n selected: number;\n disabled?: boolean;\n onSelectAll: () => void;\n onClear: () => void;\n}\n\n// Selects or clears every row of an Items or Children editor at once (#638).\n// Checked when every row is selected, indeterminate when only some are.\n// Clicking it selects all rows unless all already are, then clears them.\nconst SelectAllCheckbox = ({\n total,\n selected,\n disabled = false,\n onSelectAll,\n onClear,\n}: Props) => {\n const messages = useLiveMessages();\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n const isAllSelected = total > 0 && selected >= total;\n const isIndeterminate = selected > 0 && !isAllSelected;\n\n // `indeterminate` is a DOM property only, with no attribute for it.\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = isIndeterminate;\n }\n }, [isIndeterminate]);\n\n return (\n <label className={styles.selectAll}>\n <input\n ref={inputRef}\n type=\"checkbox\"\n className={styles.checkbox}\n checked={isAllSelected}\n disabled={disabled}\n onChange={() => (isAllSelected ? onClear() : onSelectAll())}\n />\n {messages.selection.selectAll}\n </label>\n );\n};\n\nexport default SelectAllCheckbox;\n","import styles from './selection.module.css';\n\ninterface Props {\n checked: boolean;\n disabled?: boolean;\n onToggle: (shiftKey: boolean) => void;\n}\n\n// The checkbox that selects an Items or Children row. Reads Shift from the\n// click for range selection; Space and Shift+Space reach it as a click too.\n// The parent owns `checked`, so the box shows the new state once `onToggle`\n// updates it.\nconst SelectionCheckbox = ({ checked, disabled = false, onToggle }: Props) => (\n <input\n type=\"checkbox\"\n className={styles.checkbox}\n checked={checked}\n disabled={disabled}\n readOnly\n onClick={e => onToggle(e.shiftKey)}\n />\n);\n\nexport default SelectionCheckbox;\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.\ntype 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\ninterface 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 '../selection/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 { Plus } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { findEditableChildren } from '~/utils/ast/binding';\nimport { type DataAttrNode } from '~/utils/ast/types';\nimport { cn } from '~/utils/cn';\n\nimport styles from '../structure.module.css';\n\nimport Button from '../../button';\nimport {\n type PanelNodeChange,\n resolvePanelBindings,\n withPanelCommit,\n} from '../../panel-binding';\nimport ElementFields from '../element-fields';\nimport RowControls from '../row-controls';\nimport BulkActionsBar from '../selection/bulk-actions-bar';\nimport SelectAllCheckbox from '../selection/select-all-checkbox';\nimport SelectionCheckbox from '../selection/selection-checkbox';\nimport { useDndChildren } from './use-dnd-children';\n\n// A child node's bindings, committing through `onChange` by its own\n// `data-id`. Empty for a node with nothing bound.\nconst bindingsOf = (node: DataAttrNode, onChange?: PanelNodeChange) => {\n const source = resolvePanelBindings(node);\n\n return source ? withPanelCommit(source.bindings, onChange) : [];\n};\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={cn(styles.children, styles.stackLoose)}>\n <div className={styles.row}>\n <div className={styles.heading}>\n {messages.children.heading(items.length)}\n </div>\n <Button\n size=\"small\"\n tone=\"success\"\n icon={<Plus />}\n onClick={actions.add}\n >\n {messages.children.add}\n </Button>\n </div>\n\n {items.length > 0 && (\n <SelectAllCheckbox\n total={items.length}\n selected={selection.selected.size}\n onSelectAll={() =>\n selection.replace(new Set(items.map((_, index) => index)))\n }\n onClear={selection.clear}\n />\n )}\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 key={item.id || itemIndex} className={styles.card}>\n <div className={styles.row}>\n <div className={styles.rowStart}>\n <SelectionCheckbox\n checked={selection.isSelected(itemIndex)}\n onToggle={shiftKey => selection.toggle(itemIndex, shiftKey)}\n />\n <div className={styles.label}>\n {messages.children.child(\n itemIndex + 1,\n item.tagName || 'fragment',\n )}\n </div>\n </div>\n\n <RowControls\n index={itemIndex}\n count={items.length}\n labels={messages.children}\n onMove={toIndex => actions.move(itemIndex, toIndex)}\n onDelete={() => actions.remove(itemIndex)}\n />\n </div>\n\n {editableChildrenMap.has(itemIndex) && (\n <div className={styles.stack}>\n <div className={styles.label}>\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 <ElementFields\n key={`editable-${nodeId || idx}`}\n id={nodeId ?? undefined}\n className={styles.element}\n header={\n <div className={styles.elementTag}>\n {editableNode.tagName}\n </div>\n }\n bindings={bindingsOf(editableNode, onNodeChange)}\n onNodeChange={onNodeChange}\n />\n );\n })}\n </div>\n )}\n\n {!!item.children && !editableChildrenMap.has(itemIndex) && (\n <div className={styles.stackTight}>\n <div className={styles.label}>{messages.children.childNodes}</div>\n {item.children.map((node, nodeIndex) => (\n <ElementFields\n key={`node-${itemIndex}-${nodeIndex}`}\n className={cn(styles.element, styles.indented)}\n bindings={bindingsOf(node, onNodeChange)}\n onNodeChange={onNodeChange}\n />\n ))}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n};\n\nexport default Children;\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useDebounce } from '@jbpark/use-hooks';\n\nimport { cn } from '~/utils/cn';\n\nimport styles from './fields.module.css';\n\n// A color input 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// `value` as the `#rrggbb` a color input takes: a 6-digit hex color as is,\n// a 3-digit one expanded, anything else black.\nconst normalizeToHex = (value: string): string => {\n const trimmed = value.trim();\n\n if (/^#[0-9A-Fa-f]{6}$/.test(trimmed)) {\n return trimmed;\n }\n\n if (/^#[0-9A-Fa-f]{3}$/.test(trimmed)) {\n const [, r, g, b] = trimmed;\n\n return `#${r}${r}${g}${g}${b}${b}`;\n }\n\n return '#000000';\n};\n\ninterface Props extends Pick<\n React.ComponentProps<'input'>,\n 'id' | 'aria-label' | 'aria-invalid' | 'aria-describedby'\n> {\n // Any source text; anything but a hex color shows as black.\n value: string;\n onChange: (value: string) => void;\n}\n\n// A native color input with the source text beside it. Commits shortly\n// after the last drag frame, and at once on blur so leaving the field\n// can't drop the last color.\nconst ColorField = ({ value: source, onChange, ...controlProps }: Props) => {\n const value = normalizeToHex(source);\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\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 <div className={styles.color}>\n <input\n {...controlProps}\n type=\"color\"\n value={liveValue}\n className={cn(styles.control, styles.colorSwatch)}\n onChange={e => {\n setLiveValue(e.target.value);\n debouncedCommit();\n }}\n onBlur={() => commit(liveValue)}\n />\n <code className={styles.colorSource}>{source}</code>\n </div>\n );\n};\n\nexport default ColorField;\n","import { type FocusEvent, useCallback, useRef } from 'react';\n\nimport type {\n EditorSelection,\n EditorView,\n ViewUpdate,\n} from '@uiw/react-codemirror';\n\nimport CoreEditor from '~/components/editor/core';\n\ninterface Props {\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 }: Props) => {\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\nexport default JSXEditorField;\n","import { useId } from 'react';\n\nimport { FieldIdsContext, LABELABLE_KINDS } from './field-ids';\nimport { type FieldKindBinding, getFieldKind } from './field-kind';\n\ninterface Props {\n // The field's binding, to tell whether the built-in control takes the id.\n binding: FieldKindBinding;\n label: React.ReactNode;\n labelClassName?: string;\n children: React.ReactNode;\n}\n\n// A field's `<label>` and the field it names, tied together by id so the\n// label names the control and clicking it focuses the control (#637). The\n// label points at a built-in control with `htmlFor`, and carries an id of\n// its own for a control that points back with `aria-labelledby`, such as\n// one from `renderField`. Renders no wrapper, so it fits any layout around\n// it.\nconst LabeledField = ({ binding, label, labelClassName, children }: Props) => {\n const controlId = useId();\n const labelId = `${controlId}-label`;\n const isLabelable = LABELABLE_KINDS.has(getFieldKind(binding));\n\n return (\n <FieldIdsContext.Provider value={{ controlId, labelId }}>\n <label\n id={labelId}\n htmlFor={isLabelable ? controlId : undefined}\n className={labelClassName}\n >\n {label}\n </label>\n {children}\n </FieldIdsContext.Provider>\n );\n};\n\nexport default LabeledField;\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 styles from '../structure.module.css';\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={styles.stackLoose}>{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 && styles.dragging)}\n >\n <div className={styles.row}>\n <div className={styles.rowStart}>\n <button\n type=\"button\"\n ref={setActivatorNodeRef}\n {...attributes}\n {...listeners}\n aria-label={messages.items.reorder(title)}\n disabled={disabled}\n className={styles.handle}\n >\n <GripVertical size={14} />\n </button>\n {checkbox}\n <button\n type=\"button\"\n aria-expanded={expanded}\n onClick={onToggle}\n className={styles.toggle}\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 * as t from '@babel/types';\n\nimport { type SourceEdit, applyEdits } from './patch';\nimport { parseArrayExpression } from './value';\n\n// Gaps between dense elements contain only whitespace, comments and one\n// comma. Scan those gaps, never the expressions (which can contain JSX,\n// regexes, templates and nested commas).\nconst commaIn = (source: string, start: number, end: number): number | null => {\n let comma: number | null = null;\n\n for (let at = start; at < end; at++) {\n if (/\\s/.test(source[at]!)) {\n continue;\n }\n\n if (source.startsWith('/*', at)) {\n const close = source.indexOf('*/', at + 2);\n\n if (close < 0 || close + 2 > end) {\n return null;\n }\n\n at = close + 1;\n } else if (source.startsWith('//', at)) {\n const newline = source.indexOf('\\n', at + 2);\n at = newline < 0 ? end : newline;\n } else if (source[at] === ',' && comma === null) {\n comma = at;\n } else {\n return null;\n }\n }\n\n return comma;\n};\n\nexport const denseArraySource = (source: string) => {\n const array = parseArrayExpression(source);\n\n // Holes/spreads have source positions but no stable visible item count.\n // Value edits can preserve them; structural edits deliberately refuse.\n if (\n !array ||\n array.elements.some(\n node => !t.isExpression(node) || node.extra?.parenthesized,\n )\n ) {\n return null;\n }\n\n const elements = array.elements as t.Expression[];\n const commas = elements\n .slice(0, -1)\n .map((node, index) =>\n commaIn(source, node.end!, elements[index + 1]!.start!),\n );\n\n if (commas.some(comma => comma === null)) {\n return null;\n }\n\n const last = elements.at(-1);\n const trailing = last ? commaIn(source, last.end!, array.end! - 1) : null;\n\n return { array, elements, commas: commas as number[], trailing };\n};\n\n// Keep presentation and mutation on the same syntax boundary. Consumers can\n// use this before offering structural controls, while every write still calls\n// denseArraySource() again so stale source is refused at commit time.\nexport const canStructurallyEditArray = (source: string) =>\n denseArraySource(source) !== null;\n\nexport const validArrayIndices = (indices: Iterable<number>, length: number) =>\n [...indices].every(\n index => Number.isInteger(index) && index >= 0 && index < length,\n );\n\nexport const reorderArraySource = (\n source: string,\n elements: t.Expression[],\n next: t.Expression[],\n): string =>\n applyEdits(\n source,\n elements.map((node, index) => ({\n start: node.start!,\n end: node.end!,\n content: source.slice(next[index]!.start!, next[index]!.end!),\n })),\n );\n\nexport const removeArraySource = (\n source: string,\n data: NonNullable<ReturnType<typeof denseArraySource>>,\n indices: Set<number>,\n): string => {\n const edits: SourceEdit[] = [];\n const removedCommas = new Set<number>();\n const { elements, commas, trailing } = data;\n\n // Each consecutive removed run consumes its following commas. A run\n // ending at the last element consumes the preceding separator instead;\n // a trailing comma, when present, stays a trailing comma.\n for (let index = 0; index < elements.length; index++) {\n if (!indices.has(index)) {\n continue;\n }\n\n const start = index;\n\n while (index + 1 < elements.length && indices.has(index + 1)) {\n index++;\n }\n\n for (let current = start; current <= index; current++) {\n const node = elements[current]!;\n edits.push({ start: node.start!, end: node.end!, content: '' });\n\n if (current < elements.length - 1) {\n removedCommas.add(commas[current]!);\n }\n }\n\n if (index === elements.length - 1) {\n if (trailing !== null) {\n removedCommas.add(trailing);\n } else if (start > 0) {\n removedCommas.add(commas[start - 1]!);\n }\n }\n }\n\n for (const comma of removedCommas) {\n edits.push({ start: comma, end: comma + 1, content: '' });\n }\n\n return applyEdits(source, edits);\n};\n\nexport const appendArraySource = (\n source: string,\n data: NonNullable<ReturnType<typeof denseArraySource>>,\n copies: string[],\n): string => {\n const last = data.elements.at(-1);\n\n if (!last || copies.length === 0) {\n return source;\n }\n\n // Insert before the old trailing gap so line comments cannot swallow a\n // new item, and keep an existing trailing comma in its original role.\n return applyEdits(source, [\n {\n start: last.end!,\n end: last.end!,\n content: `, ${copies.join(', ')}`,\n },\n ]);\n};\n","import { parseExpression } from '@babel/parser';\nimport * as t from '@babel/types';\nimport { nanoid } from 'nanoid';\n\nimport { BINDING_PROP } from '../../constants';\nimport { moveSelectedIndices, removeIndices } from '../selection';\nimport {\n appendArraySource,\n denseArraySource,\n removeArraySource,\n reorderArraySource,\n validArrayIndices,\n} from './array-source';\nimport { generateCode } from './helpers';\nimport { type SourceEdit, applyEdits } from './patch';\nimport type {\n BindingRenderLeaf,\n BindingRenderMap,\n NodeValueType,\n} from './types';\nimport {\n extractNodeValue,\n extractObjectProperties,\n isLosslesslyEvaluable,\n parseArrayExpression,\n parseValue,\n} from './value';\nimport { createNodeFromValue, valueToExpression } from './value-expression';\n\n// Array edits are source patches. Parsing locates the requested value or\n// element; unrelated expressions, comments and formatting are not printed\n// again. Structural edits require dense arrays; value edits preserve holes\n// and spreads at their existing source positions. `null` means refusal.\n\ntype ItemKind = 'object' | 'primitive';\n\nconst elementsOf = (code: string) =>\n parseArrayExpression(code)?.elements ?? null;\n\nconst kindOf = (element: t.Expression): ItemKind =>\n t.isObjectExpression(element) ? 'object' : 'primitive';\n\nconst resolveRenderLeaf = (\n render: BindingRenderMap | undefined,\n key: string,\n): BindingRenderLeaf | null => {\n const leaf = render?.[key];\n\n return leaf && 'type' in leaf ? (leaf as BindingRenderLeaf) : null;\n};\n\n// Escapes text for a template literal's raw source: backticks, `${`,\n// backslashes and carriage returns. Without this, pasted markup can throw\n// in `@babel/types`, and CRLF doesn't survive a round trip.\nconst toTemplateRaw = (value: string): string => {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/`/g, '\\\\`')\n .replace(/\\$\\{/g, '\\\\${')\n .replace(/\\r/g, '\\\\r');\n};\n\n// Builds the node a property should hold, from the value the panel produced.\n// Returns `undefined` when the value can't be represented, which callers\n// treat as \"leave the source alone\".\nconst buildPropertyValue = (\n value: unknown,\n declaredType: NodeValueType,\n renderLeaf: BindingRenderLeaf | null,\n current: t.Expression,\n): t.Expression | undefined => {\n // innerHTML is raw markup: a template literal keeps it as written.\n if (renderLeaf?.property === BINDING_PROP.INNER_HTML) {\n const raw = String(value);\n\n return t.templateLiteral(\n [t.templateElement({ raw: toTemplateRaw(raw), cooked: raw }, true)],\n [],\n );\n }\n\n // JSX when the render map declares `jsx`, or when the current value is\n // already JSX without a declaration, so it stays JSX (#298).\n if (\n renderLeaf?.type === 'jsx' ||\n t.isJSXElement(current) ||\n t.isJSXFragment(current)\n ) {\n const trimmed = String(value).trim();\n\n // Anything that isn't markup is a plain string for this property.\n if (!trimmed.startsWith('<')) {\n return t.stringLiteral(trimmed);\n }\n\n try {\n return parseExpression(trimmed, { plugins: ['jsx', 'typescript'] });\n } catch {\n return undefined;\n }\n }\n\n if (declaredType === 'array' || declaredType === 'object') {\n // The nested Items editor commits source text; parse it as is. The\n // object editor and the fallback text area commit a JS value instead.\n if (typeof value === 'string') {\n try {\n return parseExpression(value, { plugins: ['jsx', 'typescript'] });\n } catch {\n return undefined;\n }\n }\n\n // A JS value can be rebuilt exactly only when the property held nothing\n // but literals. Otherwise the edit is refused and the source stays.\n if (!isLosslesslyEvaluable(current)) {\n return undefined;\n }\n\n return valueToExpression(value) ?? undefined;\n }\n\n // Scalars arrive as typed text, so convert first: the string `'true'`\n // would otherwise become `false` for a boolean.\n return createNodeFromValue(declaredType, parseValue(value)) ?? undefined;\n};\n\nexport const updateArrayItemProperty = (\n code: string,\n index: number,\n key: string,\n value: unknown,\n render?: BindingRenderMap,\n): string | null => {\n const elements = elementsOf(code);\n const element = elements?.[index];\n\n if (!elements || !t.isObjectExpression(element)) {\n return null;\n }\n\n const target = element.properties.find(\n (property): property is t.ObjectProperty =>\n t.isObjectProperty(property) &&\n t.isIdentifier(property.key) &&\n property.key.name === key,\n );\n\n if (!target) {\n return null;\n }\n\n const declaredType = extractObjectProperties(element)[key]?.type ?? 'string';\n const nextValue = buildPropertyValue(\n value,\n declaredType,\n resolveRenderLeaf(render, key),\n target.value as t.Expression,\n );\n\n if (!nextValue) {\n return null;\n }\n\n let serialized =\n typeof value === 'string' &&\n (declaredType === 'array' ||\n declaredType === 'object' ||\n t.isJSXElement(nextValue) ||\n t.isJSXFragment(nextValue))\n ? value.trim()\n : generateCode(nextValue);\n\n if (\n nextValue.trailingComments?.some(comment => comment.type === 'CommentLine')\n ) {\n serialized += '\\n';\n }\n\n // A shorthand property shares the key/value span: expand it explicitly.\n const content = target.shorthand ? `${key}: ${serialized}` : serialized;\n\n return applyEdits(code, [\n { start: target.value.start!, end: target.value.end!, content },\n ]);\n};\n\nexport const updateArrayItemValue = (\n code: string,\n index: number,\n value: unknown,\n): string | null => {\n const elements = elementsOf(code);\n const element = elements?.[index];\n\n if (!elements || !t.isExpression(element)) {\n return null;\n }\n\n const nextValue = createNodeFromValue(\n extractNodeValue(element).type,\n parseValue(value),\n );\n\n if (!nextValue) {\n return null;\n }\n\n return applyEdits(code, [\n {\n start: element.start!,\n end: element.end!,\n content: generateCode(nextValue),\n },\n ]);\n};\n\nexport const moveArrayItem = (\n code: string,\n from: number,\n to: number,\n): string | null => {\n const data = denseArraySource(code);\n\n if (\n !data ||\n !validArrayIndices([from], data.elements.length) ||\n !Number.isInteger(to)\n ) {\n return null;\n }\n\n // Preserve the existing splice destination semantics (including append).\n const next = [...data.elements];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved!);\n\n return reorderArraySource(code, data.elements, next);\n};\n\nexport const moveArrayItems = (\n code: string,\n indices: Set<number>,\n direction: 'up' | 'down',\n): { code: string; indices: Set<number> } | null => {\n const data = denseArraySource(code);\n\n if (\n !data ||\n !validArrayIndices(indices, data.elements.length) ||\n !['up', 'down'].includes(direction)\n ) {\n return null;\n }\n\n const next = moveSelectedIndices(data.elements, indices, direction);\n\n return {\n code: reorderArraySource(code, data.elements, next.items),\n indices: next.indices,\n };\n};\n\n// Keep the last-item guard until the empty-array creation contract (#316)\n// is implemented. It must count the visible kind in a mixed array.\nexport const removeArrayItems = (\n code: string,\n indices: Set<number>,\n kind?: ItemKind,\n): string | null => {\n const data = denseArraySource(code);\n\n if (!data || !validArrayIndices(indices, data.elements.length)) {\n return null;\n }\n\n const remaining = removeIndices(data.elements, indices);\n const survivors =\n kind === undefined\n ? remaining\n : remaining.filter(node => kindOf(node) === kind);\n\n if (!survivors.length) {\n return null;\n }\n\n return removeArraySource(code, data, indices);\n};\n\n// Copy exact source; only static object keys / JSX identities get changed.\n// Re-evaluating modeled property values here would erase expressions.\nconst copyItem = (\n code: string,\n element: t.Expression,\n generateId: () => string,\n usedIds: Set<string>,\n): string | null => {\n const edits: SourceEdit[] = [];\n let unsupported = false;\n const reserveId = (id: string) => {\n if (usedIds.has(id)) {\n unsupported = true;\n }\n\n usedIds.add(id);\n\n return JSON.stringify(id);\n };\n\n t.traverseFast(element, node => {\n if (!t.isJSXOpeningElement(node)) {\n return;\n }\n\n const ids = node.attributes.filter(\n (attr): attr is t.JSXAttribute =>\n t.isJSXAttribute(attr) &&\n t.isJSXIdentifier(attr.name, { name: 'data-id' }),\n );\n const attr = ids[0];\n\n if (\n ids.length > 1 ||\n (attr &&\n (!t.isStringLiteral(attr.value) ||\n node.attributes\n .slice(node.attributes.indexOf(attr) + 1)\n .some(a => t.isJSXSpreadAttribute(a))))\n ) {\n unsupported = true;\n return;\n }\n\n if (attr && t.isStringLiteral(attr.value)) {\n edits.push({\n start: attr.value.start!,\n end: attr.value.end!,\n content: reserveId(generateId()),\n });\n }\n });\n\n if (t.isObjectExpression(element)) {\n const keys = element.properties.filter(\n (prop): prop is t.ObjectProperty =>\n t.isObjectProperty(prop) &&\n !prop.computed &&\n (t.isIdentifier(prop.key, { name: 'key' }) ||\n t.isStringLiteral(prop.key, { value: 'key' })),\n );\n const key = keys[0];\n\n if (\n keys.length > 1 ||\n (key &&\n (!t.isStringLiteral(key.value) ||\n element.properties\n .slice(element.properties.indexOf(key) + 1)\n .some(\n prop =>\n t.isSpreadElement(prop) ||\n ('computed' in prop && prop.computed),\n )))\n ) {\n return null;\n }\n\n if (key && t.isStringLiteral(key.value)) {\n edits.push({\n start: key.value.start!,\n end: key.value.end!,\n content: reserveId(`${key.value.value}-${generateId()}`),\n });\n }\n }\n\n if (unsupported) {\n return null;\n }\n\n return applyEdits(\n code.slice(element.start!, element.end!),\n edits.map(edit => ({\n ...edit,\n start: edit.start - element.start!,\n end: edit.end - element.start!,\n })),\n );\n};\n\nexport const duplicateArrayItems = (\n code: string,\n indices: Set<number>,\n generateId: () => string = () => nanoid(6),\n): string | null => {\n const data = denseArraySource(code);\n\n if (\n !data ||\n !indices.size ||\n !validArrayIndices(indices, data.elements.length)\n ) {\n return null;\n }\n\n const usedIds = new Set<string>();\n\n t.traverseFast(data.array, node => {\n if (\n t.isJSXAttribute(node) &&\n t.isJSXIdentifier(node.name, { name: 'data-id' }) &&\n t.isStringLiteral(node.value)\n ) {\n usedIds.add(node.value.value);\n } else if (\n t.isObjectProperty(node) &&\n !node.computed &&\n (t.isIdentifier(node.key, { name: 'key' }) ||\n t.isStringLiteral(node.key, { value: 'key' })) &&\n t.isStringLiteral(node.value)\n ) {\n usedIds.add(node.value.value);\n }\n });\n\n const copies = [...indices]\n .sort((a, b) => a - b)\n .map(index => copyItem(code, data.elements[index]!, generateId, usedIds));\n\n return copies.every((copy): copy is string => copy !== null)\n ? appendArraySource(code, data, copies)\n : null;\n};\n\n// Appends a copy of the first item of `kind`. Items are never created from\n// scratch, because their shape comes from their siblings. So an array\n// needs at least one item to be editable, and `removeArrayItems` never\n// empties it. `null` means there is no item of `kind` to copy; the first\n// one has to be written in the source (#316).\nexport const appendArrayItem = (\n code: string,\n kind: ItemKind,\n generateId: () => string = () => nanoid(6),\n): string | null => {\n const data = denseArraySource(code);\n const index = data?.elements.findIndex(node => kindOf(node) === kind) ?? -1;\n\n return index < 0\n ? null\n : duplicateArrayItems(code, new Set([index]), generateId);\n};\n","import { type BindingRenderMap } from '~/utils/ast/types';\nimport { canLosslesslyEvaluateSource, parseValue } from '~/utils/ast/value';\n\nimport {\n type PanelBinding,\n type PanelNodeChange,\n resolvePanelBindings,\n resolveRenderEntry,\n toBindingFields,\n withPanelCommit,\n} from '../../panel-binding';\nimport type { RawObjectItem, RawPrimitiveItem } from './items-source';\nimport type { DndItemsItem, DndItemsNestedGroup } from './use-dnd-items';\n\ninterface ItemBindingOptions {\n // The item's stable id from `useDndItems`' identity state.\n id: string;\n // The array source the item was parsed from.\n value: string;\n render?: BindingRenderMap;\n onNodeChange?: PanelNodeChange;\n // Commits a primitive item's new value.\n onValueChange: (next: unknown) => void;\n // Commits a new value for one of an object item's properties.\n onPropertyChange: (property: string, next: unknown) => void;\n}\n\nconst isPrimitiveItem = (\n item: RawObjectItem | RawPrimitiveItem,\n): item is RawPrimitiveItem => !('editableProperties' in item);\n\n// The panel bindings for one parsed item: a primitive item's value, or an\n// object item's plain properties through the `render` map and its\n// JSX-valued properties as nested elements, or as a `jsx` binding when the\n// JSX has none (#298, #308).\nexport const toItemBindings = (\n item: RawObjectItem | RawPrimitiveItem,\n {\n id,\n value,\n render,\n onNodeChange,\n onValueChange,\n onPropertyChange,\n }: ItemBindingOptions,\n): DndItemsItem => {\n if (isPrimitiveItem(item)) {\n return {\n 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: onValueChange,\n },\n };\n }\n\n const properties: PanelBinding[] = Object.entries(\n item.editableProperties,\n ).map(([key, prop]) => {\n const binding = resolveRenderEntry(render, key);\n const propertySource = value.slice(prop.astNode.start!, prop.astNode.end!);\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 over an\n // authored `valueType`.\n meta: { ...binding.meta, valueType: prop.type },\n value: parseValue(String(prop.value)),\n rawValue: prop.type === 'unknown' ? propertySource : String(prop.value),\n canEditValue: canLosslesslyEvaluateSource(propertySource),\n onChange: next => onPropertyChange(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) => onPropertyChange(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","// Which kind of array item the panel is editing.\ntype ItemKind = 'object' | 'primitive';\n\n// What identity needs of an item: its generated `id` and its source text.\ninterface IdentifiedItem {\n id: string;\n source: string;\n}\n\n// The ids that follow each item through edits, so a row keeps its identity\n// (and its expanded state) after a move or delete. `signatures` is the source\n// of each item when the ids were last assigned.\ninterface ItemIdentityState {\n value: string;\n kind: ItemKind;\n ids: string[];\n signatures: string[];\n}\n\nexport const createIdentityState = (\n value: string,\n kind: ItemKind,\n items: IdentifiedItem[],\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\nexport const reconcileIdentityState = (\n current: ItemIdentityState | null,\n value: string,\n kind: ItemKind,\n items: IdentifiedItem[],\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\nexport const 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\nexport const removeIds = (ids: string[], indices: Set<number>) => {\n return ids.filter((_, index) => !indices.has(index));\n};\n","import * as t from '@babel/types';\nimport { nanoid } from 'nanoid';\n\nimport { findEditableChildren } from '~/utils/ast/binding';\nimport { extract } from '~/utils/ast/extract';\nimport { type BindingOptions, type DataAttrNode } from '~/utils/ast/types';\nimport {\n extractNodeValue,\n extractObjectProperties,\n parseArrayExpression,\n} from '~/utils/ast/value';\n\n// One item of the array source as parsed, before the panel bindings are\n// built on it. `id` is a fresh id for this parse; `useDndItems` keeps the\n// stable one in its identity state.\nexport interface 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\nexport interface 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// 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// Splits the array source into its object and primitive items, with\n// `parseError` set when it isn't an array expression. Kept apart from\n// building the bindings, so `useDndItems` memoizes the parse on the source\n// while the callbacks stay current every render.\nexport const 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","import { useSet } from '@jbpark/use-hooks';\n\nimport type { DndItemsExpansion } from './use-dnd-items';\n\n// Which of `ids` are expanded. It holds the collapsed ids rather than the\n// expanded ones, so an id it hasn't seen yet, such as a just-added item's,\n// starts expanded. Ids are never reused, so one left behind by a removed\n// item can't collapse another.\nexport const useItemExpansion = (ids: string[]): DndItemsExpansion => {\n const [collapsed, { toggle, set }] = useSet<string>();\n\n return {\n expandedIds: ids.filter(id => !collapsed.has(id)),\n isExpanded: id => !collapsed.has(id),\n toggle: id => toggle(id),\n setExpanded: expandedIds => {\n const expanded = new Set(expandedIds);\n\n set(ids.filter(id => !expanded.has(id)));\n },\n };\n};\n","import { useEffect, useMemo, useState } from 'react';\n\nimport * as t from '@babel/types';\nimport {\n useLatest,\n type useMultiSelect,\n usePendingCommit,\n} from '@jbpark/use-hooks';\nimport { nanoid } from 'nanoid';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { canStructurallyEditArray } from '~/utils/ast/array-source';\nimport {\n appendArrayItem,\n duplicateArrayItems,\n moveArrayItem,\n moveArrayItems,\n removeArrayItems,\n updateArrayItemProperty,\n updateArrayItemValue,\n} from '~/utils/ast/items';\nimport { type BindingRenderMap } from '~/utils/ast/types';\nimport { parseArrayExpression } from '~/utils/ast/value';\nimport { moveSelectedIndices } from '~/utils/selection';\n\nimport { useDndEditOptions } from '../../edit-options';\nimport { type PanelBinding, type PanelNodeChange } from '../../panel-binding';\nimport {\n selectionAfter,\n useStructuralSelection,\n} from '../selection/use-structural-selection';\nimport { toItemBindings } from './item-bindings';\nimport {\n createIdentityState,\n moveId,\n reconcileIdentityState,\n removeIds,\n} from './item-identity';\nimport {\n type RawObjectItem,\n type RawPrimitiveItem,\n parseSource,\n} from './items-source';\nimport { useItemExpansion } from './use-item-expansion';\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 // Whether `count` more items (default 1) stay within `maxItems`, and\n // whether removing `count` leaves at least `minItems` (at least 1). The\n // actions refuse an edit past either limit.\n canAddItems: (count?: number) => boolean;\n canRemoveItems: (count?: number) => 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 // The binding's item count limits (`BindingFieldSpec.minItems` and\n // `maxItems`).\n minItems?: number;\n maxItems?: number;\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\n// What a commit leaves for the next edit in the same tick.\ninterface PendingCommit {\n value: string;\n ids: string[];\n selected: Set<number>;\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, minItems, maxItems }: 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 = useLatest(reportError);\n const messagesRef = useLatest(messages);\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, reportErrorRef, messagesRef]);\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 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 // read only while `value` is still the render value it was built on. Edits\n // read `latest()`, so a second edit in the same tick builds on the first\n // instead of undoing it (#451). Dropped after each render, when the new\n // `value` takes over, as in `useSectionDocument` (#450).\n const pending = usePendingCommit<string, PendingCommit>(value);\n\n const latest = (): Snapshot => {\n const last = pending.read();\n\n if (!last) {\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 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 // The editor never removes the last item (#316), whatever `minItems` says.\n const fewestItems = Math.max(minItems ?? 1, 1);\n\n // Reports and returns `true` when an edit would leave `length` items,\n // outside the binding's limits. Below 1 without a `minItems` is left to\n // the AST functions, which refuse it with the usual error.\n const refuseCount = (length: number) => {\n const description =\n maxItems !== undefined && length > maxItems\n ? messages.validation.maxItems(maxItems)\n : minItems !== undefined && length < fewestItems\n ? messages.validation.minItems(fewestItems)\n : null;\n\n if (description === null) {\n return false;\n }\n\n reportError({\n type: 'items',\n title: messages.editErrors.itemUpdateFailed,\n description,\n });\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\n if (refuseCount(snapshot.items.length + 1)) {\n return;\n }\n\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 || refuseCount(snapshot.items.length - 1)) {\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\n if (refuseCount(snapshot.items.length + selected.size)) {\n return;\n }\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 const selected = elementIndicesOf(snapshot, snapshot.selected);\n\n if (refuseCount(snapshot.items.length - selected.size)) {\n return;\n }\n\n commit(\n snapshot,\n removeArrayItems(snapshot.value, selected, kind),\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` (#336). A cheap walk with no parsing.\n const items: DndItemsItem[] = rawItems.map(item =>\n toItemBindings(item, {\n id: identity.ids[item.index] ?? item.id,\n value,\n render,\n onNodeChange,\n onValueChange: next => updateValue(item.elementIndex, next),\n onPropertyChange: (key, next) =>\n updateProperty(item.elementIndex, key, next),\n }),\n );\n\n const expansion = useItemExpansion(items.map(item => item.id));\n\n return {\n kind,\n items,\n selection,\n expansion,\n actions,\n canEditStructure,\n canAddItems: (count = 1) =>\n maxItems === undefined || items.length + count <= maxItems,\n canRemoveItems: (count = 1) => items.length - count >= fewestItems,\n parseError,\n };\n};\n","import { Plus } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { BindingRenderMap } from '~/utils/ast/types';\nimport { cn } from '~/utils/cn';\n\nimport styles from '../structure.module.css';\n\nimport Button from '../../button';\nimport type { PanelNodeChange } from '../../panel-binding';\nimport ElementFields from '../element-fields';\nimport Field from '../field';\nimport LabeledField from '../fields/labeled-field';\nimport RowControls from '../row-controls';\nimport BulkActionsBar from '../selection/bulk-actions-bar';\nimport SelectAllCheckbox from '../selection/select-all-checkbox';\nimport SelectionCheckbox from '../selection/selection-checkbox';\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 minItems?: number;\n maxItems?: number;\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={styles.stack}>\n <div className={styles.label}>{group.property}</div>\n <Field binding={group.fallback} onNodeChange={onNodeChange} />\n </div>\n );\n }\n\n return (\n <div className={styles.stack}>\n <div className={styles.label}>\n {group.property} Bindings ({group.elements.length}):\n </div>\n {group.elements.map(element => (\n <ElementFields\n key={`${group.property}-${element.id}`}\n id={element.id}\n className={styles.element}\n header={\n <div className={styles.elementTag}>&lt;{element.tagName}&gt;</div>\n }\n bindings={element.bindings}\n onNodeChange={onNodeChange}\n />\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 = ({\n value,\n render,\n minItems,\n maxItems,\n onChange,\n onChildChange,\n}: Props) => {\n const messages = useLiveMessages();\n const {\n kind,\n items,\n selection,\n expansion,\n actions,\n canEditStructure,\n canAddItems,\n canRemoveItems,\n parseError,\n } = useDndItems(value, {\n render,\n onChange,\n onNodeChange: onChildChange,\n minItems,\n maxItems,\n });\n\n const header = (\n <div className={styles.row}>\n <div className={styles.heading}>\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 tone=\"success\"\n disabled={!canAddItems()}\n onClick={actions.add}\n >\n {messages.items.add}\n </Button>\n )}\n </div>\n );\n\n if (parseError) {\n return (\n <div className={cn(styles.items, styles.stackLoose)}>\n {header}\n <div className={styles.noticeDanger}>{messages.items.unreadable}</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={cn(styles.items, styles.stackLoose)}>\n {header}\n <div className={styles.notice}>{messages.items.empty}</div>\n </div>\n );\n }\n\n const bulkBar = (\n <BulkActionsBar\n count={selection.selected.size}\n disabled={!canEditStructure}\n duplicateDisabled={!canAddItems(selection.selected.size)}\n deleteDisabled={!canRemoveItems(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\n const objectBody = (item: DndItemsItem) => (\n <>\n <div className={styles.stack}>\n {item.properties.map(binding => (\n <div key={`${item.id}-${binding.property}-${binding.label}`}>\n <div className={styles.stack}>\n <LabeledField\n binding={binding}\n labelClassName={styles.propertyLabel}\n label={binding.label}\n >\n <Field binding={binding} onNodeChange={onChildChange} />\n </LabeledField>\n </div>\n <span className={styles.valueType}>\n ({String(binding.meta?.valueType)})\n </span>\n </div>\n ))}\n </div>\n <div className={styles.nested}>\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={styles.muted}>\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={cn(styles.items, styles.stackLoose)}>\n {header}\n\n <div className={styles.row}>\n <SelectAllCheckbox\n total={items.length}\n selected={selection.selected.size}\n disabled={!canEditStructure}\n onSelectAll={() =>\n selection.replace(new Set(items.map(item => item.index)))\n }\n onClear={selection.clear}\n />\n {items.length > 1 && (\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 )}\n </div>\n\n {bulkBar}\n\n {!canEditStructure && (\n <div className={styles.noticeWarning}>\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={\n <SelectionCheckbox\n checked={selection.isSelected(item.index)}\n disabled={!canEditStructure}\n onToggle={shiftKey => selection.toggle(item.index, shiftKey)}\n />\n }\n controls={\n <RowControls\n index={item.index}\n count={items.length}\n labels={messages.items}\n disabled={!canEditStructure}\n deleteDisabled={!canRemoveItems()}\n onMove={toIndex => actions.move(item.elementIndex, toIndex)}\n onDelete={() => actions.remove(item.elementIndex)}\n />\n }\n className={cn(\n styles.card,\n kind === 'primitive' && styles.cardCompact,\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 { useLiveMessages } from '~/components/context/messages';\nimport { type DataAttrNode } from '~/utils/ast/types';\nimport { parseValue } from '~/utils/ast/value';\nimport { cn } from '~/utils/cn';\n\nimport styles from './fields/fields.module.css';\n\nimport { useDndEditOptions } from '../edit-options';\nimport { resolveRenderEntry, toBindingFields } from '../panel-binding';\nimport Children from './children/children';\nimport ColorField from './fields/color-field';\nimport FieldError from './fields/field-error';\nimport { getFieldKind } from './fields/field-kind';\nimport JSXEditorField from './fields/jsx-editor-field';\nimport LabeledField from './fields/labeled-field';\nimport { useFieldState } from './fields/use-field-state';\nimport Items from './items/items';\nimport type { FieldProps } from './types';\n\n// The built-in control for one binding: native inputs, selects and text\n// areas, plus the structural and source editors. `@jbpark/live-editor/ui-kit`\n// offers ui-kit controls in their place through `renderField`.\nconst BuiltinField = ({ binding, onNodeChange }: FieldProps) => {\n const messages = useLiveMessages();\n const { id, value, rawValue, onChange } = binding;\n const {\n text,\n setText,\n validationError,\n errorId,\n controlProps,\n commitIfChanged,\n validateAndCommit,\n } = useFieldState(binding);\n\n const kind = getFieldKind(binding);\n\n if (kind === 'readonly') {\n return (\n <div className={styles.readonly}>\n <div>{messages.panel.expressionPreserved}</div>\n <code className={styles.readonlyCode}>{rawValue}</code>\n <div>{messages.panel.useCodeEditor}</div>\n </div>\n );\n }\n\n if (kind === 'items') {\n return (\n <Items\n value={rawValue}\n render={binding.render}\n minItems={binding.minItems}\n maxItems={binding.maxItems}\n onChange={onChange}\n onChildChange={onNodeChange}\n />\n );\n }\n\n if (kind === 'richtext') {\n return (\n // The HTML source as text; `@jbpark/live-editor/ui-kit` offers a\n // formatting editor instead.\n <textarea\n {...controlProps}\n rows={4}\n value={text}\n className={cn(styles.control, styles.mono)}\n onChange={e => setText(e.target.value)}\n onBlur={e => commitIfChanged(e.target.value)}\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={styles.object}>\n {Object.entries(objectValue).map(([key, val]) => {\n const nested = resolveRenderEntry(binding.render, key);\n\n return (\n <div key={key} className={styles.stack}>\n <LabeledField\n binding={{ ...nested, value: val }}\n labelClassName={styles.label}\n label={nested.label}\n >\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 </LabeledField>\n </div>\n );\n })}\n </div>\n );\n }\n\n if (kind === 'boolean') {\n return (\n <input\n {...controlProps}\n type=\"checkbox\"\n checked={value === true || value === 'true'}\n className={styles.checkbox}\n onChange={e => {\n onChange(e.target.checked);\n }}\n />\n );\n }\n\n if (kind === 'select') {\n return (\n <select\n {...controlProps}\n value={rawValue}\n className={styles.control}\n onChange={e => commitIfChanged(e.target.value)}\n >\n {(binding.options ?? []).map(option => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n }\n\n if (kind === 'color') {\n return (\n <ColorField\n {...controlProps}\n value={rawValue}\n onChange={commitIfChanged}\n />\n );\n }\n\n if (kind === 'date' || kind === 'datetime' || kind === 'time') {\n // The stored formats (`YYYY-MM-DD`, `YYYY-MM-DDTHH:mm`, `HH:mm`) are the\n // ones these inputs read and write, so no conversion is needed.\n return (\n <div>\n <input\n {...controlProps}\n type={kind === 'datetime' ? 'datetime-local' : kind}\n value={rawValue}\n className={styles.control}\n onChange={e => validateAndCommit(e.target.value)}\n />\n <FieldError id={errorId} message={validationError} />\n </div>\n );\n }\n\n if (kind === 'url' || kind === 'email' || kind === 'tel') {\n return (\n <div>\n <input\n {...controlProps}\n type={kind}\n value={text}\n className={styles.control}\n onChange={e => setText(e.target.value)}\n placeholder={\n kind === 'url'\n ? messages.panel.urlPlaceholder\n : kind === 'email'\n ? messages.panel.emailPlaceholder\n : messages.panel.telPlaceholder\n }\n onBlur={e => validateAndCommit(e.target.value.trim())}\n />\n <FieldError id={errorId} message={validationError} />\n </div>\n );\n }\n\n if (kind === 'number') {\n return (\n <div>\n <input\n {...controlProps}\n type=\"number\"\n step={binding.step}\n value={text}\n className={styles.control}\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\n validateAndCommit(next);\n }}\n />\n <FieldError id={errorId} message={validationError} />\n </div>\n );\n }\n\n return (\n <div>\n <textarea\n {...controlProps}\n rows={2}\n value={text}\n className={styles.control}\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\n validateAndCommit(next);\n }}\n />\n <FieldError id={errorId} 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 { useContext, useEffect, useRef } from 'react';\n\nimport styles from './panel.module.css';\n\nimport type { PanelBinding, PanelNodeChange } from '../panel-binding';\nimport { ElementSelectionContext } from './element-selection';\nimport Field from './field';\nimport LabeledField from './fields/labeled-field';\n\ninterface Props extends Omit<React.ComponentPropsWithoutRef<'div'>, 'id'> {\n // The element's `data-id`. Absent for an element the editor can't\n // address, whose card can't be picked or hovered.\n id?: string;\n header?: React.ReactNode;\n bindings: PanelBinding[];\n onNodeChange?: PanelNodeChange;\n}\n\n// How long a newly marked card keeps itself in view. Fields above it can\n// still grow for a moment after it renders (a rich-text editor mounting,\n// for one) and push it back out.\nconst KEEP_IN_VIEW_MS = 600;\n\n// One element's card in the panel: its fields, each under its label, and\n// anything passed as `children` after them. The card carries the\n// element's `data-id`, which the panel reads to outline the element on the\n// canvas, and marks itself with `data-picked` while the selection holds its\n// id (#432, #643). Its look is the caller's, through `className`.\nconst ElementFields = ({\n id,\n header,\n bindings,\n onNodeChange,\n children,\n ...props\n}: Props) => {\n const { ids, scrollRootRef } = useContext(ElementSelectionContext);\n\n const ref = useRef<HTMLDivElement>(null);\n\n const isPicked = id !== undefined && ids.has(id);\n\n useEffect(() => {\n const card = ref.current;\n\n if (!isPicked || !card) {\n return;\n }\n\n const until = performance.now() + KEEP_IN_VIEW_MS;\n let frame = 0;\n\n const keepInView = () => {\n const root = scrollRootRef?.current;\n const box = card.getBoundingClientRect();\n const view = root?.getBoundingClientRect();\n\n if (!view || box.top < view.top || box.bottom > view.bottom) {\n card.scrollIntoView?.({ block: 'nearest' });\n }\n\n if (performance.now() < until) {\n frame = requestAnimationFrame(keepInView);\n }\n };\n\n keepInView();\n\n return () => cancelAnimationFrame(frame);\n }, [isPicked, scrollRootRef]);\n\n return (\n <div\n {...props}\n ref={ref}\n data-node-id={id}\n data-picked={isPicked ? '' : undefined}\n >\n {header}\n {bindings.length > 0 && (\n <div className={styles.bindings}>\n {/* Keyed by `property` and `label`, since two bindings can share\n a label (#318). */}\n {bindings.map(binding => (\n <div\n key={`${binding.property}-${binding.label}`}\n className={styles.binding}\n >\n <LabeledField\n binding={binding}\n labelClassName={styles.bindingLabel}\n label={\n <>\n {binding.label}\n <span className={styles.bindingProperty}>\n ({binding.property})\n </span>\n </>\n }\n >\n <Field binding={binding} onNodeChange={onNodeChange} />\n </LabeledField>\n </div>\n ))}\n </div>\n )}\n {children}\n </div>\n );\n};\n\nexport default ElementFields;\n","import { useContext, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { ChevronDown, ChevronUp, Trash } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { Section } from '~/types';\n\nimport styles from './panel.module.css';\n\nimport Button from '../button';\nimport { DndInspectorContext } from '../inspector';\nimport type { PanelBinding, PanelNodeChange } from '../panel-binding';\nimport ElementFields from './element-fields';\nimport {\n type ElementSelection,\n ElementSelectionContext,\n} from './element-selection';\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).\ninterface 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 // Marks the fields of an element picked in the preview and keeps them in\n // view, 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 nothing is marked then.\n const selection = useMemo<ElementSelection>(\n () => ({\n ids: new Set(pickedId ? [pickedId] : []),\n scrollRootRef: rootRef,\n }),\n [pickedId],\n );\n\n if (!item) {\n return <p className={styles.empty}>{messages.panel.selectSection}</p>;\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={styles.panel}\n >\n <div className={styles.header}>\n <h2 className={styles.title}>{item.name}</h2>\n <div className={styles.actions}>\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 tone=\"danger\"\n icon={<Trash />}\n onClick={() => onDelete(item.id)}\n aria-label={messages.section.delete}\n />\n )}\n </div>\n </div>\n {readOnly && (\n <span role=\"status\" className={styles.readOnly}>\n {messages.panel.readOnly}\n </span>\n )}\n {!groups.length && (\n <span className={styles.note}>{messages.panel.noEditableElements}</span>\n )}\n <ElementSelectionContext.Provider value={selection}>\n {groups.map(group => {\n const element = describeElement(group[0]!);\n\n return (\n <ElementFields\n key={group[0]!.id}\n id={group[0]!.id}\n role=\"group\"\n aria-label={element.label}\n className={styles.element}\n header={\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 className={styles.elementHeader}>\n <code className={styles.elementTag}>{element.tagName}</code>\n {element.text && (\n <span className={styles.elementText}>{element.text}</span>\n )}\n </div>\n )\n }\n bindings={group}\n onNodeChange={onNodeChange}\n />\n );\n })}\n </ElementSelectionContext.Provider>\n </div>\n );\n};\n\nexport default Panel;\n","@layer components {\n .container {\n display: flex;\n width: 100%;\n height: 100%;\n min-width: 0;\n }\n\n .pane {\n flex-grow: 0;\n flex-shrink: 0;\n min-width: 0;\n height: 100%;\n overflow: hidden;\n\n &[hidden] {\n display: none;\n }\n }\n\n .center {\n flex: 1 1 0;\n min-width: 0;\n height: 100%;\n }\n\n /* A thin line with a wider hit area, drawn over the panes' edges. */\n .handle {\n position: relative;\n z-index: 1;\n flex: 0 0 1px;\n margin: 0 -3px;\n border-inline: 3px solid transparent;\n background: var(--live-editor-color-border-subtle);\n background-clip: padding-box;\n cursor: col-resize;\n touch-action: none;\n\n &:hover,\n &:focus-visible {\n background-color: var(--live-editor-color-focus);\n outline: none;\n }\n }\n}\n","import { useRef, useState } from 'react';\n\nimport styles from './split-panes.module.css';\n\n// Percentages of the container's width.\nconst DEFAULT_SIZE = 20;\nconst MIN_SIZE = 15;\nconst MAX_SIZE = 35;\nconst KEYBOARD_STEP = 2;\n\ntype Side = 'start' | 'end';\n\ninterface Props {\n start: React.ReactNode;\n center: React.ReactNode;\n end: React.ReactNode;\n labels: Record<Side, string>;\n}\n\n// Clamps a dragged size to the pane's range. Dragged below half the minimum,\n// the pane collapses to nothing.\nconst clampSize = (size: number) => {\n if (size < MIN_SIZE / 2) {\n return 0;\n }\n\n return Math.min(MAX_SIZE, Math.max(MIN_SIZE, size));\n};\n\n// Three panes side by side, with a handle between each side pane and the\n// center one. A handle resizes its side pane by dragging, by the arrow keys\n// or Home and End, and Enter collapses or restores it. The center pane takes\n// what is left.\nconst SplitPanes = ({ start, center, end, labels }: Props) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [sizes, setSizes] = useState<Record<Side, number>>({\n start: DEFAULT_SIZE,\n end: DEFAULT_SIZE,\n });\n // The size a collapsed pane goes back to.\n const restoreRef = useRef<Record<Side, number>>({\n start: DEFAULT_SIZE,\n end: DEFAULT_SIZE,\n });\n\n const resize = (side: Side, size: number) => {\n if (size > 0) {\n restoreRef.current[side] = size;\n }\n\n setSizes(prev => ({ ...prev, [side]: size }));\n };\n\n const onPointerDown =\n (side: Side) => (e: React.PointerEvent<HTMLElement>) => {\n const container = containerRef.current;\n\n if (!container || e.button !== 0) {\n return;\n }\n\n e.preventDefault();\n\n const handle = e.currentTarget;\n const width = container.getBoundingClientRect().width;\n const startX = e.clientX;\n const startSize = sizes[side];\n\n handle.setPointerCapture(e.pointerId);\n\n const onMove = (move: PointerEvent) => {\n const delta = ((move.clientX - startX) / width) * 100;\n\n resize(\n side,\n clampSize(startSize + (side === 'start' ? delta : -delta)),\n );\n };\n\n const onUp = () => {\n handle.removeEventListener('pointermove', onMove);\n handle.removeEventListener('pointerup', onUp);\n handle.removeEventListener('pointercancel', onUp);\n };\n\n handle.addEventListener('pointermove', onMove);\n handle.addEventListener('pointerup', onUp);\n handle.addEventListener('pointercancel', onUp);\n };\n\n const onKeyDown = (side: Side) => (e: React.KeyboardEvent) => {\n // The arrow that moves the handle toward the center grows the pane.\n const grow = side === 'start' ? 'ArrowRight' : 'ArrowLeft';\n const shrink = side === 'start' ? 'ArrowLeft' : 'ArrowRight';\n const size = sizes[side];\n\n if (e.key === grow || e.key === shrink) {\n e.preventDefault();\n\n const step = e.key === grow ? KEYBOARD_STEP : -KEYBOARD_STEP;\n\n resize(side, Math.min(MAX_SIZE, Math.max(MIN_SIZE, size + step)));\n\n return;\n }\n\n if (e.key === 'Home' || e.key === 'End') {\n e.preventDefault();\n resize(side, e.key === 'Home' ? MIN_SIZE : MAX_SIZE);\n\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault();\n resize(side, size > 0 ? 0 : restoreRef.current[side]);\n }\n };\n\n const handle = (side: Side) => (\n <div\n role=\"separator\"\n tabIndex={0}\n aria-orientation=\"vertical\"\n aria-label={labels[side]}\n aria-valuenow={Math.round(sizes[side])}\n aria-valuemin={0}\n aria-valuemax={MAX_SIZE}\n className={styles.handle}\n onPointerDown={onPointerDown(side)}\n onKeyDown={onKeyDown(side)}\n onDoubleClick={() =>\n resize(side, sizes[side] > 0 ? 0 : restoreRef.current[side])\n }\n />\n );\n\n return (\n <div ref={containerRef} className={styles.container}>\n <div\n className={styles.pane}\n style={{ flexBasis: `${sizes.start}%` }}\n hidden={sizes.start === 0}\n >\n {start}\n </div>\n {handle('start')}\n <div className={styles.center}>{center}</div>\n {handle('end')}\n <div\n className={styles.pane}\n style={{ flexBasis: `${sizes.end}%` }}\n hidden={sizes.end === 0}\n >\n {end}\n </div>\n </div>\n );\n};\n\nexport default SplitPanes;\n","import { Crosshair, LayoutGrid } from 'lucide-react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport { cn } from '~/utils/cn';\n\nimport styles from './layout.module.css';\n\nimport Button from './button';\nimport Drawer from './drawer';\nimport { useDndInspector } from './inspector';\nimport { useDndRegions } from './layout-context';\nimport { DefaultDraggableItem } from './palette/draggable';\nimport PropertyPanel from './panel';\nimport SplitPanes from './split-panes';\n\n// A region's props: everything a `div` takes except `children`, which comes\n// from context. The region's styles sit in the `components` cascade layer,\n// so a Tailwind utility or an unlayered rule in `className` 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 <div className={styles.paletteItems}>\n {items.map(item => (\n <DefaultDraggableItem\n key={item.id}\n item={item}\n onAdd={onAdd}\n tapToAdd={isMobile}\n />\n ))}\n </div>\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 className={cn(styles.palette, className)} {...restProps}>\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(styles.canvas, className)}\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={styles.pickerDock}>\n <div className={styles.picker}>\n <Button\n icon={<Crosshair />}\n tone=\"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 className={cn(styles.panel, className)} {...restProps}>\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: three resizable panes 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 <SplitPanes\n start={palette ?? <Palette />}\n center={<Canvas />}\n end={panel ?? <Panel />}\n labels={{\n start: messages.canvas.resizePalette,\n end: messages.canvas.resizePanel,\n }}\n />\n )}\n <Button\n variant=\"solid\"\n tone=\"primary\"\n shape=\"circle\"\n icon={<LayoutGrid />}\n aria-label={messages.canvas.palette}\n className={styles.paletteButton}\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 title={messages.canvas.palette}\n closeLabel={messages.canvas.close}\n >\n {palette ?? <PaletteItems subject=\"<Live.Dnd.Layout>\" />}\n </Drawer>\n <Drawer\n open={isMobile && Boolean(selectedId)}\n onClose={clearSelection}\n title={messages.canvas.properties}\n closeLabel={messages.canvas.close}\n >\n {panel ?? <PanelFields subject=\"<Live.Dnd.Layout>\" />}\n </Drawer>\n </>\n );\n};\n\nexport default Layout;\n","import { useCallback } from 'react';\n\nimport { useLatest } from '@jbpark/use-hooks';\n\nimport type { DocumentProblem } from '~/utils/ast/document';\nimport type { UpdateFailure } from '~/utils/ast/update';\n\nimport { type LiveMessages, useLiveMessages } from '../../context/messages';\nimport { type DndEditError, toastEditError } from '../edit-options';\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).\nexport const 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).\nexport const 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\n// Builds the error from the messages current at the time it is reported.\nexport type ReportLatest = (\n build: (messages: LiveMessages) => DndEditError,\n) => void;\n\n// The edit-error plumbing of `Live.Dnd`: where an error goes (the host's\n// `onEditError`, else a toast) and the messages it is written in.\n// `reportLatest` keeps one identity for the life of the component and reads\n// the latest handler and messages when it runs, so an effect that reports a\n// failure fires once per failure, even when the host passes a new\n// `onEditError` or new messages every render.\nexport const useEditErrors = (onEditError?: (error: DndEditError) => void) => {\n const messages = useLiveMessages();\n const reportError = onEditError ?? toastEditError;\n\n const reportErrorRef = useLatest(reportError);\n const messagesRef = useLatest(messages);\n\n const reportLatest = useCallback<ReportLatest>(\n build => reportErrorRef.current(build(messagesRef.current)),\n [reportErrorRef, messagesRef],\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(\n (problem: DocumentProblem) => {\n if (problem.reason === 'parse-error') {\n reportLatest(m => blockedEditError(problem.error, m));\n }\n },\n [reportLatest],\n );\n\n return { reportError, messages, reportLatest, onBlockedEdit };\n};\n","import { useLatest } from '@jbpark/use-hooks';\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 = useLatest(remove);\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/section-handlers';\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, useState } from 'react';\n\nimport { useElementPosition, useKeyPress } from '@jbpark/use-hooks';\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`).\n const [fieldTarget, setFieldTarget] = useState<string | 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 useKeyPress('esc', stopInspecting, { enabled: inspecting });\n\n // Follows the element a panel field points at, through canvas scrolls,\n // resizes and re-renders, measuring its box in viewport coordinates. The\n // section is looked up when measuring, since `sectionNodes` is filled by\n // ref callbacks after render.\n const fieldRect = useElementPosition(\n () => {\n const section =\n selectedId === null ? undefined : sectionNodes.get(selectedId);\n\n return fieldTarget && section\n ? findElementById(section, fieldTarget)\n : null;\n },\n { measure: viewportRect },\n );\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, useMemo, useState } from 'react';\n\nimport { arrayMove } from '@dnd-kit/sortable';\nimport { usePendingCommit } from '@jbpark/use-hooks';\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\ninterface 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\ninterface 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, read only while `document` is\n // still the one it was built on. Mutations read through\n // `latestDocument()`, so a second commit in the same tick builds on the\n // first instead of undoing it (#450). The hook drops it after each render,\n // when the new `value` takes over, including when the host didn't accept\n // the commit.\n const pending = usePendingCommit<string, string>(document);\n\n const latestDocument = useCallback(\n () => pending.read() ?? document,\n [document, pending],\n );\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 pending.write(nextCode);\n onChange?.(nextCode);\n setCode(nextCode);\n\n return readSections(nextCode);\n },\n [containerId, latestDocument, onChange, pending, readSections, setCode],\n );\n\n const getCommittedSection = useCallback(\n (id: string) => {\n const code = pending.read();\n\n return code === undefined\n ? undefined\n : readSections(code).find(s => s.id === id);\n },\n [pending, readSections],\n );\n\n // True, after reporting through `onBlockedEdit`, while the document is\n // 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 // Every mutation starts here. It runs on the latest sections, or not at\n // all while the document is stale.\n const mutate = useCallback(\n (fn: (current: Section[]) => void) => {\n if (refuse()) {\n return;\n }\n\n fn(latestSections());\n },\n [latestSections, refuse],\n );\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 mutate(current => {\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, mutate],\n );\n\n const remove = useCallback(\n (id: string) =>\n mutate(current => {\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, mutate, selectedId],\n );\n\n const copy = useCallback(\n (id: string) =>\n mutate(current => {\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, mutate],\n );\n\n const move = useCallback(\n (id: string | null, direction: 'up' | 'down') =>\n mutate(current => {\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, mutate],\n );\n\n const reorder = useCallback(\n (activeId: string, overId: string) =>\n mutate(current => {\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, mutate],\n );\n\n const patch = useCallback(\n (next: Partial<Section> & { id: string }) =>\n mutate(current => {\n commit(current.map(s => (s.id === next.id ? { ...s, ...next } : s)));\n }),\n [commit, mutate],\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 { useEffect, useMemo } from 'react';\n\nimport type { Section } from '~/types';\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';\n\nimport { type LiveMessages } from '../../context/messages';\nimport type { DndEditError } from '../edit-options';\nimport {\n type PanelBinding,\n type PanelNodeChange,\n resolvePanelBindings,\n withPanelCommit,\n} from '../panel-binding';\nimport {\n type ReportLatest,\n blockedEditError,\n describeUpdateFailure,\n} from './edit-errors';\nimport type { useSectionDocument } from './use-section-document';\n\ntype SectionDocument = ReturnType<typeof useSectionDocument>;\n\ninterface Options {\n selectedSection: SectionDocument['selectedSection'];\n stale: SectionDocument['stale'];\n problem: SectionDocument['problem'];\n // The container id the document is missing, or `null`.\n missingContainer: string | null;\n getCommittedSection: SectionDocument['getCommittedSection'];\n onChange: (next: Partial<Section>) => void;\n bindingOptions: BindingOptions;\n reportError: (error: DndEditError) => void;\n messages: LiveMessages;\n reportLatest: ReportLatest;\n}\n\n// What the panel edits: the selected section's bound elements as\n// `bindings`, and the one path that turns a panel edit into a new section\n// source. Also reports what keeps the document from being edited, a missing\n// container or a section that doesn't parse.\nexport const useSectionEditing = ({\n selectedSection,\n stale,\n problem,\n missingContainer,\n getCommittedSection,\n onChange,\n bindingOptions,\n reportError,\n messages,\n reportLatest,\n}: Options) => {\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 reportLatest(m => ({\n type: 'parse',\n target: 'document',\n reason: 'container-not-found',\n containerId: missingContainer,\n title: m.editErrors.missingContainer(missingContainer),\n description: m.editErrors.missingContainerDetail(missingContainer),\n }));\n }\n }, [missingContainer, reportLatest]);\n\n useEffect(() => {\n if (parseError) {\n reportLatest(m => ({\n type: 'parse',\n target: 'section',\n error: parseError.error,\n title: m.editErrors.sectionParseFailed,\n description: m.editErrors.checkConsole,\n }));\n }\n }, [parseError, reportLatest]);\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 return { bindings, onFieldChange, commitChanges };\n};\n","import { Children, useEffect, useMemo, useState } 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 { useResponsiveSize, useStableValue } from '@jbpark/use-hooks';\n\nimport { PALETTE_SECTIONS } from '~/constants';\nimport type { Section } from '~/types';\nimport type { DocumentProblem } from '~/utils/ast/document';\nimport { type BindingOptions } from '~/utils/ast/types';\n\nimport canvasStyles from './canvas/canvas.module.css';\nimport layoutStyles from './layout.module.css';\n\nimport { cn } from '../../utils/cn';\nimport { preloadScripts } from '../../utils/scripts';\nimport type { LiveMessages } from '../context/messages';\nimport { usePreview } from '../context/states';\nimport CanvasNotice from './canvas/canvas-notice';\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 {\n type SectionHandlers,\n SectionHandlersContext,\n} from './canvas/section-handlers';\nimport Sortable from './canvas/sortable';\nimport { DndEditOptionsContext } from './edit-options';\nimport { DndInspectorContext } from './inspector';\nimport Layout from './layout';\nimport { DndRegionContext } from './layout-context';\nimport { paletteSectionOf } from './palette/palette-drag';\nimport { useEditErrors } from './state/edit-errors';\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 { useSectionEditing } from './state/use-section-editing';\nimport type { DndPalette, DndPanel, Props } from './types';\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\n// The title and detail an empty canvas shows: the document doesn't parse,\n// its container is missing, or it has no sections yet.\nconst emptyCanvasNotice = (\n messages: LiveMessages,\n problem: DocumentProblem | null,\n isMobile: boolean,\n) => {\n if (problem?.reason === 'parse-error') {\n return {\n title: messages.canvas.syntaxError,\n detail: messages.canvas.syntaxErrorDetail,\n };\n }\n\n if (problem?.reason === 'container-not-found') {\n return {\n title: messages.canvas.missingContainer(problem.containerId),\n detail: messages.canvas.missingContainerDetail(problem.containerId),\n };\n }\n\n return {\n title: messages.canvas.empty,\n detail: isMobile\n ? messages.canvas.emptyHintTouch\n : messages.canvas.emptyHintDrag,\n };\n};\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 = useStableValue(_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 { reportError, messages, onBlockedEdit, reportLatest } =\n useEditErrors(onEditError);\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 const { bindings, onFieldChange, commitChanges } = useSectionEditing({\n selectedSection,\n stale,\n problem,\n missingContainer,\n getCommittedSection,\n onChange,\n bindingOptions,\n reportError,\n messages,\n reportLatest,\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 const sectionHandlers: SectionHandlers = {\n inspecting,\n onInspectMove,\n onInspectPick,\n onInspectLeave,\n nodeRef: sectionNodes.register,\n onNavigate,\n onDeleteKey,\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 <SectionHandlersContext.Provider value={sectionHandlers}>\n {stale && (\n <div role=\"status\" className={canvasStyles.stale}>\n {messages.canvas.stale}\n </div>\n )}\n <Droppable className={cn(!sections.length && canvasStyles.fill)}>\n {!sections.length ? (\n <div className={canvasStyles.empty}>\n <CanvasNotice {...emptyCanvasNotice(messages, problem, isMobile)} />\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 >\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 </SectionHandlersContext.Provider>\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 className={cn(layoutStyles.root, className)} {...restProps}>\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 {\n type DndChildren,\n type DndChildrenOptions,\n useDndChildren,\n} from './panel/children/use-dnd-children';\nimport Field from './panel/field';\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/items/use-dnd-items';\nimport type { FieldProps } from './panel/types';\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/fields/field-kind';\nexport type { FieldKind, FieldKindBinding } from './panel/fields/field-kind';\n\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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"}