@kubuild/components 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -21,16 +21,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ComponentRegistry: () => ComponentRegistry,
24
+ STARTER_BLOCKS: () => STARTER_BLOCKS,
24
25
  TRAIT_GROUP_LABELS: () => TRAIT_GROUP_LABELS,
25
26
  TRAIT_GROUP_ORDER: () => TRAIT_GROUP_ORDER,
27
+ acceptTrait: () => acceptTrait,
26
28
  actionTrait: () => actionTrait,
27
29
  altTrait: () => altTrait,
28
30
  ariaLabelTrait: () => ariaLabelTrait,
29
31
  autoCompleteTrait: () => autoCompleteTrait,
32
+ autoDisableOnSubmitTrait: () => autoDisableOnSubmitTrait,
33
+ autoGrowTrait: () => autoGrowTrait,
30
34
  autoplayTrait: () => autoplayTrait,
31
35
  badgeDefinition: () => badgeDefinition,
32
36
  blockquoteDefinition: () => blockquoteDefinition,
33
37
  buttonDefinition: () => buttonDefinition,
38
+ buttonSubmitDefinition: () => buttonSubmitDefinition,
34
39
  buttonTypeTrait: () => buttonTypeTrait,
35
40
  checkboxDefinition: () => checkboxDefinition,
36
41
  citeTrait: () => citeTrait,
@@ -44,42 +49,68 @@ __export(index_exports, {
44
49
  coreComponentDefinitions: () => coreComponentDefinitions,
45
50
  createDefaultComponentRegistry: () => createDefaultComponentRegistry,
46
51
  defaultCheckedTrait: () => defaultCheckedTrait,
52
+ defaultSelectedTrait: () => defaultSelectedTrait,
47
53
  defaultValueTrait: () => defaultValueTrait,
48
54
  disabledTrait: () => disabledTrait,
49
55
  extractComponentRequirements: () => extractComponentRequirements,
50
56
  fieldNameTrait: () => fieldNameTrait,
57
+ fileUploadDefinition: () => fileUploadDefinition,
51
58
  formDefinition: () => formDefinition,
52
59
  headingDefinition: () => headingDefinition,
60
+ helperTextTrait: () => helperTextTrait,
53
61
  hrefTrait: () => hrefTrait,
54
62
  htmlEmbedDefinition: () => htmlEmbedDefinition,
55
63
  iconDefinition: () => iconDefinition,
56
64
  idTrait: () => idTrait,
57
65
  imageDefinition: () => imageDefinition,
66
+ indeterminateTrait: () => indeterminateTrait,
58
67
  inputDefinition: () => inputDefinition,
59
68
  inputTypeTrait: () => inputTypeTrait,
60
69
  isBindableField: () => isBindableField,
70
+ labelTextTrait: () => labelTextTrait,
61
71
  linkDefinition: () => linkDefinition,
62
72
  listDefinition: () => listDefinition,
63
73
  listItemDefinition: () => listItemDefinition,
74
+ loadingTextTrait: () => loadingTextTrait,
64
75
  loadingTrait: () => loadingTrait,
65
76
  loopTrait: () => loopTrait,
77
+ maxCharCountTrait: () => maxCharCountTrait,
78
+ maxFileSizeTrait: () => maxFileSizeTrait,
79
+ maxLengthTrait: () => maxLengthTrait,
66
80
  methodTrait: () => methodTrait,
81
+ minLengthTrait: () => minLengthTrait,
82
+ multipleTrait: () => multipleTrait,
67
83
  mutedTrait: () => mutedTrait,
84
+ optionsListTrait: () => optionsListTrait,
85
+ orientationTrait: () => orientationTrait,
68
86
  pageDefinition: () => pageDefinition,
69
87
  paragraphDefinition: () => paragraphDefinition,
88
+ patternTrait: () => patternTrait,
70
89
  placeholderTrait: () => placeholderTrait,
71
90
  posterTrait: () => posterTrait,
91
+ prefixIconTrait: () => prefixIconTrait,
92
+ preventDefaultTrait: () => preventDefaultTrait,
72
93
  primitiveTypeForField: () => primitiveTypeForField,
73
94
  radioDefinition: () => radioDefinition,
95
+ radioGroupDefinition: () => radioGroupDefinition,
96
+ radioItemDefinition: () => radioItemDefinition,
74
97
  readOnlyTrait: () => readOnlyTrait,
75
98
  relTrait: () => relTrait,
76
99
  requiredTrait: () => requiredTrait,
100
+ resetOnSubmitTrait: () => resetOnSubmitTrait,
101
+ resizeTrait: () => resizeTrait,
77
102
  rowSpanTrait: () => rowSpanTrait,
78
103
  rowsTrait: () => rowsTrait,
104
+ scrollToFirstErrorTrait: () => scrollToFirstErrorTrait,
79
105
  sectionDefinition: () => sectionDefinition,
80
106
  selectDefinition: () => selectDefinition,
107
+ showPreviewTrait: () => showPreviewTrait,
108
+ showSpinnerTrait: () => showSpinnerTrait,
81
109
  sortTraits: () => sortTraits,
82
110
  srcTrait: () => srcTrait,
111
+ suffixIconTrait: () => suffixIconTrait,
112
+ switchDefinition: () => switchDefinition,
113
+ switchSizeTrait: () => switchSizeTrait,
83
114
  tableCellDefinition: () => tableCellDefinition,
84
115
  tableDefinition: () => tableDefinition,
85
116
  tableRowDefinition: () => tableRowDefinition,
@@ -670,6 +701,341 @@ function buttonTypeTrait(overrides) {
670
701
  overrides
671
702
  );
672
703
  }
704
+ function preventDefaultTrait(overrides) {
705
+ return withOverrides(
706
+ {
707
+ name: "preventDefault",
708
+ label: "Prevent Default",
709
+ type: "boolean",
710
+ defaultValue: true,
711
+ group: "form",
712
+ description: "Intercept the native browser submit and handle it via the KUBUILD action pipeline instead."
713
+ },
714
+ overrides
715
+ );
716
+ }
717
+ function scrollToFirstErrorTrait(overrides) {
718
+ return withOverrides(
719
+ {
720
+ name: "scrollToFirstError",
721
+ label: "Scroll to First Error",
722
+ type: "boolean",
723
+ defaultValue: true,
724
+ group: "form",
725
+ description: "Automatically scroll to and focus the first invalid field when submission fails validation."
726
+ },
727
+ overrides
728
+ );
729
+ }
730
+ function resetOnSubmitTrait(overrides) {
731
+ return withOverrides(
732
+ {
733
+ name: "resetOnSubmit",
734
+ label: "Reset on Submit",
735
+ type: "boolean",
736
+ defaultValue: false,
737
+ group: "form",
738
+ description: "Reset all fields to their initial values after a successful form submission."
739
+ },
740
+ overrides
741
+ );
742
+ }
743
+ function patternTrait(overrides) {
744
+ return withOverrides(
745
+ {
746
+ name: "pattern",
747
+ label: "Pattern (regex)",
748
+ type: "string",
749
+ attribute: "pattern",
750
+ group: "form",
751
+ description: "A regular expression the input value must match to pass validation."
752
+ },
753
+ overrides
754
+ );
755
+ }
756
+ function minLengthTrait(overrides) {
757
+ return withOverrides(
758
+ {
759
+ name: "minLength",
760
+ label: "Min Length",
761
+ type: "number",
762
+ attribute: "minlength",
763
+ group: "form",
764
+ description: "The minimum number of characters the user must enter."
765
+ },
766
+ overrides
767
+ );
768
+ }
769
+ function maxLengthTrait(overrides) {
770
+ return withOverrides(
771
+ {
772
+ name: "maxLength",
773
+ label: "Max Length",
774
+ type: "number",
775
+ attribute: "maxlength",
776
+ group: "form",
777
+ description: "The maximum number of characters the user is allowed to enter."
778
+ },
779
+ overrides
780
+ );
781
+ }
782
+ function prefixIconTrait(overrides) {
783
+ return withOverrides(
784
+ {
785
+ name: "prefixIcon",
786
+ label: "Prefix Icon",
787
+ type: "string",
788
+ group: "form",
789
+ description: 'Lucide icon name displayed before the input value (e.g. "mail", "search").'
790
+ },
791
+ overrides
792
+ );
793
+ }
794
+ function suffixIconTrait(overrides) {
795
+ return withOverrides(
796
+ {
797
+ name: "suffixIcon",
798
+ label: "Suffix Icon",
799
+ type: "string",
800
+ group: "form",
801
+ description: 'Lucide icon name displayed after the input value (e.g. "eye", "check").'
802
+ },
803
+ overrides
804
+ );
805
+ }
806
+ function helperTextTrait(overrides) {
807
+ return withOverrides(
808
+ {
809
+ name: "helperText",
810
+ label: "Helper Text",
811
+ type: "string",
812
+ group: "form",
813
+ description: 'A short message displayed below the input to guide the user (e.g. "Must be at least 8 characters").'
814
+ },
815
+ overrides
816
+ );
817
+ }
818
+ function resizeTrait(overrides) {
819
+ return withOverrides(
820
+ {
821
+ name: "resize",
822
+ label: "Resize",
823
+ type: "select",
824
+ defaultValue: "vertical",
825
+ group: "form",
826
+ options: [
827
+ { label: "Vertical only", value: "vertical" },
828
+ { label: "Horizontal only", value: "horizontal" },
829
+ { label: "Both", value: "both" },
830
+ { label: "None", value: "none" }
831
+ ],
832
+ description: "Controls whether and how the user can resize the textarea."
833
+ },
834
+ overrides
835
+ );
836
+ }
837
+ function autoGrowTrait(overrides) {
838
+ return withOverrides(
839
+ {
840
+ name: "autoGrow",
841
+ label: "Auto Grow",
842
+ type: "boolean",
843
+ defaultValue: false,
844
+ group: "form",
845
+ description: "Automatically expand the textarea height to fit the content without scrolling."
846
+ },
847
+ overrides
848
+ );
849
+ }
850
+ function maxCharCountTrait(overrides) {
851
+ return withOverrides(
852
+ {
853
+ name: "maxCharCount",
854
+ label: "Max Character Count",
855
+ type: "number",
856
+ group: "form",
857
+ description: 'Maximum character limit displayed as a counter below the textarea (e.g. "120 / 500").'
858
+ },
859
+ overrides
860
+ );
861
+ }
862
+ function optionsListTrait(overrides) {
863
+ return withOverrides(
864
+ {
865
+ name: "options",
866
+ label: "Options",
867
+ type: "string",
868
+ group: "form",
869
+ description: "The list of dropdown options, each with a label and value. Editable via the inspector trait panel."
870
+ },
871
+ overrides
872
+ );
873
+ }
874
+ function labelTextTrait(overrides) {
875
+ return withOverrides(
876
+ {
877
+ name: "label",
878
+ label: "Label Text",
879
+ type: "string",
880
+ group: "form",
881
+ description: "The visible text label displayed alongside the control."
882
+ },
883
+ overrides
884
+ );
885
+ }
886
+ function indeterminateTrait(overrides) {
887
+ return withOverrides(
888
+ {
889
+ name: "indeterminate",
890
+ label: "Indeterminate",
891
+ type: "boolean",
892
+ defaultValue: false,
893
+ group: "form",
894
+ description: "Renders the checkbox in a mixed/indeterminate visual state (neither checked nor unchecked)."
895
+ },
896
+ overrides
897
+ );
898
+ }
899
+ function switchSizeTrait(overrides) {
900
+ return withOverrides(
901
+ {
902
+ name: "switchSize",
903
+ label: "Size",
904
+ type: "select",
905
+ defaultValue: "md",
906
+ group: "form",
907
+ options: [
908
+ { label: "Small", value: "sm" },
909
+ { label: "Medium", value: "md" },
910
+ { label: "Large", value: "lg" }
911
+ ],
912
+ description: "The visual size of the switch toggle."
913
+ },
914
+ overrides
915
+ );
916
+ }
917
+ function orientationTrait(overrides) {
918
+ return withOverrides(
919
+ {
920
+ name: "orientation",
921
+ label: "Orientation",
922
+ type: "select",
923
+ defaultValue: "vertical",
924
+ group: "form",
925
+ options: [
926
+ { label: "Vertical", value: "vertical" },
927
+ { label: "Horizontal", value: "horizontal" }
928
+ ],
929
+ description: "The layout direction of the child controls (vertical stack or horizontal row)."
930
+ },
931
+ overrides
932
+ );
933
+ }
934
+ function defaultSelectedTrait(overrides) {
935
+ return withOverrides(
936
+ {
937
+ name: "defaultSelected",
938
+ label: "Default Selected",
939
+ type: "string",
940
+ group: "form",
941
+ description: "The value of the radio item that is selected by default."
942
+ },
943
+ overrides
944
+ );
945
+ }
946
+ function acceptTrait(overrides) {
947
+ return withOverrides(
948
+ {
949
+ name: "accept",
950
+ label: "Accepted File Types",
951
+ type: "string",
952
+ attribute: "accept",
953
+ defaultValue: "*/*",
954
+ group: "form",
955
+ description: 'Comma-separated list of MIME types or file extensions accepted (e.g. "image/*,.pdf,.docx").'
956
+ },
957
+ overrides
958
+ );
959
+ }
960
+ function maxFileSizeTrait(overrides) {
961
+ return withOverrides(
962
+ {
963
+ name: "maxFileSize",
964
+ label: "Max File Size (MB)",
965
+ type: "number",
966
+ defaultValue: 10,
967
+ group: "form",
968
+ description: "The maximum allowable file size in megabytes (MB)."
969
+ },
970
+ overrides
971
+ );
972
+ }
973
+ function multipleTrait(overrides) {
974
+ return withOverrides(
975
+ {
976
+ name: "multiple",
977
+ label: "Allow Multiple Files",
978
+ type: "boolean",
979
+ attribute: "multiple",
980
+ defaultValue: false,
981
+ group: "form",
982
+ description: "Allow multiple files to be selected and uploaded at once."
983
+ },
984
+ overrides
985
+ );
986
+ }
987
+ function showPreviewTrait(overrides) {
988
+ return withOverrides(
989
+ {
990
+ name: "showPreview",
991
+ label: "Show Preview",
992
+ type: "boolean",
993
+ defaultValue: true,
994
+ group: "form",
995
+ description: "Display an interactive preview (image thumbnail or file list with badges) for selected files."
996
+ },
997
+ overrides
998
+ );
999
+ }
1000
+ function loadingTextTrait(overrides) {
1001
+ return withOverrides(
1002
+ {
1003
+ name: "loadingText",
1004
+ label: "Loading Text",
1005
+ type: "string",
1006
+ defaultValue: "Submitting...",
1007
+ group: "behavior",
1008
+ description: "Text displayed on the button while the form submission is in progress."
1009
+ },
1010
+ overrides
1011
+ );
1012
+ }
1013
+ function showSpinnerTrait(overrides) {
1014
+ return withOverrides(
1015
+ {
1016
+ name: "showSpinner",
1017
+ label: "Show Loading Spinner",
1018
+ type: "boolean",
1019
+ defaultValue: true,
1020
+ group: "behavior",
1021
+ description: "Automatically show an animated loading spinner icon while form is submitting."
1022
+ },
1023
+ overrides
1024
+ );
1025
+ }
1026
+ function autoDisableOnSubmitTrait(overrides) {
1027
+ return withOverrides(
1028
+ {
1029
+ name: "autoDisableOnSubmit",
1030
+ label: "Auto Disable on Submit",
1031
+ type: "boolean",
1032
+ defaultValue: true,
1033
+ group: "behavior",
1034
+ description: "Automatically disable the button to prevent duplicate submissions while the form is submitting."
1035
+ },
1036
+ overrides
1037
+ );
1038
+ }
673
1039
  function sortTraits(traits) {
674
1040
  const groupRank = (group) => {
675
1041
  if (!group) return Number.MAX_SAFE_INTEGER;
@@ -703,12 +1069,17 @@ var CONTENT_CHILD_TYPES = [
703
1069
  "icon",
704
1070
  "html-embed",
705
1071
  "button",
1072
+ "button-submit",
706
1073
  "form",
707
1074
  "input",
708
1075
  "textarea",
709
1076
  "select",
710
1077
  "checkbox",
1078
+ "switch",
1079
+ "radio-group",
711
1080
  "radio",
1081
+ "radio-item",
1082
+ "file-upload",
712
1083
  "list",
713
1084
  "table",
714
1085
  "collection",
@@ -1800,7 +2171,10 @@ var formDefinition = {
1800
2171
  method: "POST",
1801
2172
  action: "",
1802
2173
  target: "_self",
1803
- autoComplete: "on"
2174
+ autoComplete: "on",
2175
+ preventDefault: true,
2176
+ scrollToFirstError: true,
2177
+ resetOnSubmit: false
1804
2178
  },
1805
2179
  defaultChildren: [
1806
2180
  { type: "input", props: { name: "name", type: "text", placeholder: "Your Name", required: true } },
@@ -1841,7 +2215,10 @@ var formDefinition = {
1841
2215
  { label: "On", value: "on" },
1842
2216
  { label: "Off", value: "off" }
1843
2217
  ]
1844
- }
2218
+ },
2219
+ { name: "preventDefault", label: "Prevent Default", type: "boolean", defaultValue: true },
2220
+ { name: "scrollToFirstError", label: "Scroll to First Error", type: "boolean", defaultValue: true },
2221
+ { name: "resetOnSubmit", label: "Reset on Submit", type: "boolean", defaultValue: false }
1845
2222
  ],
1846
2223
  traits: [
1847
2224
  fieldNameTrait({ defaultValue: "contact_form", required: false }),
@@ -1854,6 +2231,9 @@ var formDefinition = {
1854
2231
  { label: "Top (_top)", value: "_top" }
1855
2232
  ] }),
1856
2233
  autoCompleteTrait(),
2234
+ preventDefaultTrait(),
2235
+ scrollToFirstErrorTrait(),
2236
+ resetOnSubmitTrait(),
1857
2237
  idTrait(),
1858
2238
  ariaLabelTrait({ description: "Accessible name for the form landmark." })
1859
2239
  ],
