@kubuild/components 0.1.0 → 0.3.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 (135) hide show
  1. package/README.md +110 -0
  2. package/dist/blocks/forms.d.ts +6 -0
  3. package/dist/blocks/forms.d.ts.map +1 -0
  4. package/dist/blocks/index.cjs +1661 -0
  5. package/dist/blocks/index.cjs.map +1 -0
  6. package/dist/blocks/index.d.ts +11 -0
  7. package/dist/blocks/index.d.ts.map +1 -0
  8. package/dist/blocks/index.js +15 -0
  9. package/dist/blocks/index.js.map +1 -0
  10. package/dist/blocks/layout.d.ts +6 -0
  11. package/dist/blocks/layout.d.ts.map +1 -0
  12. package/dist/blocks/sections.d.ts +6 -0
  13. package/dist/blocks/sections.d.ts.map +1 -0
  14. package/dist/{blocks.d.ts → blocks/types.d.ts} +2 -5
  15. package/dist/blocks/types.d.ts.map +1 -0
  16. package/dist/chunk-JTQ35OQQ.js +1631 -0
  17. package/dist/chunk-JTQ35OQQ.js.map +1 -0
  18. package/dist/chunk-K6I6U7F3.js +2707 -0
  19. package/dist/chunk-K6I6U7F3.js.map +1 -0
  20. package/dist/chunk-OK53DS7G.js +911 -0
  21. package/dist/chunk-OK53DS7G.js.map +1 -0
  22. package/dist/definitions/constants.d.ts +10 -0
  23. package/dist/definitions/constants.d.ts.map +1 -0
  24. package/dist/definitions/data/collection.d.ts +3 -0
  25. package/dist/definitions/data/collection.d.ts.map +1 -0
  26. package/dist/definitions/data/index.d.ts +4 -0
  27. package/dist/definitions/data/index.d.ts.map +1 -0
  28. package/dist/definitions/data/list.d.ts +4 -0
  29. package/dist/definitions/data/list.d.ts.map +1 -0
  30. package/dist/definitions/data/table.d.ts +5 -0
  31. package/dist/definitions/data/table.d.ts.map +1 -0
  32. package/dist/definitions/form/button.d.ts +4 -0
  33. package/dist/definitions/form/button.d.ts.map +1 -0
  34. package/dist/definitions/form/checkbox.d.ts +3 -0
  35. package/dist/definitions/form/checkbox.d.ts.map +1 -0
  36. package/dist/definitions/form/file-upload.d.ts +3 -0
  37. package/dist/definitions/form/file-upload.d.ts.map +1 -0
  38. package/dist/definitions/form/form.d.ts +3 -0
  39. package/dist/definitions/form/form.d.ts.map +1 -0
  40. package/dist/definitions/form/index.d.ts +10 -0
  41. package/dist/definitions/form/index.d.ts.map +1 -0
  42. package/dist/definitions/form/input.d.ts +3 -0
  43. package/dist/definitions/form/input.d.ts.map +1 -0
  44. package/dist/definitions/form/radio.d.ts +5 -0
  45. package/dist/definitions/form/radio.d.ts.map +1 -0
  46. package/dist/definitions/form/select.d.ts +3 -0
  47. package/dist/definitions/form/select.d.ts.map +1 -0
  48. package/dist/definitions/form/switch.d.ts +3 -0
  49. package/dist/definitions/form/switch.d.ts.map +1 -0
  50. package/dist/definitions/form/textarea.d.ts +3 -0
  51. package/dist/definitions/form/textarea.d.ts.map +1 -0
  52. package/dist/definitions/index.cjs +3512 -0
  53. package/dist/definitions/index.cjs.map +1 -0
  54. package/dist/definitions/index.d.ts +12 -0
  55. package/dist/definitions/index.d.ts.map +1 -0
  56. package/dist/definitions/index.js +90 -0
  57. package/dist/definitions/index.js.map +1 -0
  58. package/dist/definitions/interactive/collapsible.d.ts +3 -0
  59. package/dist/definitions/interactive/collapsible.d.ts.map +1 -0
  60. package/dist/definitions/interactive/drawer.d.ts +3 -0
  61. package/dist/definitions/interactive/drawer.d.ts.map +1 -0
  62. package/dist/definitions/interactive/index.d.ts +4 -0
  63. package/dist/definitions/interactive/index.d.ts.map +1 -0
  64. package/dist/definitions/interactive/modal.d.ts +3 -0
  65. package/dist/definitions/interactive/modal.d.ts.map +1 -0
  66. package/dist/definitions/layout/columns.d.ts +3 -0
  67. package/dist/definitions/layout/columns.d.ts.map +1 -0
  68. package/dist/definitions/layout/container.d.ts +3 -0
  69. package/dist/definitions/layout/container.d.ts.map +1 -0
  70. package/dist/definitions/layout/flex.d.ts +7 -0
  71. package/dist/definitions/layout/flex.d.ts.map +1 -0
  72. package/dist/definitions/layout/grid.d.ts +7 -0
  73. package/dist/definitions/layout/grid.d.ts.map +1 -0
  74. package/dist/definitions/layout/index.d.ts +7 -0
  75. package/dist/definitions/layout/index.d.ts.map +1 -0
  76. package/dist/definitions/layout/page.d.ts +3 -0
  77. package/dist/definitions/layout/page.d.ts.map +1 -0
  78. package/dist/definitions/layout/section.d.ts +3 -0
  79. package/dist/definitions/layout/section.d.ts.map +1 -0
  80. package/dist/definitions/media/html-embed.d.ts +3 -0
  81. package/dist/definitions/media/html-embed.d.ts.map +1 -0
  82. package/dist/definitions/media/icon.d.ts +3 -0
  83. package/dist/definitions/media/icon.d.ts.map +1 -0
  84. package/dist/definitions/media/image.d.ts +3 -0
  85. package/dist/definitions/media/image.d.ts.map +1 -0
  86. package/dist/definitions/media/index.d.ts +5 -0
  87. package/dist/definitions/media/index.d.ts.map +1 -0
  88. package/dist/definitions/media/video.d.ts +3 -0
  89. package/dist/definitions/media/video.d.ts.map +1 -0
  90. package/dist/definitions/types.d.ts +5 -0
  91. package/dist/definitions/types.d.ts.map +1 -0
  92. package/dist/definitions/typography/badge.d.ts +3 -0
  93. package/dist/definitions/typography/badge.d.ts.map +1 -0
  94. package/dist/definitions/typography/blockquote.d.ts +3 -0
  95. package/dist/definitions/typography/blockquote.d.ts.map +1 -0
  96. package/dist/definitions/typography/code-block.d.ts +3 -0
  97. package/dist/definitions/typography/code-block.d.ts.map +1 -0
  98. package/dist/definitions/typography/heading.d.ts +3 -0
  99. package/dist/definitions/typography/heading.d.ts.map +1 -0
  100. package/dist/definitions/typography/index.d.ts +8 -0
  101. package/dist/definitions/typography/index.d.ts.map +1 -0
  102. package/dist/definitions/typography/link.d.ts +3 -0
  103. package/dist/definitions/typography/link.d.ts.map +1 -0
  104. package/dist/definitions/typography/paragraph.d.ts +3 -0
  105. package/dist/definitions/typography/paragraph.d.ts.map +1 -0
  106. package/dist/definitions/typography/text.d.ts +3 -0
  107. package/dist/definitions/typography/text.d.ts.map +1 -0
  108. package/dist/index.cjs +3114 -708
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.js +151 -2741
  111. package/dist/index.js.map +1 -1
  112. package/dist/traits/common.d.ts +8 -0
  113. package/dist/traits/common.d.ts.map +1 -0
  114. package/dist/traits/form.d.ts +80 -0
  115. package/dist/traits/form.d.ts.map +1 -0
  116. package/dist/traits/index.cjs +998 -0
  117. package/dist/traits/index.cjs.map +1 -0
  118. package/dist/traits/index.d.ts +7 -0
  119. package/dist/traits/index.d.ts.map +1 -0
  120. package/dist/traits/index.js +129 -0
  121. package/dist/traits/index.js.map +1 -0
  122. package/dist/traits/link.d.ts +8 -0
  123. package/dist/traits/link.d.ts.map +1 -0
  124. package/dist/traits/media.d.ts +18 -0
  125. package/dist/traits/media.d.ts.map +1 -0
  126. package/dist/traits/structure.d.ts +10 -0
  127. package/dist/traits/structure.d.ts.map +1 -0
  128. package/dist/traits/types.d.ts +69 -0
  129. package/dist/traits/types.d.ts.map +1 -0
  130. package/package.json +20 -4
  131. package/dist/blocks.d.ts.map +0 -1
  132. package/dist/definitions.d.ts +0 -32
  133. package/dist/definitions.d.ts.map +0 -1
  134. package/dist/traits.d.ts +0 -137
  135. package/dist/traits.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,2233 +1,119 @@
