@jbpark/live-editor 5.0.0 → 6.1.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 (69) hide show
  1. package/README.ko.md +34 -32
  2. package/README.md +34 -32
  3. package/dist/{boundary-6_nTsWxP.js → boundary-CySnDUs2.js} +5 -4
  4. package/dist/boundary-CySnDUs2.js.map +1 -0
  5. package/dist/{compile-DwOyWrmI.js → compile-my0AjsCw.js} +3 -3
  6. package/dist/{compile-DwOyWrmI.js.map → compile-my0AjsCw.js.map} +1 -1
  7. package/dist/{constants-D-XKuEY2.js → constants-st9gnJ5g.js} +1 -4
  8. package/dist/{constants-D-XKuEY2.js.map → constants-st9gnJ5g.js.map} +1 -1
  9. package/dist/{context-DDR1xVKo.js → context-Bjq0CvBE.js} +3 -3
  10. package/dist/{context-DDR1xVKo.js.map → context-Bjq0CvBE.js.map} +1 -1
  11. package/dist/{core-CKazr4tT.js → core-BNVuH8-l.js} +51 -14
  12. package/dist/core-BNVuH8-l.js.map +1 -0
  13. package/dist/{detect-typescript-CoAO-QUJ.js → detect-typescript-CMF0FVKD.js} +2 -2
  14. package/dist/{detect-typescript-CoAO-QUJ.js.map → detect-typescript-CMF0FVKD.js.map} +1 -1
  15. package/dist/dnd/index.d.ts +2 -1
  16. package/dist/dnd/index.js +2 -1
  17. package/dist/{dnd-BlC1gqUy.js → dnd-COjjjuD7.js} +1242 -1459
  18. package/dist/dnd-COjjjuD7.js.map +1 -0
  19. package/dist/{document-DcwIEHRV.js → document-BkGWDZGc.js} +685 -531
  20. package/dist/document-BkGWDZGc.js.map +1 -0
  21. package/dist/edit-options-C_r9aCz4.d.ts +100 -0
  22. package/dist/editor/index.d.ts +1 -1
  23. package/dist/editor/index.js +2 -2
  24. package/dist/{editor-Bty5XzpV.js → editor-CvnzrM9J.js} +2 -2
  25. package/dist/{editor-Bty5XzpV.js.map → editor-CvnzrM9J.js.map} +1 -1
  26. package/dist/error/index.d.ts +1 -1
  27. package/dist/error/index.js +2 -2
  28. package/dist/{error-DyYx2NQ2.js → error-CFzvnLCf.js} +4 -4
  29. package/dist/error-CFzvnLCf.js.map +1 -0
  30. package/dist/{index-tAiuHZsC.d.ts → index-BZpZwrxT.d.ts} +2 -2
  31. package/dist/{index-13BDSrQc.d.ts → index-C93npmTU.d.ts} +4 -6
  32. package/dist/{index-Cl79M7ZJ.d.ts → index-CqsS207F.d.ts} +2 -10
  33. package/dist/{index-0VB5C3Jk.d.ts → index-DQcdHg_V.d.ts} +4 -100
  34. package/dist/{index-kKUjo9lr.d.ts → index-DfIvkht8.d.ts} +3 -3
  35. package/dist/index.d.ts +8 -7
  36. package/dist/index.js +6 -6
  37. package/dist/{messages-Yb3b7YJt.d.ts → messages-BpN3QIhj.d.ts} +4 -1
  38. package/dist/{messages-Bt5WXKTE.js → messages-DrINcRdG.js} +4 -1
  39. package/dist/messages-DrINcRdG.js.map +1 -0
  40. package/dist/preview/index.d.ts +2 -2
  41. package/dist/preview/index.js +2 -3
  42. package/dist/{preview-DC0pyOdu.js → preview-8ejC5VP2.js} +16 -13
  43. package/dist/preview-8ejC5VP2.js.map +1 -0
  44. package/dist/provider/index.d.ts +2 -2
  45. package/dist/provider/index.js +2 -2
  46. package/dist/{sections-4uirsXRU.js → sections-rD8NuRI8.js} +3 -3
  47. package/dist/{sections-4uirsXRU.js.map → sections-rD8NuRI8.js.map} +1 -1
  48. package/dist/style.css +801 -5372
  49. package/dist/ui-kit/index.d.ts +22 -0
  50. package/dist/ui-kit/index.js +1552 -0
  51. package/dist/ui-kit/index.js.map +1 -0
  52. package/dist/ui-kit/style.css +5039 -0
  53. package/dist/{update-DNInQSM7.js → update-DyFnX8yE.js} +3 -3
  54. package/dist/{update-DNInQSM7.js.map → update-DyFnX8yE.js.map} +1 -1
  55. package/dist/{use-dynamic-tailwind-CSYKXDmX.js → use-dynamic-tailwind-0nuRN57N.js} +30 -34
  56. package/dist/use-dynamic-tailwind-0nuRN57N.js.map +1 -0
  57. package/dist/use-field-state-iQGW0vc6.js +131 -0
  58. package/dist/use-field-state-iQGW0vc6.js.map +1 -0
  59. package/dist/utils/ast/index.js +2 -2
  60. package/dist/utils/index.js +2 -2
  61. package/package.json +14 -4
  62. package/dist/boundary-6_nTsWxP.js.map +0 -1
  63. package/dist/core-CKazr4tT.js.map +0 -1
  64. package/dist/dnd-BlC1gqUy.js.map +0 -1
  65. package/dist/document-DcwIEHRV.js.map +0 -1
  66. package/dist/error-DyYx2NQ2.js.map +0 -1
  67. package/dist/messages-Bt5WXKTE.js.map +0 -1
  68. package/dist/preview-DC0pyOdu.js.map +0 -1
  69. package/dist/use-dynamic-tailwind-CSYKXDmX.js.map +0 -1
@@ -1,22 +1,21 @@
1
- import { C as isJSXElement, D as isJSXIdentifier, E as isJSXFragment, I as isSpreadElement, L as isStringLiteral, N as isObjectExpression, O as isJSXOpeningElement, P as isObjectProperty, S as isJSXAttribute, a as inspectDocument, at as stringLiteral, b as isExpression, ct as traverseFast, d as applyEdits, dt as parseExpression, k as isJSXSpreadAttribute, l as fillIdsFrom, n as fillSectionIds, ot as templateElement, p as nanoid, st as templateLiteral, t as createSectionPreviewCache, u as replaceIds, x as isIdentifier } from "./document-DcwIEHRV.js";
2
- import { r as DATA_ATTR, s as RESERVED_BINDING_PROPERTIES, t as BINDING_PROP } from "./constants-D-XKuEY2.js";
3
- import { n as validateBindingValue } from "./validate-CZz30Pnb.js";
4
- import { i as useLiveMessages } from "./messages-Bt5WXKTE.js";
1
+ import { C as isJSXElement, D as isJSXIdentifier, E as isJSXFragment, I as isSpreadElement, L as isStringLiteral, N as isObjectExpression, O as isJSXOpeningElement, P as isObjectProperty, S as isJSXAttribute, a as inspectDocument, at as stringLiteral, b as isExpression, ct as traverseFast, d as applyEdits, dt as parseExpression, k as isJSXSpreadAttribute, l as fillIdsFrom, n as fillSectionIds, ot as templateElement, p as nanoid, st as templateLiteral, t as createSectionPreviewCache, u as replaceIds, x as isIdentifier } from "./document-BkGWDZGc.js";
2
+ import { r as DATA_ATTR, s as RESERVED_BINDING_PROPERTIES, t as BINDING_PROP } from "./constants-st9gnJ5g.js";
3
+ import { i as useLiveMessages } from "./messages-DrINcRdG.js";
5
4
  import { i as usePreview } from "./states-Ci1AvoQ9.js";
6
- import { _ as parseArrayExpression, a as getChildrenSignatures, b as generateCode, c as removeIndices, d as getStructuredValue, f as readNodeBindings, g as isLosslesslyEvaluable, h as extractObjectProperties, i as valueToExpression, l as findEditableChildren, m as extractNodeValue, n as updateAll, o as extract, p as canLosslesslyEvaluateSource, r as createNodeFromValue, s as moveSelectedIndices, u as getCurrentValue, v as parseValue } from "./update-DNInQSM7.js";
5
+ import { _ as parseArrayExpression, a as getChildrenSignatures, b as generateCode, c as removeIndices, d as getStructuredValue, f as readNodeBindings, g as isLosslesslyEvaluable, h as extractObjectProperties, i as valueToExpression, l as findEditableChildren, m as extractNodeValue, n as updateAll, o as extract, p as canLosslesslyEvaluateSource, r as createNodeFromValue, s as moveSelectedIndices, u as getCurrentValue, v as parseValue } from "./update-DyFnX8yE.js";
7
6
  import { t as cn } from "./cn-CAnad2vL.js";
8
- import { r as preloadScripts } from "./compile-DwOyWrmI.js";
9
- import { a as replaceSections, i as generateSection, r as extractSections } from "./sections-4uirsXRU.js";
10
- import { n as Error$1, t as ErrorBoundary } from "./boundary-6_nTsWxP.js";
11
- import { i as Frame, n as useCompiledModule, t as useDynamicTailwind } from "./use-dynamic-tailwind-CSYKXDmX.js";
12
- import { t as Core } from "./core-CKazr4tT.js";
7
+ import { r as preloadScripts } from "./compile-my0AjsCw.js";
8
+ import { a as replaceSections, i as generateSection, r as extractSections } from "./sections-rD8NuRI8.js";
9
+ import { n as Error$1, t as ErrorBoundary } from "./boundary-CySnDUs2.js";
10
+ import { a as renderStableComponent, n as useCompiledModule, o as Frame, t as useDynamicTailwind } from "./use-dynamic-tailwind-0nuRN57N.js";
11
+ import { i as getFieldKind, n as FieldIdsContext, o as FieldError, r as LABELABLE_KINDS, s as fields_module_default, t as useFieldState } from "./use-field-state-iQGW0vc6.js";
12
+ import { t as Core } from "./core-BNVuH8-l.js";
13
13
  import { Children, createContext, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
14
14
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
15
15
  import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, PointerSensor, TouchSensor, closestCenter, useDndContext, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
16
16
  import { restrictToParentElement, restrictToVerticalAxis } from "@dnd-kit/modifiers";
17
17
  import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
18
18
  import { useDebounce, useElementPosition, useKeyPress, useLatest, useMultiSelect, usePendingCommit, useResponsiveSize, useSet, useStableValue } from "@jbpark/use-hooks";
19
- import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, RichTextEditor, Select, Space, Splitter, TimePicker, Toast, Typography } from "@jbpark/ui-kit";
20
19
  import { CSS as CSS$1 } from "@dnd-kit/utilities";
21
20
  import { ArrowDown, ArrowUp, ChevronDown, ChevronRight, ChevronUp, Copy, Crosshair, GripVertical, LayoutGrid, Plus, Trash, X } from "lucide-react";
22
21
  //#region src/constants/palette-sections.ts
@@ -25,14 +24,8 @@ const PALETTE_SECTIONS = [
25
24
  id: "hero",
26
25
  name: "Hero",
27
26
  code: `
28
- <section
29
- data-name="Hero"
30
- className={cn(
31
- 'text-center text-white',
32
- //
33
- )}
34
- >
35
- <ui.Space
27
+ <section data-name="Hero" className="text-center text-white">
28
+ <div
36
29
  data-id=""
37
30
  data-binding={[
38
31
  {
@@ -43,33 +36,25 @@ const PALETTE_SECTIONS = [
43
36
  // fields as a top-level binding.
44
37
  render: {
45
38
  backgroundColor: { type: 'color', label: 'Background Color' },
39
+ gap: {
40
+ type: 'number',
41
+ label: 'Content Spacing',
42
+ // Constraints the library validates with or without a
43
+ // widget.
44
+ min: 0,
45
+ max: 40,
46
+ // Presentation only: the built-in panel ignores it and
47
+ // shows a number input; a custom panel can switch on
48
+ // widget.type.
49
+ widget: { type: 'slider', step: 4, unit: 'px' },
50
+ },
46
51
  },
47
52
  // Not a library field, so it arrives as meta.group.
48
53
  group: 'layout',
49
54
  },
50
- {
51
- label: 'Content Spacing',
52
- property: 'size',
53
- type: 'number',
54
- // Constraints the library validates with or without a widget.
55
- min: 0,
56
- max: 40,
57
- // Presentation only: the built-in panel ignores it and shows a
58
- // number input; a custom panel can switch on widget.type.
59
- widget: { type: 'slider', step: 4, unit: 'px' },
60
- group: 'layout',
61
- },
62
55
  ]}
63
- style={{
64
- backgroundColor: '#6366f1',
65
- }}
66
- orientation="vertical"
67
- size={16}
68
- align="center"
69
- className={cn(
70
- 'px-5 py-15',
71
- //
72
- )}
56
+ style={{ backgroundColor: '#6366f1', gap: 16 }}
57
+ className="flex flex-col items-center px-5 py-15"
73
58
  >
74
59
  <h1
75
60
  data-id=""
@@ -81,71 +66,29 @@ const PALETTE_SECTIONS = [
81
66
  required: true,
82
67
  },
83
68
  ]}
84
- className={cn(
85
- 'text-5xl font-bold',
86
- //
87
- )}
69
+ className="text-5xl font-bold"
88
70
  >
89
71
  Welcome to Live Editor
90
72
  </h1>
91
73
  <p
92
74
  data-id=""
93
- data-binding={[
94
- {
95
- label: 'Description',
96
- type: 'richtext',
97
- },
98
- ]}
99
- className={cn(
100
- 'text-xl',
101
- //
102
- )}
75
+ data-binding={[{ label: 'Description', type: 'richtext' }]}
76
+ className="text-xl"
103
77
  >
104
78
  Build <strong>dynamic components</strong> with drag & drop
105
79
  </p>
106
- <ui.Button
80
+ <a
107
81
  data-id=""
108
82
  data-binding={[
109
- {
110
- label: 'Button Text',
111
- property: 'innerText',
112
- },
113
- {
114
- label: 'Button Icon',
115
- property: 'icon',
116
- type: 'jsx',
117
- },
118
- {
119
- label: 'Button Size',
120
- property: 'size',
121
- options: [
122
- { label: 'Small', value: 'small' },
123
- { label: 'Middle', value: 'middle' },
124
- { label: 'Large', value: 'large' },
125
- ],
126
- },
127
- {
128
- label: 'Button Variant',
129
- property: 'variant',
130
- options: [
131
- { label: 'Solid', value: 'solid' },
132
- { label: 'Outlined', value: 'outlined' },
133
- { label: 'Filled', value: 'filled' },
134
- ],
135
- },
83
+ { label: 'Button Text', property: 'innerText' },
84
+ { label: 'Button Link', property: 'href', type: 'url' },
136
85
  ]}
137
- icon={<span>🚀</span>}
138
- size="large"
139
- variant="solid"
140
- className={cn(
141
- 'bg-white text-indigo-500',
142
- 'hover:bg-gray-50',
143
- //
144
- )}
86
+ href="https://github.com/pjb0811/live-editor"
87
+ className="rounded-md bg-white px-6 py-3 text-lg font-medium text-indigo-500 hover:bg-gray-50"
145
88
  >
146
- Get Started
147
- </ui.Button>
148
- </ui.Space>
89
+ 🚀 Get Started
90
+ </a>
91
+ </div>
149
92
  </section>
150
93
  `
151
94
  },
@@ -153,191 +96,82 @@ const PALETTE_SECTIONS = [
153
96
  id: "features",
154
97
  name: "Features",
155
98
  code: `
156
- <section
157
- data-name="Features"
158
- className={cn(
159
- 'px-5 py-10',
160
- //
161
- )}
162
- >
163
- <ui.Space
99
+ <section data-name="Features" className="px-5 py-10">
100
+ <div
164
101
  data-id=""
165
- data-binding={[
166
- {
167
- label: 'Feature Cards',
168
- property: 'children',
169
- },
170
- ]}
171
- className={cn(
172
- 'mx-auto max-w-7xl',
173
- //
174
- )}
175
- size="large"
176
- wrap
102
+ data-binding={[{ label: 'Feature Cards', property: 'children' }]}
103
+ className="mx-auto flex max-w-7xl flex-wrap gap-6"
177
104
  >
178
- <ui.Card
179
- className={cn(
180
- 'min-w-70 flex-1 text-center',
181
- //
182
- )}
183
- >
184
- <ui.Space orientation="vertical" size="middle" align="center">
185
- <div
186
- data-id=""
187
- data-binding={[
188
- {
189
- label: 'Icon',
190
- property: 'innerText',
191
- },
192
- ]}
193
- className={cn(
194
- 'text-5xl',
195
- //
196
- )}
197
- >
198
- 🚀
199
- </div>
200
- <h3
201
- data-id=""
202
- data-binding={[
203
- {
204
- label: 'Title',
205
- property: 'innerText',
206
- },
207
- ]}
208
- className={cn(
209
- 'text-2xl text-gray-800',
210
- //
211
- )}
212
- >
213
- Feature 1
214
- </h3>
215
- <p
216
- data-id=""
217
- data-binding={[
218
- {
219
- label: 'Description',
220
- property: 'innerText',
221
- },
222
- ]}
223
- className={cn(
224
- 'text-gray-600',
225
- //
226
- )}
227
- >
228
- Amazing feature description
229
- </p>
230
- </ui.Space>
231
- </ui.Card>
232
- <ui.Card
233
- className={cn(
234
- 'min-w-70 flex-1 text-center',
235
- //
236
- )}
237
- >
238
- <ui.Space orientation="vertical" size="middle" align="center">
239
- <div
240
- data-id=""
241
- data-binding={[
242
- {
243
- label: 'Icon',
244
- property: 'innerText',
245
- },
246
- ]}
247
- className={cn(
248
- 'text-5xl',
249
- //
250
- )}
251
- >
252
- ⚡
253
- </div>
254
- <h3
255
- data-id=""
256
- data-binding={[
257
- {
258
- label: 'Title',
259
- property: 'innerText',
260
- },
261
- ]}
262
- className={cn(
263
- 'text-2xl text-gray-800',
264
- //
265
- )}
266
- >
267
- Feature 2
268
- </h3>
269
- <p
270
- data-id=""
271
- data-binding={[
272
- {
273
- label: 'Description',
274
- property: 'innerText',
275
- },
276
- ]}
277
- className={cn(
278
- 'text-gray-600',
279
- //
280
- )}
281
- >
282
- Another great feature
283
- </p>
284
- </ui.Space>
285
- </ui.Card>
286
- <ui.Card
287
- className={cn(
288
- 'min-w-70 flex-1 text-center',
289
- //
290
- )}
291
- >
292
- <ui.Space orientation="vertical" size="middle" align="center">
293
- <div
294
- data-id=""
295
- data-binding={[
296
- {
297
- label: 'Icon',
298
- property: 'innerText',
299
- },
300
- ]}
301
- className={cn(
302
- 'text-5xl',
303
- //
304
- )}
305
- >
306
- ✨
307
- </div>
308
- <h3
309
- data-id=""
310
- data-binding={[
311
- {
312
- label: 'Title',
313
- property: 'innerText',
314
- },
315
- ]}
316
- className={cn(
317
- 'text-2xl text-gray-800',
318
- //
319
- )}
320
- >
321
- Feature 3
322
- </h3>
323
- <p
324
- data-id=""
325
- data-binding={[
326
- {
327
- label: 'Description',
328
- property: 'innerText',
329
- },
330
- ]}
331
- className={cn(
332
- 'text-gray-600',
333
- //
334
- )}
335
- >
336
- One more awesome thing
337
- </p>
338
- </ui.Space>
339
- </ui.Card>
340
- </ui.Space>
105
+ <div className="min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center">
106
+ <div
107
+ data-id=""
108
+ data-binding={[{ label: 'Icon', property: 'innerText' }]}
109
+ className="mb-3 text-5xl"
110
+ >
111
+ 🚀
112
+ </div>
113
+ <h3
114
+ data-id=""
115
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
116
+ className="mb-2 text-2xl text-gray-800"
117
+ >
118
+ Feature 1
119
+ </h3>
120
+ <p
121
+ data-id=""
122
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
123
+ className="text-gray-600"
124
+ >
125
+ Amazing feature description
126
+ </p>
127
+ </div>
128
+ <div className="min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center">
129
+ <div
130
+ data-id=""
131
+ data-binding={[{ label: 'Icon', property: 'innerText' }]}
132
+ className="mb-3 text-5xl"
133
+ >
134
+ ⚡
135
+ </div>
136
+ <h3
137
+ data-id=""
138
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
139
+ className="mb-2 text-2xl text-gray-800"
140
+ >
141
+ Feature 2
142
+ </h3>
143
+ <p
144
+ data-id=""
145
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
146
+ className="text-gray-600"
147
+ >
148
+ Another great feature
149
+ </p>
150
+ </div>
151
+ <div className="min-w-70 flex-1 rounded-lg border border-gray-200 bg-white p-6 text-center">
152
+ <div
153
+ data-id=""
154
+ data-binding={[{ label: 'Icon', property: 'innerText' }]}
155
+ className="mb-3 text-5xl"
156
+ >
157
+ ✨
158
+ </div>
159
+ <h3
160
+ data-id=""
161
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
162
+ className="mb-2 text-2xl text-gray-800"
163
+ >
164
+ Feature 3
165
+ </h3>
166
+ <p
167
+ data-id=""
168
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
169
+ className="text-gray-600"
170
+ >
171
+ One more awesome thing
172
+ </p>
173
+ </div>
174
+ </div>
341
175
  </section>
342
176
  `
343
177
  },