@@ -1880,6 +2260,15 @@ var formDefinition = {
1880
2260
  errors.push('Form "autoComplete" must be either "on" or "off".');
1881
2261
  }
1882
2262
  }
2263
+ if (props.preventDefault !== void 0 && typeof props.preventDefault !== "boolean" && !(0, import_schema.isVariableBinding)(props.preventDefault)) {
2264
+ errors.push('Form "preventDefault" must be a boolean when provided.');
2265
+ }
2266
+ if (props.scrollToFirstError !== void 0 && typeof props.scrollToFirstError !== "boolean" && !(0, import_schema.isVariableBinding)(props.scrollToFirstError)) {
2267
+ errors.push('Form "scrollToFirstError" must be a boolean when provided.');
2268
+ }
2269
+ if (props.resetOnSubmit !== void 0 && typeof props.resetOnSubmit !== "boolean" && !(0, import_schema.isVariableBinding)(props.resetOnSubmit)) {
2270
+ errors.push('Form "resetOnSubmit" must be a boolean when provided.');
2271
+ }
1883
2272
  return errors.length > 0 ? errors : true;
1884
2273
  },
1885
2274
  defaultStyles: {
@@ -1905,7 +2294,13 @@ var inputDefinition = {
1905
2294
  defaultValue: "",
1906
2295
  required: false,
1907
2296
  disabled: false,
1908
- readOnly: false
2297
+ readOnly: false,
2298
+ pattern: "",
2299
+ minLength: void 0,
2300
+ maxLength: void 0,
2301
+ prefixIcon: "",
2302
+ suffixIcon: "",
2303
+ helperText: ""
1909
2304
  },
1910
2305
  propFields: [
1911
2306
  { name: "name", label: "Field Name", type: "string", defaultValue: "input_field" },
@@ -1929,7 +2324,13 @@ var inputDefinition = {
1929
2324
  { name: "defaultValue", label: "Default Value", type: "string" },
1930
2325
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
1931
2326
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1932
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
2327
+ { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false },
2328
+ { name: "pattern", label: "Pattern (regex)", type: "string" },
2329
+ { name: "minLength", label: "Min Length", type: "number" },
2330
+ { name: "maxLength", label: "Max Length", type: "number" },
2331
+ { name: "prefixIcon", label: "Prefix Icon", type: "string" },
2332
+ { name: "suffixIcon", label: "Suffix Icon", type: "string" },
2333
+ { name: "helperText", label: "Helper Text", type: "string" }
1933
2334
  ],
1934
2335
  traits: [
1935
2336
  inputTypeTrait({ options: [
@@ -1947,6 +2348,12 @@ var inputDefinition = {
1947
2348
  placeholderTrait({ defaultValue: "Enter text..." }),
1948
2349
  defaultValueTrait(),
1949
2350
  requiredTrait(),
2351
+ patternTrait(),
2352
+ minLengthTrait(),
2353
+ maxLengthTrait(),
2354
+ prefixIconTrait(),
2355
+ suffixIconTrait(),
2356
+ helperTextTrait(),
1950
2357
  disabledTrait(),
1951
2358
  readOnlyTrait(),
1952
2359
  idTrait(),
@@ -1975,6 +2382,28 @@ var inputDefinition = {
1975
2382
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !(0, import_schema.isVariableBinding)(props.readOnly)) {
1976
2383
  errors.push('Input "readOnly" must be a boolean when provided.');
1977
2384
  }
2385
+ if (props.pattern !== void 0 && typeof props.pattern !== "string" && !(0, import_schema.isVariableBinding)(props.pattern)) {
2386
+ errors.push('Input "pattern" must be a string when provided.');
2387
+ }
2388
+ if (props.minLength !== void 0 && !(0, import_schema.isVariableBinding)(props.minLength)) {
2389
+ if (typeof props.minLength !== "number" || props.minLength < 0 || !Number.isInteger(props.minLength)) {
2390
+ errors.push('Input "minLength" must be a non-negative integer when provided.');
2391
+ }
2392
+ }
2393
+ if (props.maxLength !== void 0 && !(0, import_schema.isVariableBinding)(props.maxLength)) {
2394
+ if (typeof props.maxLength !== "number" || props.maxLength < 0 || !Number.isInteger(props.maxLength)) {
2395
+ errors.push('Input "maxLength" must be a non-negative integer when provided.');
2396
+ }
2397
+ }
2398
+ if (props.prefixIcon !== void 0 && typeof props.prefixIcon !== "string" && !(0, import_schema.isVariableBinding)(props.prefixIcon)) {
2399
+ errors.push('Input "prefixIcon" must be a string when provided.');
2400
+ }
2401
+ if (props.suffixIcon !== void 0 && typeof props.suffixIcon !== "string" && !(0, import_schema.isVariableBinding)(props.suffixIcon)) {
2402
+ errors.push('Input "suffixIcon" must be a string when provided.');
2403
+ }
2404
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2405
+ errors.push('Input "helperText" must be a string when provided.');
2406
+ }
1978
2407
  return errors.length > 0 ? errors : true;
1979
2408
  },
1980
2409
  defaultStyles: {
@@ -2009,7 +2438,11 @@ var textareaDefinition = {
2009
2438
  rows: 4,
2010
2439
  required: false,
2011
2440
  disabled: false,
2012
- readOnly: false
2441
+ readOnly: false,
2442
+ resize: "vertical",
2443
+ autoGrow: false,
2444
+ maxCharCount: void 0,
2445
+ helperText: ""
2013
2446
  },
2014
2447
  propFields: [
2015
2448
  { name: "name", label: "Field Name", type: "string", defaultValue: "message" },
@@ -2018,13 +2451,32 @@ var textareaDefinition = {
2018
2451
  { name: "rows", label: "Rows", type: "number", defaultValue: 4 },
2019
2452
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2020
2453
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2021
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
2454
+ { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false },
2455
+ {
2456
+ name: "resize",
2457
+ label: "Resize",
2458
+ type: "select",
2459
+ defaultValue: "vertical",
2460
+ options: [
2461
+ { label: "Vertical only", value: "vertical" },
2462
+ { label: "Horizontal only", value: "horizontal" },
2463
+ { label: "Both", value: "both" },
2464
+ { label: "None", value: "none" }
2465
+ ]
2466
+ },
2467
+ { name: "autoGrow", label: "Auto Grow", type: "boolean", defaultValue: false },
2468
+ { name: "maxCharCount", label: "Max Character Count", type: "number" },
2469
+ { name: "helperText", label: "Helper Text", type: "string" }
2022
2470
  ],
2023
2471
  traits: [
2024
2472
  fieldNameTrait({ defaultValue: "message" }),
2025
2473
  placeholderTrait({ defaultValue: "Enter your message..." }),
2026
2474
  defaultValueTrait(),
2027
2475
  rowsTrait(),
2476
+ resizeTrait(),
2477
+ autoGrowTrait(),
2478
+ maxCharCountTrait(),
2479
+ helperTextTrait(),
2028
2480
  requiredTrait(),
2029
2481
  disabledTrait(),
2030
2482
  readOnlyTrait(),
@@ -2053,6 +2505,23 @@ var textareaDefinition = {
2053
2505
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !(0, import_schema.isVariableBinding)(props.readOnly)) {
2054
2506
  errors.push('Textarea "readOnly" must be a boolean when provided.');
2055
2507
  }
2508
+ if (props.resize !== void 0 && !(0, import_schema.isVariableBinding)(props.resize)) {
2509
+ const allowedResize = ["vertical", "horizontal", "both", "none"];
2510
+ if (typeof props.resize !== "string" || !allowedResize.includes(props.resize)) {
2511
+ errors.push(`Textarea "resize" must be one of: ${allowedResize.join(", ")}.`);
2512
+ }
2513
+ }
2514
+ if (props.autoGrow !== void 0 && typeof props.autoGrow !== "boolean" && !(0, import_schema.isVariableBinding)(props.autoGrow)) {
2515
+ errors.push('Textarea "autoGrow" must be a boolean when provided.');
2516
+ }
2517
+ if (props.maxCharCount !== void 0 && !(0, import_schema.isVariableBinding)(props.maxCharCount)) {
2518
+ if (typeof props.maxCharCount !== "number" || props.maxCharCount < 1 || !Number.isInteger(props.maxCharCount)) {
2519
+ errors.push('Textarea "maxCharCount" must be a positive integer (>= 1) when provided.');
2520
+ }
2521
+ }
2522
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2523
+ errors.push('Textarea "helperText" must be a string when provided.');
2524
+ }
2056
2525
  return errors.length > 0 ? errors : true;
2057
2526
  },
2058
2527
  defaultStyles: {
@@ -2090,7 +2559,8 @@ var selectDefinition = {
2090
2559
  ],
2091
2560
  defaultValue: "",
2092
2561
  required: false,
2093
- disabled: false
2562
+ disabled: false,
2563
+ helperText: ""
2094
2564
  },
2095
2565
  propFields: [
2096
2566
  { name: "name", label: "Field Name", type: "string", defaultValue: "select_field" },
@@ -2107,12 +2577,15 @@ var selectDefinition = {
2107
2577
  },
2108
2578
  { name: "defaultValue", label: "Default Selected Value", type: "string" },
2109
2579
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2110
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2580
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2581
+ { name: "helperText", label: "Helper Text", type: "string" }
2111
2582
  ],
2112
2583
  traits: [
2113
2584
  fieldNameTrait({ defaultValue: "select_field" }),
2114
2585
  placeholderTrait({ defaultValue: "Select an option..." }),
2586
+ optionsListTrait({ description: "The list of dropdown choices (label + value pairs). Editable via the inspector trait panel." }),
2115
2587
  defaultValueTrait({ description: "The initially selected option value (must match one of the option values)." }),
2588
+ helperTextTrait(),
2116
2589
  requiredTrait(),
2117
2590
  disabledTrait(),
2118
2591
  idTrait(),
@@ -2134,6 +2607,9 @@ var selectDefinition = {
2134
2607
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2135
2608
  errors.push('Select "disabled" must be a boolean when provided.');
2136
2609
  }
2610
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2611
+ errors.push('Select "helperText" must be a string when provided.');
2612
+ }
2137
2613
  return errors.length > 0 ? errors : true;
2138
2614
  },
2139
2615
  defaultStyles: {
@@ -2166,21 +2642,28 @@ var checkboxDefinition = {
2166
2642
  label: "I agree to the terms and conditions",
2167
2643
  value: "yes",
2168
2644
  defaultChecked: false,
2645
+ indeterminate: false,
2169
2646
  required: false,
2170
- disabled: false
2647
+ disabled: false,
2648
+ helperText: ""
2171
2649
  },
2172
2650
  propFields: [
2173
2651
  { name: "name", label: "Field Name", type: "string", defaultValue: "checkbox_field" },
2174
2652
  { name: "label", label: "Label Text", type: "string", defaultValue: "I agree to the terms and conditions" },
2175
2653
  { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2176
2654
  { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2655
+ { name: "indeterminate", label: "Indeterminate", type: "boolean", defaultValue: false },
2177
2656
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2178
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2657
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2658
+ { name: "helperText", label: "Helper Text", type: "string" }
2179
2659
  ],
2180
2660
  traits: [
2181
2661
  fieldNameTrait({ defaultValue: "checkbox_field" }),
2662
+ labelTextTrait({ defaultValue: "I agree to the terms and conditions" }),
2182
2663
  valueTrait({ defaultValue: "yes" }),
2183
2664
  defaultCheckedTrait(),
2665
+ indeterminateTrait(),
2666
+ helperTextTrait(),
2184
2667
  requiredTrait(),
2185
2668
  disabledTrait(),
2186
2669
  idTrait(),
@@ -2200,12 +2683,18 @@ var checkboxDefinition = {
2200
2683
  if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !(0, import_schema.isVariableBinding)(props.defaultChecked)) {
2201
2684
  errors.push('Checkbox "defaultChecked" must be a boolean when provided.');
2202
2685
  }
2686
+ if (props.indeterminate !== void 0 && typeof props.indeterminate !== "boolean" && !(0, import_schema.isVariableBinding)(props.indeterminate)) {
2687
+ errors.push('Checkbox "indeterminate" must be a boolean when provided.');
2688
+ }
2203
2689
  if (props.required !== void 0 && typeof props.required !== "boolean" && !(0, import_schema.isVariableBinding)(props.required)) {
2204
2690
  errors.push('Checkbox "required" must be a boolean when provided.');
2205
2691
  }
2206
2692
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2207
2693
  errors.push('Checkbox "disabled" must be a boolean when provided.');
2208
2694
  }
2695
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2696
+ errors.push('Checkbox "helperText" must be a string when provided.');
2697
+ }
2209
2698
  return errors.length > 0 ? errors : true;
2210
2699
  },
2211
2700
  defaultStyles: {
@@ -2220,20 +2709,194 @@ var checkboxDefinition = {
2220
2709
  }
2221
2710
  }
2222
2711
  };
2223
- var radioDefinition = {
2224
- type: "radio",
2225
- label: "Radio",
2712
+ var switchDefinition = {
2713
+ type: "switch",
2714
+ label: "Switch",
2226
2715
  category: "form",
2227
- icon: "radio",
2716
+ icon: "switch",
2228
2717
  acceptsChildren: false,
2229
2718
  disallowedParents: ["page"],
2230
2719
  defaultProps: {
2231
- name: "radio_group",
2232
- label: "Option 1",
2233
- value: "option1",
2720
+ name: "switch_field",
2721
+ label: "Enable feature",
2722
+ value: "yes",
2234
2723
  defaultChecked: false,
2724
+ switchSize: "md",
2235
2725
  required: false,
2236
- disabled: false
2726
+ disabled: false,
2727
+ helperText: ""
2728
+ },
2729
+ propFields: [
2730
+ { name: "name", label: "Field Name", type: "string", defaultValue: "switch_field" },
2731
+ { name: "label", label: "Label Text", type: "string", defaultValue: "Enable feature" },
2732
+ { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2733
+ { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2734
+ {
2735
+ name: "switchSize",
2736
+ label: "Size",
2737
+ type: "select",
2738
+ defaultValue: "md",
2739
+ options: [
2740
+ { label: "Small", value: "sm" },
2741
+ { label: "Medium", value: "md" },
2742
+ { label: "Large", value: "lg" }
2743
+ ]
2744
+ },
2745
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2746
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2747
+ { name: "helperText", label: "Helper Text", type: "string" }
2748
+ ],
2749
+ traits: [
2750
+ fieldNameTrait({ defaultValue: "switch_field" }),
2751
+ labelTextTrait({ defaultValue: "Enable feature" }),
2752
+ valueTrait({ defaultValue: "yes" }),
2753
+ defaultCheckedTrait(),
2754
+ switchSizeTrait(),
2755
+ helperTextTrait(),
2756
+ requiredTrait(),
2757
+ disabledTrait(),
2758
+ idTrait(),
2759
+ ariaLabelTrait()
2760
+ ],
2761
+ validateProps: (props) => {
2762
+ const errors = [];
2763
+ if (props.label !== void 0 && typeof props.label !== "string" && !(0, import_schema.isVariableBinding)(props.label)) {
2764
+ errors.push('Switch "label" must be a string when provided.');
2765
+ }
2766
+ if (props.name !== void 0 && typeof props.name !== "string" && !(0, import_schema.isVariableBinding)(props.name)) {
2767
+ errors.push('Switch "name" must be a string when provided.');
2768
+ }
2769
+ if (props.value !== void 0 && typeof props.value !== "string" && !(0, import_schema.isVariableBinding)(props.value)) {
2770
+ errors.push('Switch "value" must be a string when provided.');
2771
+ }
2772
+ if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !(0, import_schema.isVariableBinding)(props.defaultChecked)) {
2773
+ errors.push('Switch "defaultChecked" must be a boolean when provided.');
2774
+ }
2775
+ if (props.switchSize !== void 0 && !(0, import_schema.isVariableBinding)(props.switchSize)) {
2776
+ const allowedSizes = ["sm", "md", "lg"];
2777
+ if (typeof props.switchSize !== "string" || !allowedSizes.includes(props.switchSize)) {
2778
+ errors.push(`Switch "switchSize" must be one of: ${allowedSizes.join(", ")}.`);
2779
+ }
2780
+ }
2781
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !(0, import_schema.isVariableBinding)(props.required)) {
2782
+ errors.push('Switch "required" must be a boolean when provided.');
2783
+ }
2784
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2785
+ errors.push('Switch "disabled" must be a boolean when provided.');
2786
+ }
2787
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2788
+ errors.push('Switch "helperText" must be a string when provided.');
2789
+ }
2790
+ return errors.length > 0 ? errors : true;
2791
+ },
2792
+ defaultStyles: {
2793
+ base: {
2794
+ display: "inline-flex",
2795
+ alignItems: "center",
2796
+ gap: "8px",
2797
+ fontSize: "14px",
2798
+ color: "#1e293b",
2799
+ cursor: "pointer",
2800
+ userSelect: "none"
2801
+ }
2802
+ }
2803
+ };
2804
+ var radioGroupDefinition = {
2805
+ type: "radio-group",
2806
+ label: "Radio Group",
2807
+ category: "form",
2808
+ icon: "radio-group",
2809
+ acceptsChildren: true,
2810
+ allowedChildren: ["radio", "radio-item", "custom"],
2811
+ disallowedParents: ["page"],
2812
+ defaultProps: {
2813
+ name: "radio_group",
2814
+ defaultSelected: "option1",
2815
+ orientation: "vertical",
2816
+ required: false,
2817
+ disabled: false,
2818
+ helperText: ""
2819
+ },
2820
+ defaultChildren: [
2821
+ { type: "radio", props: { name: "radio_group", label: "Option 1", value: "option1", defaultChecked: true } },
2822
+ { type: "radio", props: { name: "radio_group", label: "Option 2", value: "option2", defaultChecked: false } },
2823
+ { type: "radio", props: { name: "radio_group", label: "Option 3", value: "option3", defaultChecked: false } }
2824
+ ],
2825
+ propFields: [
2826
+ { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
2827
+ { name: "defaultSelected", label: "Default Selected", type: "string", defaultValue: "option1" },
2828
+ {
2829
+ name: "orientation",
2830
+ label: "Orientation",
2831
+ type: "select",
2832
+ defaultValue: "vertical",
2833
+ options: [
2834
+ { label: "Vertical", value: "vertical" },
2835
+ { label: "Horizontal", value: "horizontal" }
2836
+ ]
2837
+ },
2838
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2839
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2840
+ { name: "helperText", label: "Helper Text", type: "string" }
2841
+ ],
2842
+ traits: [
2843
+ fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2844
+ defaultSelectedTrait({ defaultValue: "option1" }),
2845
+ orientationTrait(),
2846
+ helperTextTrait(),
2847
+ requiredTrait(),
2848
+ disabledTrait(),
2849
+ idTrait(),
2850
+ ariaLabelTrait()
2851
+ ],
2852
+ validateProps: (props) => {
2853
+ const errors = [];
2854
+ if (props.name !== void 0 && typeof props.name !== "string" && !(0, import_schema.isVariableBinding)(props.name)) {
2855
+ errors.push('RadioGroup "name" must be a string when provided.');
2856
+ }
2857
+ if (props.defaultSelected !== void 0 && typeof props.defaultSelected !== "string" && !(0, import_schema.isVariableBinding)(props.defaultSelected)) {
2858
+ errors.push('RadioGroup "defaultSelected" must be a string when provided.');
2859
+ }
2860
+ if (props.orientation !== void 0 && !(0, import_schema.isVariableBinding)(props.orientation)) {
2861
+ const allowedOrientations = ["vertical", "horizontal"];
2862
+ if (typeof props.orientation !== "string" || !allowedOrientations.includes(props.orientation)) {
2863
+ errors.push(`RadioGroup "orientation" must be one of: ${allowedOrientations.join(", ")}.`);
2864
+ }
2865
+ }
2866
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !(0, import_schema.isVariableBinding)(props.required)) {
2867
+ errors.push('RadioGroup "required" must be a boolean when provided.');
2868
+ }
2869
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2870
+ errors.push('RadioGroup "disabled" must be a boolean when provided.');
2871
+ }
2872
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2873
+ errors.push('RadioGroup "helperText" must be a string when provided.');
2874
+ }
2875
+ return errors.length > 0 ? errors : true;
2876
+ },
2877
+ defaultStyles: {
2878
+ base: {
2879
+ display: "flex",
2880
+ flexDirection: "column",
2881
+ gap: "8px"
2882
+ }
2883
+ }
2884
+ };
2885
+ var radioDefinition = {
2886
+ type: "radio",
2887
+ label: "Radio",
2888
+ category: "form",
2889
+ icon: "radio",
2890
+ acceptsChildren: false,
2891
+ disallowedParents: ["page"],
2892
+ defaultProps: {
2893
+ name: "radio_group",
2894
+ label: "Option 1",
2895
+ value: "option1",
2896
+ defaultChecked: false,
2897
+ required: false,
2898
+ disabled: false,
2899
+ helperText: ""
2237
2900
  },
2238
2901
  propFields: [
2239
2902
  { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
@@ -2241,12 +2904,15 @@ var radioDefinition = {
2241
2904
  { name: "value", label: "Radio Value", type: "string", defaultValue: "option1" },
2242
2905
  { name: "defaultChecked", label: "Default Selected", type: "boolean", defaultValue: false },
2243
2906
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2244
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2907
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2908
+ { name: "helperText", label: "Helper Text", type: "string" }
2245
2909
  ],
2246
2910
  traits: [
2247
2911
  fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2912
+ labelTextTrait({ defaultValue: "Option 1" }),
2248
2913
  valueTrait({ defaultValue: "option1" }),
2249
2914
  defaultCheckedTrait(),
2915
+ helperTextTrait(),
2250
2916
  requiredTrait(),
2251
2917
  disabledTrait(),
2252
2918
  idTrait(),
@@ -2272,6 +2938,9 @@ var radioDefinition = {
2272
2938
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2273
2939
  errors.push('Radio "disabled" must be a boolean when provided.');
2274
2940
  }
2941
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
2942
+ errors.push('Radio "helperText" must be a string when provided.');
2943
+ }
2275
2944
  return errors.length > 0 ? errors : true;
2276
2945
  },
2277
2946
  defaultStyles: {
@@ -2286,6 +2955,206 @@ var radioDefinition = {
2286
2955
  }
2287
2956
  }
2288
2957
  };
2958
+ var radioItemDefinition = {
2959
+ ...radioDefinition,
2960
+ type: "radio-item",
2961
+ label: "Radio Item"
2962
+ };
2963
+ var fileUploadDefinition = {
2964
+ type: "file-upload",
2965
+ label: "File Upload",
2966
+ category: "form",
2967
+ icon: "upload",
2968
+ acceptsChildren: false,
2969
+ disallowedParents: ["page"],
2970
+ defaultProps: {
2971
+ name: "file_upload",
2972
+ label: "Upload File",
2973
+ accept: "*/*",
2974
+ maxFileSize: 10,
2975
+ multiple: false,
2976
+ showPreview: true,
2977
+ required: false,
2978
+ disabled: false,
2979
+ helperText: ""
2980
+ },
2981
+ propFields: [
2982
+ { name: "name", label: "Field Name", type: "string", defaultValue: "file_upload" },
2983
+ { name: "label", label: "Label Text", type: "string", defaultValue: "Upload File" },
2984
+ { name: "accept", label: "Accepted File Types", type: "string", defaultValue: "*/*" },
2985
+ { name: "maxFileSize", label: "Max File Size (MB)", type: "number", defaultValue: 10 },
2986
+ { name: "multiple", label: "Allow Multiple Files", type: "boolean", defaultValue: false },
2987
+ { name: "showPreview", label: "Show Preview", type: "boolean", defaultValue: true },
2988
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2989
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2990
+ { name: "helperText", label: "Helper Text", type: "string" }
2991
+ ],
2992
+ traits: [
2993
+ fieldNameTrait({ defaultValue: "file_upload" }),
2994
+ labelTextTrait({ defaultValue: "Upload File" }),
2995
+ acceptTrait(),
2996
+ maxFileSizeTrait(),
2997
+ multipleTrait(),
2998
+ showPreviewTrait(),
2999
+ helperTextTrait(),
3000
+ requiredTrait(),
3001
+ disabledTrait(),
3002
+ idTrait(),
3003
+ ariaLabelTrait()
3004
+ ],
3005
+ validateProps: (props) => {
3006
+ const errors = [];
3007
+ if (props.label !== void 0 && typeof props.label !== "string" && !(0, import_schema.isVariableBinding)(props.label)) {
3008
+ errors.push('FileUpload "label" must be a string when provided.');
3009
+ }
3010
+ if (props.name !== void 0 && typeof props.name !== "string" && !(0, import_schema.isVariableBinding)(props.name)) {
3011
+ errors.push('FileUpload "name" must be a string when provided.');
3012
+ }
3013
+ if (props.accept !== void 0 && typeof props.accept !== "string" && !(0, import_schema.isVariableBinding)(props.accept)) {
3014
+ errors.push('FileUpload "accept" must be a string when provided.');
3015
+ }
3016
+ if (props.maxFileSize !== void 0 && !(0, import_schema.isVariableBinding)(props.maxFileSize)) {
3017
+ if (typeof props.maxFileSize !== "number" || props.maxFileSize <= 0) {
3018
+ errors.push('FileUpload "maxFileSize" must be a positive number when provided.');
3019
+ }
3020
+ }
3021
+ if (props.multiple !== void 0 && typeof props.multiple !== "boolean" && !(0, import_schema.isVariableBinding)(props.multiple)) {
3022
+ errors.push('FileUpload "multiple" must be a boolean when provided.');
3023
+ }
3024
+ if (props.showPreview !== void 0 && typeof props.showPreview !== "boolean" && !(0, import_schema.isVariableBinding)(props.showPreview)) {
3025
+ errors.push('FileUpload "showPreview" must be a boolean when provided.');
3026
+ }
3027
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !(0, import_schema.isVariableBinding)(props.required)) {
3028
+ errors.push('FileUpload "required" must be a boolean when provided.');
3029
+ }
3030
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
3031
+ errors.push('FileUpload "disabled" must be a boolean when provided.');
3032
+ }
3033
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !(0, import_schema.isVariableBinding)(props.helperText)) {
3034
+ errors.push('FileUpload "helperText" must be a string when provided.');
3035
+ }
3036
+ return errors.length > 0 ? errors : true;
3037
+ },
3038
+ defaultStyles: {
3039
+ base: {
3040
+ display: "flex",
3041
+ flexDirection: "column",
3042
+ gap: "8px",
3043
+ fontSize: "14px",
3044
+ color: "#1e293b"
3045
+ }
3046
+ }
3047
+ };
3048
+ var buttonSubmitDefinition = {
3049
+ type: "button-submit",
3050
+ label: "Submit Button",
3051
+ category: "form",
3052
+ icon: "send",
3053
+ acceptsChildren: false,
3054
+ capabilities: ["actionRegistry"],
3055
+ disallowedParents: ["page"],
3056
+ defaultProps: {
3057
+ label: "Submit",
3058
+ loadingText: "Submitting...",
3059
+ showSpinner: true,
3060
+ autoDisableOnSubmit: true,
3061
+ variant: "primary",
3062
+ disabled: false,
3063
+ buttonType: "submit"
3064
+ },
3065
+ propFields: [
3066
+ { name: "label", label: "Label", type: "string", defaultValue: "Submit" },
3067
+ { name: "loadingText", label: "Loading Text", type: "string", defaultValue: "Submitting..." },
3068
+ { name: "showSpinner", label: "Show Loading Spinner", type: "boolean", defaultValue: true },
3069
+ { name: "autoDisableOnSubmit", label: "Auto Disable on Submit", type: "boolean", defaultValue: true },
3070
+ {
3071
+ name: "buttonType",
3072
+ label: "Button Type",
3073
+ type: "select",
3074
+ defaultValue: "submit",
3075
+ options: [
3076
+ { label: "Submit Form (submit)", value: "submit" },
3077
+ { label: "Reset Form (reset)", value: "reset" }
3078
+ ]
3079
+ },
3080
+ {
3081
+ name: "variant",
3082
+ label: "Variant",
3083
+ type: "select",
3084
+ defaultValue: "primary",
3085
+ options: [
3086
+ { label: "Primary", value: "primary" },
3087
+ { label: "Secondary", value: "secondary" }
3088
+ ]
3089
+ },
3090
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
3091
+ { name: "prefixIcon", label: "Prefix Icon", type: "string" },
3092
+ { name: "suffixIcon", label: "Suffix Icon", type: "string" }
3093
+ ],
3094
+ traits: [
3095
+ buttonTypeTrait({
3096
+ defaultValue: "submit",
3097
+ options: [
3098
+ { label: "Submit Form (submit)", value: "submit" },
3099
+ { label: "Reset Form (reset)", value: "reset" }
3100
+ ]
3101
+ }),
3102
+ labelTextTrait({ defaultValue: "Submit", label: "Label" }),
3103
+ loadingTextTrait(),
3104
+ showSpinnerTrait(),
3105
+ autoDisableOnSubmitTrait(),
3106
+ disabledTrait(),
3107
+ prefixIconTrait(),
3108
+ suffixIconTrait(),
3109
+ idTrait(),
3110
+ titleTrait(),
3111
+ ariaLabelTrait()
3112
+ ],
3113
+ validateProps: (props) => {
3114
+ const errors = [];
3115
+ const hasLabel = typeof props.label === "string" && props.label.trim().length > 0 || (0, import_schema.isVariableBinding)(props.label);
3116
+ if (!hasLabel) {
3117
+ errors.push('Submit Button requires a non-empty "label".');
3118
+ }
3119
+ if (props.loadingText !== void 0 && typeof props.loadingText !== "string" && !(0, import_schema.isVariableBinding)(props.loadingText)) {
3120
+ errors.push('Submit Button "loadingText" must be a string when provided.');
3121
+ }
3122
+ if (props.showSpinner !== void 0 && typeof props.showSpinner !== "boolean" && !(0, import_schema.isVariableBinding)(props.showSpinner)) {
3123
+ errors.push('Submit Button "showSpinner" must be a boolean when provided.');
3124
+ }
3125
+ if (props.autoDisableOnSubmit !== void 0 && typeof props.autoDisableOnSubmit !== "boolean" && !(0, import_schema.isVariableBinding)(props.autoDisableOnSubmit)) {
3126
+ errors.push('Submit Button "autoDisableOnSubmit" must be a boolean when provided.');
3127
+ }
3128
+ if (props.buttonType !== void 0 && !(0, import_schema.isVariableBinding)(props.buttonType)) {
3129
+ if (!["submit", "reset", "button"].includes(props.buttonType)) {
3130
+ errors.push('Submit Button "buttonType" must be one of: "submit", "reset", "button".');
3131
+ }
3132
+ }
3133
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
3134
+ errors.push('Submit Button "disabled" must be a boolean when provided.');
3135
+ }
3136
+ return errors.length > 0 ? errors : true;
3137
+ },
3138
+ defaultStyles: {
3139
+ base: {
3140
+ backgroundColor: "#2563eb",
3141
+ color: "#ffffff",
3142
+ paddingTop: "10px",
3143
+ paddingBottom: "10px",
3144
+ paddingLeft: "20px",
3145
+ paddingRight: "20px",
3146
+ borderRadius: "6px",
3147
+ fontWeight: "500",
3148
+ fontSize: "15px",
3149
+ border: "none",
3150
+ cursor: "pointer",
3151
+ display: "inline-flex",
3152
+ alignItems: "center",
3153
+ justifyContent: "center",
3154
+ gap: "8px"
3155
+ }
3156
+ }
3157
+ };
2289
3158
  var coreComponentDefinitions = [
2290
3159
  pageDefinition,
2291
3160
  sectionDefinition,
@@ -2303,12 +3172,17 @@ var coreComponentDefinitions = [
2303
3172
  iconDefinition,
2304
3173
  htmlEmbedDefinition,
2305
3174
  buttonDefinition,
3175
+ buttonSubmitDefinition,
2306
3176
  formDefinition,
2307
3177
  inputDefinition,
2308
3178
  textareaDefinition,
2309
3179
  selectDefinition,
2310
3180
  checkboxDefinition,
3181
+ switchDefinition,
3182
+ radioGroupDefinition,
2311
3183
  radioDefinition,
3184
+ radioItemDefinition,
3185
+ fileUploadDefinition,
2312
3186
  collectionDefinition,
2313
3187
  listDefinition,
2314
3188
  listItemDefinition,
@@ -2363,19 +3237,1291 @@ function primitiveTypeForField(field) {
2363
3237
  function isBindableField(field) {
2364
3238
  return primitiveTypeForField(field) !== void 0;
2365
3239
  }
3240
+
3241
+ // src/blocks.ts
3242
+ var nextId = 1;
3243
+ function defaultGenId(prefix = "node") {
3244
+ return `${prefix}-${Date.now().toString(36)}-${(nextId++).toString(36)}`;
3245
+ }
3246
+ var STARTER_BLOCKS = [
3247
+ // --- Layout Blocks (STORA-241) ---
3248
+ {
3249
+ id: "layout-1-col",
3250
+ name: "1 Column",
3251
+ category: "layout",
3252
+ categoryLabel: "Layout Blocks",
3253
+ description: "Full-width single column container inside a section",
3254
+ icon: "layout",
3255
+ createNodeTree: (gen = defaultGenId) => ({
3256
+ id: gen("section"),
3257
+ type: "section",
3258
+ styles: { base: { padding: "40px 20px", width: "100%" } },
3259
+ children: [
3260
+ {
3261
+ id: gen("container"),
3262
+ type: "container",
3263
+ props: { tag: "div" },
3264
+ styles: { base: { maxWidth: "1200px", margin: "0 auto", width: "100%" } },
3265
+ children: []
3266
+ }
3267
+ ]
3268
+ })
3269
+ },
3270
+ {
3271
+ id: "layout-2-col-50-50",
3272
+ name: "2 Columns (50/50)",
3273
+ category: "layout",
3274
+ categoryLabel: "Layout Blocks",
3275
+ description: "Two equal-width 50/50 columns with flexible layout",
3276
+ icon: "columns",
3277
+ createNodeTree: (gen = defaultGenId) => ({
3278
+ id: gen("section"),
3279
+ type: "section",
3280
+ styles: { base: { padding: "40px 20px", width: "100%" } },
3281
+ children: [
3282
+ {
3283
+ id: gen("columns"),
3284
+ type: "columns",
3285
+ props: { columns: 2, gap: "24px" },
3286
+ styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
3287
+ children: [
3288
+ {
3289
+ id: gen("container"),
3290
+ type: "container",
3291
+ props: { tag: "div" },
3292
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3293
+ children: []
3294
+ },
3295
+ {
3296
+ id: gen("container"),
3297
+ type: "container",
3298
+ props: { tag: "div" },
3299
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3300
+ children: []
3301
+ }
3302
+ ]
3303
+ }
3304
+ ]
3305
+ })
3306
+ },
3307
+ {
3308
+ id: "layout-2-col-30-70",
3309
+ name: "2 Columns (30/70)",
3310
+ category: "layout",
3311
+ categoryLabel: "Layout Blocks",
3312
+ description: "Two asymmetric columns: 30% sidebar and 70% main area",
3313
+ icon: "columns",
3314
+ createNodeTree: (gen = defaultGenId) => ({
3315
+ id: gen("section"),
3316
+ type: "section",
3317
+ styles: { base: { padding: "40px 20px", width: "100%" } },
3318
+ children: [
3319
+ {
3320
+ id: gen("columns"),
3321
+ type: "columns",
3322
+ props: { columns: 2, gap: "24px" },
3323
+ styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
3324
+ children: [
3325
+ {
3326
+ id: gen("container"),
3327
+ type: "container",
3328
+ props: { tag: "div" },
3329
+ styles: { base: { flex: "0 0 30%", minWidth: "0" } },
3330
+ children: []
3331
+ },
3332
+ {
3333
+ id: gen("container"),
3334
+ type: "container",
3335
+ props: { tag: "div" },
3336
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3337
+ children: []
3338
+ }
3339
+ ]
3340
+ }
3341
+ ]
3342
+ })
3343
+ },
3344
+ {
3345
+ id: "layout-3-col",
3346
+ name: "3 Columns",
3347
+ category: "layout",
3348
+ categoryLabel: "Layout Blocks",
3349
+ description: "Three equal-width columns for grid showcases or card groups",
3350
+ icon: "grid",
3351
+ createNodeTree: (gen = defaultGenId) => ({
3352
+ id: gen("section"),
3353
+ type: "section",
3354
+ styles: { base: { padding: "40px 20px", width: "100%" } },
3355
+ children: [
3356
+ {
3357
+ id: gen("columns"),
3358
+ type: "columns",
3359
+ props: { columns: 3, gap: "24px" },
3360
+ styles: { base: { display: "flex", gap: "24px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
3361
+ children: [
3362
+ {
3363
+ id: gen("container"),
3364
+ type: "container",
3365
+ props: { tag: "div" },
3366
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3367
+ children: []
3368
+ },
3369
+ {
3370
+ id: gen("container"),
3371
+ type: "container",
3372
+ props: { tag: "div" },
3373
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3374
+ children: []
3375
+ },
3376
+ {
3377
+ id: gen("container"),
3378
+ type: "container",
3379
+ props: { tag: "div" },
3380
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3381
+ children: []
3382
+ }
3383
+ ]
3384
+ }
3385
+ ]
3386
+ })
3387
+ },
3388
+ {
3389
+ id: "layout-4-col",
3390
+ name: "4 Columns",
3391
+ category: "layout",
3392
+ categoryLabel: "Layout Blocks",
3393
+ description: "Four equal columns for metric stats, logos, or compact feature cards",
3394
+ icon: "grid",
3395
+ createNodeTree: (gen = defaultGenId) => ({
3396
+ id: gen("section"),
3397
+ type: "section",
3398
+ styles: { base: { padding: "40px 20px", width: "100%" } },
3399
+ children: [
3400
+ {
3401
+ id: gen("columns"),
3402
+ type: "columns",
3403
+ props: { columns: 4, gap: "16px" },
3404
+ styles: { base: { display: "flex", gap: "16px", width: "100%", maxWidth: "1200px", margin: "0 auto" } },
3405
+ children: [
3406
+ {
3407
+ id: gen("container"),
3408
+ type: "container",
3409
+ props: { tag: "div" },
3410
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3411
+ children: []
3412
+ },
3413
+ {
3414
+ id: gen("container"),
3415
+ type: "container",
3416
+ props: { tag: "div" },
3417
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3418
+ children: []
3419
+ },
3420
+ {
3421
+ id: gen("container"),
3422
+ type: "container",
3423
+ props: { tag: "div" },
3424
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3425
+ children: []
3426
+ },
3427
+ {
3428
+ id: gen("container"),
3429
+ type: "container",
3430
+ props: { tag: "div" },
3431
+ styles: { base: { flex: "1 1 0%", minWidth: "0" } },
3432
+ children: []
3433
+ }
3434
+ ]
3435
+ }
3436
+ ]
3437
+ })
3438
+ },
3439
+ // --- Pre-composed UI Blocks (STORA-242) ---
3440
+ {
3441
+ id: "hero-section",
3442
+ name: "Hero Section",
3443
+ category: "sections",
3444
+ categoryLabel: "Hero & Headers",
3445
+ description: "Engaging hero banner with headline, lead paragraph, and call-to-action button",
3446
+ icon: "layout",
3447
+ createNodeTree: (gen = defaultGenId) => ({
3448
+ id: gen("section"),
3449
+ type: "section",
3450
+ styles: {
3451
+ base: {
3452
+ padding: "80px 24px",
3453
+ backgroundColor: "#f8fafc",
3454
+ textAlign: "center",
3455
+ width: "100%"
3456
+ }
3457
+ },
3458
+ children: [
3459
+ {
3460
+ id: gen("container"),
3461
+ type: "container",
3462
+ props: { tag: "div" },
3463
+ styles: { base: { maxWidth: "768px", margin: "0 auto" } },
3464
+ children: [
3465
+ {
3466
+ id: gen("heading"),
3467
+ type: "heading",
3468
+ props: { text: "Build Remarkable Experiences", level: 1 },
3469
+ styles: {
3470
+ base: {
3471
+ fontSize: "44px",
3472
+ fontWeight: "800",
3473
+ color: "#0f172a",
3474
+ marginBottom: "16px",
3475
+ lineHeight: "1.2"
3476
+ }
3477
+ }
3478
+ },
3479
+ {
3480
+ id: gen("paragraph"),
3481
+ type: "paragraph",
3482
+ props: {
3483
+ content: "A visual builder designed for maximum craft, responsiveness, and performance."
3484
+ },
3485
+ styles: {
3486
+ base: {
3487
+ fontSize: "18px",
3488
+ color: "#475569",
3489
+ marginBottom: "32px",
3490
+ lineHeight: "1.6"
3491
+ }
3492
+ }
3493
+ },
3494
+ {
3495
+ id: gen("button"),
3496
+ type: "button",
3497
+ props: { label: "Get Started Today", href: "#explore" },
3498
+ styles: {
3499
+ base: {
3500
+ backgroundColor: "#2563eb",
3501
+ color: "#ffffff",
3502
+ padding: "12px 28px",
3503
+ borderRadius: "8px",
3504
+ fontWeight: "600",
3505
+ display: "inline-block"
3506
+ },
3507
+ states: {
3508
+ ":hover": { backgroundColor: "#1d4ed8" }
3509
+ }
3510
+ }
3511
+ }
3512
+ ]
3513
+ }
3514
+ ]
3515
+ })
3516
+ },
3517
+ {
3518
+ id: "feature-card",
3519
+ name: "Feature Card",
3520
+ category: "ui",
3521
+ categoryLabel: "UI Blocks",
3522
+ description: "Clean elevated feature card with badge, title, text, and action link",
3523
+ icon: "box",
3524
+ createNodeTree: (gen = defaultGenId) => ({
3525
+ id: gen("container"),
3526
+ type: "container",
3527
+ props: { tag: "div" },
3528
+ styles: {
3529
+ base: {
3530
+ padding: "24px",
3531
+ backgroundColor: "#ffffff",
3532
+ borderRadius: "12px",
3533
+ border: "1px solid #e2e8f0",
3534
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.05)"
3535
+ }
3536
+ },
3537
+ children: [
3538
+ {
3539
+ id: gen("badge"),
3540
+ type: "badge",
3541
+ props: { label: "PRO FEATURE", variant: "primary" },
3542
+ styles: { base: { marginBottom: "12px", display: "inline-block" } }
3543
+ },
3544
+ {
3545
+ id: gen("heading"),
3546
+ type: "heading",
3547
+ props: { text: "Next-Gen Performance", level: 3 },
3548
+ styles: {
3549
+ base: { fontSize: "20px", fontWeight: "700", color: "#1e293b", marginBottom: "8px" }
3550
+ }
3551
+ },
3552
+ {
3553
+ id: gen("paragraph"),
3554
+ type: "paragraph",
3555
+ props: {
3556
+ content: "Engineered for sub-millisecond render updates and zero runtime overhead."
3557
+ },
3558
+ styles: { base: { fontSize: "14px", color: "#64748b", lineHeight: "1.5" } }
3559
+ }
3560
+ ]
3561
+ })
3562
+ },
3563
+ {
3564
+ id: "media-object",
3565
+ name: "Media Object",
3566
+ category: "ui",
3567
+ categoryLabel: "UI Blocks",
3568
+ description: "Horizontal media layout with image beside text content",
3569
+ icon: "image",
3570
+ createNodeTree: (gen = defaultGenId) => ({
3571
+ id: gen("container"),
3572
+ type: "container",
3573
+ props: { tag: "div" },
3574
+ styles: {
3575
+ base: {
3576
+ display: "flex",
3577
+ gap: "16px",
3578
+ alignItems: "flex-start",
3579
+ padding: "16px",
3580
+ backgroundColor: "#ffffff",
3581
+ borderRadius: "8px",
3582
+ border: "1px solid #e2e8f0"
3583
+ }
3584
+ },
3585
+ children: [
3586
+ {
3587
+ id: gen("image"),
3588
+ type: "image",
3589
+ props: {
3590
+ src: "https://images.unsplash.com/photo-1579546929518-9e396f3cc809?w=160&auto=format&fit=crop&q=80",
3591
+ alt: "Visual preview"
3592
+ },
3593
+ styles: {
3594
+ base: {
3595
+ width: "80px",
3596
+ height: "80px",
3597
+ borderRadius: "8px",
3598
+ objectFit: "cover",
3599
+ flexShrink: "0"
3600
+ }
3601
+ }
3602
+ },
3603
+ {
3604
+ id: gen("container"),
3605
+ type: "container",
3606
+ props: { tag: "div" },
3607
+ styles: { base: { flex: "1 1 0%" } },
3608
+ children: [
3609
+ {
3610
+ id: gen("heading"),
3611
+ type: "heading",
3612
+ props: { text: "Creative Studio Asset", level: 4 },
3613
+ styles: {
3614
+ base: { fontSize: "16px", fontWeight: "600", color: "#0f172a", marginBottom: "4px" }
3615
+ }
3616
+ },
3617
+ {
3618
+ id: gen("paragraph"),
3619
+ type: "paragraph",
3620
+ props: { content: "High dynamic range gradients crafted for modern presentations." },
3621
+ styles: { base: { fontSize: "13px", color: "#64748b", lineHeight: "1.4" } }
3622
+ }
3623
+ ]
3624
+ }
3625
+ ]
3626
+ })
3627
+ },
3628
+ {
3629
+ id: "pricing-table",
3630
+ name: "Pricing Table",
3631
+ category: "pricing",
3632
+ categoryLabel: "Pricing",
3633
+ description: "Highlighted subscription pricing plan with price, feature list, and buy button",
3634
+ icon: "table",
3635
+ createNodeTree: (gen = defaultGenId) => ({
3636
+ id: gen("container"),
3637
+ type: "container",
3638
+ props: { tag: "div" },
3639
+ styles: {
3640
+ base: {
3641
+ padding: "32px 24px",
3642
+ backgroundColor: "#ffffff",
3643
+ borderRadius: "16px",
3644
+ border: "2px solid #3b82f6",
3645
+ boxShadow: "0 10px 15px -3px rgba(59, 130, 246, 0.1)",
3646
+ textAlign: "center",
3647
+ maxWidth: "360px"
3648
+ }
3649
+ },
3650
+ children: [
3651
+ {
3652
+ id: gen("badge"),
3653
+ type: "badge",
3654
+ props: { label: "MOST POPULAR", variant: "primary" },
3655
+ styles: { base: { marginBottom: "12px", display: "inline-block" } }
3656
+ },
3657
+ {
3658
+ id: gen("heading"),
3659
+ type: "heading",
3660
+ props: { text: "Professional", level: 3 },
3661
+ styles: { base: { fontSize: "22px", fontWeight: "700", color: "#0f172a" } }
3662
+ },
3663
+ {
3664
+ id: gen("heading"),
3665
+ type: "heading",
3666
+ props: { text: "$29 / mo", level: 2 },
3667
+ styles: {
3668
+ base: { fontSize: "36px", fontWeight: "800", color: "#2563eb", margin: "16px 0 24px 0" }
3669
+ }
3670
+ },
3671
+ {
3672
+ id: gen("paragraph"),
3673
+ type: "paragraph",
3674
+ props: { content: "Includes unlimited pages, custom domains, and team collaboration." },
3675
+ styles: { base: { fontSize: "14px", color: "#64748b", marginBottom: "24px" } }
3676
+ },
3677
+ {
3678
+ id: gen("button"),
3679
+ type: "button",
3680
+ props: { label: "Upgrade to Pro", href: "#checkout" },
3681
+ styles: {
3682
+ base: {
3683
+ width: "100%",
3684
+ backgroundColor: "#2563eb",
3685
+ color: "#ffffff",
3686
+ padding: "12px",
3687
+ borderRadius: "8px",
3688
+ fontWeight: "600",
3689
+ display: "block"
3690
+ },
3691
+ states: {
3692
+ ":hover": { backgroundColor: "#1d4ed8" }
3693
+ }
3694
+ }
3695
+ }
3696
+ ]
3697
+ })
3698
+ },
3699
+ {
3700
+ id: "cta-banner",
3701
+ name: "CTA Banner",
3702
+ category: "cta",
3703
+ categoryLabel: "Call to Action",
3704
+ description: "High-contrast conversion banner with title and action button",
3705
+ icon: "layout",
3706
+ createNodeTree: (gen = defaultGenId) => ({
3707
+ id: gen("section"),
3708
+ type: "section",
3709
+ styles: {
3710
+ base: {
3711
+ padding: "60px 24px",
3712
+ backgroundColor: "#0f172a",
3713
+ color: "#ffffff",
3714
+ borderRadius: "16px",
3715
+ textAlign: "center",
3716
+ width: "100%"
3717
+ }
3718
+ },
3719
+ children: [
3720
+ {
3721
+ id: gen("heading"),
3722
+ type: "heading",
3723
+ props: { text: "Ready to boost your workflow?", level: 2 },
3724
+ styles: {
3725
+ base: { fontSize: "32px", fontWeight: "700", color: "#ffffff", marginBottom: "12px" }
3726
+ }
3727
+ },
3728
+ {
3729
+ id: gen("paragraph"),
3730
+ type: "paragraph",
3731
+ props: { content: "Start building with zero installation and instant live preview." },
3732
+ styles: {
3733
+ base: { fontSize: "16px", color: "#94a3b8", marginBottom: "24px", maxWidth: "600px", margin: "0 auto 24px auto" }
3734
+ }
3735
+ },
3736
+ {
3737
+ id: gen("button"),
3738
+ type: "button",
3739
+ props: { label: "Start Free Trial", href: "#signup" },
3740
+ styles: {
3741
+ base: {
3742
+ backgroundColor: "#ffffff",
3743
+ color: "#0f172a",
3744
+ padding: "12px 28px",
3745
+ borderRadius: "8px",
3746
+ fontWeight: "700",
3747
+ display: "inline-block"
3748
+ },
3749
+ states: {
3750
+ ":hover": { backgroundColor: "#f1f5f9" }
3751
+ }
3752
+ }
3753
+ }
3754
+ ]
3755
+ })
3756
+ },
3757
+ // --- Starter Form Templates (STORA-350) ---
3758
+ {
3759
+ id: "form-contact-us",
3760
+ name: "Contact Us Form",
3761
+ category: "forms",
3762
+ categoryLabel: "Form Templates",
3763
+ description: "Contact form with Name, Email, Subject, Message, and submit action pipeline with API request and toast notifications",
3764
+ icon: "form",
3765
+ createNodeTree: (gen = defaultGenId) => ({
3766
+ id: gen("section"),
3767
+ type: "section",
3768
+ styles: {
3769
+ base: {
3770
+ padding: "64px 20px",
3771
+ backgroundColor: "#f8fafc",
3772
+ width: "100%"
3773
+ }
3774
+ },
3775
+ children: [
3776
+ {
3777
+ id: gen("container"),
3778
+ type: "container",
3779
+ props: { tag: "div", maxWidth: "640px" },
3780
+ styles: {
3781
+ base: {
3782
+ maxWidth: "640px",
3783
+ margin: "0 auto",
3784
+ width: "100%",
3785
+ backgroundColor: "#ffffff",
3786
+ padding: "36px",
3787
+ borderRadius: "16px",
3788
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05)",
3789
+ border: "1px solid #e2e8f0"
3790
+ }
3791
+ },
3792
+ children: [
3793
+ {
3794
+ id: gen("heading"),
3795
+ type: "heading",
3796
+ props: { text: "Contact Us", level: 2 },
3797
+ styles: {
3798
+ base: {
3799
+ fontSize: "28px",
3800
+ fontWeight: "700",
3801
+ color: "#0f172a",
3802
+ marginBottom: "8px",
3803
+ textAlign: "center"
3804
+ }
3805
+ }
3806
+ },
3807
+ {
3808
+ id: gen("paragraph"),
3809
+ type: "paragraph",
3810
+ props: {
3811
+ content: "Have questions or need assistance? Fill out the form below and we will get back to you shortly."
3812
+ },
3813
+ styles: {
3814
+ base: {
3815
+ fontSize: "15px",
3816
+ color: "#64748b",
3817
+ marginBottom: "28px",
3818
+ textAlign: "center",
3819
+ lineHeight: "1.5"
3820
+ }
3821
+ }
3822
+ },
3823
+ {
3824
+ id: gen("form"),
3825
+ type: "form",
3826
+ props: {
3827
+ name: "contact_us_form",
3828
+ method: "POST",
3829
+ preventDefault: true,
3830
+ scrollToFirstError: true,
3831
+ resetOnSubmit: true
3832
+ },
3833
+ styles: {
3834
+ base: {
3835
+ display: "flex",
3836
+ flexDirection: "column",
3837
+ gap: "20px",
3838
+ width: "100%"
3839
+ }
3840
+ },
3841
+ actions: [
3842
+ {
3843
+ id: gen("pipeline"),
3844
+ trigger: "submit",
3845
+ label: "Submit Contact Form",
3846
+ enabled: true,
3847
+ steps: [
3848
+ {
3849
+ id: gen("step"),
3850
+ type: "api_request",
3851
+ label: "Send Contact Message",
3852
+ payload: {
3853
+ url: "/api/mock/submit-lead",
3854
+ method: "POST",
3855
+ bodyFormat: "json"
3856
+ },
3857
+ onSuccess: [
3858
+ {
3859
+ id: gen("step"),
3860
+ type: "show_toast",
3861
+ label: "Show Success Toast",
3862
+ payload: {
3863
+ message: "Thank you! Your message has been sent successfully.",
3864
+ type: "success",
3865
+ title: "Message Sent",
3866
+ duration: 4e3
3867
+ }
3868
+ },
3869
+ {
3870
+ id: gen("step"),
3871
+ type: "reset_form",
3872
+ label: "Reset Form",
3873
+ payload: {}
3874
+ }
3875
+ ],
3876
+ onError: [
3877
+ {
3878
+ id: gen("step"),
3879
+ type: "show_toast",
3880
+ label: "Show Error Toast",
3881
+ payload: {
3882
+ message: "Failed to send message. Please check your connection and try again.",
3883
+ type: "error",
3884
+ title: "Submission Failed",
3885
+ duration: 5e3
3886
+ }
3887
+ }
3888
+ ]
3889
+ }
3890
+ ]
3891
+ }
3892
+ ],
3893
+ children: [
3894
+ {
3895
+ id: gen("input"),
3896
+ type: "input",
3897
+ props: {
3898
+ name: "name",
3899
+ label: "Your Name",
3900
+ type: "text",
3901
+ placeholder: "Jane Doe",
3902
+ required: true,
3903
+ rules: [
3904
+ { type: "required", message: "Please enter your name" },
3905
+ { type: "min_length", value: 2, message: "Name must be at least 2 characters" }
3906
+ ]
3907
+ },
3908
+ styles: {
3909
+ base: {
3910
+ width: "100%",
3911
+ padding: "10px 14px",
3912
+ borderRadius: "8px",
3913
+ border: "1px solid #cbd5e1",
3914
+ fontSize: "14px"
3915
+ }
3916
+ }
3917
+ },
3918
+ {
3919
+ id: gen("input"),
3920
+ type: "input",
3921
+ props: {
3922
+ name: "email",
3923
+ label: "Email Address",
3924
+ type: "email",
3925
+ placeholder: "jane@example.com",
3926
+ required: true,
3927
+ rules: [
3928
+ { type: "required", message: "Please enter your email" },
3929
+ { type: "email", message: "Please enter a valid email address" }
3930
+ ]
3931
+ },
3932
+ styles: {
3933
+ base: {
3934
+ width: "100%",
3935
+ padding: "10px 14px",
3936
+ borderRadius: "8px",
3937
+ border: "1px solid #cbd5e1",
3938
+ fontSize: "14px"
3939
+ }
3940
+ }
3941
+ },
3942
+ {
3943
+ id: gen("input"),
3944
+ type: "input",
3945
+ props: {
3946
+ name: "subject",
3947
+ label: "Subject",
3948
+ type: "text",
3949
+ placeholder: "How can we help you?",
3950
+ required: true,
3951
+ rules: [
3952
+ { type: "required", message: "Please enter a subject" }
3953
+ ]
3954
+ },
3955
+ styles: {
3956
+ base: {
3957
+ width: "100%",
3958
+ padding: "10px 14px",
3959
+ borderRadius: "8px",
3960
+ border: "1px solid #cbd5e1",
3961
+ fontSize: "14px"
3962
+ }
3963
+ }
3964
+ },
3965
+ {
3966
+ id: gen("textarea"),
3967
+ type: "textarea",
3968
+ props: {
3969
+ name: "message",
3970
+ label: "Message",
3971
+ placeholder: "Write your message here...",
3972
+ rows: 4,
3973
+ required: true,
3974
+ rules: [
3975
+ { type: "required", message: "Please enter your message" },
3976
+ { type: "min_length", value: 10, message: "Message must be at least 10 characters" }
3977
+ ]
3978
+ },
3979
+ styles: {
3980
+ base: {
3981
+ width: "100%",
3982
+ padding: "10px 14px",
3983
+ borderRadius: "8px",
3984
+ border: "1px solid #cbd5e1",
3985
+ fontSize: "14px"
3986
+ }
3987
+ }
3988
+ },
3989
+ {
3990
+ id: gen("button"),
3991
+ type: "button",
3992
+ props: {
3993
+ label: "Send Message",
3994
+ variant: "primary",
3995
+ buttonType: "submit"
3996
+ },
3997
+ styles: {
3998
+ base: {
3999
+ width: "100%",
4000
+ backgroundColor: "#2563eb",
4001
+ color: "#ffffff",
4002
+ padding: "12px",
4003
+ borderRadius: "8px",
4004
+ fontWeight: "600",
4005
+ fontSize: "15px",
4006
+ display: "inline-block",
4007
+ textAlign: "center"
4008
+ },
4009
+ states: {
4010
+ ":hover": { backgroundColor: "#1d4ed8" }
4011
+ }
4012
+ }
4013
+ }
4014
+ ]
4015
+ }
4016
+ ]
4017
+ }
4018
+ ]
4019
+ })
4020
+ },
4021
+ {
4022
+ id: "form-newsletter",
4023
+ name: "Newsletter Subscribe Form",
4024
+ category: "forms",
4025
+ categoryLabel: "Form Templates",
4026
+ description: "Inline email newsletter subscription form with real-time feedback",
4027
+ icon: "mail",
4028
+ createNodeTree: (gen = defaultGenId) => ({
4029
+ id: gen("section"),
4030
+ type: "section",
4031
+ styles: {
4032
+ base: {
4033
+ padding: "48px 20px",
4034
+ backgroundColor: "#f1f5f9",
4035
+ width: "100%"
4036
+ }
4037
+ },
4038
+ children: [
4039
+ {
4040
+ id: gen("container"),
4041
+ type: "container",
4042
+ props: { tag: "div", maxWidth: "580px" },
4043
+ styles: {
4044
+ base: {
4045
+ maxWidth: "580px",
4046
+ margin: "0 auto",
4047
+ width: "100%",
4048
+ textAlign: "center"
4049
+ }
4050
+ },
4051
+ children: [
4052
+ {
4053
+ id: gen("heading"),
4054
+ type: "heading",
4055
+ props: { text: "Stay in the Loop", level: 3 },
4056
+ styles: {
4057
+ base: {
4058
+ fontSize: "26px",
4059
+ fontWeight: "700",
4060
+ color: "#0f172a",
4061
+ marginBottom: "8px"
4062
+ }
4063
+ }
4064
+ },
4065
+ {
4066
+ id: gen("paragraph"),
4067
+ type: "paragraph",
4068
+ props: {
4069
+ content: "Subscribe to our newsletter for weekly curated insights, updates, and best practices."
4070
+ },
4071
+ styles: {
4072
+ base: {
4073
+ fontSize: "15px",
4074
+ color: "#64748b",
4075
+ marginBottom: "24px",
4076
+ lineHeight: "1.5"
4077
+ }
4078
+ }
4079
+ },
4080
+ {
4081
+ id: gen("form"),
4082
+ type: "form",
4083
+ props: {
4084
+ name: "newsletter_form",
4085
+ method: "POST",
4086
+ preventDefault: true,
4087
+ resetOnSubmit: true
4088
+ },
4089
+ styles: {
4090
+ base: {
4091
+ display: "flex",
4092
+ flexDirection: "row",
4093
+ gap: "8px",
4094
+ alignItems: "center",
4095
+ width: "100%"
4096
+ },
4097
+ mobile: {
4098
+ flexDirection: "column"
4099
+ }
4100
+ },
4101
+ actions: [
4102
+ {
4103
+ id: gen("pipeline"),
4104
+ trigger: "submit",
4105
+ label: "Subscribe to Newsletter",
4106
+ enabled: true,
4107
+ steps: [
4108
+ {
4109
+ id: gen("step"),
4110
+ type: "api_request",
4111
+ label: "Submit Subscription",
4112
+ payload: {
4113
+ url: "/api/mock/submit-lead",
4114
+ method: "POST",
4115
+ bodyFormat: "json"
4116
+ },
4117
+ onSuccess: [
4118
+ {
4119
+ id: gen("step"),
4120
+ type: "show_toast",
4121
+ label: "Show Success Toast",
4122
+ payload: {
4123
+ message: "Thank you for subscribing to our newsletter!",
4124
+ type: "success",
4125
+ title: "Subscription Confirmed",
4126
+ duration: 4e3
4127
+ }
4128
+ },
4129
+ {
4130
+ id: gen("step"),
4131
+ type: "reset_form",
4132
+ label: "Reset Form",
4133
+ payload: {}
4134
+ }
4135
+ ],
4136
+ onError: [
4137
+ {
4138
+ id: gen("step"),
4139
+ type: "show_toast",
4140
+ label: "Show Error Toast",
4141
+ payload: {
4142
+ message: "Unable to subscribe right now. Please try again later.",
4143
+ type: "error",
4144
+ title: "Error",
4145
+ duration: 5e3
4146
+ }
4147
+ }
4148
+ ]
4149
+ }
4150
+ ]
4151
+ }
4152
+ ],
4153
+ children: [
4154
+ {
4155
+ id: gen("input"),
4156
+ type: "input",
4157
+ props: {
4158
+ name: "email",
4159
+ type: "email",
4160
+ placeholder: "Enter your email address...",
4161
+ required: true,
4162
+ rules: [
4163
+ { type: "required", message: "Email address is required" },
4164
+ { type: "email", message: "Please enter a valid email address" }
4165
+ ]
4166
+ },
4167
+ styles: {
4168
+ base: {
4169
+ flex: "1 1 0%",
4170
+ minWidth: "0",
4171
+ padding: "12px 16px",
4172
+ borderRadius: "8px",
4173
+ border: "1px solid #cbd5e1",
4174
+ backgroundColor: "#ffffff",
4175
+ fontSize: "14px"
4176
+ }
4177
+ }
4178
+ },
4179
+ {
4180
+ id: gen("button"),
4181
+ type: "button",
4182
+ props: {
4183
+ label: "Subscribe",
4184
+ variant: "primary",
4185
+ buttonType: "submit"
4186
+ },
4187
+ styles: {
4188
+ base: {
4189
+ backgroundColor: "#2563eb",
4190
+ color: "#ffffff",
4191
+ padding: "12px 24px",
4192
+ borderRadius: "8px",
4193
+ fontWeight: "600",
4194
+ fontSize: "14px",
4195
+ whiteSpace: "nowrap"
4196
+ },
4197
+ states: {
4198
+ ":hover": { backgroundColor: "#1d4ed8" }
4199
+ }
4200
+ }
4201
+ }
4202
+ ]
4203
+ }
4204
+ ]
4205
+ }
4206
+ ]
4207
+ })
4208
+ },
4209
+ {
4210
+ id: "form-lead-gen",
4211
+ name: "Lead Generation Form",
4212
+ category: "forms",
4213
+ categoryLabel: "Form Templates",
4214
+ description: "Multi-field lead generation form with phone validation, interest dropdown, and API submission pipeline",
4215
+ icon: "users",
4216
+ createNodeTree: (gen = defaultGenId) => ({
4217
+ id: gen("section"),
4218
+ type: "section",
4219
+ styles: {
4220
+ base: {
4221
+ padding: "64px 20px",
4222
+ backgroundColor: "#ffffff",
4223
+ width: "100%"
4224
+ }
4225
+ },
4226
+ children: [
4227
+ {
4228
+ id: gen("container"),
4229
+ type: "container",
4230
+ props: { tag: "div", maxWidth: "640px" },
4231
+ styles: {
4232
+ base: {
4233
+ maxWidth: "640px",
4234
+ margin: "0 auto",
4235
+ width: "100%",
4236
+ backgroundColor: "#ffffff",
4237
+ padding: "36px",
4238
+ borderRadius: "16px",
4239
+ border: "1px solid #e2e8f0",
4240
+ boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.05)"
4241
+ }
4242
+ },
4243
+ children: [
4244
+ {
4245
+ id: gen("badge"),
4246
+ type: "badge",
4247
+ props: { label: "FREE CONSULTATION", variant: "primary" },
4248
+ styles: { base: { marginBottom: "12px", display: "inline-block" } }
4249
+ },
4250
+ {
4251
+ id: gen("heading"),
4252
+ type: "heading",
4253
+ props: { text: "Schedule a Consultation", level: 2 },
4254
+ styles: {
4255
+ base: {
4256
+ fontSize: "28px",
4257
+ fontWeight: "700",
4258
+ color: "#0f172a",
4259
+ marginBottom: "8px"
4260
+ }
4261
+ }
4262
+ },
4263
+ {
4264
+ id: gen("paragraph"),
4265
+ type: "paragraph",
4266
+ props: {
4267
+ content: "Share your project details with our solutions team. We will analyze your needs and provide a personalized roadmap."
4268
+ },
4269
+ styles: {
4270
+ base: {
4271
+ fontSize: "15px",
4272
+ color: "#64748b",
4273
+ marginBottom: "28px",
4274
+ lineHeight: "1.5"
4275
+ }
4276
+ }
4277
+ },
4278
+ {
4279
+ id: gen("form"),
4280
+ type: "form",
4281
+ props: {
4282
+ name: "lead_generation_form",
4283
+ method: "POST",
4284
+ preventDefault: true,
4285
+ scrollToFirstError: true,
4286
+ resetOnSubmit: true
4287
+ },
4288
+ styles: {
4289
+ base: {
4290
+ display: "flex",
4291
+ flexDirection: "column",
4292
+ gap: "18px",
4293
+ width: "100%"
4294
+ }
4295
+ },
4296
+ actions: [
4297
+ {
4298
+ id: gen("pipeline"),
4299
+ trigger: "submit",
4300
+ label: "Submit Lead Form",
4301
+ enabled: true,
4302
+ steps: [
4303
+ {
4304
+ id: gen("step"),
4305
+ type: "api_request",
4306
+ label: "Send Lead Data",
4307
+ payload: {
4308
+ url: "/api/mock/submit-lead",
4309
+ method: "POST",
4310
+ bodyFormat: "json"
4311
+ },
4312
+ onSuccess: [
4313
+ {
4314
+ id: gen("step"),
4315
+ type: "show_toast",
4316
+ label: "Show Success Toast",
4317
+ payload: {
4318
+ message: "Thank you! Your request has been received. Our team will contact you shortly.",
4319
+ type: "success",
4320
+ title: "Request Submitted",
4321
+ duration: 4e3
4322
+ }
4323
+ },
4324
+ {
4325
+ id: gen("step"),
4326
+ type: "reset_form",
4327
+ label: "Reset Form",
4328
+ payload: {}
4329
+ }
4330
+ ],
4331
+ onError: [
4332
+ {
4333
+ id: gen("step"),
4334
+ type: "show_toast",
4335
+ label: "Show Error Toast",
4336
+ payload: {
4337
+ message: "Submission failed. Please verify your information and try again.",
4338
+ type: "error",
4339
+ title: "Submission Error",
4340
+ duration: 5e3
4341
+ }
4342
+ }
4343
+ ]
4344
+ }
4345
+ ]
4346
+ }
4347
+ ],
4348
+ children: [
4349
+ {
4350
+ id: gen("input"),
4351
+ type: "input",
4352
+ props: {
4353
+ name: "full_name",
4354
+ label: "Full Name",
4355
+ type: "text",
4356
+ placeholder: "Alex Morgan",
4357
+ required: true,
4358
+ rules: [
4359
+ { type: "required", message: "Full name is required" },
4360
+ { type: "min_length", value: 2, message: "Name must be at least 2 characters" }
4361
+ ]
4362
+ },
4363
+ styles: {
4364
+ base: {
4365
+ width: "100%",
4366
+ padding: "10px 14px",
4367
+ borderRadius: "8px",
4368
+ border: "1px solid #cbd5e1",
4369
+ fontSize: "14px"
4370
+ }
4371
+ }
4372
+ },
4373
+ {
4374
+ id: gen("input"),
4375
+ type: "input",
4376
+ props: {
4377
+ name: "email",
4378
+ label: "Business Email",
4379
+ type: "email",
4380
+ placeholder: "alex@company.com",
4381
+ required: true,
4382
+ rules: [
4383
+ { type: "required", message: "Business email is required" },
4384
+ { type: "email", message: "Please enter a valid email address" }
4385
+ ]
4386
+ },
4387
+ styles: {
4388
+ base: {
4389
+ width: "100%",
4390
+ padding: "10px 14px",
4391
+ borderRadius: "8px",
4392
+ border: "1px solid #cbd5e1",
4393
+ fontSize: "14px"
4394
+ }
4395
+ }
4396
+ },
4397
+ {
4398
+ id: gen("input"),
4399
+ type: "input",
4400
+ props: {
4401
+ name: "phone",
4402
+ label: "Phone Number",
4403
+ type: "tel",
4404
+ placeholder: "+62 812-3456-7890",
4405
+ required: true,
4406
+ rules: [
4407
+ { type: "required", message: "Phone number is required" },
4408
+ {
4409
+ type: "custom_regex",
4410
+ value: "^[+]?[0-9\\s-()]{8,20}$",
4411
+ message: "Please enter a valid phone number (min 8 digits)"
4412
+ }
4413
+ ]
4414
+ },
4415
+ styles: {
4416
+ base: {
4417
+ width: "100%",
4418
+ padding: "10px 14px",
4419
+ borderRadius: "8px",
4420
+ border: "1px solid #cbd5e1",
4421
+ fontSize: "14px"
4422
+ }
4423
+ }
4424
+ },
4425
+ {
4426
+ id: gen("select"),
4427
+ type: "select",
4428
+ props: {
4429
+ name: "interest",
4430
+ label: "Area of Interest",
4431
+ placeholder: "Select your interest / service...",
4432
+ required: true,
4433
+ defaultValue: "",
4434
+ options: [
4435
+ { label: "Web Platform Development", value: "web_platform" },
4436
+ { label: "Mobile Application", value: "mobile_app" },
4437
+ { label: "Cloud Architecture & DevOps", value: "cloud_devops" },
4438
+ { label: "UI/UX Product Design", value: "product_design" },
4439
+ { label: "General Inquiry", value: "general" }
4440
+ ],
4441
+ rules: [
4442
+ { type: "required", message: "Please select an area of interest" }
4443
+ ]
4444
+ },
4445
+ styles: {
4446
+ base: {
4447
+ width: "100%",
4448
+ padding: "10px 14px",
4449
+ borderRadius: "8px",
4450
+ border: "1px solid #cbd5e1",
4451
+ fontSize: "14px",
4452
+ backgroundColor: "#ffffff"
4453
+ }
4454
+ }
4455
+ },
4456
+ {
4457
+ id: gen("input"),
4458
+ type: "input",
4459
+ props: {
4460
+ name: "company",
4461
+ label: "Company Name (Optional)",
4462
+ type: "text",
4463
+ placeholder: "Company / Organization"
4464
+ },
4465
+ styles: {
4466
+ base: {
4467
+ width: "100%",
4468
+ padding: "10px 14px",
4469
+ borderRadius: "8px",
4470
+ border: "1px solid #cbd5e1",
4471
+ fontSize: "14px"
4472
+ }
4473
+ }
4474
+ },
4475
+ {
4476
+ id: gen("button"),
4477
+ type: "button",
4478
+ props: {
4479
+ label: "Request Consultation",
4480
+ variant: "primary",
4481
+ buttonType: "submit"
4482
+ },
4483
+ styles: {
4484
+ base: {
4485
+ width: "100%",
4486
+ backgroundColor: "#2563eb",
4487
+ color: "#ffffff",
4488
+ padding: "12px 24px",
4489
+ borderRadius: "8px",
4490
+ fontWeight: "600",
4491
+ fontSize: "15px",
4492
+ marginTop: "4px"
4493
+ },
4494
+ states: {
4495
+ ":hover": { backgroundColor: "#1d4ed8" }
4496
+ }
4497
+ }
4498
+ }
4499
+ ]
4500
+ }
4501
+ ]
4502
+ }
4503
+ ]
4504
+ })
4505
+ }
4506
+ ];
2366
4507
  // Annotate the CommonJS export names for ESM import in node:
2367
4508
  0 && (module.exports = {
2368
4509
  ComponentRegistry,
4510
+ STARTER_BLOCKS,
2369
4511
  TRAIT_GROUP_LABELS,
2370
4512
  TRAIT_GROUP_ORDER,
4513
+ acceptTrait,
2371
4514
  actionTrait,
2372
4515
  altTrait,
2373
4516
  ariaLabelTrait,
2374
4517
  autoCompleteTrait,
4518
+ autoDisableOnSubmitTrait,
4519
+ autoGrowTrait,
2375
4520
  autoplayTrait,
2376
4521
  badgeDefinition,
2377
4522
  blockquoteDefinition,
2378
4523
  buttonDefinition,
4524
+ buttonSubmitDefinition,
2379
4525
  buttonTypeTrait,
2380
4526
  checkboxDefinition,
2381
4527
  citeTrait,
@@ -2389,42 +4535,68 @@ function isBindableField(field) {
2389
4535
  coreComponentDefinitions,
2390
4536
  createDefaultComponentRegistry,
2391
4537
  defaultCheckedTrait,
4538
+ defaultSelectedTrait,
2392
4539
  defaultValueTrait,
2393
4540
  disabledTrait,
2394
4541
  extractComponentRequirements,
2395
4542
  fieldNameTrait,
4543
+ fileUploadDefinition,
2396
4544
  formDefinition,
2397
4545
  headingDefinition,
4546
+ helperTextTrait,
2398
4547
  hrefTrait,
2399
4548
  htmlEmbedDefinition,
2400
4549
  iconDefinition,
2401
4550
  idTrait,
2402
4551
  imageDefinition,
4552
+ indeterminateTrait,
2403
4553
  inputDefinition,
2404
4554
  inputTypeTrait,
2405
4555
  isBindableField,
4556
+ labelTextTrait,
2406
4557
  linkDefinition,
2407
4558
  listDefinition,
2408
4559
  listItemDefinition,
4560
+ loadingTextTrait,
2409
4561
  loadingTrait,
2410
4562
  loopTrait,
4563
+ maxCharCountTrait,
4564
+ maxFileSizeTrait,
4565
+ maxLengthTrait,
2411
4566
  methodTrait,
4567
+ minLengthTrait,
4568
+ multipleTrait,
2412
4569
  mutedTrait,
4570
+ optionsListTrait,
4571
+ orientationTrait,
2413
4572
  pageDefinition,
2414
4573
  paragraphDefinition,
4574
+ patternTrait,
2415
4575
  placeholderTrait,
2416
4576
  posterTrait,
4577
+ prefixIconTrait,
4578
+ preventDefaultTrait,
2417
4579
  primitiveTypeForField,
2418
4580
  radioDefinition,
4581
+ radioGroupDefinition,
4582
+ radioItemDefinition,
2419
4583
  readOnlyTrait,
2420
4584
  relTrait,
2421
4585
  requiredTrait,
4586
+ resetOnSubmitTrait,
4587
+ resizeTrait,
2422
4588
  rowSpanTrait,
2423
4589
  rowsTrait,
4590
+ scrollToFirstErrorTrait,
2424
4591
  sectionDefinition,
2425
4592
  selectDefinition,
4593
+ showPreviewTrait,
4594
+ showSpinnerTrait,
2426
4595
  sortTraits,
2427
4596
  srcTrait,
4597
+ suffixIconTrait,
4598
+ switchDefinition,
4599
+ switchSizeTrait,
2428
4600
  tableCellDefinition,
2429
4601
  tableDefinition,
2430
4602
  tableRowDefinition,