1
- // src/registry.ts
2
- var ComponentRegistry = class {
3
- components = /* @__PURE__ */ new Map();
4
- register(definition, allowOverride = false) {
5
- if (!allowOverride && this.components.has(definition.type)) {
6
- throw new Error(`Component type "${definition.type}" is already registered.`);
7
- }
8
- this.components.set(definition.type, definition);
9
- }
10
- unregister(type) {
11
- return this.components.delete(type);
12
- }
13
- get(type) {
14
- return this.components.get(type);
15
- }
16
- has(type) {
17
- return this.components.has(type);
18
- }
19
- list() {
20
- return Array.from(this.components.values());
21
- }
22
- listByCategory(category) {
23
- return this.list().filter((c) => c.category === category);
24
- }
25
- /**
26
- * Check whether `childType` is a valid insertion target under `parentType`,
27
- * covering both directions of child policy: the parent's `acceptsChildren`/
28
- * `allowedChildren` (by type, category, or `'*'`) and the child's own
29
- * `disallowedParents`. Used by the builder to reject an invalid insertion
30
- * before a node is constructed, rather than after the fact via `validateNode`.
31
- */
32
- canInsertChild(parentType, childType) {
33
- const errors = [];
34
- const parentDef = this.get(parentType);
35
- const childDef = this.get(childType);
36
- if (!parentDef) {
37
- errors.push(`Unknown target parent type: "${parentType}".`);
38
- }
39
- if (!childDef) {
40
- errors.push(`Unknown component type: "${childType}".`);
41
- }
42
- if (!parentDef || !childDef) {
43
- return { valid: false, errors };
44
- }
45
- if (!parentDef.acceptsChildren) {
46
- errors.push(`"${parentDef.label}" does not accept children.`);
47
- } else if (parentDef.allowedChildren) {
48
- const allowed = parentDef.allowedChildren.includes("*") || parentDef.allowedChildren.includes(childType) || parentDef.allowedChildren.includes(childDef.category);
49
- if (!allowed) {
50
- errors.push(`"${parentDef.label}" does not allow "${childDef.label}" as a child.`);
51
- }
52
- }
53
- if (childDef.disallowedParents?.includes(parentType)) {
54
- errors.push(`"${childDef.label}" is not allowed inside "${parentDef.label}".`);
55
- }
56
- return { valid: errors.length === 0, errors };
57
- }
58
- validateNode(node, parentType) {
59
- const def = this.get(node.type);
60
- const errors = [];
61
- if (!def) {
62
- errors.push(`Unknown component type: "${node.type}"`);
63
- return { valid: false, errors };
64
- }
65
- if (!def.acceptsChildren && node.children && node.children.length > 0) {
66
- errors.push(`Component "${node.type}" does not accept children.`);
67
- }
68
- if (def.allowedChildren && node.children) {
69
- for (const child of node.children) {
70
- const childCategory = this.get(child.type)?.category;
71
- const allowed = def.allowedChildren.includes("*") || def.allowedChildren.includes(child.type) || childCategory !== void 0 && def.allowedChildren.includes(childCategory);
72
- if (!allowed) {
73
- errors.push(`Component "${node.type}" does not allow child type "${child.type}".`);
74
- }
75
- }
76
- }
77
- if (parentType && def.disallowedParents?.includes(parentType)) {
78
- errors.push(`Component "${node.type}" is not allowed inside parent "${parentType}".`);
79
- }
80
- if (def.validateProps && node.props) {
81
- const propResult = def.validateProps(node.props);
82
- if (Array.isArray(propResult) && propResult.length > 0) {
83
- errors.push(...propResult);
84
- } else if (propResult === false) {
85
- errors.push(`Props validation failed for component "${node.type}".`);
86
- }
87
- }
88
- return { valid: errors.length === 0, errors };
89
- }
90
- };
91
-
92
- // src/definitions.ts
93
- import { isActionBinding, isAssetReference, isVariableBinding } from "@kubuild/schema";
94
-
95
- // src/traits.ts
96
- var TRAIT_GROUP_ORDER = [
97
- "identity",
98
- "link",
99
- "media",
100
- "form",
101
- "behavior",
102
- "semantic",
103
- "accessibility"
104
- ];
105
- var TRAIT_GROUP_LABELS = {
106
- identity: "Identity",
107
- link: "Link",
108
- media: "Media",
109
- form: "Form",
110
- behavior: "Behavior",
111
- semantic: "Semantic",
112
- accessibility: "Accessibility"
113
- };
114
- function withOverrides(base, overrides) {
115
- return overrides ? { ...base, ...overrides } : base;
116
- }
117
- function hrefTrait(overrides) {
118
- return withOverrides(
119
- {
120
- name: "href",
121
- label: "Link URL",
122
- type: "string",
123
- defaultValue: "#",
124
- attribute: "href",
125
- group: "link",
126
- description: "The destination URL the element navigates to when activated."
127
- },
128
- overrides
129
- );
130
- }
131
- function targetTrait(overrides) {
132
- return withOverrides(
133
- {
134
- name: "target",
135
- label: "Open In",
136
- type: "select",
137
- defaultValue: "_self",
138
- attribute: "target",
139
- group: "link",
140
- options: [
141
- { label: "Same tab (_self)", value: "_self" },
142
- { label: "New tab (_blank)", value: "_blank" },
143
- { label: "Parent frame (_parent)", value: "_parent" },
144
- { label: "Top frame (_top)", value: "_top" }
145
- ],
146
- description: "Where the linked resource should open."
147
- },
148
- overrides
149
- );
150
- }
151
- function relTrait(overrides) {
152
- return withOverrides(
153
- {
154
- name: "rel",
155
- label: "Relationship (rel)",
156
- type: "string",
157
- defaultValue: "",
158
- attribute: "rel",
159
- group: "link",
160
- description: 'Space-separated relationship tokens (e.g. "noopener noreferrer").'
161
- },
162
- overrides
163
- );
164
- }
165
- function altTrait(overrides) {
166
- return withOverrides(
167
- {
168
- name: "alt",
169
- label: "Alt Text",
170
- type: "string",
171
- attribute: "alt",
172
- group: "accessibility",
173
- required: true,
174
- description: "Alternative text describing the media for screen readers and fallback."
175
- },
176
- overrides
177
- );
178
- }
179
- function titleTrait(overrides) {
180
- return withOverrides(
181
- {
182
- name: "title",
183
- label: "Title",
184
- type: "string",
185
- attribute: "title",
186
- group: "semantic",
187
- description: "Advisory title for the element (tooltip / document title)."
188
- },
189
- overrides
190
- );
191
- }
192
- function placeholderTrait(overrides) {
193
- return withOverrides(
194
- {
195
- name: "placeholder",
196
- label: "Placeholder",
197
- type: "string",
198
- attribute: "placeholder",
199
- group: "form",
200
- description: "Hint text shown inside the control when it is empty."
201
- },
202
- overrides
203
- );
204
- }
205
- function ariaLabelTrait(overrides) {
206
- return withOverrides(
207
- {
208
- name: "ariaLabel",
209
- label: "Accessible Label (aria-label)",
210
- type: "string",
211
- attribute: "aria-label",
212
- group: "accessibility",
213
- description: "Accessible name for assistive technology when no visible label exists."
214
- },
215
- overrides
216
- );
217
- }
218
- function idTrait(overrides) {
219
- return withOverrides(
220
- {
221
- name: "id",
222
- label: "Element ID",
223
- type: "string",
224
- attribute: "id",
225
- group: "identity",
226
- description: "A custom, document-unique identifier used for anchors, CSS, and scripting."
227
- },
228
- overrides
229
- );
230
- }
231
- function fieldNameTrait(overrides) {
232
- return withOverrides(
233
- {
234
- name: "name",
235
- label: "Field Name",
236
- type: "string",
237
- attribute: "name",
238
- group: "form",
239
- required: true,
240
- description: "The name submitted with the form data for this field."
241
- },
242
- overrides
243
- );
244
- }
245
- function requiredTrait(overrides) {
246
- return withOverrides(
247
- {
248
- name: "required",
249
- label: "Required",
250
- type: "boolean",
251
- defaultValue: false,
252
- attribute: "required",
253
- group: "form",
254
- description: "Whether the field must be filled before the form can be submitted."
255
- },
256
- overrides
257
- );
258
- }
259
- function disabledTrait(overrides) {
260
- return withOverrides(
261
- {
262
- name: "disabled",
263
- label: "Disabled",
264
- type: "boolean",
265
- defaultValue: false,
266
- attribute: "disabled",
267
- group: "behavior",
268
- description: "Disables the control so it cannot be focused or activated."
269
- },
270
- overrides
271
- );
272
- }
273
- function readOnlyTrait(overrides) {
274
- return withOverrides(
275
- {
276
- name: "readOnly",
277
- label: "Read Only",
278
- type: "boolean",
279
- defaultValue: false,
280
- attribute: "readonly",
281
- group: "behavior",
282
- description: "Prevents the user from modifying the control value."
283
- },
284
- overrides
285
- );
286
- }
287
- function srcTrait(overrides) {
288
- return withOverrides(
289
- {
290
- name: "src",
291
- label: "Source URL",
292
- type: "string",
293
- attribute: "src",
294
- group: "media",
295
- required: true,
296
- description: "The source URL of the media resource."
297
- },
298
- overrides
299
- );
300
- }
301
- function posterTrait(overrides) {
302
- return withOverrides(
303
- {
304
- name: "poster",
305
- label: "Poster Image URL",
306
- type: "string",
307
- attribute: "poster",
308
- group: "media",
309
- description: "A preview image shown before the video starts playing."
310
- },
311
- overrides
312
- );
313
- }
314
- function controlsTrait(overrides) {
315
- return withOverrides(
316
- {
317
- name: "controls",
318
- label: "Show Controls",
319
- type: "boolean",
320
- defaultValue: true,
321
- attribute: "controls",
322
- group: "media",
323
- description: "Whether to show the native play/pause/volume controls."
324
- },
325
- overrides
326
- );
327
- }
328
- function autoplayTrait(overrides) {
329
- return withOverrides(
330
- {
331
- name: "autoplay",
332
- label: "Autoplay",
333
- type: "boolean",
334
- defaultValue: false,
335
- attribute: "autoplay",
336
- group: "media",
337
- description: "Whether the media starts playing automatically on load."
338
- },
339
- overrides
340
- );
341
- }
342
- function loopTrait(overrides) {
343
- return withOverrides(
344
- {
345
- name: "loop",
346
- label: "Loop",
347
- type: "boolean",
348
- defaultValue: false,
349
- attribute: "loop",
350
- group: "media",
351
- description: "Whether the media restarts automatically when it reaches the end."
352
- },
353
- overrides
354
- );
355
- }
356
- function mutedTrait(overrides) {
357
- return withOverrides(
358
- {
359
- name: "muted",
360
- label: "Muted",
361
- type: "boolean",
362
- defaultValue: false,
363
- attribute: "muted",
364
- group: "media",
365
- description: "Whether the media starts with the audio muted."
366
- },
367
- overrides
368
- );
369
- }
370
- function citeTrait(overrides) {
371
- return withOverrides(
372
- {
373
- name: "cite",
374
- label: "Citation URL (cite)",
375
- type: "string",
376
- attribute: "cite",
377
- group: "semantic",
378
- description: "The URL of the source document the quote is taken from."
379
- },
380
- overrides
381
- );
382
- }
383
- function loadingTrait(overrides) {
384
- return withOverrides(
385
- {
386
- name: "loading",
387
- label: "Loading Mode",
388
- type: "select",
389
- defaultValue: "lazy",
390
- attribute: "loading",
391
- group: "media",
392
- options: [
393
- { label: "Lazy (load when near viewport)", value: "lazy" },
394
- { label: "Eager (load immediately)", value: "eager" }
395
- ],
396
- description: "Native loading hint: lazy defers offscreen images, eager loads immediately."
397
- },
398
- overrides
399
- );
400
- }
401
- function actionTrait(overrides) {
402
- return withOverrides(
403
- {
404
- name: "action",
405
- label: "Action URL",
406
- type: "string",
407
- attribute: "action",
408
- group: "form",
409
- description: "The URL the form data is submitted to."
410
- },
411
- overrides
412
- );
413
- }
414
- function methodTrait(overrides) {
415
- return withOverrides(
416
- {
417
- name: "method",
418
- label: "Method",
419
- type: "select",
420
- defaultValue: "POST",
421
- attribute: "method",
422
- group: "form",
423
- options: [
424
- { label: "POST", value: "POST" },
425
- { label: "GET", value: "GET" }
426
- ],
427
- description: "The HTTP method used to submit the form."
428
- },
429
- overrides
430
- );
431
- }
432
- function autoCompleteTrait(overrides) {
433
- return withOverrides(
434
- {
435
- name: "autoComplete",
436
- label: "Auto Complete",
437
- type: "select",
438
- defaultValue: "on",
439
- attribute: "autocomplete",
440
- group: "form",
441
- options: [
442
- { label: "On", value: "on" },
443
- { label: "Off", value: "off" }
444
- ],
445
- description: "Whether the browser may autofill values for this form."
446
- },
447
- overrides
448
- );
449
- }
450
- function valueTrait(overrides) {
451
- return withOverrides(
452
- {
453
- name: "value",
454
- label: "Value",
455
- type: "string",
456
- attribute: "value",
457
- group: "form",
458
- description: "The value submitted with the form data when the control is selected."
459
- },
460
- overrides
461
- );
462
- }
463
- function defaultCheckedTrait(overrides) {
464
- return withOverrides(
465
- {
466
- name: "defaultChecked",
467
- label: "Default Checked",
468
- type: "boolean",
469
- defaultValue: false,
470
- attribute: "checked",
471
- group: "form",
472
- description: "Whether the control starts in the checked state."
473
- },
474
- overrides
475
- );
476
- }
477
- function defaultValueTrait(overrides) {
478
- return withOverrides(
479
- {
480
- name: "defaultValue",
481
- label: "Default Value",
482
- type: "string",
483
- attribute: "value",
484
- group: "form",
485
- description: "The initial value of the control before the user edits it."
486
- },
487
- overrides
488
- );
489
- }
490
- function rowsTrait(overrides) {
491
- return withOverrides(
492
- {
493
- name: "rows",
494
- label: "Rows",
495
- type: "number",
496
- defaultValue: 4,
497
- attribute: "rows",
498
- group: "form",
499
- description: "The number of visible text lines in the textarea."
500
- },
501
- overrides
502
- );
503
- }
504
- function colSpanTrait(overrides) {
505
- return withOverrides(
506
- {
507
- name: "colSpan",
508
- label: "Column Span (colSpan)",
509
- type: "number",
510
- defaultValue: 1,
511
- attribute: "colspan",
512
- group: "semantic",
513
- description: "The number of columns the cell spans."
514
- },
515
- overrides
516
- );
517
- }
518
- function rowSpanTrait(overrides) {
519
- return withOverrides(
520
- {
521
- name: "rowSpan",
522
- label: "Row Span (rowSpan)",
523
- type: "number",
524
- defaultValue: 1,
525
- attribute: "rowspan",
526
- group: "semantic",
527
- description: "The number of rows the cell spans."
528
- },
529
- overrides
530
- );
531
- }
532
- function tagTrait(overrides) {
533
- return withOverrides(
534
- {
535
- name: "tag",
536
- label: "HTML Tag",
537
- type: "select",
538
- attribute: "tag",
539
- group: "semantic",
540
- description: "The semantic HTML tag the component renders as."
541
- },
542
- overrides
543
- );
544
- }
545
- function inputTypeTrait(overrides) {
546
- return withOverrides(
547
- {
548
- name: "type",
549
- label: "Input Type",
550
- type: "select",
551
- defaultValue: "text",
552
- attribute: "type",
553
- group: "form",
554
- description: "The semantic input type of the control."
555
- },
556
- overrides
557
- );
558
- }
559
- function buttonTypeTrait(overrides) {
560
- return withOverrides(
561
- {
562
- name: "buttonType",
563
- label: "Button Type",
564
- type: "select",
565
- defaultValue: "button",
566
- attribute: "type",
567
- group: "form",
568
- options: [
569
- { label: "Button", value: "button" },
570
- { label: "Submit Form (submit)", value: "submit" },
571
- { label: "Reset Form (reset)", value: "reset" }
572
- ],
573
- description: "The button\u2019s behavior inside a form."
574
- },
575
- overrides
576
- );
577
- }
578
- function sortTraits(traits) {
579
- const groupRank = (group) => {
580
- if (!group) return Number.MAX_SAFE_INTEGER;
581
- const idx = TRAIT_GROUP_ORDER.indexOf(group);
582
- return idx === -1 ? Number.MAX_SAFE_INTEGER : idx;
583
- };
584
- return [...traits].sort((a, b) => groupRank(a.group) - groupRank(b.group));
585
- }
586
- function collectTraitNames(traitsList) {
587
- const names = /* @__PURE__ */ new Set();
588
- for (const traits of traitsList) {
589
- for (const trait of traits) {
590
- names.add(trait.name);
591
- }
592
- }
593
- return Array.from(names);
594
- }
595
-
596
- // src/definitions.ts
597
- var LAYOUT_PARENTS = ["page", "section", "container", "columns"];
598
- var CONTENT_CHILD_TYPES = [
599
- "heading",
600
- "text",
601
- "paragraph",
602
- "link",
603
- "blockquote",
604
- "badge",
605
- "code-block",
606
- "image",
607
- "video",
608
- "icon",
609
- "html-embed",
610
- "button",
611
- "form",
612
- "input",
613
- "textarea",
614
- "select",
615
- "checkbox",
616
- "radio",
617
- "list",
618
- "table",
619
- "collection",
620
- "custom"
621
- ];
622
- var pageDefinition = {
623
- type: "page",
624
- label: "Page",
625
- category: "layout",
626
- icon: "layout",
627
- acceptsChildren: true,
628
- allowedChildren: ["section", "custom"],
629
- disallowedParents: [...LAYOUT_PARENTS, ...CONTENT_CHILD_TYPES, "list-item", "table-row", "table-cell"],
630
- defaultProps: { title: "New Page" },
631
- traits: [
632
- titleTrait({ defaultValue: "New Page", description: "The document title shown in the browser tab and search results." }),
633
- idTrait()
634
- ],
635
- defaultStyles: { base: { minHeight: "100vh", backgroundColor: "#ffffff" } }
636
- };
637
- var sectionDefinition = {
638
- type: "section",
639
- label: "Section",
640
- category: "layout",
641
- icon: "rows",
642
- acceptsChildren: true,
643
- allowedChildren: ["container", "columns", ...CONTENT_CHILD_TYPES],
644
- defaultProps: {},
645
- traits: [
646
- idTrait(),
647
- ariaLabelTrait({ description: "Accessible name for the section landmark." })
648
- ],
649
- defaultStyles: {
650
- base: {
651
- paddingTop: "48px",
652
- paddingBottom: "48px",
653
- paddingLeft: "16px",
654
- paddingRight: "16px"
655
- },
656
- tablet: {
657
- paddingTop: "32px",
658
- paddingBottom: "32px"
659
- },
660
- mobile: {
661
- paddingTop: "24px",
662
- paddingBottom: "24px",
663
- paddingLeft: "16px",
664
- paddingRight: "16px"
665
- }
666
- }
667
- };
668
- var containerDefinition = {
669
- type: "container",
670
- label: "Container",
671
- category: "layout",
672
- icon: "box",
673
- acceptsChildren: true,
674
- allowedChildren: ["columns", ...CONTENT_CHILD_TYPES],
675
- defaultProps: { maxWidth: "1200px" },
676
- traits: [
677
- idTrait()
678
- ],
679
- defaultStyles: {
680
- base: {
681
- maxWidth: "1200px",
682
- margin: "0 auto",
683
- width: "100%"
684
- },
685
- tablet: {
686
- maxWidth: "720px"
687
- },
688
- mobile: {
689
- maxWidth: "100%",
690
- paddingLeft: "16px",
691
- paddingRight: "16px"
692
- }
693
- }
694
- };
695
- var columnsDefinition = {
696
- type: "columns",
697
- label: "Columns",
698
- category: "layout",
699
- icon: "columns",
700
- acceptsChildren: true,
701
- allowedChildren: ["container", ...CONTENT_CHILD_TYPES],
702
- defaultProps: { columns: 2, gap: "16px" },
703
- traits: [
704
- idTrait()
705
- ],
706
- defaultStyles: {
707
- base: {
708
- display: "grid",
709
- gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
710
- gap: "16px"
711
- },
712
- tablet: {
713
- gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
714
- gap: "12px"
715
- },
716
- mobile: {
717
- gridTemplateColumns: "repeat(1, minmax(0, 1fr))",
718
- gap: "12px"
719
- }
720
- }
721
- };
722
- var headingDefinition = {
723
- type: "heading",
724
- label: "Heading",
725
- category: "typography",
726
- icon: "heading",
727
- acceptsChildren: false,
728
- defaultProps: { text: "Heading Text", level: 2 },
729
- propFields: [
730
- { name: "text", label: "Text", type: "string", defaultValue: "Heading Text" },
731
- {
732
- name: "level",
733
- label: "Heading Level",
734
- type: "select",
735
- defaultValue: 2,
736
- options: [1, 2, 3, 4, 5, 6].map((level) => ({ label: `H${level}`, value: level }))
737
- }
738
- ],
739
- traits: [
740
- idTrait(),
741
- titleTrait({ description: "Advisory title shown when hovering the heading." }),
742
- ariaLabelTrait()
743
- ],
744
- validateProps: (props) => {
745
- const errors = [];
746
- if (!isVariableBinding(props.text) && (typeof props.text !== "string" || props.text.trim().length === 0)) {
747
- errors.push('Heading requires a non-empty "text".');
748
- }
749
- if (props.level !== void 0 && (typeof props.level !== "number" || props.level < 1 || props.level > 6)) {
750
- errors.push('Heading "level" must be a number between 1 and 6.');
751
- }
752
- return errors.length > 0 ? errors : true;
753
- },
754
- defaultStyles: {
755
- base: {
756
- fontSize: "32px",
757
- fontWeight: "700",
758
- color: "#111827",
759
- margin: "0 0 16px 0"
760
- }
761
- }
762
- };
763
- var textDefinition = {
764
- type: "text",
765
- label: "Text",
766
- category: "typography",
767
- icon: "type",
768
- acceptsChildren: false,
769
- defaultProps: { content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." },
770
- propFields: [
771
- { name: "content", label: "Content", type: "string", defaultValue: "Lorem ipsum dolor sit amet." }
772
- ],
773
- traits: [
774
- idTrait(),
775
- titleTrait(),
776
- ariaLabelTrait()
777
- ],
778
- validateProps: (props) => {
779
- if (!isVariableBinding(props.content) && (typeof props.content !== "string" || props.content.trim().length === 0)) {
780
- return ['Text requires a non-empty "content".'];
781
- }
782
- return true;
783
- },
784
- defaultStyles: {
785
- base: {
786
- fontSize: "16px",
787
- color: "#4b5563",
788
- lineHeight: "1.6"
789
- }
790
- }
791
- };
792
- var imageDefinition = {
793
- type: "image",
794
- label: "Image",
795
- category: "media",
796
- icon: "image",
797
- acceptsChildren: false,
798
- capabilities: ["assetProvider"],
799
- defaultProps: {
800
- src: "https://images.unsplash.com/photo-1579546929518-9e396f3cc809?w=800&auto=format&fit=crop&q=80",
801
- alt: "Default image",
802
- width: 600,
803
- height: 400
804
- },
805
- propFields: [
806
- { name: "src", label: "Image URL", type: "string" },
807
- { name: "asset", label: "Asset Reference", type: "json" },
808
- { name: "alt", label: "Alt Text", type: "string", defaultValue: "Default image" },
809
- { name: "width", label: "Width", type: "number" },
810
- { name: "height", label: "Height", type: "number" }
811
- ],
812
- traits: [
813
- srcTrait(),
814
- altTrait({ defaultValue: "Default image" }),
815
- loadingTrait(),
816
- idTrait(),
817
- titleTrait(),
818
- ariaLabelTrait({ description: "Override the alt text for assistive technology (rarely needed)." })
819
- ],
820
- validateProps: (props) => {
821
- const errors = [];
822
- const hasSrc = typeof props.src === "string" && props.src.trim().length > 0 || isVariableBinding(props.src);
823
- const hasAsset = isAssetReference(props.asset);
824
- if (!hasSrc && !hasAsset) {
825
- errors.push('Image requires either a non-empty "src" URL or a valid "asset" reference.');
826
- }
827
- const hasAlt = typeof props.alt === "string" && props.alt.trim().length > 0 || isVariableBinding(props.alt);
828
- if (!hasAlt) {
829
- errors.push('Image requires non-empty "alt" text.');
830
- }
831
- return errors.length > 0 ? errors : true;
832
- },
833
- defaultStyles: {
834
- base: {
835
- maxWidth: "100%",
836
- height: "auto",
837
- borderRadius: "8px"
838
- }
839
- }
840
- };
841
- var buttonDefinition = {
842
- type: "button",
843
- label: "Button",
844
- category: "interactive",
845
- icon: "mouse-pointer",
846
- acceptsChildren: false,
847
- capabilities: ["actionRegistry"],
848
- defaultProps: {
849
- label: "Click Me",
850
- variant: "primary"
851
- },
852
- propFields: [
853
- { name: "label", label: "Label", type: "string", defaultValue: "Click Me" },
854
- { name: "href", label: "Link URL", type: "string" },
855
- { name: "action", label: "Action", type: "action" },
856
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
857
- {
858
- name: "buttonType",
859
- label: "Button Type",
860
- type: "select",
861
- defaultValue: "button",
862
- options: [
863
- { label: "Button", value: "button" },
864
- { label: "Submit Form (submit)", value: "submit" },
865
- { label: "Reset Form (reset)", value: "reset" }
866
- ]
867
- },
868
- {
869
- name: "variant",
870
- label: "Variant",
871
- type: "select",
872
- defaultValue: "primary",
873
- options: [
874
- { label: "Primary", value: "primary" },
875
- { label: "Secondary", value: "secondary" }
876
- ]
877
- }
878
- ],
879
- traits: [
880
- buttonTypeTrait(),
881
- disabledTrait(),
882
- hrefTrait({ description: "Optional URL \u2014 when set, the button renders as an anchor styled like a button." }),
883
- targetTrait({ description: "Where to open the href URL (only used when href is set)." }),
884
- relTrait({ description: "Relationship tokens (only used when href is set)." }),
885
- idTrait(),
886
- titleTrait(),
887
- ariaLabelTrait()
888
- ],
889
- validateProps: (props) => {
890
- const errors = [];
891
- const hasLabel = typeof props.label === "string" && props.label.trim().length > 0 || isVariableBinding(props.label);
892
- if (!hasLabel) {
893
- errors.push('Button requires a non-empty "label".');
894
- }
895
- if (props.href !== void 0 && typeof props.href !== "string" && !isVariableBinding(props.href)) {
896
- errors.push('Button "href" must be a string when provided.');
897
- }
898
- if (props.buttonType !== void 0 && !isVariableBinding(props.buttonType)) {
899
- if (!["button", "submit", "reset"].includes(props.buttonType)) {
900
- errors.push('Button "buttonType" must be one of: "button", "submit", "reset".');
901
- }
902
- }
903
- if (props.action !== void 0 && !isActionBinding(props.action)) {
904
- errors.push('Button "action" must be a valid action binding when provided.');
905
- }
906
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
907
- errors.push('Button "disabled" must be a boolean when provided.');
908
- }
909
- return errors.length > 0 ? errors : true;
910
- },
911
- defaultStyles: {
912
- base: {
913
- backgroundColor: "#2563eb",
914
- color: "#ffffff",
915
- paddingTop: "10px",
916
- paddingBottom: "10px",
917
- paddingLeft: "20px",
918
- paddingRight: "20px",
919
- borderRadius: "6px",
920
- fontWeight: "500",
921
- fontSize: "15px",
922
- border: "none",
923
- cursor: "pointer"
924
- }
925
- }
926
- };
927
- var collectionDefinition = {
928
- type: "collection",
929
- label: "Collection",
930
- category: "data",
931
- icon: "database",
932
- acceptsChildren: true,
933
- defaultProps: {
934
- sourceKey: "items",
935
- itemAlias: "item"
936
- },
937
- propFields: [
938
- { name: "sourceKey", label: "Source Variable", type: "string", defaultValue: "items" },
939
- { name: "itemAlias", label: "Item Alias", type: "string", defaultValue: "item" }
940
- ],
941
- traits: [
942
- idTrait(),
943
- ariaLabelTrait({ description: 'Accessible name summarizing the repeated collection (e.g. "Product list").' })
944
- ]
945
- };
946
- var listDefinition = {
947
- type: "list",
948
- label: "List",
949
- category: "typography",
950
- icon: "list",
951
- acceptsChildren: true,
952
- allowedChildren: ["list-item"],
953
- defaultProps: {
954
- tag: "ul",
955
- listStyleType: "disc"
956
- },
957
- defaultChildren: [
958
- { type: "list-item", props: { text: "List item 1" } },
959
- { type: "list-item", props: { text: "List item 2" } },
960
- { type: "list-item", props: { text: "List item 3" } }
961
- ],
962
- propFields: [
963
- {
964
- name: "tag",
965
- label: "Tag",
966
- type: "select",
967
- defaultValue: "ul",
968
- options: [
969
- { label: "Unordered (ul)", value: "ul" },
970
- { label: "Ordered (ol)", value: "ol" }
971
- ]
972
- },
973
- {
974
- name: "listStyleType",
975
- label: "List Style Type",
976
- type: "select",
977
- defaultValue: "disc",
978
- options: [
979
- { label: "Disc", value: "disc" },
980
- { label: "Circle", value: "circle" },
981
- { label: "Square", value: "square" },
982
- { label: "Decimal", value: "decimal" },
983
- { label: "None", value: "none" },
984
- { label: "Custom Icon", value: "custom-icon" }
985
- ]
986
- }
987
- ],
988
- traits: [
989
- idTrait(),
990
- ariaLabelTrait({ description: 'Accessible name for the list (e.g. "Navigation menu", "Features").' })
991
- ],
992
- validateProps: (props) => {
993
- const errors = [];
994
- if (props.tag !== void 0 && !isVariableBinding(props.tag)) {
995
- if (props.tag !== "ul" && props.tag !== "ol") {
996
- errors.push('List "tag" must be either "ul" or "ol".');
997
- }
998
- }
999
- if (props.listStyleType !== void 0 && !isVariableBinding(props.listStyleType)) {
1000
- const allowed = ["disc", "circle", "square", "decimal", "none", "custom-icon"];
1001
- if (typeof props.listStyleType !== "string" || !allowed.includes(props.listStyleType)) {
1002
- errors.push(`List "listStyleType" must be one of: ${allowed.join(", ")}.`);
1003
- }
1004
- }
1005
- return errors.length > 0 ? errors : true;
1006
- },
1007
- defaultStyles: {
1008
- base: {
1009
- margin: "0 0 16px 0",
1010
- paddingLeft: "24px"
1011
- }
1012
- }
1013
- };
1014
- var listItemDefinition = {
1015
- type: "list-item",
1016
- label: "List Item",
1017
- category: "typography",
1018
- icon: "list-item",
1019
- acceptsChildren: true,
1020
- allowedChildren: [
1021
- "heading",
1022
- "text",
1023
- "paragraph",
1024
- "link",
1025
- "blockquote",
1026
- "badge",
1027
- "code-block",
1028
- "image",
1029
- "video",
1030
- "icon",
1031
- "html-embed",
1032
- "button",
1033
- "list",
1034
- "custom"
1035
- ],
1036
- defaultProps: {
1037
- text: "List item"
1038
- },
1039
- propFields: [
1040
- {
1041
- name: "text",
1042
- label: "Text",
1043
- type: "string",
1044
- defaultValue: "List item"
1045
- }
1046
- ],
1047
- traits: [
1048
- idTrait(),
1049
- titleTrait(),
1050
- ariaLabelTrait()
1051
- ],
1052
- validateProps: (props) => {
1053
- const errors = [];
1054
- if (props.text !== void 0 && typeof props.text !== "string" && !isVariableBinding(props.text)) {
1055
- errors.push('List Item "text" must be a string when provided.');
1056
- }
1057
- return errors.length > 0 ? errors : true;
1058
- },
1059
- defaultStyles: {
1060
- base: {
1061
- margin: "4px 0",
1062
- fontSize: "16px",
1063
- color: "#374151",
1064
- lineHeight: "1.5"
1065
- }
1066
- }
1067
- };
1068
- var paragraphDefinition = {
1069
- type: "paragraph",
1070
- label: "Paragraph",
1071
- category: "typography",
1072
- icon: "paragraph",
1073
- acceptsChildren: false,
1074
- defaultProps: {
1075
- text: "A paragraph of text with clean semantic typography."
1076
- },
1077
- propFields: [
1078
- {
1079
- name: "text",
1080
- label: "Text",
1081
- type: "string",
1082
- defaultValue: "A paragraph of text with clean semantic typography."
1083
- }
1084
- ],
1085
- traits: [
1086
- idTrait(),
1087
- titleTrait(),
1088
- ariaLabelTrait()
1089
- ],
1090
- validateProps: (props) => {
1091
- const errors = [];
1092
- const textVal = props.text ?? props.content;
1093
- if (textVal !== void 0 && !isVariableBinding(textVal) && (typeof textVal !== "string" || textVal.trim().length === 0)) {
1094
- errors.push('Paragraph requires a non-empty "text".');
1095
- }
1096
- return errors.length > 0 ? errors : true;
1097
- },
1098
- defaultStyles: {
1099
- base: {
1100
- fontSize: "16px",
1101
- color: "#4b5563",
1102
- lineHeight: "1.6",
1103
- margin: "0 0 16px 0"
1104
- }
1105
- }
1106
- };
1107
- var linkDefinition = {
1108
- type: "link",
1109
- label: "Link",
1110
- category: "typography",
1111
- icon: "link",
1112
- acceptsChildren: false,
1113
- defaultProps: {
1114
- text: "Click here",
1115
- href: "#",
1116
- target: "_self",
1117
- rel: ""
1118
- },
1119
- propFields: [
1120
- { name: "text", label: "Link Text", type: "string", defaultValue: "Click here" },
1121
- { name: "href", label: "URL (href)", type: "string", defaultValue: "#" },
1122
- {
1123
- name: "target",
1124
- label: "Target",
1125
- type: "select",
1126
- defaultValue: "_self",
1127
- options: [
1128
- { label: "Same tab (_self)", value: "_self" },
1129
- { label: "New tab (_blank)", value: "_blank" },
1130
- { label: "Parent (_parent)", value: "_parent" },
1131
- { label: "Top (_top)", value: "_top" }
1132
- ]
1133
- },
1134
- { name: "rel", label: "Relationship (rel)", type: "string", defaultValue: "" }
1135
- ],
1136
- traits: [
1137
- hrefTrait(),
1138
- targetTrait(),
1139
- relTrait(),
1140
- idTrait(),
1141
- titleTrait({ description: "Advisory title shown when hovering the link." }),
1142
- ariaLabelTrait()
1143
- ],
1144
- validateProps: (props) => {
1145
- const errors = [];
1146
- if (props.text !== void 0 && !isVariableBinding(props.text) && (typeof props.text !== "string" || props.text.trim().length === 0)) {
1147
- errors.push('Link requires a non-empty "text".');
1148
- }
1149
- if (props.href !== void 0 && typeof props.href !== "string" && !isVariableBinding(props.href)) {
1150
- errors.push('Link "href" must be a string when provided.');
1151
- }
1152
- if (props.target !== void 0 && !isVariableBinding(props.target)) {
1153
- const allowedTargets = ["_self", "_blank", "_parent", "_top"];
1154
- if (typeof props.target !== "string" || !allowedTargets.includes(props.target)) {
1155
- errors.push(`Link "target" must be one of: ${allowedTargets.join(", ")}.`);
1156
- }
1157
- }
1158
- if (props.rel !== void 0 && typeof props.rel !== "string" && !isVariableBinding(props.rel)) {
1159
- errors.push('Link "rel" must be a string when provided.');
1160
- }
1161
- return errors.length > 0 ? errors : true;
1162
- },
1163
- defaultStyles: {
1164
- base: {
1165
- color: "#2563eb",
1166
- textDecoration: "underline",
1167
- cursor: "pointer"
1168
- }
1169
- }
1170
- };
1171
- var blockquoteDefinition = {
1172
- type: "blockquote",
1173
- label: "Blockquote",
1174
- category: "typography",
1175
- icon: "blockquote",
1176
- acceptsChildren: true,
1177
- allowedChildren: [
1178
- "paragraph",
1179
- "text",
1180
- "heading",
1181
- "link",
1182
- "badge",
1183
- "code-block",
1184
- "image",
1185
- "video",
1186
- "icon",
1187
- "html-embed",
1188
- "custom"
1189
- ],
1190
- defaultProps: {
1191
- text: "\u201CSimplicity is the soul of efficiency.\u201D"
1192
- },
1193
- propFields: [
1194
- {
1195
- name: "text",
1196
- label: "Quote Text",
1197
- type: "string",
1198
- defaultValue: "\u201CSimplicity is the soul of efficiency.\u201D"
1199
- },
1200
- { name: "cite", label: "Citation URL (cite)", type: "string" }
1201
- ],
1202
- traits: [
1203
- citeTrait(),
1204
- idTrait(),
1205
- titleTrait(),
1206
- ariaLabelTrait()
1207
- ],
1208
- validateProps: (props) => {
1209
- const errors = [];
1210
- if (props.text !== void 0 && typeof props.text !== "string" && !isVariableBinding(props.text)) {
1211
- errors.push('Blockquote "text" must be a string when provided.');
1212
- }
1213
- if (props.cite !== void 0 && typeof props.cite !== "string" && !isVariableBinding(props.cite)) {
1214
- errors.push('Blockquote "cite" must be a string when provided.');
1215
- }
1216
- return errors.length > 0 ? errors : true;
1217
- },
1218
- defaultStyles: {
1219
- base: {
1220
- borderLeftWidth: "4px",
1221
- borderLeftColor: "#3b82f6",
1222
- borderLeftStyle: "solid",
1223
- paddingTop: "8px",
1224
- paddingBottom: "8px",
1225
- paddingLeft: "16px",
1226
- paddingRight: "12px",
1227
- margin: "0 0 16px 0",
1228
- fontStyle: "italic",
1229
- color: "#4b5563",
1230
- backgroundColor: "#f8fafc"
1231
- }
1232
- }
1233
- };
1234
- var badgeDefinition = {
1235
- type: "badge",
1236
- label: "Badge",
1237
- category: "typography",
1238
- icon: "badge",
1239
- acceptsChildren: false,
1240
- defaultProps: {
1241
- text: "Badge",
1242
- variant: "default"
1243
- },
1244
- propFields: [
1245
- { name: "text", label: "Badge Text", type: "string", defaultValue: "Badge" },
1246
- {
1247
- name: "variant",
1248
- label: "Variant",
1249
- type: "select",
1250
- defaultValue: "default",
1251
- options: [
1252
- { label: "Default", value: "default" },
1253
- { label: "Success", value: "success" },
1254
- { label: "Warning", value: "warning" },
1255
- { label: "Danger", value: "danger" },
1256
- { label: "Info", value: "info" }
1257
- ]
1258
- }
1259
- ],
1260
- traits: [
1261
- idTrait(),
1262
- titleTrait(),
1263
- ariaLabelTrait()
1264
- ],
1265
- validateProps: (props) => {
1266
- const errors = [];
1267
- if (props.text !== void 0 && !isVariableBinding(props.text) && (typeof props.text !== "string" || props.text.trim().length === 0)) {
1268
- errors.push('Badge requires a non-empty "text".');
1269
- }
1270
- if (props.variant !== void 0 && typeof props.variant !== "string" && !isVariableBinding(props.variant)) {
1271
- errors.push('Badge "variant" must be a string.');
1272
- }
1273
- return errors.length > 0 ? errors : true;
1274
- },
1275
- defaultStyles: {
1276
- base: {
1277
- display: "inline-flex",
1278
- alignItems: "center",
1279
- paddingLeft: "10px",
1280
- paddingRight: "10px",
1281
- paddingTop: "2px",
1282
- paddingBottom: "2px",
1283
- borderRadius: "9999px",
1284
- fontSize: "12px",
1285
- fontWeight: "500",
1286
- lineHeight: "1.4",
1287
- backgroundColor: "#e0e7ff",
1288
- color: "#3730a3"
1289
- }
1290
- }
1291
- };
1292
- var codeBlockDefinition = {
1293
- type: "code-block",
1294
- label: "Code Block",
1295
- category: "typography",
1296
- icon: "code-block",
1297
- acceptsChildren: false,
1298
- defaultProps: {
1299
- code: 'console.log("Hello, world!");',
1300
- language: "javascript"
1301
- },
1302
- propFields: [
1303
- {
1304
- name: "code",
1305
- label: "Code",
1306
- type: "textarea",
1307
- defaultValue: 'console.log("Hello, world!");'
1308
- },
1309
- {
1310
- name: "language",
1311
- label: "Language",
1312
- type: "string",
1313
- defaultValue: "javascript"
1314
- }
1315
- ],
1316
- traits: [
1317
- idTrait(),
1318
- titleTrait(),
1319
- ariaLabelTrait({ description: "Accessible label describing what the code example shows." })
1320
- ],
1321
- validateProps: (props) => {
1322
- const errors = [];
1323
- if (props.code !== void 0 && typeof props.code !== "string" && !isVariableBinding(props.code)) {
1324
- errors.push('Code Block "code" must be a string when provided.');
1325
- }
1326
- if (props.language !== void 0 && typeof props.language !== "string" && !isVariableBinding(props.language)) {
1327
- errors.push('Code Block "language" must be a string when provided.');
1328
- }
1329
- return errors.length > 0 ? errors : true;
1330
- },
1331
- defaultStyles: {
1332
- base: {
1333
- backgroundColor: "#1e293b",
1334
- color: "#f8fafc",
1335
- padding: "16px",
1336
- borderRadius: "8px",
1337
- fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
1338
- fontSize: "14px",
1339
- lineHeight: "1.5",
1340
- overflowX: "auto",
1341
- margin: "0 0 16px 0",
1342
- whiteSpace: "pre"
1343
- }
1344
- }
1345
- };
1346
- var videoDefinition = {
1347
- type: "video",
1348
- label: "Video",
1349
- category: "media",
1350
- icon: "video",
1351
- acceptsChildren: false,
1352
- defaultProps: {
1353
- src: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
1354
- provider: "auto",
1355
- poster: "",
1356
- controls: true,
1357
- autoplay: false,
1358
- loop: false,
1359
- muted: false,
1360
- aspectRatio: "16:9"
1361
- },
1362
- propFields: [
1363
- {
1364
- name: "src",
1365
- label: "Video URL (HTML5, YouTube, Vimeo)",
1366
- type: "string",
1367
- defaultValue: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
1368
- },
1369
- {
1370
- name: "provider",
1371
- label: "Provider",
1372
- type: "select",
1373
- defaultValue: "auto",
1374
- options: [
1375
- { label: "Auto Detect", value: "auto" },
1376
- { label: "HTML5 Video", value: "html5" },
1377
- { label: "YouTube Embed", value: "youtube" },
1378
- { label: "Vimeo Embed", value: "vimeo" }
1379
- ]
1380
- },
1381
- { name: "poster", label: "Poster Image URL", type: "string", defaultValue: "" },
1382
- { name: "controls", label: "Show Controls", type: "boolean", defaultValue: true },
1383
- { name: "autoplay", label: "Autoplay", type: "boolean", defaultValue: false },
1384
- { name: "loop", label: "Loop", type: "boolean", defaultValue: false },
1385
- { name: "muted", label: "Muted", type: "boolean", defaultValue: false },
1386
- {
1387
- name: "aspectRatio",
1388
- label: "Aspect Ratio",
1389
- type: "select",
1390
- defaultValue: "16:9",
1391
- options: [
1392
- { label: "16:9 (Widescreen)", value: "16:9" },
1393
- { label: "4:3 (Standard)", value: "4:3" },
1394
- { label: "1:1 (Square)", value: "1:1" },
1395
- { label: "9:16 (Vertical)", value: "9:16" },
1396
- { label: "Auto", value: "auto" }
1397
- ]
1398
- }
1399
- ],
1400
- traits: [
1401
- srcTrait(),
1402
- posterTrait(),
1403
- controlsTrait(),
1404
- autoplayTrait(),
1405
- loopTrait(),
1406
- mutedTrait(),
1407
- idTrait(),
1408
- titleTrait(),
1409
- ariaLabelTrait({ description: "Accessible name summarizing the video content." })
1410
- ],
1411
- validateProps: (props) => {
1412
- const errors = [];
1413
- if (props.src !== void 0 && typeof props.src !== "string" && !isVariableBinding(props.src)) {
1414
- errors.push('Video "src" must be a string when provided.');
1415
- }
1416
- if (props.provider !== void 0 && !isVariableBinding(props.provider)) {
1417
- const allowed = ["auto", "html5", "youtube", "vimeo"];
1418
- if (typeof props.provider !== "string" || !allowed.includes(props.provider)) {
1419
- errors.push(`Video "provider" must be one of: ${allowed.join(", ")}.`);
1420
- }
1421
- }
1422
- if (props.controls !== void 0 && typeof props.controls !== "boolean" && !isVariableBinding(props.controls)) {
1423
- errors.push('Video "controls" must be a boolean.');
1424
- }
1425
- if (props.autoplay !== void 0 && typeof props.autoplay !== "boolean" && !isVariableBinding(props.autoplay)) {
1426
- errors.push('Video "autoplay" must be a boolean.');
1427
- }
1428
- if (props.loop !== void 0 && typeof props.loop !== "boolean" && !isVariableBinding(props.loop)) {
1429
- errors.push('Video "loop" must be a boolean.');
1430
- }
1431
- if (props.muted !== void 0 && typeof props.muted !== "boolean" && !isVariableBinding(props.muted)) {
1432
- errors.push('Video "muted" must be a boolean.');
1433
- }
1434
- return errors.length > 0 ? errors : true;
1435
- },
1436
- defaultStyles: {
1437
- base: {
1438
- width: "100%",
1439
- maxWidth: "800px",
1440
- borderRadius: "8px",
1441
- overflow: "hidden",
1442
- display: "block",
1443
- margin: "0 0 16px 0"
1444
- }
1445
- }
1446
- };
1447
- var iconDefinition = {
1448
- type: "icon",
1449
- label: "Icon",
1450
- category: "media",
1451
- icon: "sparkles",
1452
- acceptsChildren: false,
1453
- defaultProps: {
1454
- name: "star",
1455
- size: 24,
1456
- color: "#2563eb",
1457
- strokeWidth: 2
1458
- },
1459
- propFields: [
1460
- { name: "name", label: "Icon Name (Lucide)", type: "string", defaultValue: "star" },
1461
- { name: "size", label: "Size (px)", type: "number", defaultValue: 24 },
1462
- { name: "color", label: "Color", type: "color", defaultValue: "#2563eb" },
1463
- { name: "strokeWidth", label: "Stroke Width", type: "number", defaultValue: 2 }
1464
- ],
1465
- traits: [
1466
- idTrait(),
1467
- titleTrait(),
1468
- ariaLabelTrait({ required: true, description: "Required: describes what the icon represents for screen readers." })
1469
- ],
1470
- validateProps: (props) => {
1471
- const errors = [];
1472
- if (props.name !== void 0 && !isVariableBinding(props.name) && (typeof props.name !== "string" || props.name.trim().length === 0)) {
1473
- errors.push('Icon requires a non-empty "name".');
1474
- }
1475
- if (props.size !== void 0 && !isVariableBinding(props.size)) {
1476
- if (typeof props.size !== "number" || props.size < 0) {
1477
- errors.push('Icon "size" must be a non-negative number.');
1478
- }
1479
- }
1480
- if (props.strokeWidth !== void 0 && !isVariableBinding(props.strokeWidth)) {
1481
- if (typeof props.strokeWidth !== "number" || props.strokeWidth < 0) {
1482
- errors.push('Icon "strokeWidth" must be a non-negative number.');
1483
- }
1484
- }
1485
- return errors.length > 0 ? errors : true;
1486
- },
1487
- defaultStyles: {
1488
- base: {
1489
- display: "inline-flex",
1490
- alignItems: "center",
1491
- justifyContent: "center"
1492
- }
1493
- }
1494
- };
1495
- var htmlEmbedDefinition = {
1496
- type: "html-embed",
1497
- label: "HTML Embed",
1498
- category: "custom",
1499
- icon: "code",
1500
- acceptsChildren: false,
1501
- defaultProps: {
1502
- html: '<div style="padding: 16px; background: #f1f5f9; border-radius: 8px; text-align: center; font-family: sans-serif; color: #475569;">Custom HTML Embed Content</div>'
1503
- },
1504
- propFields: [
1505
- {
1506
- name: "html",
1507
- label: "HTML / Embed Code",
1508
- type: "textarea",
1509
- defaultValue: '<div style="padding: 16px; background: #f1f5f9; border-radius: 8px; text-align: center; font-family: sans-serif; color: #475569;">Custom HTML Embed Content</div>'
1510
- }
1511
- ],
1512
- traits: [
1513
- idTrait(),
1514
- ariaLabelTrait()
1515
- ],
1516
- validateProps: (props) => {
1517
- const errors = [];
1518
- if (props.html !== void 0 && typeof props.html !== "string" && !isVariableBinding(props.html)) {
1519
- errors.push('HTML Embed "html" must be a string.');
1520
- }
1521
- return errors.length > 0 ? errors : true;
1522
- },
1523
- defaultStyles: {
1524
- base: {
1525
- width: "100%",
1526
- margin: "0 0 16px 0"
1527
- }
1528
- }
1529
- };
1530
- var tableDefinition = {
1531
- type: "table",
1532
- label: "Table",
1533
- category: "layout",
1534
- icon: "table",
1535
- acceptsChildren: true,
1536
- allowedChildren: ["table-row"],
1537
- defaultProps: {
1538
- striped: false,
1539
- bordered: true,
1540
- compact: false
1541
- },
1542
- defaultChildren: [
1543
- {
1544
- type: "table-row",
1545
- children: [
1546
- { type: "table-cell", props: { tag: "th", text: "Header 1" } },
1547
- { type: "table-cell", props: { tag: "th", text: "Header 2" } }
1548
- ]
1549
- },
1550
- {
1551
- type: "table-row",
1552
- children: [
1553
- { type: "table-cell", props: { tag: "td", text: "Data 1" } },
1554
- { type: "table-cell", props: { tag: "td", text: "Data 2" } }
1555
- ]
1556
- }
1557
- ],
1558
- propFields: [
1559
- { name: "striped", label: "Striped Rows", type: "boolean", defaultValue: false },
1560
- { name: "bordered", label: "Bordered", type: "boolean", defaultValue: true },
1561
- { name: "compact", label: "Compact Spacing", type: "boolean", defaultValue: false }
1562
- ],
1563
- traits: [
1564
- idTrait(),
1565
- ariaLabelTrait({ description: "Required: provides a caption summary for the table when no visible caption exists." })
1566
- ],
1567
- validateProps: (props) => {
1568
- const errors = [];
1569
- if (props.striped !== void 0 && typeof props.striped !== "boolean" && !isVariableBinding(props.striped)) {
1570
- errors.push('Table "striped" must be a boolean.');
1571
- }
1572
- if (props.bordered !== void 0 && typeof props.bordered !== "boolean" && !isVariableBinding(props.bordered)) {
1573
- errors.push('Table "bordered" must be a boolean.');
1574
- }
1575
- if (props.compact !== void 0 && typeof props.compact !== "boolean" && !isVariableBinding(props.compact)) {
1576
- errors.push('Table "compact" must be a boolean.');
1577
- }
1578
- return errors.length > 0 ? errors : true;
1579
- },
1580
- defaultStyles: {
1581
- base: {
1582
- width: "100%",
1583
- margin: "0 0 16px 0",
1584
- borderCollapse: "collapse"
1585
- }
1586
- }
1587
- };
1588
- var tableRowDefinition = {
1589
- type: "table-row",
1590
- label: "Table Row",
1591
- category: "layout",
1592
- icon: "table-row",
1593
- acceptsChildren: true,
1594
- allowedChildren: ["table-cell"],
1595
- disallowedParents: ["page"],
1596
- defaultProps: {},
1597
- defaultChildren: [
1598
- { type: "table-cell", props: { tag: "td", text: "Data" } }
1599
- ],
1600
- traits: [
1601
- idTrait(),
1602
- ariaLabelTrait()
1603
- ],
1604
- defaultStyles: {
1605
- base: {}
1606
- }
1607
- };
1608
- var tableCellDefinition = {
1609
- type: "table-cell",
1610
- label: "Table Cell",
1611
- category: "layout",
1612
- icon: "table-cell",
1613
- acceptsChildren: true,
1614
- allowedChildren: [
1615
- "heading",
1616
- "text",
1617
- "paragraph",
1618
- "link",
1619
- "blockquote",
1620
- "badge",
1621
- "code-block",
1622
- "image",
1623
- "video",
1624
- "icon",
1625
- "html-embed",
1626
- "button",
1627
- "list",
1628
- "custom"
1629
- ],
1630
- disallowedParents: ["page"],
1631
- defaultProps: {
1632
- tag: "td",
1633
- text: "Cell",
1634
- colSpan: 1,
1635
- rowSpan: 1
1636
- },
1637
- propFields: [
1638
- {
1639
- name: "tag",
1640
- label: "Cell Type",
1641
- type: "select",
1642
- defaultValue: "td",
1643
- options: [
1644
- { label: "Data Cell (td)", value: "td" },
1645
- { label: "Header Cell (th)", value: "th" }
1646
- ]
1647
- },
1648
- { name: "text", label: "Text", type: "string", defaultValue: "Cell" },
1649
- { name: "colSpan", label: "Column Span (colSpan)", type: "number", defaultValue: 1 },
1650
- { name: "rowSpan", label: "Row Span (rowSpan)", type: "number", defaultValue: 1 }
1651
- ],
1652
- traits: [
1653
- colSpanTrait(),
1654
- rowSpanTrait(),
1655
- idTrait(),
1656
- ariaLabelTrait()
1657
- ],
1658
- validateProps: (props) => {
1659
- const errors = [];
1660
- if (props.tag !== void 0 && !isVariableBinding(props.tag)) {
1661
- if (props.tag !== "td" && props.tag !== "th") {
1662
- errors.push('Table Cell "tag" must be either "td" or "th".');
1663
- }
1664
- }
1665
- if (props.colSpan !== void 0 && !isVariableBinding(props.colSpan)) {
1666
- if (typeof props.colSpan !== "number" || props.colSpan < 1 || !Number.isInteger(props.colSpan)) {
1667
- errors.push('Table Cell "colSpan" must be a positive integer (>= 1).');
1668
- }
1669
- }
1670
- if (props.rowSpan !== void 0 && !isVariableBinding(props.rowSpan)) {
1671
- if (typeof props.rowSpan !== "number" || props.rowSpan < 1 || !Number.isInteger(props.rowSpan)) {
1672
- errors.push('Table Cell "rowSpan" must be a positive integer (>= 1).');
1673
- }
1674
- }
1675
- if (props.text !== void 0 && typeof props.text !== "string" && !isVariableBinding(props.text)) {
1676
- errors.push('Table Cell "text" must be a string when provided.');
1677
- }
1678
- return errors.length > 0 ? errors : true;
1679
- },
1680
- defaultStyles: {
1681
- base: {
1682
- padding: "8px 12px",
1683
- borderWidth: "1px",
1684
- borderColor: "#e2e8f0",
1685
- borderStyle: "solid",
1686
- textAlign: "left"
1687
- }
1688
- }
1689
- };
1690
- var formDefinition = {
1691
- type: "form",
1692
- label: "Form",
1693
- category: "form",
1694
- icon: "form",
1695
- acceptsChildren: true,
1696
- allowedChildren: [
1697
- ...CONTENT_CHILD_TYPES,
1698
- "container",
1699
- "columns",
1700
- "section"
1701
- ],
1702
- disallowedParents: ["page"],
1703
- defaultProps: {
1704
- name: "contact_form",
1705
- method: "POST",
1706
- action: "",
1707
- target: "_self",
1708
- autoComplete: "on"
1709
- },
1710
- defaultChildren: [
1711
- { type: "input", props: { name: "name", type: "text", placeholder: "Your Name", required: true } },
1712
- { type: "input", props: { name: "email", type: "email", placeholder: "Your Email", required: true } },
1713
- { type: "textarea", props: { name: "message", placeholder: "Your Message", rows: 4, required: true } },
1714
- { type: "checkbox", props: { name: "agree", label: "I agree to the terms and privacy policy", required: true } },
1715
- { type: "button", props: { label: "Send Message", variant: "primary", buttonType: "submit" } }
1716
- ],
1717
- propFields: [
1718
- { name: "name", label: "Form Name", type: "string", defaultValue: "contact_form" },
1719
- { name: "action", label: "Action URL", type: "string" },
1720
- {
1721
- name: "method",
1722
- label: "Method",
1723
- type: "select",
1724
- defaultValue: "POST",
1725
- options: [
1726
- { label: "POST", value: "POST" },
1727
- { label: "GET", value: "GET" }
1728
- ]
1729
- },
1730
- {
1731
- name: "target",
1732
- label: "Target",
1733
- type: "select",
1734
- defaultValue: "_self",
1735
- options: [
1736
- { label: "Same Window (_self)", value: "_self" },
1737
- { label: "New Tab (_blank)", value: "_blank" }
1738
- ]
1739
- },
1740
- {
1741
- name: "autoComplete",
1742
- label: "Auto Complete",
1743
- type: "select",
1744
- defaultValue: "on",
1745
- options: [
1746
- { label: "On", value: "on" },
1747
- { label: "Off", value: "off" }
1748
- ]
1749
- }
1750
- ],
1751
- traits: [
1752
- fieldNameTrait({ defaultValue: "contact_form", required: false }),
1753
- actionTrait(),
1754
- methodTrait(),
1755
- targetTrait({ options: [
1756
- { label: "Same Window (_self)", value: "_self" },
1757
- { label: "New Tab (_blank)", value: "_blank" },
1758
- { label: "Parent (_parent)", value: "_parent" },
1759
- { label: "Top (_top)", value: "_top" }
1760
- ] }),
1761
- autoCompleteTrait(),
1762
- idTrait(),
1763
- ariaLabelTrait({ description: "Accessible name for the form landmark." })
1764
- ],
1765
- validateProps: (props) => {
1766
- const errors = [];
1767
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
1768
- errors.push('Form "name" must be a string when provided.');
1769
- }
1770
- if (props.action !== void 0 && typeof props.action !== "string" && !isVariableBinding(props.action)) {
1771
- errors.push('Form "action" must be a string when provided.');
1772
- }
1773
- if (props.method !== void 0 && !isVariableBinding(props.method)) {
1774
- if (!["GET", "POST", "get", "post"].includes(props.method)) {
1775
- errors.push('Form "method" must be either "GET" or "POST".');
1776
- }
1777
- }
1778
- if (props.target !== void 0 && !isVariableBinding(props.target)) {
1779
- if (!["_self", "_blank", "_parent", "_top"].includes(props.target)) {
1780
- errors.push('Form "target" must be one of: "_self", "_blank", "_parent", "_top".');
1781
- }
1782
- }
1783
- if (props.autoComplete !== void 0 && !isVariableBinding(props.autoComplete)) {
1784
- if (!["on", "off"].includes(props.autoComplete)) {
1785
- errors.push('Form "autoComplete" must be either "on" or "off".');
1786
- }
1787
- }
1788
- return errors.length > 0 ? errors : true;
1789
- },
1790
- defaultStyles: {
1791
- base: {
1792
- width: "100%",
1793
- display: "flex",
1794
- flexDirection: "column",
1795
- gap: "16px"
1796
- }
1797
- }
1798
- };
1799
- var inputDefinition = {
1800
- type: "input",
1801
- label: "Input",
1802
- category: "form",
1803
- icon: "input",
1804
- acceptsChildren: false,
1805
- disallowedParents: ["page"],
1806
- defaultProps: {
1807
- name: "input_field",
1808
- type: "text",
1809
- placeholder: "Enter text...",
1810
- defaultValue: "",
1811
- required: false,
1812
- disabled: false,
1813
- readOnly: false
1814
- },
1815
- propFields: [
1816
- { name: "name", label: "Field Name", type: "string", defaultValue: "input_field" },
1817
- {
1818
- name: "type",
1819
- label: "Input Type",
1820
- type: "select",
1821
- defaultValue: "text",
1822
- options: [
1823
- { label: "Text", value: "text" },
1824
- { label: "Email", value: "email" },
1825
- { label: "Number", value: "number" },
1826
- { label: "Password", value: "password" },
1827
- { label: "Phone (tel)", value: "tel" },
1828
- { label: "URL", value: "url" },
1829
- { label: "Search", value: "search" },
1830
- { label: "Date", value: "date" }
1831
- ]
1832
- },
1833
- { name: "placeholder", label: "Placeholder", type: "string", defaultValue: "Enter text..." },
1834
- { name: "defaultValue", label: "Default Value", type: "string" },
1835
- { name: "required", label: "Required", type: "boolean", defaultValue: false },
1836
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1837
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
1838
- ],
1839
- traits: [
1840
- inputTypeTrait({ options: [
1841
- { label: "Text", value: "text" },
1842
- { label: "Email", value: "email" },
1843
- { label: "Number", value: "number" },
1844
- { label: "Password", value: "password" },
1845
- { label: "Phone (tel)", value: "tel" },
1846
- { label: "URL", value: "url" },
1847
- { label: "Search", value: "search" },
1848
- { label: "Date", value: "date" },
1849
- { label: "Hidden", value: "hidden" }
1850
- ] }),
1851
- fieldNameTrait({ defaultValue: "input_field" }),
1852
- placeholderTrait({ defaultValue: "Enter text..." }),
1853
- defaultValueTrait(),
1854
- requiredTrait(),
1855
- disabledTrait(),
1856
- readOnlyTrait(),
1857
- idTrait(),
1858
- ariaLabelTrait()
1859
- ],
1860
- validateProps: (props) => {
1861
- const errors = [];
1862
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
1863
- errors.push('Input "name" must be a string when provided.');
1864
- }
1865
- if (props.type !== void 0 && !isVariableBinding(props.type)) {
1866
- const validTypes = ["text", "email", "number", "password", "tel", "url", "search", "date", "hidden"];
1867
- if (!validTypes.includes(props.type)) {
1868
- errors.push(`Input "type" must be one of: ${validTypes.join(", ")}.`);
1869
- }
1870
- }
1871
- if (props.placeholder !== void 0 && typeof props.placeholder !== "string" && !isVariableBinding(props.placeholder)) {
1872
- errors.push('Input "placeholder" must be a string when provided.');
1873
- }
1874
- if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
1875
- errors.push('Input "required" must be a boolean when provided.');
1876
- }
1877
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
1878
- errors.push('Input "disabled" must be a boolean when provided.');
1879
- }
1880
- if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !isVariableBinding(props.readOnly)) {
1881
- errors.push('Input "readOnly" must be a boolean when provided.');
1882
- }
1883
- return errors.length > 0 ? errors : true;
1884
- },
1885
- defaultStyles: {
1886
- base: {
1887
- width: "100%",
1888
- paddingTop: "10px",
1889
- paddingBottom: "10px",
1890
- paddingLeft: "14px",
1891
- paddingRight: "14px",
1892
- borderRadius: "6px",
1893
- borderWidth: "1px",
1894
- borderStyle: "solid",
1895
- borderColor: "#cbd5e1",
1896
- fontSize: "14px",
1897
- backgroundColor: "#ffffff",
1898
- color: "#1e293b",
1899
- boxSizing: "border-box"
1900
- }
1901
- }
1902
- };
1903
- var textareaDefinition = {
1904
- type: "textarea",
1905
- label: "Textarea",
1906
- category: "form",
1907
- icon: "textarea",
1908
- acceptsChildren: false,
1909
- disallowedParents: ["page"],
1910
- defaultProps: {
1911
- name: "message",
1912
- placeholder: "Enter your message...",
1913
- defaultValue: "",
1914
- rows: 4,
1915
- required: false,
1916
- disabled: false,
1917
- readOnly: false
1918
- },
1919
- propFields: [
1920
- { name: "name", label: "Field Name", type: "string", defaultValue: "message" },
1921
- { name: "placeholder", label: "Placeholder", type: "string", defaultValue: "Enter your message..." },
1922
- { name: "defaultValue", label: "Default Value", type: "textarea" },
1923
- { name: "rows", label: "Rows", type: "number", defaultValue: 4 },
1924
- { name: "required", label: "Required", type: "boolean", defaultValue: false },
1925
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1926
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
1927
- ],
1928
- traits: [
1929
- fieldNameTrait({ defaultValue: "message" }),
1930
- placeholderTrait({ defaultValue: "Enter your message..." }),
1931
- defaultValueTrait(),
1932
- rowsTrait(),
1933
- requiredTrait(),
1934
- disabledTrait(),
1935
- readOnlyTrait(),
1936
- idTrait(),
1937
- ariaLabelTrait()
1938
- ],
1939
- validateProps: (props) => {
1940
- const errors = [];
1941
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
1942
- errors.push('Textarea "name" must be a string when provided.');
1943
- }
1944
- if (props.rows !== void 0 && !isVariableBinding(props.rows)) {
1945
- if (typeof props.rows !== "number" || props.rows < 1 || !Number.isInteger(props.rows)) {
1946
- errors.push('Textarea "rows" must be a positive integer (>= 1).');
1947
- }
1948
- }
1949
- if (props.placeholder !== void 0 && typeof props.placeholder !== "string" && !isVariableBinding(props.placeholder)) {
1950
- errors.push('Textarea "placeholder" must be a string when provided.');
1951
- }
1952
- if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
1953
- errors.push('Textarea "required" must be a boolean when provided.');
1954
- }
1955
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
1956
- errors.push('Textarea "disabled" must be a boolean when provided.');
1957
- }
1958
- if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !isVariableBinding(props.readOnly)) {
1959
- errors.push('Textarea "readOnly" must be a boolean when provided.');
1960
- }
1961
- return errors.length > 0 ? errors : true;
1962
- },
1963
- defaultStyles: {
1964
- base: {
1965
- width: "100%",
1966
- paddingTop: "10px",
1967
- paddingBottom: "10px",
1968
- paddingLeft: "14px",
1969
- paddingRight: "14px",
1970
- borderRadius: "6px",
1971
- borderWidth: "1px",
1972
- borderStyle: "solid",
1973
- borderColor: "#cbd5e1",
1974
- fontSize: "14px",
1975
- backgroundColor: "#ffffff",
1976
- color: "#1e293b",
1977
- boxSizing: "border-box"
1978
- }
1979
- }
1980
- };
1981
- var selectDefinition = {
1982
- type: "select",
1983
- label: "Select",
1984
- category: "form",
1985
- icon: "select",
1986
- acceptsChildren: false,
1987
- disallowedParents: ["page"],
1988
- defaultProps: {
1989
- name: "select_field",
1990
- placeholder: "Select an option...",
1991
- options: [
1992
- { label: "Option 1", value: "option1" },
1993
- { label: "Option 2", value: "option2" },
1994
- { label: "Option 3", value: "option3" }
1995
- ],
1996
- defaultValue: "",
1997
- required: false,
1998
- disabled: false
1999
- },
2000
- propFields: [
2001
- { name: "name", label: "Field Name", type: "string", defaultValue: "select_field" },
2002
- { name: "placeholder", label: "Placeholder", type: "string", defaultValue: "Select an option..." },
2003
- {
2004
- name: "options",
2005
- label: "Options (JSON list)",
2006
- type: "json",
2007
- defaultValue: [
2008
- { label: "Option 1", value: "option1" },
2009
- { label: "Option 2", value: "option2" },
2010
- { label: "Option 3", value: "option3" }
2011
- ]
2012
- },
2013
- { name: "defaultValue", label: "Default Selected Value", type: "string" },
2014
- { name: "required", label: "Required", type: "boolean", defaultValue: false },
2015
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2016
- ],
2017
- traits: [
2018
- fieldNameTrait({ defaultValue: "select_field" }),
2019
- placeholderTrait({ defaultValue: "Select an option..." }),
2020
- defaultValueTrait({ description: "The initially selected option value (must match one of the option values)." }),
2021
- requiredTrait(),
2022
- disabledTrait(),
2023
- idTrait(),
2024
- ariaLabelTrait()
2025
- ],
2026
- validateProps: (props) => {
2027
- const errors = [];
2028
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2029
- errors.push('Select "name" must be a string when provided.');
2030
- }
2031
- if (props.options !== void 0 && !isVariableBinding(props.options)) {
2032
- if (!Array.isArray(props.options) && typeof props.options !== "string") {
2033
- errors.push('Select "options" must be an array of option objects or a JSON string.');
2034
- }
2035
- }
2036
- if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2037
- errors.push('Select "required" must be a boolean when provided.');
2038
- }
2039
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2040
- errors.push('Select "disabled" must be a boolean when provided.');
2041
- }
2042
- return errors.length > 0 ? errors : true;
2043
- },
2044
- defaultStyles: {
2045
- base: {
2046
- width: "100%",
2047
- paddingTop: "10px",
2048
- paddingBottom: "10px",
2049
- paddingLeft: "14px",
2050
- paddingRight: "14px",
2051
- borderRadius: "6px",
2052
- borderWidth: "1px",
2053
- borderStyle: "solid",
2054
- borderColor: "#cbd5e1",
2055
- fontSize: "14px",
2056
- backgroundColor: "#ffffff",
2057
- color: "#1e293b",
2058
- boxSizing: "border-box"
2059
- }
2060
- }
2061
- };
2062
- var checkboxDefinition = {
2063
- type: "checkbox",
2064
- label: "Checkbox",
2065
- category: "form",
2066
- icon: "checkbox",
2067
- acceptsChildren: false,
2068
- disallowedParents: ["page"],
2069
- defaultProps: {
2070
- name: "checkbox_field",
2071
- label: "I agree to the terms and conditions",
2072
- value: "yes",
2073
- defaultChecked: false,
2074
- required: false,
2075
- disabled: false
2076
- },
2077
- propFields: [
2078
- { name: "name", label: "Field Name", type: "string", defaultValue: "checkbox_field" },
2079
- { name: "label", label: "Label Text", type: "string", defaultValue: "I agree to the terms and conditions" },
2080
- { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2081
- { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2082
- { name: "required", label: "Required", type: "boolean", defaultValue: false },
2083
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2084
- ],
2085
- traits: [
2086
- fieldNameTrait({ defaultValue: "checkbox_field" }),
2087
- valueTrait({ defaultValue: "yes" }),
2088
- defaultCheckedTrait(),
2089
- requiredTrait(),
2090
- disabledTrait(),
2091
- idTrait(),
2092
- ariaLabelTrait()
2093
- ],
2094
- validateProps: (props) => {
2095
- const errors = [];
2096
- if (props.label !== void 0 && typeof props.label !== "string" && !isVariableBinding(props.label)) {
2097
- errors.push('Checkbox "label" must be a string when provided.');
2098
- }
2099
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2100
- errors.push('Checkbox "name" must be a string when provided.');
2101
- }
2102
- if (props.value !== void 0 && typeof props.value !== "string" && !isVariableBinding(props.value)) {
2103
- errors.push('Checkbox "value" must be a string when provided.');
2104
- }
2105
- if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !isVariableBinding(props.defaultChecked)) {
2106
- errors.push('Checkbox "defaultChecked" must be a boolean when provided.');
2107
- }
2108
- if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2109
- errors.push('Checkbox "required" must be a boolean when provided.');
2110
- }
2111
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2112
- errors.push('Checkbox "disabled" must be a boolean when provided.');
2113
- }
2114
- return errors.length > 0 ? errors : true;
2115
- },
2116
- defaultStyles: {
2117
- base: {
2118
- display: "inline-flex",
2119
- alignItems: "center",
2120
- gap: "8px",
2121
- fontSize: "14px",
2122
- color: "#1e293b",
2123
- cursor: "pointer",
2124
- userSelect: "none"
2125
- }
2126
- }
2127
- };
2128
- var radioDefinition = {
2129
- type: "radio",
2130
- label: "Radio",
2131
- category: "form",
2132
- icon: "radio",
2133
- acceptsChildren: false,
2134
- disallowedParents: ["page"],
2135
- defaultProps: {
2136
- name: "radio_group",
2137
- label: "Option 1",
2138
- value: "option1",
2139
- defaultChecked: false,
2140
- required: false,
2141
- disabled: false
2142
- },
2143
- propFields: [
2144
- { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
2145
- { name: "label", label: "Label Text", type: "string", defaultValue: "Option 1" },
2146
- { name: "value", label: "Radio Value", type: "string", defaultValue: "option1" },
2147
- { name: "defaultChecked", label: "Default Selected", type: "boolean", defaultValue: false },
2148
- { name: "required", label: "Required", type: "boolean", defaultValue: false },
2149
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2150
- ],
2151
- traits: [
2152
- fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2153
- valueTrait({ defaultValue: "option1" }),
2154
- defaultCheckedTrait(),
2155
- requiredTrait(),
2156
- disabledTrait(),
2157
- idTrait(),
2158
- ariaLabelTrait()
2159
- ],
2160
- validateProps: (props) => {
2161
- const errors = [];
2162
- if (props.label !== void 0 && typeof props.label !== "string" && !isVariableBinding(props.label)) {
2163
- errors.push('Radio "label" must be a string when provided.');
2164
- }
2165
- if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2166
- errors.push('Radio "name" must be a string when provided.');
2167
- }
2168
- if (props.value !== void 0 && typeof props.value !== "string" && !isVariableBinding(props.value)) {
2169
- errors.push('Radio "value" must be a string when provided.');
2170
- }
2171
- if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !isVariableBinding(props.defaultChecked)) {
2172
- errors.push('Radio "defaultChecked" must be a boolean when provided.');
2173
- }
2174
- if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2175
- errors.push('Radio "required" must be a boolean when provided.');
2176
- }
2177
- if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2178
- errors.push('Radio "disabled" must be a boolean when provided.');
2179
- }
2180
- return errors.length > 0 ? errors : true;
2181
- },
2182
- defaultStyles: {
2183
- base: {
2184
- display: "inline-flex",
2185
- alignItems: "center",
2186
- gap: "8px",
2187
- fontSize: "14px",
2188
- color: "#1e293b",
2189
- cursor: "pointer",
2190
- userSelect: "none"
2191
- }
2192
- }
2193
- };
2194
- var coreComponentDefinitions = [
2195
- pageDefinition,
2196
- sectionDefinition,
2197
- containerDefinition,
2198
- columnsDefinition,
2199
- headingDefinition,
2200
- textDefinition,
2201
- paragraphDefinition,
2202
- linkDefinition,
2203
- blockquoteDefinition,
1
+ import {
2
+ CONTENT_CHILD_TYPES,
3
+ ComponentRegistry,
4
+ LAYOUT_PARENTS,
2204
5
  badgeDefinition,
2205
- codeBlockDefinition,
2206
- imageDefinition,
2207
- videoDefinition,
2208
- iconDefinition,
2209
- htmlEmbedDefinition,
6
+ blockquoteDefinition,
2210
7
  buttonDefinition,
2211
- formDefinition,
2212
- inputDefinition,
2213
- textareaDefinition,
2214
- selectDefinition,
8
+ buttonSubmitDefinition,
2215
9
  checkboxDefinition,
2216
- radioDefinition,
10
+ codeBlockDefinition,
11
+ collapsibleDefinition,
2217
12
  collectionDefinition,
13
+ columnsDefinition,
14
+ containerDefinition,
15
+ coreComponentDefinitions,
16
+ createDefaultComponentRegistry,
17
+ drawerDefinition,
18
+ fileUploadDefinition,
19
+ flexDefinition,
20
+ formDefinition,
21
+ gridDefinition,
22
+ headingDefinition,
23
+ htmlEmbedDefinition,
24
+ iconDefinition,
25
+ imageDefinition,
26
+ inputDefinition,
27
+ linkDefinition,
2218
28
  listDefinition,
2219
29
  listItemDefinition,
30
+ modalDefinition,
31
+ pageDefinition,
32
+ paragraphDefinition,
33
+ radioDefinition,
34
+ radioGroupDefinition,
35
+ radioItemDefinition,
36
+ sectionDefinition,
37
+ selectDefinition,
38
+ switchDefinition,
39
+ tableCellDefinition,
2220
40
  tableDefinition,
2221
41
  tableRowDefinition,
2222
- tableCellDefinition
2223
- ];
2224
- function createDefaultComponentRegistry() {
2225
- const registry = new ComponentRegistry();
2226
- for (const def of coreComponentDefinitions) {
2227
- registry.register(def);
2228
- }
2229
- return registry;
2230
- }
42
+ textDefinition,
43
+ textareaDefinition,
44
+ videoDefinition
45
+ } from "./chunk-K6I6U7F3.js";
46
+ import {
47
+ TRAIT_GROUP_LABELS,
48
+ TRAIT_GROUP_ORDER,
49
+ acceptTrait,
50
+ actionTrait,
51
+ altTrait,
52
+ ariaLabelTrait,
53
+ autoCompleteTrait,
54
+ autoDisableOnSubmitTrait,
55
+ autoGrowTrait,
56
+ autoplayTrait,
57
+ buttonTypeTrait,
58
+ citeTrait,
59
+ colSpanTrait,
60
+ collectTraitNames,
61
+ controlsTrait,
62
+ defaultCheckedTrait,
63
+ defaultSelectedTrait,
64
+ defaultValueTrait,
65
+ disabledTrait,
66
+ fieldNameTrait,
67
+ helperTextTrait,
68
+ hrefTrait,
69
+ idTrait,
70
+ indeterminateTrait,
71
+ inputTypeTrait,
72
+ labelTextTrait,
73
+ loadingTextTrait,
74
+ loadingTrait,
75
+ loopTrait,
76
+ maxCharCountTrait,
77
+ maxFileSizeTrait,
78
+ maxLengthTrait,
79
+ methodTrait,
80
+ minLengthTrait,
81
+ multipleTrait,
82
+ mutedTrait,
83
+ optionsListTrait,
84
+ orientationTrait,
85
+ patternTrait,
86
+ placeholderTrait,
87
+ posterTrait,
88
+ prefixIconTrait,
89
+ preventDefaultTrait,
90
+ readOnlyTrait,
91
+ relTrait,
92
+ requiredTrait,
93
+ resetOnSubmitTrait,
94
+ resizeTrait,
95
+ rowSpanTrait,
96
+ rowsTrait,
97
+ scrollToFirstErrorTrait,
98
+ showPreviewTrait,
99
+ showSpinnerTrait,
100
+ sortTraits,
101
+ srcTrait,
102
+ suffixIconTrait,
103
+ switchSizeTrait,
104
+ tagTrait,
105
+ targetTrait,
106
+ titleTrait,
107
+ valueTrait,
108
+ withOverrides
109
+ } from "./chunk-OK53DS7G.js";
110
+ import {
111
+ FORM_STARTER_BLOCKS,
112
+ LAYOUT_STARTER_BLOCKS,
113
+ STARTER_BLOCKS,
114
+ UI_STARTER_BLOCKS,
115
+ defaultGenId
116
+ } from "./chunk-JTQ35OQQ.js";
2231
117
 