@@ -345,60 +179,34 @@ const PALETTE_SECTIONS = [
345
179
  id: "about",
346
180
  name: "About",
347
181
  code: `
348
- <section
349
- data-name="About"
350
- className={cn(
351
- 'mx-auto max-w-3xl px-5 py-10',
352
- //
353
- )}
354
- >
355
- <ui.Typography.Title
182
+ <section data-name="About" className="mx-auto max-w-3xl px-5 py-10">
183
+ <h2
356
184
  data-id=""
357
185
  data-binding={[{ label: 'Title', property: 'innerText' }]}
358
- level={2}
359
- className={cn(
360
- 'mb-5 text-4xl text-gray-800',
361
- //
362
- )}
186
+ className="mb-5 text-4xl font-semibold text-gray-800"
363
187
  >
364
188
  About Live Editor
365
- </ui.Typography.Title>
366
- <ui.Typography.Paragraph
189
+ </h2>
190
+ <p
367
191
  data-id=""
368
- data-binding={[
369
- {
370
- label: 'Description 1',
371
- type: 'richtext',
372
- },
373
- ]}
374
- className={cn(
375
- 'mb-4 text-lg leading-relaxed text-gray-600',
376
- //
377
- )}
192
+ data-binding={[{ label: 'Description 1', type: 'richtext' }]}
193
+ className="mb-4 text-lg leading-relaxed text-gray-600"
378
194
  >
379
195
  Live Editor is a powerful visual development tool that enables you to
380
196
  create stunning web interfaces through an intuitive drag-and-drop
381
197
  experience. Built with modern web technologies, it streamlines your
382
198
  workflow and accelerates development cycles.
383
- </ui.Typography.Paragraph>
384
- <ui.Typography.Paragraph
199
+ </p>
200
+ <p
385
201
  data-id=""
386
- data-binding={[
387
- {
388
- label: 'Description 2',
389
- type: 'richtext',
390
- },
391
- ]}
392
- className={cn(
393
- 'text-lg leading-relaxed text-gray-600',
394
- //
395
- )}
202
+ data-binding={[{ label: 'Description 2', type: 'richtext' }]}
203
+ className="text-lg leading-relaxed text-gray-600"
396
204
  >
397
205
  Whether you&apos;re a seasoned developer or just starting out, Live
398
206
  Editor provides the flexibility and control you need to bring your
399
207
  creative vision to life. Focus on what matters most - building great
400
208
  products.
401
- </ui.Typography.Paragraph>
209
+ </p>
402
210
  </section>
403
211
  `
404
212
  },