2232
118
  // src/requirements.ts
2233
119
  function extractComponentRequirements(root, registry) {
@@ -2268,542 +154,34 @@ function primitiveTypeForField(field) {
2268
154
  function isBindableField(field) {
2269
155
  return primitiveTypeForField(field) !== void 0;
2270
156
  }
2271
-
2272
- // src/blocks.ts
2273
- var nextId = 1;
2274
- function defaultGenId(prefix = "node") {
2275
- return `${prefix}-${Date.now().toString(36)}-${(nextId++).toString(36)}`;
2276
- }
2277
- var STARTER_BLOCKS = [
2278
- // --- Layout Blocks (STORA-241) ---
2279
- {
2280
- id: "layout-1-col",
2281
- name: "1 Column",
2282
- category: "layout",
2283
- categoryLabel: "Layout Blocks",
2284
- description: "Full-width single column container inside a section",
2285
- icon: "layout",
2286
- createNodeTree: (gen = defaultGenId) => ({
2287
- id: gen("section"),
2288
- type: "section",
2289
- styles: { base: { padding: "40px 20px", width: "100%" } },
2290
- children: [
2291
- {
2292
- id: gen("container"),
2293
- type: "container",
2294
- props: { tag: "div" },
2295
- styles: { base: { maxWidth: "1200px", margin: "0 auto", width: "100%" } },
2296
- children: []
2297
- }
2298
- ]
2299
- })
2300
- },
2301
- {
2302
- id: "layout-2-col-50-50",
2303
- name: "2 Columns (50/50)",
2304
- category: "layout",
2305
- categoryLabel: "Layout Blocks",
2306
- description: "Two equal-width 50/50 columns with flexible layout",
2307
- icon: "columns",
2308
- createNodeTree: (gen = defaultGenId) => ({
2309
- id: gen("section"),
2310
- type: "section",
2311
- styles: { base: { padding: "40px 20px", width: "100%" } },
2312
- children: [
2313
- {
2314
- id: gen("columns"),
2315
- type: "columns",
2316
- props: { columns: 2, gap: "24px" },
2317
- styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
2318
- children: [
2319
- {
2320
- id: gen("container"),
2321
- type: "container",
2322
- props: { tag: "div" },
2323
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2324
- children: []
2325
- },
2326
- {
2327
- id: gen("container"),
2328
- type: "container",
2329
- props: { tag: "div" },
2330
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2331
- children: []
2332
- }
2333
- ]
2334
- }
2335
- ]
2336
- })
2337
- },
2338
- {
2339
- id: "layout-2-col-30-70",
2340
- name: "2 Columns (30/70)",
2341
- category: "layout",
2342
- categoryLabel: "Layout Blocks",
2343
- description: "Two asymmetric columns: 30% sidebar and 70% main area",
2344
- icon: "columns",
2345
- createNodeTree: (gen = defaultGenId) => ({
2346
- id: gen("section"),
2347
- type: "section",
2348
- styles: { base: { padding: "40px 20px", width: "100%" } },
2349
- children: [
2350
- {
2351
- id: gen("columns"),
2352
- type: "columns",
2353
- props: { columns: 2, gap: "24px" },
2354
- styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
2355
- children: [
2356
- {
2357
- id: gen("container"),
2358
- type: "container",
2359
- props: { tag: "div" },
2360
- styles: { base: { flex: "0 0 30%", minWidth: "0" } },
2361
- children: []
2362
- },
2363
- {
2364
- id: gen("container"),
2365
- type: "container",
2366
- props: { tag: "div" },
2367
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2368
- children: []
2369
- }
2370
- ]
2371
- }
2372
- ]
2373
- })
2374
- },
2375
- {
2376
- id: "layout-3-col",
2377
- name: "3 Columns",
2378
- category: "layout",
2379
- categoryLabel: "Layout Blocks",
2380
- description: "Three equal-width columns for grid showcases or card groups",
2381
- icon: "grid",
2382
- createNodeTree: (gen = defaultGenId) => ({
2383
- id: gen("section"),
2384
- type: "section",
2385
- styles: { base: { padding: "40px 20px", width: "100%" } },
2386
- children: [
2387
- {
2388
- id: gen("columns"),
2389
- type: "columns",
2390
- props: { columns: 3, gap: "24px" },
2391
- styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
2392
- children: [
2393
- {
2394
- id: gen("container"),
2395
- type: "container",
2396
- props: { tag: "div" },
2397
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2398
- children: []
2399
- },
2400
- {
2401
- id: gen("container"),
2402
- type: "container",
2403
- props: { tag: "div" },
2404
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2405
- children: []
2406
- },
2407
- {
2408
- id: gen("container"),
2409
- type: "container",
2410
- props: { tag: "div" },
2411
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2412
- children: []
2413
- }
2414
- ]
2415
- }
2416
- ]
2417
- })
2418
- },
2419
- {
2420
- id: "layout-4-col",
2421
- name: "4 Columns",
2422
- category: "layout",
2423
- categoryLabel: "Layout Blocks",
2424
- description: "Four equal columns for metric stats, logos, or compact feature cards",
2425
- icon: "grid",
2426
- createNodeTree: (gen = defaultGenId) => ({
2427
- id: gen("section"),
2428
- type: "section",
2429
- styles: { base: { padding: "40px 20px", width: "100%" } },
2430
- children: [
2431
- {
2432
- id: gen("columns"),
2433
- type: "columns",
2434
- props: { columns: 4, gap: "16px" },
2435
- styles: { base: { display: "flex", gap: "16px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
2436
- children: [
2437
- {
2438
- id: gen("container"),
2439
- type: "container",
2440
- props: { tag: "div" },
2441
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2442
- children: []
2443
- },
2444
- {
2445
- id: gen("container"),
2446
- type: "container",
2447
- props: { tag: "div" },
2448
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2449
- children: []
2450
- },
2451
- {
2452
- id: gen("container"),
2453
- type: "container",
2454
- props: { tag: "div" },
2455
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2456
- children: []
2457
- },
2458
- {
2459
- id: gen("container"),
2460
- type: "container",
2461
- props: { tag: "div" },
2462
- styles: { base: { flex: "1 1 0%", minWidth: "0" } },
2463
- children: []
2464
- }
2465
- ]
2466
- }
2467
- ]
2468
- })
2469
- },
2470
- // --- Pre-composed UI Blocks (STORA-242) ---
2471
- {
2472
- id: "hero-section",
2473
- name: "Hero Section",
2474
- category: "sections",
2475
- categoryLabel: "Hero & Headers",
2476
- description: "Engaging hero banner with headline, lead paragraph, and call-to-action button",
2477
- icon: "layout",
2478
- createNodeTree: (gen = defaultGenId) => ({
2479
- id: gen("section"),
2480
- type: "section",
2481
- styles: {
2482
- base: {
2483
- padding: "80px 24px",
2484
- backgroundColor: "#f8fafc",
2485
- textAlign: "center",
2486
- width: "100%"
2487
- }
2488
- },
2489
- children: [
2490
- {
2491
- id: gen("container"),
2492
- type: "container",
2493
- props: { tag: "div" },
2494
- styles: { base: { maxWidth: "768px", margin: "0 auto" } },
2495
- children: [
2496
- {
2497
- id: gen("heading"),
2498
- type: "heading",
2499
- props: { text: "Build Remarkable Experiences", level: 1 },
2500
- styles: {
2501
- base: {
2502
- fontSize: "44px",
2503
- fontWeight: "800",
2504
- color: "#0f172a",
2505
- marginBottom: "16px",
2506
- lineHeight: "1.2"
2507
- }
2508
- }
2509
- },
2510
- {
2511
- id: gen("paragraph"),
2512
- type: "paragraph",
2513
- props: {
2514
- content: "A visual builder designed for maximum craft, responsiveness, and performance."
2515
- },
2516
- styles: {
2517
- base: {
2518
- fontSize: "18px",
2519
- color: "#475569",
2520
- marginBottom: "32px",
2521
- lineHeight: "1.6"
2522
- }
2523
- }
2524
- },
2525
- {
2526
- id: gen("button"),
2527
- type: "button",
2528
- props: { label: "Get Started Today", href: "#explore" },
2529
- styles: {
2530
- base: {
2531
- backgroundColor: "#2563eb",
2532
- color: "#ffffff",
2533
- padding: "12px 28px",
2534
- borderRadius: "8px",
2535
- fontWeight: "600",
2536
- display: "inline-block"
2537
- },
2538
- states: {
2539
- ":hover": { backgroundColor: "#1d4ed8" }
2540
- }
2541
- }
2542
- }
2543
- ]
2544
- }
2545
- ]
2546
- })
2547
- },
2548
- {
2549
- id: "feature-card",
2550
- name: "Feature Card",
2551
- category: "ui",
2552
- categoryLabel: "UI Blocks",
2553
- description: "Clean elevated feature card with badge, title, text, and action link",
2554
- icon: "box",
2555
- createNodeTree: (gen = defaultGenId) => ({
2556
- id: gen("container"),
2557
- type: "container",
2558
- props: { tag: "div" },
2559
- styles: {
2560
- base: {
2561
- padding: "24px",
2562
- backgroundColor: "#ffffff",
2563
- borderRadius: "12px",
2564
- border: "1px solid #e2e8f0",
2565
- boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.05)"
2566
- }
2567
- },
2568
- children: [
2569
- {
2570
- id: gen("badge"),
2571
- type: "badge",
2572
- props: { label: "PRO FEATURE", variant: "primary" },
2573
- styles: { base: { marginBottom: "12px", display: "inline-block" } }
2574
- },
2575
- {
2576
- id: gen("heading"),
2577
- type: "heading",
2578
- props: { text: "Next-Gen Performance", level: 3 },
2579
- styles: {
2580
- base: { fontSize: "20px", fontWeight: "700", color: "#1e293b", marginBottom: "8px" }
2581
- }
2582
- },
2583
- {
2584
- id: gen("paragraph"),
2585
- type: "paragraph",
2586
- props: {
2587
- content: "Engineered for sub-millisecond render updates and zero runtime overhead."
2588
- },
2589
- styles: { base: { fontSize: "14px", color: "#64748b", lineHeight: "1.5" } }
2590
- }
2591
- ]
2592
- })
2593
- },
2594
- {
2595
- id: "media-object",
2596
- name: "Media Object",
2597
- category: "ui",
2598
- categoryLabel: "UI Blocks",
2599
- description: "Horizontal media layout with image beside text content",
2600
- icon: "image",
2601
- createNodeTree: (gen = defaultGenId) => ({
2602
- id: gen("container"),
2603
- type: "container",
2604
- props: { tag: "div" },
2605
- styles: {
2606
- base: {
2607
- display: "flex",
2608
- gap: "16px",
2609
- alignItems: "flex-start",
2610
- padding: "16px",
2611
- backgroundColor: "#ffffff",
2612
- borderRadius: "8px",
2613
- border: "1px solid #e2e8f0"
2614
- }
2615
- },
2616
- children: [
2617
- {
2618
- id: gen("image"),
2619
- type: "image",
2620
- props: {
2621
- src: "https://images.unsplash.com/photo-1579546929518-9e396f3cc809?w=160&auto=format&fit=crop&q=80",
2622
- alt: "Visual preview"
2623
- },
2624
- styles: {
2625
- base: {
2626
- width: "80px",
2627
- height: "80px",
2628
- borderRadius: "8px",
2629
- objectFit: "cover",
2630
- flexShrink: "0"
2631
- }
2632
- }
2633
- },
2634
- {
2635
- id: gen("container"),
2636
- type: "container",
2637
- props: { tag: "div" },
2638
- styles: { base: { flex: "1 1 0%" } },
2639
- children: [
2640
- {
2641
- id: gen("heading"),
2642
- type: "heading",
2643
- props: { text: "Creative Studio Asset", level: 4 },
2644
- styles: {
2645
- base: { fontSize: "16px", fontWeight: "600", color: "#0f172a", marginBottom: "4px" }
2646
- }
2647
- },
2648
- {
2649
- id: gen("paragraph"),
2650
- type: "paragraph",
2651
- props: { content: "High dynamic range gradients crafted for modern presentations." },
2652
- styles: { base: { fontSize: "13px", color: "#64748b", lineHeight: "1.4" } }
2653
- }
2654
- ]
2655
- }
2656
- ]
2657
- })
2658
- },
2659
- {
2660
- id: "pricing-table",
2661
- name: "Pricing Table",
2662
- category: "pricing",
2663
- categoryLabel: "Pricing",
2664
- description: "Highlighted subscription pricing plan with price, feature list, and buy button",
2665
- icon: "table",
2666
- createNodeTree: (gen = defaultGenId) => ({
2667
- id: gen("container"),
2668
- type: "container",
2669
- props: { tag: "div" },
2670
- styles: {
2671
- base: {
2672
- padding: "32px 24px",
2673
- backgroundColor: "#ffffff",
2674
- borderRadius: "16px",
2675
- border: "2px solid #3b82f6",
2676
- boxShadow: "0 10px 15px -3px rgba(59, 130, 246, 0.1)",
2677
- textAlign: "center",
2678
- maxWidth: "360px"
2679
- }
2680
- },
2681
- children: [
2682
- {
2683
- id: gen("badge"),
2684
- type: "badge",
2685
- props: { label: "MOST POPULAR", variant: "primary" },
2686
- styles: { base: { marginBottom: "12px", display: "inline-block" } }
2687
- },
2688
- {
2689
- id: gen("heading"),
2690
- type: "heading",
2691
- props: { text: "Professional", level: 3 },
2692
- styles: { base: { fontSize: "22px", fontWeight: "700", color: "#0f172a" } }
2693
- },
2694
- {
2695
- id: gen("heading"),
2696
- type: "heading",
2697
- props: { text: "$29 / mo", level: 2 },
2698
- styles: {
2699
- base: { fontSize: "36px", fontWeight: "800", color: "#2563eb", margin: "16px 0 24px 0" }
2700
- }
2701
- },
2702
- {
2703
- id: gen("paragraph"),
2704
- type: "paragraph",
2705
- props: { content: "Includes unlimited pages, custom domains, and team collaboration." },
2706
- styles: { base: { fontSize: "14px", color: "#64748b", marginBottom: "24px" } }
2707
- },
2708
- {
2709
- id: gen("button"),
2710
- type: "button",
2711
- props: { label: "Upgrade to Pro", href: "#checkout" },
2712
- styles: {
2713
- base: {
2714
- width: "100%",
2715
- backgroundColor: "#2563eb",
2716
- color: "#ffffff",
2717
- padding: "12px",
2718
- borderRadius: "8px",
2719
- fontWeight: "600",
2720
- display: "block"
2721
- },
2722
- states: {
2723
- ":hover": { backgroundColor: "#1d4ed8" }
2724
- }
2725
- }
2726
- }
2727
- ]
2728
- })
2729
- },
2730
- {
2731
- id: "cta-banner",
2732
- name: "CTA Banner",
2733
- category: "cta",
2734
- categoryLabel: "Call to Action",
2735
- description: "High-contrast conversion banner with title and action button",
2736
- icon: "layout",
2737
- createNodeTree: (gen = defaultGenId) => ({
2738
- id: gen("section"),
2739
- type: "section",
2740
- styles: {
2741
- base: {
2742
- padding: "60px 24px",
2743
- backgroundColor: "#0f172a",
2744
- color: "#ffffff",
2745
- borderRadius: "16px",
2746
- textAlign: "center",
2747
- width: "100%"
2748
- }
2749
- },
2750
- children: [
2751
- {
2752
- id: gen("heading"),
2753
- type: "heading",
2754
- props: { text: "Ready to boost your workflow?", level: 2 },
2755
- styles: {
2756
- base: { fontSize: "32px", fontWeight: "700", color: "#ffffff", marginBottom: "12px" }
2757
- }
2758
- },
2759
- {
2760
- id: gen("paragraph"),
2761
- type: "paragraph",
2762
- props: { content: "Start building with zero installation and instant live preview." },
2763
- styles: {
2764
- base: { fontSize: "16px", color: "#94a3b8", marginBottom: "24px", maxWidth: "600px", margin: "0 auto 24px auto" }
2765
- }
2766
- },
2767
- {
2768
- id: gen("button"),
2769
- type: "button",
2770
- props: { label: "Start Free Trial", href: "#signup" },
2771
- styles: {
2772
- base: {
2773
- backgroundColor: "#ffffff",
2774
- color: "#0f172a",
2775
- padding: "12px 28px",
2776
- borderRadius: "8px",
2777
- fontWeight: "700",
2778
- display: "inline-block"
2779
- },
2780
- states: {
2781
- ":hover": { backgroundColor: "#f1f5f9" }
2782
- }
2783
- }
2784
- }
2785
- ]
2786
- })
2787
- }
2788
- ];
2789
157
  export {
158
+ CONTENT_CHILD_TYPES,
2790
159
  ComponentRegistry,
160
+ FORM_STARTER_BLOCKS,
161
+ LAYOUT_PARENTS,
162
+ LAYOUT_STARTER_BLOCKS,
2791
163
  STARTER_BLOCKS,
2792
164
  TRAIT_GROUP_LABELS,
2793
165
  TRAIT_GROUP_ORDER,
166
+ UI_STARTER_BLOCKS,
167
+ acceptTrait,
2794
168
  actionTrait,
2795
169
  altTrait,
2796
170
  ariaLabelTrait,
2797
171
  autoCompleteTrait,
172
+ autoDisableOnSubmitTrait,
173
+ autoGrowTrait,
2798
174
  autoplayTrait,
2799
175
  badgeDefinition,
2800
176
  blockquoteDefinition,
2801
177
  buttonDefinition,
178
+ buttonSubmitDefinition,
2802
179
  buttonTypeTrait,
2803
180
  checkboxDefinition,
2804
181
  citeTrait,
2805
182
  codeBlockDefinition,
2806
183
  colSpanTrait,
184
+ collapsibleDefinition,
2807
185
  collectTraitNames,
2808
186
  collectionDefinition,
2809
187
  columnsDefinition,
@@ -2812,42 +190,73 @@ export {
2812
190
  coreComponentDefinitions,
2813
191
  createDefaultComponentRegistry,
2814
192
  defaultCheckedTrait,
193
+ defaultGenId,
194
+ defaultSelectedTrait,
2815
195
  defaultValueTrait,
2816
196
  disabledTrait,
197
+ drawerDefinition,
2817
198
  extractComponentRequirements,
2818
199
  fieldNameTrait,
200
+ fileUploadDefinition,
201
+ flexDefinition,
2819
202
  formDefinition,
203
+ gridDefinition,
2820
204
  headingDefinition,
205
+ helperTextTrait,
2821
206
  hrefTrait,
2822
207
  htmlEmbedDefinition,
2823
208
  iconDefinition,
2824
209
  idTrait,
2825
210
  imageDefinition,
211
+ indeterminateTrait,
2826
212
  inputDefinition,
2827
213
  inputTypeTrait,
2828
214
  isBindableField,
215
+ labelTextTrait,
2829
216
  linkDefinition,
2830
217
  listDefinition,
2831
218
  listItemDefinition,
219
+ loadingTextTrait,
2832
220
  loadingTrait,
2833
221
  loopTrait,
222
+ maxCharCountTrait,
223
+ maxFileSizeTrait,
224
+ maxLengthTrait,
2834
225
  methodTrait,
226
+ minLengthTrait,
227
+ modalDefinition,
228
+ multipleTrait,
2835
229
  mutedTrait,
230
+ optionsListTrait,
231
+ orientationTrait,
2836
232
  pageDefinition,
2837
233
  paragraphDefinition,
234
+ patternTrait,
2838
235
  placeholderTrait,
2839
236
  posterTrait,
237
+ prefixIconTrait,
238
+ preventDefaultTrait,
2840
239
  primitiveTypeForField,
2841
240
  radioDefinition,
241
+ radioGroupDefinition,
242
+ radioItemDefinition,
2842
243
  readOnlyTrait,
2843
244
  relTrait,
2844
245
  requiredTrait,
246
+ resetOnSubmitTrait,
247
+ resizeTrait,
2845
248
  rowSpanTrait,
2846
249
  rowsTrait,
250
+ scrollToFirstErrorTrait,
2847
251
  sectionDefinition,
2848
252
  selectDefinition,
253
+ showPreviewTrait,
254
+ showSpinnerTrait,
2849
255
  sortTraits,
2850
256
  srcTrait,
257
+ suffixIconTrait,
258
+ switchDefinition,
259
+ switchSizeTrait,
2851
260
  tableCellDefinition,
2852
261
  tableDefinition,
2853
262
  tableRowDefinition,
@@ -2857,6 +266,7 @@ export {
2857
266
  textareaDefinition,
2858
267
  titleTrait,
2859
268
  valueTrait,
2860
- videoDefinition
269
+ videoDefinition,
270
+ withOverrides
2861
271
  };
2862
272
  //# sourceMappingURL=index.js.map