@@ -406,89 +214,44 @@ const PALETTE_SECTIONS = [
406
214
  id: "cta",
407
215
  name: "CTA",
408
216
  code: `
409
- <section
410
- data-name="CTA"
411
- className={cn(
412
- 'bg-gray-50 px-5 py-12 text-center',
413
- //
414
- )}
415
- >
416
- <div
417
- className={cn(
418
- 'mx-auto max-w-xl',
419
- //
420
- )}
421
- >
422
- <ui.Typography.Title
217
+ <section data-name="CTA" className="bg-gray-50 px-5 py-12 text-center">
218
+ <div className="mx-auto max-w-xl">
219
+ <h2
423
220
  data-id=""
424
221
  data-binding={[{ label: 'Title', property: 'innerText' }]}
425
- level={2}
426
- className={cn(
427
- 'mb-4 text-3xl text-gray-800',
428
- //
429
- )}
222
+ className="mb-4 text-3xl font-semibold text-gray-800"
430
223
  >
431
224
  Ready to get started?
432
- </ui.Typography.Title>
433
- <ui.Typography.Paragraph
225
+ </h2>
226
+ <p
434
227
  data-id=""
435
- data-binding={[
436
- {
437
- label: 'Description',
438
- property: 'innerText',
439
- },
440
- ]}
441
- className={cn(
442
- 'mb-6 text-lg text-gray-600',
443
- //
444
- )}
228
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
229
+ className="mb-6 text-lg text-gray-600"
445
230
  >
446
231
  Start exploring what Live Editor can do for your projects
447
- </ui.Typography.Paragraph>
448
- <ui.Space
232
+ </p>
233
+ <div
449
234
  data-id=""
450
235
  data-binding={[{ label: 'Buttons', property: 'children' }]}
451
- className={cn(
452
- 'flex flex-wrap justify-center gap-4',
453
- //
454
- )}
236
+ className="flex flex-wrap justify-center gap-4"
455
237
  >
456
- <ui.Button
238
+ <a
457
239
  data-id=""
458
- data-binding={[
459
- {
460
- label: 'Button 1 Text',
461
- property: 'innerText',
462
- },
463
- ]}
464
- size="large"
465
- className={cn(
466
- 'bg-indigo-500 px-8 text-base text-white',
467
- 'hover:bg-indigo-600',
468
- //
469
- )}
240
+ data-binding={[{ label: 'Button 1 Text', property: 'innerText' }]}
241
+ href="#"
242
+ className="rounded-md bg-indigo-500 px-8 py-3 text-base text-white hover:bg-indigo-600"
470
243
  >
471
244
  View Documentation
472
- </ui.Button>
473
- <ui.Button
245
+ </a>
246
+ <a
474
247
  data-id=""
475
- data-binding={[
476
- {
477
- label: 'Button 2 Text',
478
- property: 'innerText',
479
- },
480
- ]}
481
- variant="outlined"
482
- size="large"
483
- className={cn(
484
- 'border-2 border-indigo-500 px-8 text-base text-indigo-500',
485
- 'hover:bg-indigo-50',
486
- //
487
- )}
248
+ data-binding={[{ label: 'Button 2 Text', property: 'innerText' }]}
249
+ href="#"
250
+ className="rounded-md border-2 border-indigo-500 px-8 py-3 text-base text-indigo-500 hover:bg-indigo-50"
488
251
  >
489
252
  View Examples
490
- </ui.Button>
491
- </ui.Space>
253
+ </a>
254
+ </div>
492
255
  </div>
493
256
  </section>
494
257
  `
@@ -497,266 +260,118 @@ const PALETTE_SECTIONS = [
497
260
  id: "getting-started",
498
261
  name: "Getting Started",
499
262
  code: `
500
- <section
501
- data-name="Getting Started"
502
- className={cn(
503
- 'px-5 py-16',
504
- //
505
- )}
506
- >
507
- <div
508
- className={cn(
509
- 'mx-auto max-w-5xl',
510
- //
511
- )}
512
- >
513
- <ui.Typography.Title
263
+ <section data-name="Getting Started" className="px-5 py-16">
264
+ <div className="mx-auto max-w-5xl">
265
+ <h2
514
266
  data-id=""
515
267
  data-binding={[{ label: 'Title', property: 'innerText' }]}
516
- level={2}
517
- className={cn(
518
- 'mb-12 text-center text-4xl font-bold text-gray-800',
519
- //
520
- )}
268
+ className="mb-12 text-center text-4xl font-bold text-gray-800"
521
269
  >
522
270
  How to Get Started
523
- </ui.Typography.Title>
524
- <div
525
- className={cn(
526
- 'grid gap-8 md:grid-cols-3',
527
- //
528
- )}
529
- >
530
- <ui.Card
271
+ </h2>
272
+ <div className="grid gap-8 md:grid-cols-3">
273
+ <div
531
274
  data-id=""
532
- data-binding={[
533
- {
534
- label: 'Card 1 Content',
535
- property: 'children',
536
- },
537
- ]}
538
- className={cn(
539
- 'rounded-lg border-2 border-gray-200 bg-white p-8',
540
- //
541
- )}
275
+ data-binding={[{ label: 'Card 1 Content', property: 'children' }]}
276
+ className="rounded-lg border-2 border-gray-200 bg-white p-8"
542
277
  >
543
- <ui.Typography.Title
278
+ <h3
544
279
  data-id=""
545
- data-binding={[
546
- {
547
- label: 'Card 1 Title',
548
- property: 'innerText',
549
- },
550
- ]}
551
- level={3}
552
- className={cn(
553
- 'mb-2 text-2xl font-bold text-gray-800',
554
- //
555
- )}
280
+ data-binding={[{ label: 'Card 1 Title', property: 'innerText' }]}
281
+ className="mb-2 text-2xl font-bold text-gray-800"
556
282
  >
557
283
  Explore
558
- </ui.Typography.Title>
559
- <ui.Typography.Paragraph
284
+ </h3>
285
+ <p
560
286
  data-id=""
561
- data-binding={[
562
- {
563
- label: 'Card 1 Icon',
564
- property: 'innerText',
565
- },
566
- ]}
567
- className={cn(
568
- 'mb-6 text-4xl font-bold text-indigo-600',
569
- //
570
- )}
287
+ data-binding={[{ label: 'Card 1 Icon', property: 'innerText' }]}
288
+ className="mb-6 text-4xl font-bold text-indigo-600"
571
289
  >
572
290
  📚
573
- </ui.Typography.Paragraph>
574
- <ul
575
- className={cn(
576
- 'mb-8 space-y-3 text-gray-600',
577
- //
578
- )}
579
- >
291
+ </p>
292
+ <ul className="mb-8 space-y-3 text-gray-600">
580
293
  <li>✓ Read documentation</li>
581
294
  <li>✓ Browse examples</li>
582
295
  <li>✓ Try the demo</li>
583
296
  </ul>
584
- <ui.Button
297
+ <a
585
298
  data-id=""
586
- data-binding={[
587
- {
588
- label: 'Card 1 Button',
589
- property: 'innerText',
590
- },
591
- ]}
592
- variant="outlined"
593
- size="large"
594
- block
595
- className={cn(
596
- 'border-2 border-indigo-500 text-indigo-500',
597
- 'hover:bg-indigo-50',
598
- //
599
- )}
299
+ data-binding={[{ label: 'Card 1 Button', property: 'innerText' }]}
300
+ href="#"
301
+ className="block rounded-md border-2 border-indigo-500 px-4 py-2 text-center text-indigo-500 hover:bg-indigo-50"
600
302
  >
601
303
  View Docs
602
- </ui.Button>
603
- </ui.Card>
604
- <ui.Card
304
+ </a>
305
+ </div>
306
+ <div
605
307
  data-id=""
606
- data-binding={[
607
- {
608
- label: 'Card 2 Content',
609
- property: 'children',
610
- },
611
- ]}
612
- className={cn(
613
- 'relative rounded-lg border-2 border-indigo-500 bg-white p-8',
614
- //
615
- )}
308
+ data-binding={[{ label: 'Card 2 Content', property: 'children' }]}
309
+ className="relative rounded-lg border-2 border-indigo-500 bg-white p-8"
616
310
  >
617
- <div
618
- className={cn(
619
- 'absolute -top-4 left-1/2 -translate-x-1/2',
620
- 'rounded-full bg-indigo-500 px-4 py-1 text-sm text-white',
621
- //
622
- )}
623
- >
311
+ <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">
624
312
  Recommended
625
313
  </div>
626
- <ui.Typography.Title
314
+ <h3
627
315
  data-id=""
628
- data-binding={[
629
- {
630
- label: 'Card 2 Title',
631
- property: 'innerText',
632
- },
633
- ]}
634
- level={3}
635
- className={cn(
636
- 'mb-2 text-2xl font-bold text-gray-800',
637
- //
638
- )}
316
+ data-binding={[{ label: 'Card 2 Title', property: 'innerText' }]}
317
+ className="mb-2 text-2xl font-bold text-gray-800"
639
318
  >
640
319
  Practice
641
- </ui.Typography.Title>
642
- <ui.Typography.Paragraph
320
+ </h3>
321
+ <p
643
322
  data-id=""
644
- data-binding={[
645
- {
646
- label: 'Card 2 Icon',
647
- property: 'innerText',
648
- },
649
- ]}
650
- className={cn(
651
- 'mb-6 text-4xl font-bold text-indigo-600',
652
- //
653
- )}
323
+ data-binding={[{ label: 'Card 2 Icon', property: 'innerText' }]}
324
+ className="mb-6 text-4xl font-bold text-indigo-600"
654
325
  >
655
326
  💻
656
- </ui.Typography.Paragraph>
657
- <ul
658
- className={cn(
659
- 'mb-8 space-y-3 text-gray-600',
660
- //
661
- )}
662
- >
327
+ </p>
328
+ <ul className="mb-8 space-y-3 text-gray-600">
663
329
  <li>✓ Interactive playground</li>
664
330
  <li>✓ Experiment freely</li>
665
331
  <li>✓ Build your own</li>
666
332
  </ul>
667
- <ui.Button
333
+ <a
668
334
  data-id=""
669
- data-binding={[
670
- {
671
- label: 'Card 2 Button',
672
- property: 'innerText',
673
- },
674
- ]}
675
- size="large"
676
- block
677
- className={cn(
678
- 'bg-indigo-500 text-white',
679
- 'hover:bg-indigo-600',
680
- //
681
- )}
335
+ data-binding={[{ label: 'Card 2 Button', property: 'innerText' }]}
336
+ href="#"
337
+ className="block rounded-md bg-indigo-500 px-4 py-2 text-center text-white hover:bg-indigo-600"
682
338
  >
683
339
  Start Building
684
- </ui.Button>
685
- </ui.Card>
686
- <ui.Card
340
+ </a>
341
+ </div>
342
+ <div
687
343
  data-id=""
688
- data-binding={[
689
- {
690
- label: 'Card 3 Content',
691
- property: 'children',
692
- },
693
- ]}
694
- className={cn(
695
- 'rounded-lg border-2 border-gray-200 bg-white p-8',
696
- //
697
- )}
344
+ data-binding={[{ label: 'Card 3 Content', property: 'children' }]}
345
+ className="rounded-lg border-2 border-gray-200 bg-white p-8"
698
346
  >
699
- <ui.Typography.Title
347
+ <h3
700
348
  data-id=""
701
- data-binding={[
702
- {
703
- label: 'Card 3 Title',
704
- property: 'innerText',
705
- },
706
- ]}
707
- level={3}
708
- className={cn(
709
- 'mb-2 text-2xl font-bold text-gray-800',
710
- //
711
- )}
349
+ data-binding={[{ label: 'Card 3 Title', property: 'innerText' }]}
350
+ className="mb-2 text-2xl font-bold text-gray-800"
712
351
  >
713
352
  Contribute
714
- </ui.Typography.Title>
715
- <ui.Typography.Paragraph
353
+ </h3>
354
+ <p
716
355
  data-id=""
717
- data-binding={[
718
- {
719
- label: 'Card 3 Icon',
720
- property: 'innerText',
721
- },
722
- ]}
723
- className={cn(
724
- 'mb-6 text-4xl font-bold text-indigo-600',
725
- //
726
- )}
356
+ data-binding={[{ label: 'Card 3 Icon', property: 'innerText' }]}
357
+ className="mb-6 text-4xl font-bold text-indigo-600"
727
358
  >
728
359
  🤝
729
- </ui.Typography.Paragraph>
730
- <ul
731
- className={cn(
732
- 'mb-8 space-y-3 text-gray-600',
733
- //
734
- )}
735
- >
360
+ </p>
361
+ <ul className="mb-8 space-y-3 text-gray-600">
736
362
  <li>✓ Report issues</li>
737
363
  <li>✓ Suggest features</li>
738
364
  <li>✓ Submit pull requests</li>
739
365
  </ul>
740
- <ui.Button
366
+ <a
741
367
  data-id=""
742
- data-binding={[
743
- {
744
- label: 'Card 3 Button',
745
- property: 'innerText',
746
- },
747
- ]}
748
- variant="outlined"
749
- size="large"
750
- block
751
- className={cn(
752
- 'border-2 border-indigo-500 text-indigo-500',
753
- 'hover:bg-indigo-50',
754
- //
755
- )}
368
+ data-binding={[{ label: 'Card 3 Button', property: 'innerText' }]}
369
+ href="#"
370
+ className="block rounded-md border-2 border-indigo-500 px-4 py-2 text-center text-indigo-500 hover:bg-indigo-50"
756
371
  >
757
372
  View on GitHub
758
- </ui.Button>
759
- </ui.Card>
373
+ </a>
374
+ </div>
760
375
  </div>
761
376
  </div>
762
377
  </section>
@@ -766,96 +381,33 @@ const PALETTE_SECTIONS = [
766
381
  id: "key-features",
767
382
  name: "Key Features",
768
383
  code: `
769
- <section
770
- data-name="Key Features"
771
- className={cn(
772
- 'bg-indigo-50 px-5 py-16',
773
- //
774
- )}
775
- >
776
- <div
777
- className={cn(
778
- 'mx-auto max-w-6xl',
779
- //
780
- )}
781
- >
384
+ <section data-name="Key Features" className="bg-indigo-50 px-5 py-16">
385
+ <div className="mx-auto max-w-6xl">
782
386
  <h2
783
387
  data-id=""
784
388
  data-binding={[{ label: 'Title', property: 'innerText' }]}
785
- className={cn(
786
- 'mb-12 text-center text-4xl font-bold text-gray-800',
787
- //
788
- )}
389
+ className="mb-12 text-center text-4xl font-bold text-gray-800"
789
390
  >
790
391
  Key Features
791
392
  </h2>
792
- <div
793
- className={cn(
794
- 'grid gap-8 md:grid-cols-2',
795
- //
796
- )}
797
- >
798
- <div
799
- className={cn(
800
- 'rounded-lg bg-white p-8 shadow-md',
801
- //
802
- )}
803
- >
804
- <div
805
- className={cn(
806
- 'mb-4 text-4xl',
807
- //
808
- )}
809
- >
810
- 🎨
811
- </div>
812
- <h3
813
- className={cn(
814
- 'mb-4 text-2xl font-bold text-gray-800',
815
- //
816
- )}
817
- >
393
+ <div className="grid gap-8 md:grid-cols-2">
394
+ <div className="rounded-lg bg-white p-8 shadow-md">
395
+ <div className="mb-4 text-4xl">🎨</div>
396
+ <h3 className="mb-4 text-2xl font-bold text-gray-800">
818
397
  Visual Editing
819
398
  </h3>
820
- <p
821
- className={cn(
822
- 'text-gray-600',
823
- //
824
- )}
825
- >
399
+ <p className="text-gray-600">
826
400
  See your changes in real-time as you build. Live Editor provides
827
401
  instant visual feedback, making it easier to understand how code
828
402
  affects your interface.
829
403
  </p>
830
404
  </div>
831
- <div
832
- className={cn(
833
- 'rounded-lg bg-white p-8 shadow-md',
834
- //
835
- )}
836
- >
837
- <div
838
- className={cn(
839
- 'mb-4 text-4xl',
840
- //
841
- )}
842
- >
843
- 🧩
844
- </div>
845
- <h3
846
- className={cn(
847
- 'mb-4 text-2xl font-bold text-gray-800',
848
- //
849
- )}
850
- >
405
+ <div className="rounded-lg bg-white p-8 shadow-md">
406
+ <div className="mb-4 text-4xl">🧩</div>
407
+ <h3 className="mb-4 text-2xl font-bold text-gray-800">
851
408
  Component-Based
852
409
  </h3>
853
- <p
854
- className={cn(
855
- 'text-gray-600',
856
- //
857
- )}
858
- >
410
+ <p className="text-gray-600">
859
411
  Build with reusable components that you can drag, drop, and
860
412
  customize. Learn modern development patterns while creating your
861
413
  interface.
@@ -870,199 +422,77 @@ const PALETTE_SECTIONS = [
870
422
  id: "stats",
871
423
  name: "Stats",
872
424
  code: `
873
- <section
874
- data-name="Stats"
875
- className={cn(
876
- 'bg-indigo-600 text-white',
877
- //
878
- )}
879
- >
880
- <ui.Marquees
425
+ <section data-name="Stats" className="bg-indigo-600 px-5 py-16 text-white">
426
+ <div
881
427
  data-id=""
882
- data-binding={[
883
- { label: 'Stats Items', property: 'items' },
884
- {
885
- label: 'Scroll Speed',
886
- property: 'speed',
887
- type: 'number',
888
- min: 20,
889
- max: 300,
890
- // The bare-string form; it arrives as { type: 'slider' }.
891
- widget: 'slider',
892
- },
893
- { label: 'Pause On Hover', property: 'pauseOnHover', type: 'boolean' },
894
- ]}
895
- speed={100}
896
- pauseOnHover={true}
897
- autoFill={true}
898
- className="px-5 py-16"
899
- items={[
900
- {
901
- key: 'stats-row',
902
- children: (
903
- <div
904
- data-id=""
905
- data-binding={[
906
- {
907
- label: 'Stats Cards',
908
- property: 'children',
909
- },
910
- ]}
911
- className={cn('flex gap-20')}
912
- >
913
- <div
914
- className={cn(
915
- 'min-w-60 text-center',
916
- //
917
- )}
918
- >
919
- <p
920
- data-id=""
921
- data-binding={[
922
- {
923
- label: 'Title',
924
- property: 'innerText',
925
- },
926
- ]}
927
- className={cn(
928
- 'mb-2 text-5xl font-bold',
929
- //
930
- )}
931
- >
932
- Open
933
- </p>
934
- <p
935
- data-id=""
936
- data-binding={[
937
- {
938
- label: 'Description',
939
- property: 'innerText',
940
- },
941
- ]}
942
- className={cn(
943
- 'text-indigo-200',
944
- //
945
- )}
946
- >
947
- Source Project
948
- </p>
949
- </div>
950
- <div
951
- className={cn(
952
- 'min-w-60 text-center',
953
- //
954
- )}
955
- >
956
- <p
957
- data-id=""
958
- data-binding={[
959
- {
960
- label: 'Title',
961
- property: 'innerText',
962
- },
963
- ]}
964
- className={cn(
965
- 'mb-2 text-5xl font-bold',
966
- //
967
- )}
968
- >
969
- Free
970
- </p>
971
- <p
972
- data-id=""
973
- data-binding={[
974
- {
975
- label: 'Description',
976
- property: 'innerText',
977
- },
978
- ]}
979
- className={cn(
980
- 'text-indigo-200',
981
- //
982
- )}
983
- >
984
- For Everyone
985
- </p>
986
- </div>
987
- <div
988
- className={cn(
989
- 'min-w-60 text-center',
990
- //
991
- )}
992
- >
993
- <p
994
- data-id=""
995
- data-binding={[
996
- {
997
- label: 'Title',
998
- property: 'innerText',
999
- },
1000
- ]}
1001
- className={cn(
1002
- 'mb-2 text-5xl font-bold',
1003
- //
1004
- )}
1005
- >
1006
- Active
1007
- </p>
1008
- <p
1009
- data-id=""
1010
- data-binding={[
1011
- {
1012
- label: 'Description',
1013
- property: 'innerText',
1014
- },
1015
- ]}
1016
- className={cn(
1017
- 'text-indigo-200',
1018
- //
1019
- )}
1020
- >
1021
- Community
1022
- </p>
1023
- </div>
1024
- <div
1025
- className={cn(
1026
- 'min-w-60 text-center',
1027
- //
1028
- )}
1029
- >
1030
- <p
1031
- data-id=""
1032
- data-binding={[
1033
- {
1034
- label: 'Title',
1035
- property: 'innerText',
1036
- },
1037
- ]}
1038
- className={cn(
1039
- 'mb-2 text-5xl font-bold',
1040
- //
1041
- )}
1042
- >
1043
- Learn
1044
- </p>
1045
- <p
1046
- data-id=""
1047
- data-binding={[
1048
- {
1049
- label: 'Description',
1050
- property: 'innerText',
1051
- },
1052
- ]}
1053
- className={cn(
1054
- 'text-indigo-200',
1055
- //
1056
- )}
1057
- >
1058
- By Doing
1059
- </p>
1060
- </div>
1061
- </div>
1062
- ),
1063
- },
1064
- ]}
1065
- />
428
+ data-binding={[{ label: 'Stats Cards', property: 'children' }]}
429
+ className="mx-auto flex max-w-6xl flex-wrap justify-center gap-10"
430
+ >
431
+ <div className="min-w-50 flex-1 text-center">
432
+ <p
433
+ data-id=""
434
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
435
+ className="mb-2 text-5xl font-bold"
436
+ >
437
+ Open
438
+ </p>
439
+ <p
440
+ data-id=""
441
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
442
+ className="text-indigo-200"
443
+ >
444
+ Source Project
445
+ </p>
446
+ </div>
447
+ <div className="min-w-50 flex-1 text-center">
448
+ <p
449
+ data-id=""
450
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
451
+ className="mb-2 text-5xl font-bold"
452
+ >
453
+ Free
454
+ </p>
455
+ <p
456
+ data-id=""
457
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
458
+ className="text-indigo-200"
459
+ >
460
+ For Everyone
461
+ </p>
462
+ </div>
463
+ <div className="min-w-50 flex-1 text-center">
464
+ <p
465
+ data-id=""
466
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
467
+ className="mb-2 text-5xl font-bold"
468
+ >
469
+ Active
470
+ </p>
471
+ <p
472
+ data-id=""
473
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
474
+ className="text-indigo-200"
475
+ >
476
+ Community
477
+ </p>
478
+ </div>
479
+ <div className="min-w-50 flex-1 text-center">
480
+ <p
481
+ data-id=""
482
+ data-binding={[{ label: 'Title', property: 'innerText' }]}
483
+ className="mb-2 text-5xl font-bold"
484
+ >
485
+ Learn
486
+ </p>
487
+ <p
488
+ data-id=""
489
+ data-binding={[{ label: 'Description', property: 'innerText' }]}
490
+ className="text-indigo-200"
491
+ >
492
+ By Doing
493
+ </p>
494
+ </div>
495
+ </div>
1066
496
  </section>
1067
497
  `
1068
498
  },
@@ -1070,147 +500,311 @@ const PALETTE_SECTIONS = [
1070
500
  id: "roadmap",
1071
501
  name: "Roadmap",
1072
502
  code: `
1073
- <section
1074
- data-name="Roadmap"
1075
- className={cn(
1076
- 'px-5 py-16',
1077
- //
1078
- )}
1079
- >
1080
- <div
1081
- className={cn(
1082
- 'mx-auto max-w-3xl',
1083
- //
1084
- )}
1085
- >
503
+ <section data-name="Roadmap" className="px-5 py-16">
504
+ <div className="mx-auto max-w-3xl">
1086
505
  <h2
1087
506
  data-id=""
1088
507
  data-binding={[
1089
508
  { label: 'Title', property: 'innerText', required: true },
1090
509
  ]}
1091
- className={cn(
1092
- 'mb-8 text-center text-4xl font-bold text-gray-800',
1093
- //
1094
- )}
510
+ className="mb-8 text-center text-4xl font-bold text-gray-800"
1095
511
  >
1096
512
  Roadmap
1097
513
  </h2>
1098
- <ui.List
514
+ <ol
1099
515
  data-id=""
1100
- data-binding={[
1101
- {
1102
- label: 'Milestones',
1103
- property: 'data',
1104
- type: 'array',
1105
- // One leaf per item key. Each leaf takes the same fields as a
1106
- // top-level binding, and label falls back to the key.
1107
- render: {
1108
- title: {
1109
- type: 'string',
1110
- label: 'Title',
1111
- required: true,
1112
- },
1113
- date: { type: 'date', label: 'Release Date', required: true },
1114
- status: {
1115
- type: 'string',
1116
- label: 'Status',
1117
- options: [
1118
- { label: 'Planned', value: 'planned' },
1119
- { label: 'In Progress', value: 'in-progress' },
1120
- { label: 'Shipped', value: 'shipped' },
1121
- ],
516
+ data-binding={[{ label: 'Milestones', property: 'children' }]}
517
+ >
518
+ <li className="flex items-center gap-4 border-b border-gray-100 py-4">
519
+ <span
520
+ data-id=""
521
+ data-binding={[
522
+ {
523
+ label: 'Accent',
524
+ property: 'style',
525
+ type: 'object',
526
+ render: {
527
+ backgroundColor: { type: 'color', label: 'Accent Color' },
528
+ },
1122
529
  },
1123
- progress: {
1124
- type: 'number',
1125
- label: 'Progress',
1126
- min: 0,
1127
- max: 100,
1128
- widget: { type: 'slider', step: 10, unit: '%' },
530
+ ]}
531
+ style={{ backgroundColor: '#22c55e' }}
532
+ className="size-3 shrink-0 rounded-full"
533
+ />
534
+ <div className="min-w-0 flex-1">
535
+ <p
536
+ data-id=""
537
+ data-binding={[
538
+ { label: 'Title', property: 'innerText', required: true },
539
+ ]}
540
+ className="font-semibold text-gray-800"
541
+ >
542
+ Visual editing
543
+ </p>
544
+ <p className="text-sm text-gray-500">
545
+ <time
546
+ data-id=""
547
+ data-binding={[
548
+ {
549
+ label: 'Release Date',
550
+ property: 'dateTime',
551
+ type: 'date',
552
+ required: true,
553
+ },
554
+ { label: 'Date Text', property: 'innerText' },
555
+ ]}
556
+ dateTime="2026-03-02"
557
+ >
558
+ March 2, 2026
559
+ </time>
560
+ {' · '}
561
+ <span
562
+ data-id=""
563
+ data-binding={[
564
+ {
565
+ label: 'Status',
566
+ property: 'innerText',
567
+ options: [
568
+ { label: 'Planned', value: 'Planned' },
569
+ { label: 'In Progress', value: 'In Progress' },
570
+ { label: 'Shipped', value: 'Shipped' },
571
+ ],
572
+ },
573
+ ]}
574
+ >
575
+ Shipped
576
+ </span>
577
+ </p>
578
+ <progress
579
+ data-id=""
580
+ data-binding={[
581
+ {
582
+ label: 'Progress',
583
+ property: 'value',
584
+ type: 'number',
585
+ min: 0,
586
+ max: 100,
587
+ widget: { type: 'slider', step: 10, unit: '%' },
588
+ },
589
+ ]}
590
+ value={100}
591
+ max={100}
592
+ className="mt-2 h-2 w-full"
593
+ />
594
+ </div>
595
+ <a
596
+ data-id=""
597
+ data-binding={[
598
+ { label: 'Link Text', property: 'innerText' },
599
+ {
600
+ label: 'Link URL',
601
+ property: 'href',
602
+ type: 'url',
603
+ pattern: '^https://',
604
+ // Not a library field, so it arrives as meta.hint.
605
+ hint: 'Must use https',
1129
606
  },
1130
- color: { type: 'color', label: 'Accent Color' },
1131
- highlight: { type: 'boolean', label: 'Highlight' },
1132
- // An object-valued key: its own render map types the keys
1133
- // inside it, one level further down.
1134
- link: {
607
+ ]}
608
+ href="https://github.com"
609
+ className="text-sm text-indigo-500 hover:underline"
610
+ >
611
+ Release notes
612
+ </a>
613
+ </li>
614
+ <li className="flex items-center gap-4 border-b border-gray-100 py-4">
615
+ <span
616
+ data-id=""
617
+ data-binding={[
618
+ {
619
+ label: 'Accent',
620
+ property: 'style',
1135
621
  type: 'object',
1136
- label: 'Link',
1137
622
  render: {
1138
- text: { type: 'string', label: 'Link Text' },
1139
- href: {
1140
- type: 'url',
1141
- label: 'Link URL',
1142
- pattern: '^https://',
1143
- // Not a library field, so it arrives as meta.hint.
1144
- hint: 'Must use https',
623
+ backgroundColor: { type: 'color', label: 'Accent Color' },
624
+ },
625
+ },
626
+ ]}
627
+ style={{ backgroundColor: '#6366f1' }}
628
+ className="size-3 shrink-0 rounded-full"
629
+ />
630
+ <div className="min-w-0 flex-1">
631
+ <p
632
+ data-id=""
633
+ data-binding={[
634
+ { label: 'Title', property: 'innerText', required: true },
635
+ ]}
636
+ className="font-semibold text-gray-800"
637
+ >
638
+ Custom panels
639
+ </p>
640
+ <p className="text-sm text-gray-500">
641
+ <time
642
+ data-id=""
643
+ data-binding={[
644
+ {
645
+ label: 'Release Date',
646
+ property: 'dateTime',
647
+ type: 'date',
648
+ required: true,
1145
649
  },
650
+ { label: 'Date Text', property: 'innerText' },
651
+ ]}
652
+ dateTime="2026-09-26"
653
+ >
654
+ September 26, 2026
655
+ </time>
656
+ {' · '}
657
+ <span
658
+ data-id=""
659
+ data-binding={[
660
+ {
661
+ label: 'Status',
662
+ property: 'innerText',
663
+ options: [
664
+ { label: 'Planned', value: 'Planned' },
665
+ { label: 'In Progress', value: 'In Progress' },
666
+ { label: 'Shipped', value: 'Shipped' },
667
+ ],
668
+ },
669
+ ]}
670
+ >
671
+ In Progress
672
+ </span>
673
+ </p>
674
+ <progress
675
+ data-id=""
676
+ data-binding={[
677
+ {
678
+ label: 'Progress',
679
+ property: 'value',
680
+ type: 'number',
681
+ min: 0,
682
+ max: 100,
683
+ widget: { type: 'slider', step: 10, unit: '%' },
1146
684
  },
685
+ ]}
686
+ value={60}
687
+ max={100}
688
+ className="mt-2 h-2 w-full"
689
+ />
690
+ </div>
691
+ <a
692
+ data-id=""
693
+ data-binding={[
694
+ { label: 'Link Text', property: 'innerText' },
695
+ {
696
+ label: 'Link URL',
697
+ property: 'href',
698
+ type: 'url',
699
+ pattern: '^https://',
700
+ // Not a library field, so it arrives as meta.hint.
701
+ hint: 'Must use https',
1147
702
  },
1148
- },
1149
- },
1150
- ]}
1151
- data={[
1152
- {
1153
- title: 'Visual editing',
1154
- date: '2026-03-02',
1155
- status: 'shipped',
1156
- progress: 100,
1157
- color: '#22c55e',
1158
- highlight: false,
1159
- link: { text: 'Release notes', href: 'https://github.com' },
1160
- },
1161
- {
1162
- title: 'Custom panels',
1163
- date: '2026-09-26',
1164
- status: 'in-progress',
1165
- progress: 60,
1166
- color: '#6366f1',
1167
- highlight: true,
1168
- link: { text: 'Guide', href: 'https://github.com' },
1169
- },
1170
- {
1171
- title: 'Collaboration',
1172
- date: '2027-01-15',
1173
- status: 'planned',
1174
- progress: 0,
1175
- color: '#f59e0b',
1176
- highlight: false,
1177
- link: { text: 'Discussion', href: 'https://github.com' },
1178
- },
1179
- ]}
1180
- itemKey={item => item.title}
1181
- renderItem={item => (
1182
- <div
1183
- className={cn(
1184
- 'flex items-center gap-4 border-b border-gray-100 py-4',
1185
- item.highlight && 'rounded-lg bg-indigo-50 px-4',
1186
- )}
703
+ ]}
704
+ href="https://github.com"
705
+ className="text-sm text-indigo-500 hover:underline"
1187
706
  >
1188
- <span
1189
- className="size-3 shrink-0 rounded-full"
1190
- style={{ backgroundColor: item.color }}
707
+ Guide
708
+ </a>
709
+ </li>
710
+ <li className="flex items-center gap-4 border-b border-gray-100 py-4">
711
+ <span
712
+ data-id=""
713
+ data-binding={[
714
+ {
715
+ label: 'Accent',
716
+ property: 'style',
717
+ type: 'object',
718
+ render: {
719
+ backgroundColor: { type: 'color', label: 'Accent Color' },
720
+ },
721
+ },
722
+ ]}
723
+ style={{ backgroundColor: '#f59e0b' }}
724
+ className="size-3 shrink-0 rounded-full"
725
+ />
726
+ <div className="min-w-0 flex-1">
727
+ <p
728
+ data-id=""
729
+ data-binding={[
730
+ { label: 'Title', property: 'innerText', required: true },
731
+ ]}
732
+ className="font-semibold text-gray-800"
733
+ >
734
+ Collaboration
735
+ </p>
736
+ <p className="text-sm text-gray-500">
737
+ <time
738
+ data-id=""
739
+ data-binding={[
740
+ {
741
+ label: 'Release Date',
742
+ property: 'dateTime',
743
+ type: 'date',
744
+ required: true,
745
+ },
746
+ { label: 'Date Text', property: 'innerText' },
747
+ ]}
748
+ dateTime="2027-01-15"
749
+ >
750
+ January 15, 2027
751
+ </time>
752
+ {' · '}
753
+ <span
754
+ data-id=""
755
+ data-binding={[
756
+ {
757
+ label: 'Status',
758
+ property: 'innerText',
759
+ options: [
760
+ { label: 'Planned', value: 'Planned' },
761
+ { label: 'In Progress', value: 'In Progress' },
762
+ { label: 'Shipped', value: 'Shipped' },
763
+ ],
764
+ },
765
+ ]}
766
+ >
767
+ Planned
768
+ </span>
769
+ </p>
770
+ <progress
771
+ data-id=""
772
+ data-binding={[
773
+ {
774
+ label: 'Progress',
775
+ property: 'value',
776
+ type: 'number',
777
+ min: 0,
778
+ max: 100,
779
+ widget: { type: 'slider', step: 10, unit: '%' },
780
+ },
781
+ ]}
782
+ value={0}
783
+ max={100}
784
+ className="mt-2 h-2 w-full"
1191
785
  />
1192
- <div className="min-w-0 flex-1">
1193
- <p className="font-semibold text-gray-800">{item.title}</p>
1194
- <p className="text-sm text-gray-500">
1195
- {item.date} · {item.status}
1196
- </p>
1197
- <ui.Progress value={item.progress} className="mt-2" />
1198
- </div>
1199
- <a
1200
- href={item.link.href}
1201
- className="text-sm text-indigo-500 hover:underline"
1202
- >
1203
- {item.link.text}
1204
- </a>
1205
786
  </div>
1206
- )}
1207
- />
1208
- <p
1209
- className={cn(
1210
- 'mt-6 text-center text-sm text-gray-500',
1211
- //
1212
- )}
1213
- >
787
+ <a
788
+ data-id=""
789
+ data-binding={[
790
+ { label: 'Link Text', property: 'innerText' },
791
+ {
792
+ label: 'Link URL',
793
+ property: 'href',
794
+ type: 'url',
795
+ pattern: '^https://',
796
+ // Not a library field, so it arrives as meta.hint.
797
+ hint: 'Must use https',
798
+ },
799
+ ]}
800
+ href="https://github.com"
801
+ className="text-sm text-indigo-500 hover:underline"
802
+ >
803
+ Discussion
804
+ </a>
805
+ </li>
806
+ </ol>
807
+ <p className="mt-6 text-center text-sm text-gray-500">
1214
808
  Last updated{' '}
1215
809
  <time
1216
810
  data-id=""
@@ -1254,179 +848,133 @@ const PALETTE_SECTIONS = [
1254
848
  id: "faq",
1255
849
  name: "FAQ",
1256
850
  code: `
1257
- <section
1258
- data-name="FAQ"
1259
- className={cn(
1260
- 'px-5 py-16',
1261
- //
1262
- )}
1263
- >
1264
- <div
1265
- className={cn(
1266
- 'mx-auto max-w-3xl',
1267
- //
1268
- )}
1269
- >
1270
- <ui.Typography.Title
851
+ <section data-name="FAQ" className="px-5 py-16">
852
+ <div className="mx-auto max-w-3xl">
853
+ <h2
1271
854
  data-id=""
1272
855
  data-binding={[{ label: 'Title', property: 'innerText' }]}
1273
- level={2}
1274
- className={cn(
1275
- 'mb-12 text-center text-4xl font-bold text-gray-800',
1276
- //
1277
- )}
856
+ className="mb-12 text-center text-4xl font-bold text-gray-800"
1278
857
  >
1279
858
  Frequently Asked Questions
1280
- </ui.Typography.Title>
1281
- <ui.Collapse
859
+ </h2>
860
+ <div
1282
861
  data-id=""
1283
- data-binding={[{ label: 'FAQ Items', property: 'items' }]}
1284
- items={[
1285
- {
1286
- key: '1',
1287
- label: (
1288
- <ui.Typography.Text
1289
- data-id=""
1290
- data-binding={[
1291
- {
1292
- label: 'Question 1',
1293
- property: 'innerText',
1294
- },
1295
- ]}
1296
- className={cn('text-lg font-semibold text-gray-800')}
1297
- >
1298
- What is Live Editor?
1299
- </ui.Typography.Text>
1300
- ),
1301
- children: (
1302
- <ui.Typography.Paragraph
1303
- data-id=""
1304
- data-binding={[
1305
- {
1306
- label: 'Answer 1',
1307
- type: 'richtext',
1308
- },
1309
- ]}
1310
- className={cn('text-gray-600')}
1311
- >
1312
- Live Editor is an open-source tool for building web
1313
- interfaces visually. It helps you learn web development by
1314
- providing instant feedback as you build components.
1315
- </ui.Typography.Paragraph>
1316
- ),
1317
- },
1318
- {
1319
- key: '2',
1320
- label: (
1321
- <ui.Typography.Text
1322
- data-id=""
1323
- data-binding={[
1324
- {
1325
- label: 'Question 2',
1326
- property: 'innerText',
1327
- },
1328
- ]}
1329
- className={cn('text-lg font-semibold text-gray-800')}
1330
- >
1331
- Do I need coding experience?
1332
- </ui.Typography.Text>
1333
- ),
1334
- children: (
1335
- <ui.Typography.Paragraph
1336
- data-id=""
1337
- data-binding={[
1338
- {
1339
- label: 'Answer 2',
1340
- type: 'richtext',
1341
- },
1342
- ]}
1343
- className={cn('text-gray-600')}
1344
- >
1345
- No! Live Editor is designed for all skill levels. Beginners
1346
- can learn through visual editing, while experienced
1347
- developers can work directly with code.
1348
- </ui.Typography.Paragraph>
1349
- ),
1350
- },
1351
- {
1352
- key: '3',
1353
- label: (
1354
- <ui.Typography.Text
1355
- data-id=""
1356
- data-binding={[
1357
- {
1358
- label: 'Question 3',
1359
- property: 'innerText',
1360
- },
1361
- ]}
1362
- className={cn('text-lg font-semibold text-gray-800')}
1363
- >
1364
- Is it really free?
1365
- </ui.Typography.Text>
1366
- ),
1367
- children: (
1368
- <ui.Typography.Paragraph
1369
- data-id=""
1370
- data-binding={[
1371
- {
1372
- label: 'Answer 3',
1373
- type: 'richtext',
1374
- },
1375
- ]}
1376
- className={cn('text-gray-600')}
1377
- >
1378
- Yes, completely free! Live Editor is an open-source project
1379
- with no hidden costs or premium tiers. All features are
1380
- available to everyone.
1381
- </ui.Typography.Paragraph>
1382
- ),
1383
- },
1384
- {
1385
- key: '4',
1386
- label: (
1387
- <ui.Typography.Text
1388
- data-id=""
1389
- data-binding={[
1390
- {
1391
- label: 'Question 4',
1392
- property: 'innerText',
1393
- },
1394
- ]}
1395
- className={cn('text-lg font-semibold text-gray-800')}
1396
- >
1397
- How can I contribute?
1398
- </ui.Typography.Text>
1399
- ),
1400
- children: (
1401
- <ui.Typography.Paragraph
1402
- data-id=""
1403
- data-binding={[
1404
- {
1405
- label: 'Answer 4',
1406
- type: 'richtext',
1407
- },
1408
- ]}
1409
- className={cn('text-gray-600')}
1410
- >
1411
- You can contribute by reporting bugs, suggesting features,
1412
- sharing your projects, or contributing code. Check our
1413
- GitHub repository for more details.
1414
- </ui.Typography.Paragraph>
1415
- ),
1416
- },
1417
- ]}
1418
- />
862
+ data-binding={[{ label: 'FAQ Items', property: 'children' }]}
863
+ className="divide-y divide-gray-200"
864
+ >
865
+ <details className="py-4">
866
+ <summary
867
+ data-id=""
868
+ data-binding={[{ label: 'Question 1', property: 'innerText' }]}
869
+ className="cursor-pointer text-lg font-semibold text-gray-800"
870
+ >
871
+ What is Live Editor?
872
+ </summary>
873
+ <p
874
+ data-id=""
875
+ data-binding={[{ label: 'Answer 1', type: 'richtext' }]}
876
+ className="mt-3 text-gray-600"
877
+ >
878
+ Live Editor is an open-source tool for building web
879
+ interfaces visually. It helps you learn web development by
880
+ providing instant feedback as you build components.
881
+ </p>
882
+ </details>
883
+ <details className="py-4">
884
+ <summary
885
+ data-id=""
886
+ data-binding={[{ label: 'Question 2', property: 'innerText' }]}
887
+ className="cursor-pointer text-lg font-semibold text-gray-800"
888
+ >
889
+ Do I need coding experience?
890
+ </summary>
891
+ <p
892
+ data-id=""
893
+ data-binding={[{ label: 'Answer 2', type: 'richtext' }]}
894
+ className="mt-3 text-gray-600"
895
+ >
896
+ No! Live Editor is designed for all skill levels. Beginners
897
+ can learn through visual editing, while experienced
898
+ developers can work directly with code.
899
+ </p>
900
+ </details>
901
+ <details className="py-4">
902
+ <summary
903
+ data-id=""
904
+ data-binding={[{ label: 'Question 3', property: 'innerText' }]}
905
+ className="cursor-pointer text-lg font-semibold text-gray-800"
906
+ >
907
+ Is it really free?
908
+ </summary>
909
+ <p
910
+ data-id=""
911
+ data-binding={[{ label: 'Answer 3', type: 'richtext' }]}
912
+ className="mt-3 text-gray-600"
913
+ >
914
+ Yes, completely free! Live Editor is an open-source project
915
+ with no hidden costs or premium tiers. All features are
916
+ available to everyone.
917
+ </p>
918
+ </details>
919
+ <details className="py-4">
920
+ <summary
921
+ data-id=""
922
+ data-binding={[{ label: 'Question 4', property: 'innerText' }]}
923
+ className="cursor-pointer text-lg font-semibold text-gray-800"
924
+ >
925
+ How can I contribute?
926
+ </summary>
927
+ <p
928
+ data-id=""
929
+ data-binding={[{ label: 'Answer 4', type: 'richtext' }]}
930
+ className="mt-3 text-gray-600"
931
+ >
932
+ You can contribute by reporting bugs, suggesting features,
933
+ sharing your projects, or contributing code. Check our
934
+ GitHub repository for more details.
935
+ </p>
936
+ </details>
937
+ </div>
1419
938
  </div>
1420
939
  </section>
1421
940
  `
1422
941
  }
1423
942
  ];
1424
943
  //#endregion
944
+ //#region src/components/dnd/canvas/canvas.module.css
945
+ var canvas_module_default = {
946
+ "dropArea": "vaEhUG_dropArea",
947
+ "dropAreaOver": "vaEhUG_dropAreaOver",
948
+ "dropBottom": "vaEhUG_dropBottom",
949
+ "dropBottomOver": "vaEhUG_dropBottomOver",
950
+ "empty": "vaEhUG_empty",
951
+ "fill": "vaEhUG_fill",
952
+ "notice": "vaEhUG_notice",
953
+ "section": "vaEhUG_section",
954
+ "sectionDropTarget": "vaEhUG_sectionDropTarget",
955
+ "sectionSelected": "vaEhUG_sectionSelected",
956
+ "sectionShield": "vaEhUG_sectionShield",
957
+ "sectionToolbar": "vaEhUG_sectionToolbar",
958
+ "stale": "vaEhUG_stale"
959
+ };
960
+ //#endregion
961
+ //#region src/components/dnd/layout.module.css
962
+ var layout_module_default = {
963
+ "canvas": "_4QZ3lW_canvas",
964
+ "card": "_4QZ3lW_card",
965
+ "palette": "_4QZ3lW_palette",
966
+ "paletteButton": "_4QZ3lW_paletteButton",
967
+ "paletteItems": "_4QZ3lW_paletteItems",
968
+ "panel": "_4QZ3lW_panel",
969
+ "picker": "_4QZ3lW_picker",
970
+ "pickerDock": "_4QZ3lW_pickerDock",
971
+ "root": "_4QZ3lW_root"
972
+ };
973
+ //#endregion
1425
974
  //#region src/components/dnd/canvas/canvas-notice.tsx
1426
- const CanvasNotice = ({ title, detail }) => /* @__PURE__ */ jsxs(Space, {
1427
- orientation: "vertical",
1428
- align: "center",
1429
- children: [/* @__PURE__ */ jsx(Typography.Paragraph, { children: title }), /* @__PURE__ */ jsx(Typography.Text, { children: detail })]
975
+ const CanvasNotice = ({ title, detail }) => /* @__PURE__ */ jsxs("div", {
976
+ className: canvas_module_default.notice,
977
+ children: [/* @__PURE__ */ jsx("p", { children: title }), /* @__PURE__ */ jsx("span", { children: detail })]
1430
978
  });
1431
979
  //#endregion
1432
980
  //#region src/components/dnd/palette/palette-drag.ts
@@ -1450,14 +998,11 @@ const Droppable = ({ children, className }) => {
1450
998
  const messages = useLiveMessages();
1451
999
  return /* @__PURE__ */ jsxs("div", {
1452
1000
  ref: setNodeRef,
1453
- className: cn("min-h-full", "border-2 border-dashed p-1", shouldHighlight ? "border-blue-300 bg-blue-50" : "border-gray-200", className),
1001
+ className: cn(canvas_module_default.dropArea, shouldHighlight && canvas_module_default.dropAreaOver, className),
1454
1002
  children: [children, isPaletteSectionDragging && /* @__PURE__ */ jsx("div", {
1455
1003
  ref: setBottomRef,
1456
- className: cn("mt-2 min-h-24", "rounded-lg border-2 border-dashed", "transition-all duration-200", "flex items-center justify-center", shouldHighlightBottom ? "border-blue-400 bg-blue-100" : "border-gray-300 bg-gray-50"),
1457
- children: /* @__PURE__ */ jsx(Typography.Text, {
1458
- className: "text-sm text-gray-500",
1459
- children: shouldHighlightBottom ? messages.canvas.dropHere : messages.canvas.dropAtBottom
1460
- })
1004
+ className: cn(canvas_module_default.dropBottom, shouldHighlightBottom && canvas_module_default.dropBottomOver),
1005
+ children: shouldHighlightBottom ? messages.canvas.dropHere : messages.canvas.dropAtBottom
1461
1006
  })]
1462
1007
  });
1463
1008
  };
@@ -1507,11 +1052,11 @@ const DraggableItem = ({ item, children }) => {
1507
1052
  };
1508
1053
  const DefaultDraggableItem = ({ item, onAdd, tapToAdd = false }) => /* @__PURE__ */ jsx(DraggableItem, {
1509
1054
  item,
1510
- children: ({ ref, dragProps, isDragging }) => /* @__PURE__ */ jsx(Card, {
1055
+ children: ({ ref, dragProps, isDragging }) => /* @__PURE__ */ jsx("div", {
1511
1056
  ref,
1512
1057
  style: { opacity: isDragging ? .5 : 1 },
1513
1058
  ...dragProps,
1514
- className: cn("cursor-grab", "outline-none focus-visible:ring-2 focus-visible:ring-blue-500", "hover:border-blue-300 hover:shadow-md", isDragging && "opacity-50"),
1059
+ className: layout_module_default.card,
1515
1060
  onClick: tapToAdd && onAdd ? () => onAdd(item) : void 0,
1516
1061
  onDoubleClick: onAdd ? () => onAdd(item) : void 0,
1517
1062
  onKeyDown: (event) => {
@@ -1587,7 +1132,10 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1587
1132
  autoHeight: true,
1588
1133
  children: (container) => /* @__PURE__ */ jsx("div", {
1589
1134
  ref: wrapperRef,
1590
- className: "w-full overflow-x-hidden",
1135
+ style: {
1136
+ width: "100%",
1137
+ overflowX: "hidden"
1138
+ },
1591
1139
  "data-editor-mode": true,
1592
1140
  children: /* @__PURE__ */ jsx(ErrorBoundary, {
1593
1141
  resetKeys: [preview],
@@ -1603,7 +1151,7 @@ const Renderer = ({ preview, sectionId = "", sectionName = "", sectionCode = pre
1603
1151
  title: messages.errors.rendering
1604
1152
  })
1605
1153
  }),
1606
- children: renderProvider(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Component, {
1154
+ children: renderProvider(/* @__PURE__ */ jsxs(Fragment, { children: [renderStableComponent(Component, preview, {
1607
1155
  headers,
1608
1156
  container
1609
1157
  }), dynamicTailwind && dynamicCSS && /* @__PURE__ */ jsx("style", { children: dynamicCSS })] }))
@@ -1630,6 +1178,28 @@ const arePropsEqual = (prev, next) => {
1630
1178
  };
1631
1179
  var renderer_default = memo(Renderer, arePropsEqual);
1632
1180
  //#endregion
1181
+ //#region src/components/dnd/button.module.css
1182
+ var button_module_default = {
1183
+ "button": "_49iObG_button",
1184
+ "circle": "_49iObG_circle",
1185
+ "danger": "_49iObG_danger",
1186
+ "iconOnly": "_49iObG_iconOnly",
1187
+ "outlined": "_49iObG_outlined",
1188
+ "primary": "_49iObG_primary",
1189
+ "small": "_49iObG_small",
1190
+ "solid": "_49iObG_solid",
1191
+ "success": "_49iObG_success",
1192
+ "text": "_49iObG_text"
1193
+ };
1194
+ //#endregion
1195
+ //#region src/components/dnd/button.tsx
1196
+ const Button = ({ variant = "outlined", tone = "neutral", size = "middle", shape = "default", icon, className, children, ...restProps }) => /* @__PURE__ */ jsxs("button", {
1197
+ type: "button",
1198
+ className: cn(button_module_default.button, button_module_default[variant], tone !== "neutral" && button_module_default[tone], size === "small" && button_module_default.small, shape === "circle" && button_module_default.circle, icon && !children && button_module_default.iconOnly, className),
1199
+ ...restProps,
1200
+ children: [icon, children]
1201
+ });
1202
+ //#endregion
1633
1203
  //#region src/components/dnd/canvas/section-handlers.ts
1634
1204
  const SectionHandlersContext = createContext(null);
1635
1205
  const useSectionHandlers = () => useContext(SectionHandlersContext);
@@ -1664,6 +1234,16 @@ const Sortable = ({ id, children, selected, onClick, onDelete, onCopy, onMoveUp,
1664
1234
  onClick?.();
1665
1235
  return;
1666
1236
  }
1237
+ if (e.altKey && (e.key === "ArrowUp" || e.key === "ArrowDown") && handlers) {
1238
+ e.preventDefault();
1239
+ handlers.onMoveKey(id, e.key === "ArrowUp" ? "up" : "down");
1240
+ return;
1241
+ }
1242
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "d" && handlers) {
1243
+ e.preventDefault();
1244
+ handlers.onCopyKey(id);
1245
+ return;
1246
+ }
1667
1247
  const to = NAVIGATION_KEYS[e.key];
1668
1248
  if (to && handlers) {
1669
1249
  e.preventDefault();
@@ -1691,10 +1271,10 @@ const Sortable = ({ id, children, selected, onClick, onDelete, onCopy, onMoveUp,
1691
1271
  ...listeners,
1692
1272
  onKeyDown,
1693
1273
  onClick,
1694
- className: cn("relative", selected && "z-10 outline-2 outline-offset-2 outline-blue-500", isPaletteSectionOver && "border-t-4 border-t-green-500"),
1274
+ className: cn(canvas_module_default.section, selected && canvas_module_default.sectionSelected, isPaletteSectionOver && canvas_module_default.sectionDropTarget),
1695
1275
  children: [
1696
1276
  /* @__PURE__ */ jsx("div", {
1697
- className: cn("absolute inset-0 z-50"),
1277
+ className: canvas_module_default.sectionShield,
1698
1278
  onPointerMove: inspecting ? (e) => handlers?.onInspectMove(e.currentTarget.parentElement, e.currentTarget, e.clientX, e.clientY) : void 0,
1699
1279
  onPointerLeave: inspecting ? handlers?.onInspectLeave : void 0,
1700
1280
  onClick: inspecting ? (e) => {
@@ -1703,8 +1283,8 @@ const Sortable = ({ id, children, selected, onClick, onDelete, onCopy, onMoveUp,
1703
1283
  } : void 0
1704
1284
  }),
1705
1285
  children,
1706
- selected && /* @__PURE__ */ jsxs(Space, {
1707
- className: cn("absolute top-1 right-1 z-60"),
1286
+ selected && /* @__PURE__ */ jsxs("div", {
1287
+ className: canvas_module_default.sectionToolbar,
1708
1288
  children: [
1709
1289
  onMoveUp && /* @__PURE__ */ jsx(Button, {
1710
1290
  icon: /* @__PURE__ */ jsx(ChevronUp, {}),
@@ -1724,7 +1304,7 @@ const Sortable = ({ id, children, selected, onClick, onDelete, onCopy, onMoveUp,
1724
1304
  "aria-label": messages.section.duplicate
1725
1305
  }),
1726
1306
  /* @__PURE__ */ jsx(Button, {
1727
- danger: true,
1307
+ tone: "danger",
1728
1308
  icon: /* @__PURE__ */ jsx(Trash, {}),
1729
1309
  onClick: press(() => onDelete?.(id)),
1730
1310
  "aria-label": messages.section.delete
@@ -1762,9 +1342,51 @@ const Overlay = ({ sections, isForced, renderProps }) => {
1762
1342
  return null;
1763
1343
  };
1764
1344
  //#endregion
1345
+ //#region src/components/dnd/toast.module.css
1346
+ var toast_module_default = {
1347
+ "description": "YlF_3q_description",
1348
+ "region": "YlF_3q_region",
1349
+ "title": "YlF_3q_title",
1350
+ "toast": "YlF_3q_toast"
1351
+ };
1352
+ //#endregion
1353
+ //#region src/components/dnd/toast.ts
1354
+ const TOAST_DURATION = 6e3;
1355
+ let region = null;
1356
+ const getRegion = () => {
1357
+ if (region?.isConnected) return region;
1358
+ region = document.createElement("div");
1359
+ region.className = toast_module_default.region;
1360
+ document.body.append(region);
1361
+ return region;
1362
+ };
1363
+ const showErrorToast = (title, description) => {
1364
+ if (typeof document === "undefined") return;
1365
+ const toast = document.createElement("div");
1366
+ toast.className = toast_module_default.toast;
1367
+ toast.setAttribute("role", "alert");
1368
+ const heading = document.createElement("div");
1369
+ heading.className = toast_module_default.title;
1370
+ heading.textContent = title;
1371
+ toast.append(heading);
1372
+ if (description) {
1373
+ const detail = document.createElement("div");
1374
+ detail.className = toast_module_default.description;
1375
+ detail.textContent = description;
1376
+ toast.append(detail);
1377
+ }
1378
+ const remove = () => {
1379
+ window.clearTimeout(timer);
1380
+ toast.remove();
1381
+ };
1382
+ const timer = window.setTimeout(remove, TOAST_DURATION);
1383
+ toast.addEventListener("click", remove);
1384
+ getRegion().append(toast);
1385
+ };
1386
+ //#endregion
1765
1387
  //#region src/components/dnd/edit-options.ts
1766
1388
  const toastEditError = (error) => {
1767
- Toast.error(error.title, error.description ? { description: error.description } : void 0);
1389
+ showErrorToast(error.title, error.description);
1768
1390
  };
1769
1391
  const DndEditOptionsContext = createContext({ reportError: toastEditError });
1770
1392
  const useDndEditOptions = () => useContext(DndEditOptionsContext);
@@ -1824,6 +1446,65 @@ const viewportRect = (element) => {
1824
1446
  return new DOMRect(x, y, rect.width, rect.height);
1825
1447
  };
1826
1448
  //#endregion
1449
+ //#region src/components/dnd/drawer.module.css
1450
+ var drawer_module_default = {
1451
+ "body": "_ty1rG_body",
1452
+ "content": "_ty1rG_content",
1453
+ "drawer": "_ty1rG_drawer",
1454
+ "header": "_ty1rG_header",
1455
+ "slide-up": "_ty1rG_slide-up",
1456
+ "title": "_ty1rG_title"
1457
+ };
1458
+ //#endregion
1459
+ //#region src/components/dnd/drawer.tsx
1460
+ const Drawer = ({ open, title, closeLabel, onClose, children }) => {
1461
+ const titleId = useId();
1462
+ const dialogRef = useRef(null);
1463
+ useEffect(() => {
1464
+ const dialog = dialogRef.current;
1465
+ if (!dialog || !open) return;
1466
+ if (typeof dialog.showModal === "function") dialog.showModal();
1467
+ else dialog.setAttribute("open", "");
1468
+ return () => {
1469
+ if (typeof dialog.close === "function") dialog.close();
1470
+ else dialog.removeAttribute("open");
1471
+ };
1472
+ }, [open]);
1473
+ if (!open) return null;
1474
+ return /* @__PURE__ */ jsx("dialog", {
1475
+ ref: dialogRef,
1476
+ className: drawer_module_default.drawer,
1477
+ "aria-labelledby": titleId,
1478
+ onCancel: (e) => {
1479
+ e.preventDefault();
1480
+ onClose();
1481
+ },
1482
+ onClick: (e) => {
1483
+ if (e.target === e.currentTarget) onClose();
1484
+ },
1485
+ children: /* @__PURE__ */ jsxs("div", {
1486
+ className: drawer_module_default.content,
1487
+ children: [/* @__PURE__ */ jsxs("div", {
1488
+ className: drawer_module_default.header,
1489
+ children: [/* @__PURE__ */ jsx("h2", {
1490
+ id: titleId,
1491
+ className: drawer_module_default.title,
1492
+ children: title
1493
+ }), /* @__PURE__ */ jsx(Button, {
1494
+ variant: "text",
1495
+ size: "small",
1496
+ icon: /* @__PURE__ */ jsx(X, {}),
1497
+ "aria-label": closeLabel,
1498
+ onClick: onClose
1499
+ })]
1500
+ }), /* @__PURE__ */ jsx("div", {
1501
+ className: drawer_module_default.body,
1502
+ children
1503
+ })]
1504
+ })
1505
+ });
1506
+ };
1507
+ //#endregion
1827
1508
  //#region src/components/dnd/layout-context.ts
1828
1509
  const DndRegionContext = createContext(null);
1829
1510
  const useDndRegions = (subject) => {
@@ -1835,6 +1516,25 @@ const useDndPalette = () => useDndRegions("useDndPalette()").palette;
1835
1516
  const useDndPanel = () => useDndRegions("useDndPanel()").panel;
1836
1517
  const useDndLayout = () => useDndRegions("useDndLayout()");
1837
1518
  //#endregion
1519
+ //#region src/components/dnd/panel/panel.module.css
1520
+ var panel_module_default = {
1521
+ "actions": "gbKovW_actions",
1522
+ "binding": "gbKovW_binding",
1523
+ "bindingLabel": "gbKovW_bindingLabel",
1524
+ "bindingProperty": "gbKovW_bindingProperty",
1525
+ "bindings": "gbKovW_bindings",
1526
+ "element": "gbKovW_element",
1527
+ "elementHeader": "gbKovW_elementHeader",
1528
+ "elementTag": "gbKovW_elementTag",
1529
+ "elementText": "gbKovW_elementText",
1530
+ "empty": "gbKovW_empty",
1531
+ "header": "gbKovW_header",
1532
+ "note": "gbKovW_note",
1533
+ "panel": "gbKovW_panel",
1534
+ "readOnly": "gbKovW_readOnly",
1535
+ "title": "gbKovW_title"
1536
+ };
1537
+ //#endregion
1838
1538
  //#region src/components/dnd/panel/element-selection.ts
1839
1539
  const ElementSelectionContext = createContext({ ids: /* @__PURE__ */ new Set() });
1840
1540
  //#endregion
@@ -1924,9 +1624,40 @@ const withPanelCommit = (bindings, commit) => bindings.map((binding) => ({
1924
1624
  })
1925
1625
  }));
1926
1626
  //#endregion
1627
+ //#region src/components/dnd/panel/structure.module.css
1628
+ var structure_module_default = {
1629
+ "card": "lH7pXW_card",
1630
+ "cardCompact": "lH7pXW_cardCompact",
1631
+ "children": "lH7pXW_children",
1632
+ "dragging": "lH7pXW_dragging",
1633
+ "element": "lH7pXW_element",
1634
+ "elementTag": "lH7pXW_elementTag",
1635
+ "handle": "lH7pXW_handle",
1636
+ "heading": "lH7pXW_heading",
1637
+ "indented": "lH7pXW_indented",
1638
+ "items": "lH7pXW_items",
1639
+ "label": "lH7pXW_label",
1640
+ "muted": "lH7pXW_muted",
1641
+ "nested": "lH7pXW_nested",
1642
+ "notice": "lH7pXW_notice",
1643
+ "noticeDanger": "lH7pXW_noticeDanger",
1644
+ "noticeWarning": "lH7pXW_noticeWarning",
1645
+ "propertyLabel": "lH7pXW_propertyLabel",
1646
+ "row": "lH7pXW_row",
1647
+ "rowStart": "lH7pXW_rowStart",
1648
+ "stack": "lH7pXW_stack",
1649
+ "stackLoose": "lH7pXW_stackLoose",
1650
+ "stackTight": "lH7pXW_stackTight",
1651
+ "toggle": "lH7pXW_toggle",
1652
+ "valueType": "lH7pXW_valueType"
1653
+ };
1654
+ //#endregion
1655
+ //#region src/components/dnd/panel/row-controls.module.css
1656
+ var row_controls_module_default = { "controls": "q9alSq_controls" };
1657
+ //#endregion
1927
1658
  //#region src/components/dnd/panel/row-controls.tsx
1928
1659
  const RowControls = ({ index, count, labels, disabled = false, deleteDisabled = false, onMove, onDelete }) => /* @__PURE__ */ jsxs("div", {
1929
- className: "flex space-x-1",
1660
+ className: row_controls_module_default.controls,
1930
1661
  children: [
1931
1662
  /* @__PURE__ */ jsx(Button, {
1932
1663
  size: "small",
@@ -1943,7 +1674,7 @@ const RowControls = ({ index, count, labels, disabled = false, deleteDisabled =
1943
1674
  onClick: () => onMove(index + 1)
1944
1675
  }),
1945
1676
  /* @__PURE__ */ jsx(Button, {
1946
- danger: true,
1677
+ tone: "danger",
1947
1678
  size: "small",
1948
1679
  icon: /* @__PURE__ */ jsx(X, {}),
1949
1680
  "aria-label": labels.delete,
@@ -1954,17 +1685,26 @@ const RowControls = ({ index, count, labels, disabled = false, deleteDisabled =
1954
1685
  ]
1955
1686
  });
1956
1687
  //#endregion
1688
+ //#region src/components/dnd/panel/selection/selection.module.css
1689
+ var selection_module_default = {
1690
+ "actions": "ZTKonW_actions",
1691
+ "bar": "ZTKonW_bar",
1692
+ "checkbox": "ZTKonW_checkbox",
1693
+ "count": "ZTKonW_count",
1694
+ "selectAll": "ZTKonW_selectAll"
1695
+ };
1696
+ //#endregion
1957
1697
  //#region src/components/dnd/panel/selection/bulk-actions-bar.tsx
1958
1698
  const BulkActionsBar = ({ count, disabled = false, duplicateDisabled = false, deleteDisabled = false, onDuplicate, onMoveUp, onMoveDown, onDelete, onClear }) => {
1959
1699
  const messages = useLiveMessages();
1960
1700
  if (count === 0) return null;
1961
1701
  return /* @__PURE__ */ jsxs("div", {
1962
- className: "flex items-center justify-between rounded border\n border-blue-200 bg-blue-50 p-2",
1702
+ className: selection_module_default.bar,
1963
1703
  children: [/* @__PURE__ */ jsx("div", {
1964
- className: "text-xs font-medium text-blue-700",
1704
+ className: selection_module_default.count,
1965
1705
  children: messages.selection.count(count)
1966
1706
  }), /* @__PURE__ */ jsxs("div", {
1967
- className: "flex items-center space-x-1",
1707
+ className: selection_module_default.actions,
1968
1708
  children: [
1969
1709
  /* @__PURE__ */ jsx(Button, {
1970
1710
  size: "small",
@@ -1988,7 +1728,7 @@ const BulkActionsBar = ({ count, disabled = false, duplicateDisabled = false, de
1988
1728
  onClick: onMoveDown
1989
1729
  }),
1990
1730
  /* @__PURE__ */ jsx(Button, {
1991
- danger: true,
1731
+ tone: "danger",
1992
1732
  size: "small",
1993
1733
  icon: /* @__PURE__ */ jsx(X, {}),
1994
1734
  title: messages.selection.delete,
@@ -2008,27 +1748,33 @@ const BulkActionsBar = ({ count, disabled = false, duplicateDisabled = false, de
2008
1748
  //#region src/components/dnd/panel/selection/select-all-checkbox.tsx
2009
1749
  const SelectAllCheckbox = ({ total, selected, disabled = false, onSelectAll, onClear }) => {
2010
1750
  const messages = useLiveMessages();
1751
+ const inputRef = useRef(null);
2011
1752
  const isAllSelected = total > 0 && selected >= total;
2012
- return /* @__PURE__ */ jsx(Checkbox, {
2013
- className: "text-xs",
2014
- checked: isAllSelected,
2015
- indeterminate: selected > 0 && !isAllSelected,
2016
- disabled,
2017
- onChange: () => isAllSelected ? onClear() : onSelectAll(),
2018
- children: messages.selection.selectAll
1753
+ const isIndeterminate = selected > 0 && !isAllSelected;
1754
+ useEffect(() => {
1755
+ if (inputRef.current) inputRef.current.indeterminate = isIndeterminate;
1756
+ }, [isIndeterminate]);
1757
+ return /* @__PURE__ */ jsxs("label", {
1758
+ className: selection_module_default.selectAll,
1759
+ children: [/* @__PURE__ */ jsx("input", {
1760
+ ref: inputRef,
1761
+ type: "checkbox",
1762
+ className: selection_module_default.checkbox,
1763
+ checked: isAllSelected,
1764
+ disabled,
1765
+ onChange: () => isAllSelected ? onClear() : onSelectAll()
1766
+ }), messages.selection.selectAll]
2019
1767
  });
2020
1768
  };
2021
1769
  //#endregion
2022
1770
  //#region src/components/dnd/panel/selection/selection-checkbox.tsx
2023
- const SelectionCheckbox = ({ checked, disabled = false, onToggle }) => /* @__PURE__ */ jsx("div", {
2024
- onClick: (e) => {
2025
- if (!disabled) onToggle(e.shiftKey);
2026
- },
2027
- className: "inline-flex",
2028
- children: /* @__PURE__ */ jsx(Checkbox, {
2029
- checked,
2030
- disabled
2031
- })
1771
+ const SelectionCheckbox = ({ checked, disabled = false, onToggle }) => /* @__PURE__ */ jsx("input", {
1772
+ type: "checkbox",
1773
+ className: selection_module_default.checkbox,
1774
+ checked,
1775
+ disabled,
1776
+ readOnly: true,
1777
+ onClick: (e) => onToggle(e.shiftKey)
2032
1778
  });
2033
1779
  //#endregion
2034
1780
  //#region src/components/dnd/panel/selection/use-structural-selection.ts
@@ -2140,16 +1886,16 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
2140
1886
  return map;
2141
1887
  }, [items]);
2142
1888
  return /* @__PURE__ */ jsxs("div", {
2143
- className: "space-y-3",
1889
+ className: cn(structure_module_default.children, structure_module_default.stackLoose),
2144
1890
  children: [
2145
1891
  /* @__PURE__ */ jsxs("div", {
2146
- className: "flex items-center justify-between",
1892
+ className: structure_module_default.row,
2147
1893
  children: [/* @__PURE__ */ jsx("div", {
2148
- className: "text-sm font-semibold text-green-700",
1894
+ className: structure_module_default.heading,
2149
1895
  children: messages.children.heading(items.length)
2150
1896
  }), /* @__PURE__ */ jsx(Button, {
2151
1897
  size: "small",
2152
- color: "green",
1898
+ tone: "success",
2153
1899
  icon: /* @__PURE__ */ jsx(Plus, {}),
2154
1900
  onClick: actions.add,
2155
1901
  children: messages.children.add
@@ -2170,17 +1916,17 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
2170
1916
  onClear: selection.clear
2171
1917
  }),
2172
1918
  items.map((item, itemIndex) => /* @__PURE__ */ jsxs("div", {
2173
- className: "space-y-2 rounded border border-green-200 bg-green-50 p-3",
1919
+ className: structure_module_default.card,
2174
1920
  children: [
2175
1921
  /* @__PURE__ */ jsxs("div", {
2176
- className: "flex items-center justify-between",
1922
+ className: structure_module_default.row,
2177
1923
  children: [/* @__PURE__ */ jsxs("div", {
2178
- className: "flex items-center space-x-2",
1924
+ className: structure_module_default.rowStart,
2179
1925
  children: [/* @__PURE__ */ jsx(SelectionCheckbox, {
2180
1926
  checked: selection.isSelected(itemIndex),
2181
1927
  onToggle: (shiftKey) => selection.toggle(itemIndex, shiftKey)
2182
1928
  }), /* @__PURE__ */ jsx("div", {
2183
- className: "text-xs font-medium text-green-800",
1929
+ className: structure_module_default.label,
2184
1930
  children: messages.children.child(itemIndex + 1, item.tagName || "fragment")
2185
1931
  })]
2186
1932
  }), /* @__PURE__ */ jsx(RowControls, {
@@ -2192,17 +1938,17 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
2192
1938
  })]
2193
1939
  }),
2194
1940
  editableChildrenMap.has(itemIndex) && /* @__PURE__ */ jsxs("div", {
2195
- className: "space-y-2",
1941
+ className: structure_module_default.stack,
2196
1942
  children: [/* @__PURE__ */ jsx("div", {
2197
- className: "text-xs font-medium text-green-700",
1943
+ className: structure_module_default.label,
2198
1944
  children: messages.children.editableBindings
2199
1945
  }), editableChildrenMap.get(itemIndex).map((editableNode, idx) => {
2200
1946
  const nodeId = editableNode.dataAttributes.find((a) => a.name === "data-id")?.value;
2201
1947
  return /* @__PURE__ */ jsx(ElementFields, {
2202
1948
  id: nodeId ?? void 0,
2203
- className: "rounded border border-green-100 bg-white p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400",
1949
+ className: structure_module_default.element,
2204
1950
  header: /* @__PURE__ */ jsx("div", {
2205
- className: "mb-1 text-xs text-green-600",
1951
+ className: structure_module_default.elementTag,
2206
1952
  children: editableNode.tagName
2207
1953
  }),
2208
1954
  bindings: bindingsOf(editableNode, onNodeChange),
@@ -2211,12 +1957,12 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
2211
1957
  })]
2212
1958
  }),
2213
1959
  !!item.children && !editableChildrenMap.has(itemIndex) && /* @__PURE__ */ jsxs("div", {
2214
- className: "space-y-1",
1960
+ className: structure_module_default.stackTight,
2215
1961
  children: [/* @__PURE__ */ jsx("div", {
2216
- className: "text-xs font-medium text-green-700",
1962
+ className: structure_module_default.label,
2217
1963
  children: messages.children.childNodes
2218
1964
  }), item.children.map((node, nodeIndex) => /* @__PURE__ */ jsx(ElementFields, {
2219
- className: "ml-2 rounded border border-green-100 bg-white p-2",
1965
+ className: cn(structure_module_default.element, structure_module_default.indented),
2220
1966
  bindings: bindingsOf(node, onNodeChange),
2221
1967
  onNodeChange
2222
1968
  }, `node-${itemIndex}-${nodeIndex}`))]
@@ -2227,14 +1973,18 @@ const Children$1 = ({ value, onChange, onNodeChange }) => {
2227
1973
  });
2228
1974
  };
2229
1975
  //#endregion
2230
- //#region src/components/dnd/panel/fields/color-picker-field.tsx
1976
+ //#region src/components/dnd/panel/fields/color-field.tsx
2231
1977
  const COLOR_COMMIT_DELAY = 75;
2232
1978
  const normalizeToHex = (value) => {
2233
1979
  const trimmed = value.trim();
2234
- if (/^#([0-9A-Fa-f]{3}){1,2}$/.test(trimmed)) return trimmed;
1980
+ if (/^#[0-9A-Fa-f]{6}$/.test(trimmed)) return trimmed;
1981
+ if (/^#[0-9A-Fa-f]{3}$/.test(trimmed)) {
1982
+ const [, r, g, b] = trimmed;
1983
+ return `#${r}${r}${g}${g}${b}${b}`;
1984
+ }
2235
1985
  return "#000000";
2236
1986
  };
2237
- const ColorPickerField = ({ value: source, onChange, label }) => {
1987
+ const ColorField = ({ value: source, onChange, ...controlProps }) => {
2238
1988
  const value = normalizeToHex(source);
2239
1989
  const [liveValue, setLiveValue] = useState(value);
2240
1990
  const [prevValue, setPrevValue] = useState(value);
@@ -2255,66 +2005,25 @@ const ColorPickerField = ({ value: source, onChange, label }) => {
2255
2005
  delay: COLOR_COMMIT_DELAY,
2256
2006
  autoInvoke: false
2257
2007
  });
2258
- return /* @__PURE__ */ jsx(ColorPicker, {
2259
- "aria-label": label,
2260
- showText: true,
2261
- value: liveValue,
2262
- onChange: (next) => {
2263
- setLiveValue(next);
2264
- debouncedCommit();
2265
- },
2266
- onOpenChange: (open) => {
2267
- if (!open) commit(liveValue);
2268
- }
2008
+ return /* @__PURE__ */ jsxs("div", {
2009
+ className: fields_module_default.color,
2010
+ children: [/* @__PURE__ */ jsx("input", {
2011
+ ...controlProps,
2012
+ type: "color",
2013
+ value: liveValue,
2014
+ className: cn(fields_module_default.control, fields_module_default.colorSwatch),
2015
+ onChange: (e) => {
2016
+ setLiveValue(e.target.value);
2017
+ debouncedCommit();
2018
+ },
2019
+ onBlur: () => commit(liveValue)
2020
+ }), /* @__PURE__ */ jsx("code", {
2021
+ className: fields_module_default.colorSource,
2022
+ children: source
2023
+ })]
2269
2024
  });
2270
2025
  };
2271
2026
  //#endregion
2272
- //#region src/components/dnd/panel/fields/field-ids.ts
2273
- const FieldIdsContext = createContext(null);
2274
- const useFieldIds = () => {
2275
- const labelledId = useContext(FieldIdsContext);
2276
- const fallbackId = useId();
2277
- const controlId = labelledId ?? fallbackId;
2278
- return {
2279
- controlId,
2280
- errorId: `${controlId}-error`,
2281
- isLabelled: labelledId !== null
2282
- };
2283
- };
2284
- const LABELABLE_KINDS = /* @__PURE__ */ new Set([
2285
- "text",
2286
- "number",
2287
- "url",
2288
- "email",
2289
- "tel",
2290
- "time"
2291
- ]);
2292
- //#endregion
2293
- //#region src/components/dnd/panel/fields/field-kind.ts
2294
- const isColorProperty = (property) => property.toLowerCase().includes("color");
2295
- const getFieldKind = (binding) => {
2296
- const { property, type, value } = binding;
2297
- if (binding.canEditValue === false) return "readonly";
2298
- if (property === "items" || property === "data" || type === "array") return "items";
2299
- if (type === "richtext") return "richtext";
2300
- if (property === BINDING_PROP.INNER_HTML) return "html";
2301
- if (type === "jsx") return "jsx";
2302
- if (property === "children" && Array.isArray(value)) return "children";
2303
- if (typeof value === "object" && value !== null && !Array.isArray(value)) return "object";
2304
- if (type === "boolean" || typeof value === "boolean") return "boolean";
2305
- if (binding.options && Array.isArray(binding.options)) return "select";
2306
- if (type === "color" || isColorProperty(property)) return "color";
2307
- if (type === "date") return "date";
2308
- if (type === "time") return "time";
2309
- if (type === "datetime") return "datetime";
2310
- if (type === "url") return "url";
2311
- if (type === "email") return "email";
2312
- if (type === "tel") return "tel";
2313
- if (type === "number" || typeof value === "number") return "number";
2314
- return "text";
2315
- };
2316
- const isStructuralFieldKind = (kind) => kind === "items" || kind === "children";
2317
- //#endregion
2318
2027
  //#region src/components/dnd/panel/fields/jsx-editor-field.tsx
2319
2028
  const JSXEditorField = ({ value, isHTML, onSave }) => {
2320
2029
  const selectionRef = useRef(null);
@@ -2350,10 +2059,15 @@ const JSXEditorField = ({ value, isHTML, onSave }) => {
2350
2059
  //#region src/components/dnd/panel/fields/labeled-field.tsx
2351
2060
  const LabeledField = ({ binding, label, labelClassName, children }) => {
2352
2061
  const controlId = useId();
2062
+ const labelId = `${controlId}-label`;
2353
2063
  const isLabelable = LABELABLE_KINDS.has(getFieldKind(binding));
2354
2064
  return /* @__PURE__ */ jsxs(FieldIdsContext.Provider, {
2355
- value: isLabelable ? controlId : null,
2065
+ value: {
2066
+ controlId,
2067
+ labelId
2068
+ },
2356
2069
  children: [/* @__PURE__ */ jsx("label", {
2070
+ id: labelId,
2357
2071
  htmlFor: isLabelable ? controlId : void 0,
2358
2072
  className: labelClassName,
2359
2073
  children: label
@@ -2395,7 +2109,7 @@ const SortableItems = ({ items, disabled, onMove, children }) => {
2395
2109
  strategy: verticalListSortingStrategy,
2396
2110
  disabled,
2397
2111
  children: /* @__PURE__ */ jsx("div", {
2398
- className: "space-y-4",
2112
+ className: structure_module_default.stackLoose,
2399
2113
  children: items.map(children)
2400
2114
  })
2401
2115
  })
@@ -2413,11 +2127,11 @@ const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls,
2413
2127
  transform: CSS$1.Translate.toString(transform),
2414
2128
  transition
2415
2129
  },
2416
- className: cn(className, isDragging && "relative z-10 shadow-md"),
2130
+ className: cn(className, isDragging && structure_module_default.dragging),
2417
2131
  children: [/* @__PURE__ */ jsxs("div", {
2418
- className: "flex items-center justify-between",
2132
+ className: structure_module_default.row,
2419
2133
  children: [/* @__PURE__ */ jsxs("div", {
2420
- className: "flex items-center space-x-1",
2134
+ className: structure_module_default.rowStart,
2421
2135
  children: [
2422
2136
  /* @__PURE__ */ jsx("button", {
2423
2137
  type: "button",
@@ -2426,7 +2140,7 @@ const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls,
2426
2140
  ...listeners,
2427
2141
  "aria-label": messages.items.reorder(title),
2428
2142
  disabled,
2429
- className: "cursor-grab rounded p-0.5 text-gray-400\n hover:text-gray-700 disabled:cursor-not-allowed\n disabled:opacity-40",
2143
+ className: structure_module_default.handle,
2430
2144
  children: /* @__PURE__ */ jsx(GripVertical, { size: 14 })
2431
2145
  }),
2432
2146
  checkbox,
@@ -2434,7 +2148,7 @@ const ItemCard = ({ id, title, disabled, expanded, onToggle, checkbox, controls,
2434
2148
  type: "button",
2435
2149
  "aria-expanded": expanded,
2436
2150
  onClick: onToggle,
2437
- className: "inline-flex items-center space-x-1 rounded px-1 text-xs\n font-medium",
2151
+ className: structure_module_default.toggle,
2438
2152
  children: [expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14 }), /* @__PURE__ */ jsx("span", { children: title })]
2439
2153
  })
2440
2154
  ]
@@ -3024,9 +2738,9 @@ const useDndItems = (value, { render, onChange, onNodeChange, minItems, maxItems
3024
2738
  //#region src/components/dnd/panel/items/items.tsx
3025
2739
  const NestedGroup = ({ group, onNodeChange }) => {
3026
2740
  if (group.fallback) return /* @__PURE__ */ jsxs("div", {
3027
- className: "space-y-2",
2741
+ className: structure_module_default.stack,
3028
2742
  children: [/* @__PURE__ */ jsx("div", {
3029
- className: "text-xs font-medium text-blue-700",
2743
+ className: structure_module_default.label,
3030
2744
  children: group.property
3031
2745
  }), /* @__PURE__ */ jsx(Field, {
3032
2746
  binding: group.fallback,
@@ -3034,9 +2748,9 @@ const NestedGroup = ({ group, onNodeChange }) => {
3034
2748
  })]
3035
2749
  });
3036
2750
  return /* @__PURE__ */ jsxs("div", {
3037
- className: "space-y-2",
2751
+ className: structure_module_default.stack,
3038
2752
  children: [/* @__PURE__ */ jsxs("div", {
3039
- className: "text-xs font-medium text-blue-700",
2753
+ className: structure_module_default.label,
3040
2754
  children: [
3041
2755
  group.property,
3042
2756
  " Bindings (",
@@ -3045,9 +2759,9 @@ const NestedGroup = ({ group, onNodeChange }) => {
3045
2759
  ]
3046
2760
  }), group.elements.map((element) => /* @__PURE__ */ jsx(ElementFields, {
3047
2761
  id: element.id,
3048
- className: "rounded border border-blue-100 bg-blue-50 p-2\n data-[picked]:ring-2 data-[picked]:ring-blue-400",
2762
+ className: structure_module_default.element,
3049
2763
  header: /* @__PURE__ */ jsxs("div", {
3050
- className: "mb-1 text-xs text-blue-600",
2764
+ className: structure_module_default.elementTag,
3051
2765
  children: [
3052
2766
  "<",
3053
2767
  element.tagName,
@@ -3069,31 +2783,31 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3069
2783
  maxItems
3070
2784
  });
3071
2785
  const header = /* @__PURE__ */ jsxs("div", {
3072
- className: "flex items-center justify-between",
2786
+ className: structure_module_default.row,
3073
2787
  children: [/* @__PURE__ */ jsx("div", {
3074
- className: "text-sm font-semibold",
2788
+ className: structure_module_default.heading,
3075
2789
  children: messages.items.heading(items.length)
3076
2790
  }), items.length > 0 && canEditStructure && /* @__PURE__ */ jsx(Button, {
3077
2791
  size: "small",
3078
2792
  icon: /* @__PURE__ */ jsx(Plus, {}),
3079
2793
  variant: "solid",
3080
- color: "green",
2794
+ tone: "success",
3081
2795
  disabled: !canAddItems(),
3082
2796
  onClick: actions.add,
3083
2797
  children: messages.items.add
3084
2798
  })]
3085
2799
  });
3086
2800
  if (parseError) return /* @__PURE__ */ jsxs("div", {
3087
- className: "space-y-4",
2801
+ className: cn(structure_module_default.items, structure_module_default.stackLoose),
3088
2802
  children: [header, /* @__PURE__ */ jsx("div", {
3089
- className: "rounded border border-dashed border-red-200 p-3 text-xs\n text-red-600",
2803
+ className: structure_module_default.noticeDanger,
3090
2804
  children: messages.items.unreadable
3091
2805
  })]
3092
2806
  });
3093
2807
  if (items.length === 0) return /* @__PURE__ */ jsxs("div", {
3094
- className: "space-y-4",
2808
+ className: cn(structure_module_default.items, structure_module_default.stackLoose),
3095
2809
  children: [header, /* @__PURE__ */ jsx("div", {
3096
- className: "rounded border border-dashed border-gray-200 p-3 text-xs\n text-gray-500",
2810
+ className: structure_module_default.notice,
3097
2811
  children: messages.items.empty
3098
2812
  })]
3099
2813
  });
@@ -3109,12 +2823,12 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3109
2823
  onClear: selection.clear
3110
2824
  });
3111
2825
  const objectBody = (item) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
3112
- className: "space-y-2",
2826
+ className: structure_module_default.stack,
3113
2827
  children: item.properties.map((binding) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
3114
- className: "flex flex-col space-y-2",
2828
+ className: structure_module_default.stack,
3115
2829
  children: /* @__PURE__ */ jsx(LabeledField, {
3116
2830
  binding,
3117
- labelClassName: "w-20 shrink-0 text-xs font-medium",
2831
+ labelClassName: structure_module_default.propertyLabel,
3118
2832
  label: binding.label,
3119
2833
  children: /* @__PURE__ */ jsx(Field, {
3120
2834
  binding,
@@ -3122,7 +2836,7 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3122
2836
  })
3123
2837
  })
3124
2838
  }), /* @__PURE__ */ jsxs("span", {
3125
- className: "text-right text-xs text-gray-500",
2839
+ className: structure_module_default.valueType,
3126
2840
  children: [
3127
2841
  "(",
3128
2842
  String(binding.meta?.valueType),
@@ -3130,12 +2844,12 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3130
2844
  ]
3131
2845
  })] }, `${item.id}-${binding.property}-${binding.label}`))
3132
2846
  }), /* @__PURE__ */ jsx("div", {
3133
- className: "space-y-3 border-t pt-2",
2847
+ className: structure_module_default.nested,
3134
2848
  children: item.nested.length ? item.nested.map((group) => /* @__PURE__ */ jsx(NestedGroup, {
3135
2849
  group,
3136
2850
  onNodeChange: onChildChange
3137
2851
  }, group.property)) : /* @__PURE__ */ jsxs("div", {
3138
- className: "text-xs text-gray-500",
2852
+ className: structure_module_default.muted,
3139
2853
  children: [
3140
2854
  /* @__PURE__ */ jsx("span", {
3141
2855
  "aria-hidden": "true",
@@ -3148,11 +2862,11 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3148
2862
  })] });
3149
2863
  const allExpanded = expansion.expandedIds.length === items.length;
3150
2864
  return /* @__PURE__ */ jsxs("div", {
3151
- className: "space-y-4",
2865
+ className: cn(structure_module_default.items, structure_module_default.stackLoose),
3152
2866
  children: [
3153
2867
  header,
3154
2868
  /* @__PURE__ */ jsxs("div", {
3155
- className: "flex items-center justify-between",
2869
+ className: structure_module_default.row,
3156
2870
  children: [/* @__PURE__ */ jsx(SelectAllCheckbox, {
3157
2871
  total: items.length,
3158
2872
  selected: selection.selected.size,
@@ -3168,7 +2882,7 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3168
2882
  }),
3169
2883
  bulkBar,
3170
2884
  !canEditStructure && /* @__PURE__ */ jsx("div", {
3171
- className: "rounded border border-dashed border-amber-200 p-3 text-xs\n text-amber-700",
2885
+ className: structure_module_default.noticeWarning,
3172
2886
  children: messages.items.structureLocked
3173
2887
  }),
3174
2888
  /* @__PURE__ */ jsx(SortableItems, {
@@ -3195,7 +2909,7 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3195
2909
  onMove: (toIndex) => actions.move(item.elementIndex, toIndex),
3196
2910
  onDelete: () => actions.remove(item.elementIndex)
3197
2911
  }),
3198
- className: kind === "primitive" ? "space-y-2 rounded border border-gray-100 bg-gray-50 p-2" : "space-y-3 rounded border bg-gray-50 p-3",
2912
+ className: cn(structure_module_default.card, kind === "primitive" && structure_module_default.cardCompact),
3199
2913
  children: kind === "primitive" ? /* @__PURE__ */ jsx(Field, {
3200
2914
  binding: item.value,
3201
2915
  onNodeChange: onChildChange
@@ -3207,74 +2921,22 @@ const Items = ({ value, render, minItems, maxItems, onChange, onChildChange }) =
3207
2921
  };
3208
2922
  //#endregion
3209
2923
  //#region src/components/dnd/panel/field.tsx
3210
- const parseDateValue = (value) => {
3211
- const match = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}))?$/.exec(value.trim());
3212
- if (!match) return;
3213
- const [, year, month, day, hours = "0", minutes = "0"] = match;
3214
- const date = new Date(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes));
3215
- return Number.isNaN(date.getTime()) ? void 0 : date;
3216
- };
3217
- const pad = (value) => String(value).padStart(2, "0");
3218
- const formatDateValue = (date, withTime = false) => {
3219
- const day = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
3220
- return withTime ? `${day}T${pad(date.getHours())}:${pad(date.getMinutes())}` : day;
3221
- };
3222
- const RICHTEXT_TOOLBAR = [
3223
- "bold",
3224
- "italic",
3225
- "underline",
3226
- "bulletList",
3227
- "orderedList",
3228
- "link"
3229
- ];
3230
- const FieldError = ({ id, message }) => message ? /* @__PURE__ */ jsx("p", {
3231
- id,
3232
- role: "alert",
3233
- className: "mt-1 mb-0 text-xs text-red-500",
3234
- children: message
3235
- }) : null;
3236
2924
  const BuiltinField = ({ binding, onNodeChange }) => {
3237
2925
  const messages = useLiveMessages();
3238
- const validationOptions = { messages: messages.validation };
3239
2926
  const { id, value, rawValue, onChange } = binding;
3240
- const [validationError, setValidationError] = useState(null);
3241
- const { controlId, errorId, isLabelled } = useFieldIds();
3242
- const controlProps = {
3243
- id: controlId,
3244
- "aria-label": isLabelled ? void 0 : binding.label,
3245
- "aria-invalid": validationError ? true : void 0,
3246
- "aria-describedby": validationError ? errorId : void 0
3247
- };
3248
- const [text, setText] = useState(rawValue);
3249
- const [prevRawValue, setPrevRawValue] = useState(rawValue);
3250
- if (rawValue !== prevRawValue) {
3251
- setPrevRawValue(rawValue);
3252
- setText(rawValue);
3253
- }
2927
+ const { text, setText, validationError, errorId, controlProps, commitIfChanged, validateAndCommit } = useFieldState(binding);
3254
2928
  const kind = getFieldKind(binding);
3255
2929
  if (kind === "readonly") return /* @__PURE__ */ jsxs("div", {
3256
- className: "space-y-1 rounded border border-dashed border-amber-200 p-3\n text-xs text-amber-700",
2930
+ className: fields_module_default.readonly,
3257
2931
  children: [
3258
2932
  /* @__PURE__ */ jsx("div", { children: messages.panel.expressionPreserved }),
3259
2933
  /* @__PURE__ */ jsx("code", {
3260
- className: "block overflow-x-auto text-amber-800",
2934
+ className: fields_module_default.readonlyCode,
3261
2935
  children: rawValue
3262
2936
  }),
3263
2937
  /* @__PURE__ */ jsx("div", { children: messages.panel.useCodeEditor })
3264
2938
  ]
3265
2939
  });
3266
- const commitIfChanged = (next) => {
3267
- if (next !== (typeof next === "string" ? rawValue : value)) onChange(next);
3268
- };
3269
- const validateAndCommit = (next) => {
3270
- const result = validateBindingValue(binding, next, validationOptions);
3271
- if (!result.valid) {
3272
- setValidationError(result.message ?? messages.panel.invalidValue);
3273
- return;
3274
- }
3275
- setValidationError(null);
3276
- commitIfChanged(next);
3277
- };
3278
2940
  if (kind === "items") return /* @__PURE__ */ jsx(Items, {
3279
2941
  value: rawValue,
3280
2942
  render: binding.render,
@@ -3283,10 +2945,13 @@ const BuiltinField = ({ binding, onNodeChange }) => {
3283
2945
  onChange,
3284
2946
  onChildChange: onNodeChange
3285
2947
  });
3286
- if (kind === "richtext") return /* @__PURE__ */ jsx(RichTextEditor, {
3287
- value: rawValue,
3288
- toolbar: RICHTEXT_TOOLBAR,
3289
- onChange: commitIfChanged
2948
+ if (kind === "richtext") return /* @__PURE__ */ jsx("textarea", {
2949
+ ...controlProps,
2950
+ rows: 4,
2951
+ value: text,
2952
+ className: cn(fields_module_default.control, fields_module_default.mono),
2953
+ onChange: (e) => setText(e.target.value),
2954
+ onBlur: (e) => commitIfChanged(e.target.value)
3290
2955
  });
3291
2956
  if (kind === "html" || kind === "jsx") return /* @__PURE__ */ jsx(JSXEditorField, {
3292
2957
  value: rawValue,
@@ -3301,17 +2966,17 @@ const BuiltinField = ({ binding, onNodeChange }) => {
3301
2966
  if (kind === "object") {
3302
2967
  const objectValue = value;
3303
2968
  return /* @__PURE__ */ jsx("div", {
3304
- className: "space-y-2 rounded border border-gray-200 bg-gray-50 p-2",
2969
+ className: fields_module_default.object,
3305
2970
  children: Object.entries(objectValue).map(([key, val]) => {
3306
2971
  const nested = resolveRenderEntry(binding.render, key);
3307
2972
  return /* @__PURE__ */ jsx("div", {
3308
- className: "space-y-1",
2973
+ className: fields_module_default.stack,
3309
2974
  children: /* @__PURE__ */ jsx(LabeledField, {
3310
2975
  binding: {
3311
2976
  ...nested,
3312
2977
  value: val
3313
2978
  },
3314
- labelClassName: "block text-xs font-medium text-gray-600",
2979
+ labelClassName: fields_module_default.label,
3315
2980
  label: nested.label,
3316
2981
  children: /* @__PURE__ */ jsx(Field, {
3317
2982
  binding: {
@@ -3333,47 +2998,45 @@ const BuiltinField = ({ binding, onNodeChange }) => {
3333
2998
  })
3334
2999
  });
3335
3000
  }
3336
- if (kind === "boolean") return /* @__PURE__ */ jsx(Checkbox, {
3001
+ if (kind === "boolean") return /* @__PURE__ */ jsx("input", {
3002
+ ...controlProps,
3003
+ type: "checkbox",
3337
3004
  checked: value === true || value === "true",
3338
- onChange: (checked) => {
3339
- onChange(checked);
3005
+ className: fields_module_default.checkbox,
3006
+ onChange: (e) => {
3007
+ onChange(e.target.checked);
3340
3008
  }
3341
3009
  });
3342
- const stringValue = rawValue;
3343
- if (kind === "select") return /* @__PURE__ */ jsx(Select, {
3344
- "aria-label": binding.label,
3345
- value: stringValue,
3346
- options: binding.options ?? [],
3347
- onChange: commitIfChanged
3010
+ if (kind === "select") return /* @__PURE__ */ jsx("select", {
3011
+ ...controlProps,
3012
+ value: rawValue,
3013
+ className: fields_module_default.control,
3014
+ onChange: (e) => commitIfChanged(e.target.value),
3015
+ children: (binding.options ?? []).map((option) => /* @__PURE__ */ jsx("option", {
3016
+ value: option.value,
3017
+ children: option.label
3018
+ }, option.value))
3348
3019
  });
3349
- if (kind === "color") return /* @__PURE__ */ jsx(ColorPickerField, {
3350
- value: stringValue,
3351
- label: binding.label,
3020
+ if (kind === "color") return /* @__PURE__ */ jsx(ColorField, {
3021
+ ...controlProps,
3022
+ value: rawValue,
3352
3023
  onChange: commitIfChanged
3353
3024
  });
3354
- if (kind === "date" || kind === "datetime") {
3355
- const withTime = kind === "datetime";
3356
- return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(DatePicker, {
3357
- value: parseDateValue(stringValue),
3358
- showTime: withTime,
3359
- onChange: (date) => validateAndCommit(date ? formatDateValue(date, withTime) : "")
3360
- }), /* @__PURE__ */ jsx(FieldError, {
3361
- id: errorId,
3362
- message: validationError
3363
- })] });
3364
- }
3365
- if (kind === "time") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(TimePicker, {
3025
+ if (kind === "date" || kind === "datetime" || kind === "time") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("input", {
3366
3026
  ...controlProps,
3367
- value: stringValue || null,
3368
- onChange: (time) => validateAndCommit(time ?? "")
3027
+ type: kind === "datetime" ? "datetime-local" : kind,
3028
+ value: rawValue,
3029
+ className: fields_module_default.control,
3030
+ onChange: (e) => validateAndCommit(e.target.value)
3369
3031
  }), /* @__PURE__ */ jsx(FieldError, {
3370
3032
  id: errorId,
3371
3033
  message: validationError
3372
3034
  })] });
3373
- if (kind === "url" || kind === "email" || kind === "tel") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
3035
+ if (kind === "url" || kind === "email" || kind === "tel") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("input", {
3374
3036
  ...controlProps,
3375
3037
  type: kind,
3376
3038
  value: text,
3039
+ className: fields_module_default.control,
3377
3040
  onChange: (e) => setText(e.target.value),
3378
3041
  placeholder: kind === "url" ? messages.panel.urlPlaceholder : kind === "email" ? messages.panel.emailPlaceholder : messages.panel.telPlaceholder,
3379
3042
  onBlur: (e) => validateAndCommit(e.target.value.trim())
@@ -3381,11 +3044,12 @@ const BuiltinField = ({ binding, onNodeChange }) => {
3381
3044
  id: errorId,
3382
3045
  message: validationError
3383
3046
  })] });
3384
- if (kind === "number") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
3047
+ if (kind === "number") return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("input", {
3385
3048
  ...controlProps,
3386
3049
  type: "number",
3387
3050
  step: binding.step,
3388
3051
  value: text,
3052
+ className: fields_module_default.control,
3389
3053
  onChange: (e) => setText(e.target.value),
3390
3054
  placeholder: messages.panel.numberPlaceholder,
3391
3055
  onBlur: (e) => {
@@ -3397,9 +3061,11 @@ const BuiltinField = ({ binding, onNodeChange }) => {
3397
3061
  id: errorId,
3398
3062
  message: validationError
3399
3063
  })] });
3400
- return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input.TextArea, {
3064
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("textarea", {
3401
3065
  ...controlProps,
3066
+ rows: 2,
3402
3067
  value: text,
3068
+ className: fields_module_default.control,
3403
3069
  onChange: (e) => setText(e.target.value),
3404
3070
  placeholder: messages.panel.textPlaceholder,
3405
3071
  onBlur: (e) => {
@@ -3449,29 +3115,26 @@ const ElementFields = ({ id, header, bindings, onNodeChange, children, ...props
3449
3115
  children: [
3450
3116
  header,
3451
3117
  bindings.length > 0 && /* @__PURE__ */ jsx("div", {
3452
- className: "space-y-2 rounded",
3453
- children: /* @__PURE__ */ jsx("div", {
3454
- className: "space-y-1",
3455
- children: bindings.map((binding) => /* @__PURE__ */ jsx("div", {
3456
- className: "space-y-1",
3457
- children: /* @__PURE__ */ jsx(LabeledField, {
3118
+ className: panel_module_default.bindings,
3119
+ children: bindings.map((binding) => /* @__PURE__ */ jsx("div", {
3120
+ className: panel_module_default.binding,
3121
+ children: /* @__PURE__ */ jsx(LabeledField, {
3122
+ binding,
3123
+ labelClassName: panel_module_default.bindingLabel,
3124
+ label: /* @__PURE__ */ jsxs(Fragment, { children: [binding.label, /* @__PURE__ */ jsxs("span", {
3125
+ className: panel_module_default.bindingProperty,
3126
+ children: [
3127
+ "(",
3128
+ binding.property,
3129
+ ")"
3130
+ ]
3131
+ })] }),
3132
+ children: /* @__PURE__ */ jsx(Field, {
3458
3133
  binding,
3459
- labelClassName: "block text-xs font-semibold text-gray-700",
3460
- label: /* @__PURE__ */ jsxs(Fragment, { children: [binding.label, /* @__PURE__ */ jsxs("span", {
3461
- className: "ml-1 text-gray-400",
3462
- children: [
3463
- "(",
3464
- binding.property,
3465
- ")"
3466
- ]
3467
- })] }),
3468
- children: /* @__PURE__ */ jsx(Field, {
3469
- binding,
3470
- onNodeChange
3471
- })
3134
+ onNodeChange
3472
3135
  })
3473
- }, `${binding.property}-${binding.label}`))
3474
- })
3136
+ })
3137
+ }, `${binding.property}-${binding.label}`))
3475
3138
  }),
3476
3139
  children
3477
3140
  ]
@@ -3516,8 +3179,8 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3516
3179
  ids: new Set(pickedId ? [pickedId] : []),
3517
3180
  scrollRootRef: rootRef
3518
3181
  }), [pickedId]);
3519
- if (!item) return /* @__PURE__ */ jsx(Typography.Paragraph, {
3520
- className: cn("p-4 text-sm text-gray-500"),
3182
+ if (!item) return /* @__PURE__ */ jsx("p", {
3183
+ className: panel_module_default.empty,
3521
3184
  children: messages.panel.selectSection
3522
3185
  });
3523
3186
  return /* @__PURE__ */ jsxs("div", {
@@ -3528,15 +3191,15 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3528
3191
  onBlur: (e) => {
3529
3192
  if (!e.currentTarget.contains(e.relatedTarget)) setFocusedId(null);
3530
3193
  },
3531
- className: cn("h-full space-y-4 p-4", "overflow-x-hidden overflow-y-auto"),
3194
+ className: panel_module_default.panel,
3532
3195
  children: [
3533
3196
  /* @__PURE__ */ jsxs("div", {
3534
- className: "flex items-center justify-between",
3535
- children: [/* @__PURE__ */ jsx(Typography.Title, {
3536
- className: "text-lg font-semibold",
3197
+ className: panel_module_default.header,
3198
+ children: [/* @__PURE__ */ jsx("h2", {
3199
+ className: panel_module_default.title,
3537
3200
  children: item.name
3538
3201
  }), /* @__PURE__ */ jsxs("div", {
3539
- className: "flex items-center gap-1",
3202
+ className: panel_module_default.actions,
3540
3203
  children: [
3541
3204
  onMoveUp && /* @__PURE__ */ jsx(Button, {
3542
3205
  icon: /* @__PURE__ */ jsx(ChevronUp, {}),
@@ -3551,7 +3214,7 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3551
3214
  "aria-label": messages.section.moveDown
3552
3215
  }),
3553
3216
  onDelete && /* @__PURE__ */ jsx(Button, {
3554
- danger: true,
3217
+ tone: "danger",
3555
3218
  icon: /* @__PURE__ */ jsx(Trash, {}),
3556
3219
  onClick: () => onDelete(item.id),
3557
3220
  "aria-label": messages.section.delete
@@ -3559,13 +3222,13 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3559
3222
  ]
3560
3223
  })]
3561
3224
  }),
3562
- readOnly && /* @__PURE__ */ jsx(Typography.Text, {
3225
+ readOnly && /* @__PURE__ */ jsx("span", {
3563
3226
  role: "status",
3564
- className: "block text-xs text-amber-700",
3227
+ className: panel_module_default.readOnly,
3565
3228
  children: messages.panel.readOnly
3566
3229
  }),
3567
- !groups.length && /* @__PURE__ */ jsx(Typography.Text, {
3568
- className: "text-xs text-gray-400",
3230
+ !groups.length && /* @__PURE__ */ jsx("span", {
3231
+ className: panel_module_default.note,
3569
3232
  children: messages.panel.noEditableElements
3570
3233
  }),
3571
3234
  /* @__PURE__ */ jsx(ElementSelectionContext.Provider, {
@@ -3576,14 +3239,14 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3576
3239
  id: group[0].id,
3577
3240
  role: "group",
3578
3241
  "aria-label": element.label,
3579
- className: "rounded data-[picked]:ring-2\n data-[picked]:ring-blue-400 data-[picked]:ring-offset-2",
3242
+ className: panel_module_default.element,
3580
3243
  header: groups.length > 1 && /* @__PURE__ */ jsxs("div", {
3581
- className: "mb-2 flex min-w-0 items-baseline gap-1.5 border-b\n border-gray-100 pb-1 text-xs",
3244
+ className: panel_module_default.elementHeader,
3582
3245
  children: [/* @__PURE__ */ jsx("code", {
3583
- className: "shrink-0 text-gray-500",
3246
+ className: panel_module_default.elementTag,
3584
3247
  children: element.tagName
3585
3248
  }), element.text && /* @__PURE__ */ jsx("span", {
3586
- className: "truncate text-gray-400",
3249
+ className: panel_module_default.elementText,
3587
3250
  children: element.text
3588
3251
  })]
3589
3252
  }),
@@ -3596,12 +3259,126 @@ const Panel$1 = ({ item, onDelete, onMoveUp, onMoveDown, canMoveUp = false, canM
3596
3259
  });
3597
3260
  };
3598
3261
  //#endregion
3262
+ //#region src/components/dnd/split-panes.module.css
3263
+ var split_panes_module_default = {
3264
+ "center": "s-4F9W_center",
3265
+ "container": "s-4F9W_container",
3266
+ "handle": "s-4F9W_handle",
3267
+ "pane": "s-4F9W_pane"
3268
+ };
3269
+ //#endregion
3270
+ //#region src/components/dnd/split-panes.tsx
3271
+ const DEFAULT_SIZE = 20;
3272
+ const MIN_SIZE = 15;
3273
+ const MAX_SIZE = 35;
3274
+ const KEYBOARD_STEP = 2;
3275
+ const clampSize = (size) => {
3276
+ if (size < MIN_SIZE / 2) return 0;
3277
+ return Math.min(MAX_SIZE, Math.max(MIN_SIZE, size));
3278
+ };
3279
+ const SplitPanes = ({ start, center, end, labels }) => {
3280
+ const containerRef = useRef(null);
3281
+ const [sizes, setSizes] = useState({
3282
+ start: DEFAULT_SIZE,
3283
+ end: DEFAULT_SIZE
3284
+ });
3285
+ const restoreRef = useRef({
3286
+ start: DEFAULT_SIZE,
3287
+ end: DEFAULT_SIZE
3288
+ });
3289
+ const resize = (side, size) => {
3290
+ if (size > 0) restoreRef.current[side] = size;
3291
+ setSizes((prev) => ({
3292
+ ...prev,
3293
+ [side]: size
3294
+ }));
3295
+ };
3296
+ const onPointerDown = (side) => (e) => {
3297
+ const container = containerRef.current;
3298
+ if (!container || e.button !== 0) return;
3299
+ e.preventDefault();
3300
+ const handle = e.currentTarget;
3301
+ const width = container.getBoundingClientRect().width;
3302
+ const startX = e.clientX;
3303
+ const startSize = sizes[side];
3304
+ handle.setPointerCapture(e.pointerId);
3305
+ const onMove = (move) => {
3306
+ const delta = (move.clientX - startX) / width * 100;
3307
+ resize(side, clampSize(startSize + (side === "start" ? delta : -delta)));
3308
+ };
3309
+ const onUp = () => {
3310
+ handle.removeEventListener("pointermove", onMove);
3311
+ handle.removeEventListener("pointerup", onUp);
3312
+ handle.removeEventListener("pointercancel", onUp);
3313
+ };
3314
+ handle.addEventListener("pointermove", onMove);
3315
+ handle.addEventListener("pointerup", onUp);
3316
+ handle.addEventListener("pointercancel", onUp);
3317
+ };
3318
+ const onKeyDown = (side) => (e) => {
3319
+ const grow = side === "start" ? "ArrowRight" : "ArrowLeft";
3320
+ const shrink = side === "start" ? "ArrowLeft" : "ArrowRight";
3321
+ const size = sizes[side];
3322
+ if (e.key === grow || e.key === shrink) {
3323
+ e.preventDefault();
3324
+ const step = e.key === grow ? KEYBOARD_STEP : -2;
3325
+ resize(side, Math.min(MAX_SIZE, Math.max(MIN_SIZE, size + step)));
3326
+ return;
3327
+ }
3328
+ if (e.key === "Home" || e.key === "End") {
3329
+ e.preventDefault();
3330
+ resize(side, e.key === "Home" ? MIN_SIZE : MAX_SIZE);
3331
+ return;
3332
+ }
3333
+ if (e.key === "Enter") {
3334
+ e.preventDefault();
3335
+ resize(side, size > 0 ? 0 : restoreRef.current[side]);
3336
+ }
3337
+ };
3338
+ const handle = (side) => /* @__PURE__ */ jsx("div", {
3339
+ role: "separator",
3340
+ tabIndex: 0,
3341
+ "aria-orientation": "vertical",
3342
+ "aria-label": labels[side],
3343
+ "aria-valuenow": Math.round(sizes[side]),
3344
+ "aria-valuemin": 0,
3345
+ "aria-valuemax": MAX_SIZE,
3346
+ className: split_panes_module_default.handle,
3347
+ onPointerDown: onPointerDown(side),
3348
+ onKeyDown: onKeyDown(side),
3349
+ onDoubleClick: () => resize(side, sizes[side] > 0 ? 0 : restoreRef.current[side])
3350
+ });
3351
+ return /* @__PURE__ */ jsxs("div", {
3352
+ ref: containerRef,
3353
+ className: split_panes_module_default.container,
3354
+ children: [
3355
+ /* @__PURE__ */ jsx("div", {
3356
+ className: split_panes_module_default.pane,
3357
+ style: { flexBasis: `${sizes.start}%` },
3358
+ hidden: sizes.start === 0,
3359
+ children: start
3360
+ }),
3361
+ handle("start"),
3362
+ /* @__PURE__ */ jsx("div", {
3363
+ className: split_panes_module_default.center,
3364
+ children: center
3365
+ }),
3366
+ handle("end"),
3367
+ /* @__PURE__ */ jsx("div", {
3368
+ className: split_panes_module_default.pane,
3369
+ style: { flexBasis: `${sizes.end}%` },
3370
+ hidden: sizes.end === 0,
3371
+ children: end
3372
+ })
3373
+ ]
3374
+ });
3375
+ };
3376
+ //#endregion
3599
3377
  //#region src/components/dnd/layout.tsx
3600
3378
  const PaletteItems = ({ subject }) => {
3601
3379
  const { palette: { items, onAdd }, isMobile } = useDndRegions(subject);
3602
- return /* @__PURE__ */ jsx(Space, {
3603
- orientation: "vertical",
3604
- align: "start",
3380
+ return /* @__PURE__ */ jsx("div", {
3381
+ className: layout_module_default.paletteItems,
3605
3382
  children: items.map((item) => /* @__PURE__ */ jsx(DefaultDraggableItem, {
3606
3383
  item,
3607
3384
  onAdd,
@@ -3624,7 +3401,7 @@ const PanelFields = ({ subject }) => {
3624
3401
  });
3625
3402
  };
3626
3403
  const Palette = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
3627
- className: cn("h-full overflow-y-auto bg-gray-50 p-4", className),
3404
+ className: cn(layout_module_default.palette, className),
3628
3405
  ...restProps,
3629
3406
  children: /* @__PURE__ */ jsx(PaletteItems, { subject: "<Live.Dnd.Palette>" })
3630
3407
  });
@@ -3633,7 +3410,7 @@ const Canvas = ({ className, style, ...restProps }) => {
3633
3410
  const inspector = useDndInspector();
3634
3411
  const messages = useLiveMessages();
3635
3412
  return /* @__PURE__ */ jsxs("div", {
3636
- className: cn("relative h-full w-full overflow-y-auto", className),
3413
+ className: cn(layout_module_default.canvas, className),
3637
3414
  "data-frame-container": true,
3638
3415
  style: {
3639
3416
  isolation: "isolate",
@@ -3643,12 +3420,12 @@ const Canvas = ({ className, style, ...restProps }) => {
3643
3420
  },
3644
3421
  ...restProps,
3645
3422
  children: [canvas, !documentError && /* @__PURE__ */ jsx("div", {
3646
- className: "pointer-events-none sticky bottom-0 z-70 h-0",
3423
+ className: layout_module_default.pickerDock,
3647
3424
  children: /* @__PURE__ */ jsx("div", {
3648
- className: "pointer-events-auto absolute bottom-3 left-3",
3425
+ className: layout_module_default.picker,
3649
3426
  children: /* @__PURE__ */ jsx(Button, {
3650
3427
  icon: /* @__PURE__ */ jsx(Crosshair, {}),
3651
- color: "primary",
3428
+ tone: "primary",
3652
3429
  variant: inspector.active ? "solid" : "outlined",
3653
3430
  "aria-pressed": inspector.active,
3654
3431
  "aria-label": messages.canvas.pickElement,
@@ -3660,7 +3437,7 @@ const Canvas = ({ className, style, ...restProps }) => {
3660
3437
  });
3661
3438
  };
3662
3439
  const Panel = ({ className, ...restProps }) => /* @__PURE__ */ jsx("div", {
3663
- className: cn("h-full", className),
3440
+ className: cn(layout_module_default.panel, className),
3664
3441
  ...restProps,
3665
3442
  children: /* @__PURE__ */ jsx(PanelFields, { subject: "<Live.Dnd.Panel>" })
3666
3443
  });
@@ -3668,52 +3445,36 @@ const Layout = ({ palette, panel }) => {
3668
3445
  const { isMobile, selectedId, clearSelection, paletteOpen, setPaletteOpen } = useDndRegions("<Live.Dnd.Layout>");
3669
3446
  const messages = useLiveMessages();
3670
3447
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3671
- isMobile ? /* @__PURE__ */ jsx(Canvas, {}) : /* @__PURE__ */ jsxs(Splitter, {
3672
- withHandle: true,
3673
- orientation: "horizontal",
3674
- children: [
3675
- /* @__PURE__ */ jsx(Splitter.Panel, {
3676
- defaultSize: "20%",
3677
- minSize: "15%",
3678
- maxSize: "35%",
3679
- collapsible: true,
3680
- children: palette ?? /* @__PURE__ */ jsx(Palette, {})
3681
- }),
3682
- /* @__PURE__ */ jsx(Splitter.Panel, {
3683
- defaultSize: "60%",
3684
- children: /* @__PURE__ */ jsx(Canvas, {})
3685
- }),
3686
- /* @__PURE__ */ jsx(Splitter.Panel, {
3687
- defaultSize: "20%",
3688
- minSize: "15%",
3689
- maxSize: "35%",
3690
- collapsible: true,
3691
- children: panel ?? /* @__PURE__ */ jsx(Panel, {})
3692
- })
3693
- ]
3448
+ isMobile ? /* @__PURE__ */ jsx(Canvas, {}) : /* @__PURE__ */ jsx(SplitPanes, {
3449
+ start: palette ?? /* @__PURE__ */ jsx(Palette, {}),
3450
+ center: /* @__PURE__ */ jsx(Canvas, {}),
3451
+ end: panel ?? /* @__PURE__ */ jsx(Panel, {}),
3452
+ labels: {
3453
+ start: messages.canvas.resizePalette,
3454
+ end: messages.canvas.resizePanel
3455
+ }
3694
3456
  }),
3695
3457
  /* @__PURE__ */ jsx(Button, {
3696
- type: "primary",
3458
+ variant: "solid",
3459
+ tone: "primary",
3697
3460
  shape: "circle",
3698
3461
  icon: /* @__PURE__ */ jsx(LayoutGrid, {}),
3699
3462
  "aria-label": messages.canvas.palette,
3700
- className: "fixed right-4 bottom-4 z-20 md:hidden",
3463
+ className: layout_module_default.paletteButton,
3701
3464
  onClick: () => setPaletteOpen(true)
3702
3465
  }),
3703
3466
  /* @__PURE__ */ jsx(Drawer, {
3704
3467
  open: isMobile && paletteOpen,
3705
3468
  onClose: () => setPaletteOpen(false),
3706
- direction: "bottom",
3707
- size: "large",
3708
3469
  title: messages.canvas.palette,
3470
+ closeLabel: messages.canvas.close,
3709
3471
  children: palette ?? /* @__PURE__ */ jsx(PaletteItems, { subject: "<Live.Dnd.Layout>" })
3710
3472
  }),
3711
3473
  /* @__PURE__ */ jsx(Drawer, {
3712
3474
  open: isMobile && Boolean(selectedId),
3713
3475
  onClose: clearSelection,
3714
- direction: "bottom",
3715
- size: "large",
3716
3476
  title: messages.canvas.properties,
3477
+ closeLabel: messages.canvas.close,
3717
3478
  children: panel ?? /* @__PURE__ */ jsx(PanelFields, { subject: "<Live.Dnd.Layout>" })
3718
3479
  })
3719
3480
  ] });
@@ -3854,7 +3615,7 @@ const createNodeRegistry = () => {
3854
3615
  }
3855
3616
  };
3856
3617
  };
3857
- const useDndKeyboard = ({ sections, selectedId, selectedIndex, selectOnly, move, requestDelete }) => {
3618
+ const useDndKeyboard = ({ sections, selectedId, selectedIndex, selectOnly, move, copy, requestDelete }) => {
3858
3619
  const { announcements: say } = useLiveMessages();
3859
3620
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 10 } }), useSensor(KeyboardSensor, {
3860
3621
  coordinateGetter: sortableKeyboardCoordinates,
@@ -3892,6 +3653,23 @@ const useDndKeyboard = ({ sections, selectedId, selectedIndex, selectOnly, move,
3892
3653
  move(id, direction);
3893
3654
  if (to === 0 || to === sections.length - 1) focusSection(id);
3894
3655
  };
3656
+ const focusSelectedRef = useRef(false);
3657
+ const onMoveKey = (id, direction) => {
3658
+ const to = sections.findIndex((section) => section.id === id) + (direction === "up" ? -1 : 1);
3659
+ if (to < 0 || to >= sections.length) return;
3660
+ selectOnly(id);
3661
+ move(id, direction);
3662
+ focusSelectedRef.current = true;
3663
+ };
3664
+ const onCopyKey = (id) => {
3665
+ copy(id);
3666
+ focusSelectedRef.current = true;
3667
+ };
3668
+ useEffect(() => {
3669
+ if (!focusSelectedRef.current || selectedId === null) return;
3670
+ focusSelectedRef.current = false;
3671
+ focusSection(selectedId);
3672
+ });
3895
3673
  useEffect(() => {
3896
3674
  if (selectedId === null) return;
3897
3675
  const frame = requestAnimationFrame(() => {
@@ -3910,6 +3688,8 @@ const useDndKeyboard = ({ sections, selectedId, selectedIndex, selectOnly, move,
3910
3688
  sectionNodes,
3911
3689
  onNavigate,
3912
3690
  onDeleteKey,
3691
+ onMoveKey,
3692
+ onCopyKey,
3913
3693
  onMoveButton
3914
3694
  };
3915
3695
  };
@@ -4266,12 +4046,13 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
4266
4046
  onBeforeDelete
4267
4047
  });
4268
4048
  const onDelete = (id) => requestDelete(id);
4269
- const { sensors, announcements, screenReaderInstructions, sectionNodes, onNavigate, onDeleteKey, onMoveButton } = useDndKeyboard({
4049
+ const { sensors, announcements, screenReaderInstructions, sectionNodes, onNavigate, onDeleteKey, onMoveKey, onCopyKey, onMoveButton } = useDndKeyboard({
4270
4050
  sections,
4271
4051
  selectedId,
4272
4052
  selectedIndex,
4273
4053
  selectOnly,
4274
4054
  move: moveSection,
4055
+ copy: onCopy,
4275
4056
  requestDelete
4276
4057
  });
4277
4058
  const { inspector, inspecting, onInspectMove, onInspectPick, onInspectLeave, highlightRect } = useInspectorState({
@@ -4331,20 +4112,22 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
4331
4112
  onInspectLeave,
4332
4113
  nodeRef: sectionNodes.register,
4333
4114
  onNavigate,
4334
- onDeleteKey
4115
+ onDeleteKey,
4116
+ onMoveKey,
4117
+ onCopyKey
4335
4118
  };
4336
4119
  const canvas = /* @__PURE__ */ jsxs(SectionHandlersContext.Provider, {
4337
4120
  value: sectionHandlers,
4338
4121
  children: [
4339
4122
  stale && /* @__PURE__ */ jsx("div", {
4340
4123
  role: "status",
4341
- className: cn("sticky top-0 z-70", "border-b border-amber-200 bg-amber-50 px-3 py-2", "text-sm text-amber-900"),
4124
+ className: canvas_module_default.stale,
4342
4125
  children: messages.canvas.stale
4343
4126
  }),
4344
4127
  /* @__PURE__ */ jsx(Droppable, {
4345
- className: cn(!sections.length && "h-full"),
4128
+ className: cn(!sections.length && canvas_module_default.fill),
4346
4129
  children: !sections.length ? /* @__PURE__ */ jsx("div", {
4347
- className: cn("flex items-center justify-center", "h-full", "text-gray-500"),
4130
+ className: canvas_module_default.empty,
4348
4131
  children: /* @__PURE__ */ jsx(CanvasNotice, { ...emptyCanvasNotice(messages, problem, isMobile) })
4349
4132
  }) : /* @__PURE__ */ jsx(SortableContext, {
4350
4133
  items: sections.map((s) => s.id),
@@ -4390,7 +4173,7 @@ const Dnd$1 = ({ value: _value, props, modules: _modules = NO_MODULES, onChange:
4390
4173
  modifiers: [conditionalModifiers],
4391
4174
  onDragEnd,
4392
4175
  children: [/* @__PURE__ */ jsx("div", {
4393
- className: cn("relative flex h-full w-full", className),
4176
+ className: cn(layout_module_default.root, className),
4394
4177
  ...restProps,
4395
4178
  children: /* @__PURE__ */ jsx(DndEditOptionsContext.Provider, {
4396
4179
  value: {
@@ -4441,6 +4224,6 @@ Dnd.Canvas = Canvas;
4441
4224
  Dnd.Panel = Panel;
4442
4225
  Dnd.Layout = Layout;
4443
4226
  //#endregion
4444
- export { DraggableItem as _, Panel as a, getFieldKind as c, resolvePanelBindings as d, withPanelCommit as f, useDndInspector as g, useDndPanel as h, Palette as i, isStructuralFieldKind as l, useDndPalette as m, Canvas as n, Field as o, useDndLayout as p, Layout as r, useDndItems as s, Dnd as t, useDndChildren as u };
4227
+ export { Panel as a, useDndChildren as c, useDndLayout as d, useDndPalette as f, DraggableItem as h, Palette as i, resolvePanelBindings as l, useDndInspector as m, Canvas as n, Field as o, useDndPanel as p, Layout as r, useDndItems as s, Dnd as t, withPanelCommit as u };
4445
4228
 
4446
- //# sourceMappingURL=dnd-BlC1gqUy.js.map
4229
+ //# sourceMappingURL=dnd-COjjjuD7.js.map