@kubuild/components 0.1.0 → 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
@@ -24,14 +24,18 @@ __export(index_exports, {
24
24
  STARTER_BLOCKS: () => STARTER_BLOCKS,
25
25
  TRAIT_GROUP_LABELS: () => TRAIT_GROUP_LABELS,
26
26
  TRAIT_GROUP_ORDER: () => TRAIT_GROUP_ORDER,
27
+ acceptTrait: () => acceptTrait,
27
28
  actionTrait: () => actionTrait,
28
29
  altTrait: () => altTrait,
29
30
  ariaLabelTrait: () => ariaLabelTrait,
30
31
  autoCompleteTrait: () => autoCompleteTrait,
32
+ autoDisableOnSubmitTrait: () => autoDisableOnSubmitTrait,
33
+ autoGrowTrait: () => autoGrowTrait,
31
34
  autoplayTrait: () => autoplayTrait,
32
35
  badgeDefinition: () => badgeDefinition,
33
36
  blockquoteDefinition: () => blockquoteDefinition,
34
37
  buttonDefinition: () => buttonDefinition,
38
+ buttonSubmitDefinition: () => buttonSubmitDefinition,
35
39
  buttonTypeTrait: () => buttonTypeTrait,
36
40
  checkboxDefinition: () => checkboxDefinition,
37
41
  citeTrait: () => citeTrait,
@@ -45,42 +49,68 @@ __export(index_exports, {
45
49
  coreComponentDefinitions: () => coreComponentDefinitions,
46
50
  createDefaultComponentRegistry: () => createDefaultComponentRegistry,
47
51
  defaultCheckedTrait: () => defaultCheckedTrait,
52
+ defaultSelectedTrait: () => defaultSelectedTrait,
48
53
  defaultValueTrait: () => defaultValueTrait,
49
54
  disabledTrait: () => disabledTrait,
50
55
  extractComponentRequirements: () => extractComponentRequirements,
51
56
  fieldNameTrait: () => fieldNameTrait,
57
+ fileUploadDefinition: () => fileUploadDefinition,
52
58
  formDefinition: () => formDefinition,
53
59
  headingDefinition: () => headingDefinition,
60
+ helperTextTrait: () => helperTextTrait,
54
61
  hrefTrait: () => hrefTrait,
55
62
  htmlEmbedDefinition: () => htmlEmbedDefinition,
56
63
  iconDefinition: () => iconDefinition,
57
64
  idTrait: () => idTrait,
58
65
  imageDefinition: () => imageDefinition,
66
+ indeterminateTrait: () => indeterminateTrait,
59
67
  inputDefinition: () => inputDefinition,
60
68
  inputTypeTrait: () => inputTypeTrait,
61
69
  isBindableField: () => isBindableField,
70
+ labelTextTrait: () => labelTextTrait,
62
71
  linkDefinition: () => linkDefinition,
63
72
  listDefinition: () => listDefinition,
64
73
  listItemDefinition: () => listItemDefinition,
74
+ loadingTextTrait: () => loadingTextTrait,
65
75
  loadingTrait: () => loadingTrait,
66
76
  loopTrait: () => loopTrait,
77
+ maxCharCountTrait: () => maxCharCountTrait,
78
+ maxFileSizeTrait: () => maxFileSizeTrait,
79
+ maxLengthTrait: () => maxLengthTrait,
67
80
  methodTrait: () => methodTrait,
81
+ minLengthTrait: () => minLengthTrait,
82
+ multipleTrait: () => multipleTrait,
68
83
  mutedTrait: () => mutedTrait,
84
+ optionsListTrait: () => optionsListTrait,
85
+ orientationTrait: () => orientationTrait,
69
86
  pageDefinition: () => pageDefinition,
70
87
  paragraphDefinition: () => paragraphDefinition,
88
+ patternTrait: () => patternTrait,
71
89
  placeholderTrait: () => placeholderTrait,
72
90
  posterTrait: () => posterTrait,
91
+ prefixIconTrait: () => prefixIconTrait,
92
+ preventDefaultTrait: () => preventDefaultTrait,
73
93
  primitiveTypeForField: () => primitiveTypeForField,
74
94
  radioDefinition: () => radioDefinition,
95
+ radioGroupDefinition: () => radioGroupDefinition,
96
+ radioItemDefinition: () => radioItemDefinition,
75
97
  readOnlyTrait: () => readOnlyTrait,
76
98
  relTrait: () => relTrait,
77
99
  requiredTrait: () => requiredTrait,
100
+ resetOnSubmitTrait: () => resetOnSubmitTrait,
101
+ resizeTrait: () => resizeTrait,
78
102
  rowSpanTrait: () => rowSpanTrait,
79
103
  rowsTrait: () => rowsTrait,
104
+ scrollToFirstErrorTrait: () => scrollToFirstErrorTrait,
80
105
  sectionDefinition: () => sectionDefinition,
81
106
  selectDefinition: () => selectDefinition,
107
+ showPreviewTrait: () => showPreviewTrait,
108
+ showSpinnerTrait: () => showSpinnerTrait,
82
109
  sortTraits: () => sortTraits,
83
110
  srcTrait: () => srcTrait,
111
+ suffixIconTrait: () => suffixIconTrait,
112
+ switchDefinition: () => switchDefinition,
113
+ switchSizeTrait: () => switchSizeTrait,
84
114
  tableCellDefinition: () => tableCellDefinition,
85
115
  tableDefinition: () => tableDefinition,
86
116
  tableRowDefinition: () => tableRowDefinition,
@@ -671,6 +701,341 @@ function buttonTypeTrait(overrides) {
671
701
  overrides
672
702
  );
673
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
+ }
674
1039
  function sortTraits(traits) {
675
1040
  const groupRank = (group) => {
676
1041
  if (!group) return Number.MAX_SAFE_INTEGER;
@@ -704,12 +1069,17 @@ var CONTENT_CHILD_TYPES = [
704
1069
  "icon",
705
1070
  "html-embed",
706
1071
  "button",
1072
+ "button-submit",
707
1073
  "form",
708
1074
  "input",
709
1075
  "textarea",
710
1076
  "select",
711
1077
  "checkbox",
1078
+ "switch",
1079
+ "radio-group",
712
1080
  "radio",
1081
+ "radio-item",
1082
+ "file-upload",
713
1083
  "list",
714
1084
  "table",
715
1085
  "collection",
@@ -1801,7 +2171,10 @@ var formDefinition = {
1801
2171
  method: "POST",
1802
2172
  action: "",
1803
2173
  target: "_self",
1804
- autoComplete: "on"
2174
+ autoComplete: "on",
2175
+ preventDefault: true,
2176
+ scrollToFirstError: true,
2177
+ resetOnSubmit: false
1805
2178
  },
1806
2179
  defaultChildren: [
1807
2180
  { type: "input", props: { name: "name", type: "text", placeholder: "Your Name", required: true } },
@@ -1842,7 +2215,10 @@ var formDefinition = {
1842
2215
  { label: "On", value: "on" },
1843
2216
  { label: "Off", value: "off" }
1844
2217
  ]
1845
- }
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 }
1846
2222
  ],
1847
2223
  traits: [
1848
2224
  fieldNameTrait({ defaultValue: "contact_form", required: false }),
@@ -1855,6 +2231,9 @@ var formDefinition = {
1855
2231
  { label: "Top (_top)", value: "_top" }
1856
2232
  ] }),
1857
2233
  autoCompleteTrait(),
2234
+ preventDefaultTrait(),
2235
+ scrollToFirstErrorTrait(),
2236
+ resetOnSubmitTrait(),
1858
2237
  idTrait(),
1859
2238
  ariaLabelTrait({ description: "Accessible name for the form landmark." })
1860
2239
  ],
@@ -1881,6 +2260,15 @@ var formDefinition = {
1881
2260
  errors.push('Form "autoComplete" must be either "on" or "off".');
1882
2261
  }
1883
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
+ }
1884
2272
  return errors.length > 0 ? errors : true;
1885
2273
  },
1886
2274
  defaultStyles: {
@@ -1906,7 +2294,13 @@ var inputDefinition = {
1906
2294
  defaultValue: "",
1907
2295
  required: false,
1908
2296
  disabled: false,
1909
- readOnly: false
2297
+ readOnly: false,
2298
+ pattern: "",
2299
+ minLength: void 0,
2300
+ maxLength: void 0,
2301
+ prefixIcon: "",
2302
+ suffixIcon: "",
2303
+ helperText: ""
1910
2304
  },
1911
2305
  propFields: [
1912
2306
  { name: "name", label: "Field Name", type: "string", defaultValue: "input_field" },
@@ -1930,7 +2324,13 @@ var inputDefinition = {
1930
2324
  { name: "defaultValue", label: "Default Value", type: "string" },
1931
2325
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
1932
2326
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1933
- { 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" }
1934
2334
  ],
1935
2335
  traits: [
1936
2336
  inputTypeTrait({ options: [
@@ -1948,6 +2348,12 @@ var inputDefinition = {
1948
2348
  placeholderTrait({ defaultValue: "Enter text..." }),
1949
2349
  defaultValueTrait(),
1950
2350
  requiredTrait(),
2351
+ patternTrait(),
2352
+ minLengthTrait(),
2353
+ maxLengthTrait(),
2354
+ prefixIconTrait(),
2355
+ suffixIconTrait(),
2356
+ helperTextTrait(),
1951
2357
  disabledTrait(),
1952
2358
  readOnlyTrait(),
1953
2359
  idTrait(),
@@ -1976,6 +2382,28 @@ var inputDefinition = {
1976
2382
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !(0, import_schema.isVariableBinding)(props.readOnly)) {
1977
2383
  errors.push('Input "readOnly" must be a boolean when provided.');
1978
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
+ }
1979
2407
  return errors.length > 0 ? errors : true;
1980
2408
  },
1981
2409
  defaultStyles: {
@@ -2010,7 +2438,11 @@ var textareaDefinition = {
2010
2438
  rows: 4,
2011
2439
  required: false,
2012
2440
  disabled: false,
2013
- readOnly: false
2441
+ readOnly: false,
2442
+ resize: "vertical",
2443
+ autoGrow: false,
2444
+ maxCharCount: void 0,
2445
+ helperText: ""
2014
2446
  },
2015
2447
  propFields: [
2016
2448
  { name: "name", label: "Field Name", type: "string", defaultValue: "message" },
@@ -2019,13 +2451,32 @@ var textareaDefinition = {
2019
2451
  { name: "rows", label: "Rows", type: "number", defaultValue: 4 },
2020
2452
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2021
2453
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2022
- { 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" }
2023
2470
  ],
2024
2471
  traits: [
2025
2472
  fieldNameTrait({ defaultValue: "message" }),
2026
2473
  placeholderTrait({ defaultValue: "Enter your message..." }),
2027
2474
  defaultValueTrait(),
2028
2475
  rowsTrait(),
2476
+ resizeTrait(),
2477
+ autoGrowTrait(),
2478
+ maxCharCountTrait(),
2479
+ helperTextTrait(),
2029
2480
  requiredTrait(),
2030
2481
  disabledTrait(),
2031
2482
  readOnlyTrait(),
@@ -2054,6 +2505,23 @@ var textareaDefinition = {
2054
2505
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !(0, import_schema.isVariableBinding)(props.readOnly)) {
2055
2506
  errors.push('Textarea "readOnly" must be a boolean when provided.');
2056
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
+ }
2057
2525
  return errors.length > 0 ? errors : true;
2058
2526
  },
2059
2527
  defaultStyles: {
@@ -2091,7 +2559,8 @@ var selectDefinition = {
2091
2559
  ],
2092
2560
  defaultValue: "",
2093
2561
  required: false,
2094
- disabled: false
2562
+ disabled: false,
2563
+ helperText: ""
2095
2564
  },
2096
2565
  propFields: [
2097
2566
  { name: "name", label: "Field Name", type: "string", defaultValue: "select_field" },
@@ -2108,12 +2577,15 @@ var selectDefinition = {
2108
2577
  },
2109
2578
  { name: "defaultValue", label: "Default Selected Value", type: "string" },
2110
2579
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2111
- { 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" }
2112
2582
  ],
2113
2583
  traits: [
2114
2584
  fieldNameTrait({ defaultValue: "select_field" }),
2115
2585
  placeholderTrait({ defaultValue: "Select an option..." }),
2586
+ optionsListTrait({ description: "The list of dropdown choices (label + value pairs). Editable via the inspector trait panel." }),
2116
2587
  defaultValueTrait({ description: "The initially selected option value (must match one of the option values)." }),
2588
+ helperTextTrait(),
2117
2589
  requiredTrait(),
2118
2590
  disabledTrait(),
2119
2591
  idTrait(),
@@ -2135,6 +2607,9 @@ var selectDefinition = {
2135
2607
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2136
2608
  errors.push('Select "disabled" must be a boolean when provided.');
2137
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
+ }
2138
2613
  return errors.length > 0 ? errors : true;
2139
2614
  },
2140
2615
  defaultStyles: {
@@ -2167,21 +2642,28 @@ var checkboxDefinition = {
2167
2642
  label: "I agree to the terms and conditions",
2168
2643
  value: "yes",
2169
2644
  defaultChecked: false,
2645
+ indeterminate: false,
2170
2646
  required: false,
2171
- disabled: false
2647
+ disabled: false,
2648
+ helperText: ""
2172
2649
  },
2173
2650
  propFields: [
2174
2651
  { name: "name", label: "Field Name", type: "string", defaultValue: "checkbox_field" },
2175
2652
  { name: "label", label: "Label Text", type: "string", defaultValue: "I agree to the terms and conditions" },
2176
2653
  { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2177
2654
  { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2655
+ { name: "indeterminate", label: "Indeterminate", type: "boolean", defaultValue: false },
2178
2656
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2179
- { 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" }
2180
2659
  ],
2181
2660
  traits: [
2182
2661
  fieldNameTrait({ defaultValue: "checkbox_field" }),
2662
+ labelTextTrait({ defaultValue: "I agree to the terms and conditions" }),
2183
2663
  valueTrait({ defaultValue: "yes" }),
2184
2664
  defaultCheckedTrait(),
2665
+ indeterminateTrait(),
2666
+ helperTextTrait(),
2185
2667
  requiredTrait(),
2186
2668
  disabledTrait(),
2187
2669
  idTrait(),
@@ -2201,12 +2683,18 @@ var checkboxDefinition = {
2201
2683
  if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !(0, import_schema.isVariableBinding)(props.defaultChecked)) {
2202
2684
  errors.push('Checkbox "defaultChecked" must be a boolean when provided.');
2203
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
+ }
2204
2689
  if (props.required !== void 0 && typeof props.required !== "boolean" && !(0, import_schema.isVariableBinding)(props.required)) {
2205
2690
  errors.push('Checkbox "required" must be a boolean when provided.');
2206
2691
  }
2207
2692
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2208
2693
  errors.push('Checkbox "disabled" must be a boolean when provided.');
2209
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
+ }
2210
2698
  return errors.length > 0 ? errors : true;
2211
2699
  },
2212
2700
  defaultStyles: {
@@ -2221,20 +2709,194 @@ var checkboxDefinition = {
2221
2709
  }
2222
2710
  }
2223
2711
  };
2224
- var radioDefinition = {
2225
- type: "radio",
2226
- label: "Radio",
2712
+ var switchDefinition = {
2713
+ type: "switch",
2714
+ label: "Switch",
2227
2715
  category: "form",
2228
- icon: "radio",
2716
+ icon: "switch",
2229
2717
  acceptsChildren: false,
2230
2718
  disallowedParents: ["page"],
2231
2719
  defaultProps: {
2232
- name: "radio_group",
2233
- label: "Option 1",
2234
- value: "option1",
2720
+ name: "switch_field",
2721
+ label: "Enable feature",
2722
+ value: "yes",
2235
2723
  defaultChecked: false,
2724
+ switchSize: "md",
2236
2725
  required: false,
2237
- 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: ""
2238
2900
  },
2239
2901
  propFields: [
2240
2902
  { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
@@ -2242,12 +2904,15 @@ var radioDefinition = {
2242
2904
  { name: "value", label: "Radio Value", type: "string", defaultValue: "option1" },
2243
2905
  { name: "defaultChecked", label: "Default Selected", type: "boolean", defaultValue: false },
2244
2906
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2245
- { 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" }
2246
2909
  ],
2247
2910
  traits: [
2248
2911
  fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2912
+ labelTextTrait({ defaultValue: "Option 1" }),
2249
2913
  valueTrait({ defaultValue: "option1" }),
2250
2914
  defaultCheckedTrait(),
2915
+ helperTextTrait(),
2251
2916
  requiredTrait(),
2252
2917
  disabledTrait(),
2253
2918
  idTrait(),
@@ -2273,6 +2938,9 @@ var radioDefinition = {
2273
2938
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !(0, import_schema.isVariableBinding)(props.disabled)) {
2274
2939
  errors.push('Radio "disabled" must be a boolean when provided.');
2275
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
+ }
2276
2944
  return errors.length > 0 ? errors : true;
2277
2945
  },
2278
2946
  defaultStyles: {
@@ -2287,6 +2955,206 @@ var radioDefinition = {
2287
2955
  }
2288
2956
  }
2289
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
+ };
2290
3158
  var coreComponentDefinitions = [
2291
3159
  pageDefinition,
2292
3160
  sectionDefinition,
@@ -2304,12 +3172,17 @@ var coreComponentDefinitions = [
2304
3172
  iconDefinition,
2305
3173
  htmlEmbedDefinition,
2306
3174
  buttonDefinition,
3175
+ buttonSubmitDefinition,
2307
3176
  formDefinition,
2308
3177
  inputDefinition,
2309
3178
  textareaDefinition,
2310
3179
  selectDefinition,
2311
3180
  checkboxDefinition,
3181
+ switchDefinition,
3182
+ radioGroupDefinition,
2312
3183
  radioDefinition,
3184
+ radioItemDefinition,
3185
+ fileUploadDefinition,
2313
3186
  collectionDefinition,
2314
3187
  listDefinition,
2315
3188
  listItemDefinition,
@@ -2880,6 +3753,755 @@ var STARTER_BLOCKS = [
2880
3753
  }
2881
3754
  ]
2882
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
+ })
2883
4505
  }
2884
4506
  ];
2885
4507
  // Annotate the CommonJS export names for ESM import in node:
@@ -2888,14 +4510,18 @@ var STARTER_BLOCKS = [
2888
4510
  STARTER_BLOCKS,
2889
4511
  TRAIT_GROUP_LABELS,
2890
4512
  TRAIT_GROUP_ORDER,
4513
+ acceptTrait,
2891
4514
  actionTrait,
2892
4515
  altTrait,
2893
4516
  ariaLabelTrait,
2894
4517
  autoCompleteTrait,
4518
+ autoDisableOnSubmitTrait,
4519
+ autoGrowTrait,
2895
4520
  autoplayTrait,
2896
4521
  badgeDefinition,
2897
4522
  blockquoteDefinition,
2898
4523
  buttonDefinition,
4524
+ buttonSubmitDefinition,
2899
4525
  buttonTypeTrait,
2900
4526
  checkboxDefinition,
2901
4527
  citeTrait,
@@ -2909,42 +4535,68 @@ var STARTER_BLOCKS = [
2909
4535
  coreComponentDefinitions,
2910
4536
  createDefaultComponentRegistry,
2911
4537
  defaultCheckedTrait,
4538
+ defaultSelectedTrait,
2912
4539
  defaultValueTrait,
2913
4540
  disabledTrait,
2914
4541
  extractComponentRequirements,
2915
4542
  fieldNameTrait,
4543
+ fileUploadDefinition,
2916
4544
  formDefinition,
2917
4545
  headingDefinition,
4546
+ helperTextTrait,
2918
4547
  hrefTrait,
2919
4548
  htmlEmbedDefinition,
2920
4549
  iconDefinition,
2921
4550
  idTrait,
2922
4551
  imageDefinition,
4552
+ indeterminateTrait,
2923
4553
  inputDefinition,
2924
4554
  inputTypeTrait,
2925
4555
  isBindableField,
4556
+ labelTextTrait,
2926
4557
  linkDefinition,
2927
4558
  listDefinition,
2928
4559
  listItemDefinition,
4560
+ loadingTextTrait,
2929
4561
  loadingTrait,
2930
4562
  loopTrait,
4563
+ maxCharCountTrait,
4564
+ maxFileSizeTrait,
4565
+ maxLengthTrait,
2931
4566
  methodTrait,
4567
+ minLengthTrait,
4568
+ multipleTrait,
2932
4569
  mutedTrait,
4570
+ optionsListTrait,
4571
+ orientationTrait,
2933
4572
  pageDefinition,
2934
4573
  paragraphDefinition,
4574
+ patternTrait,
2935
4575
  placeholderTrait,
2936
4576
  posterTrait,
4577
+ prefixIconTrait,
4578
+ preventDefaultTrait,
2937
4579
  primitiveTypeForField,
2938
4580
  radioDefinition,
4581
+ radioGroupDefinition,
4582
+ radioItemDefinition,
2939
4583
  readOnlyTrait,
2940
4584
  relTrait,
2941
4585
  requiredTrait,
4586
+ resetOnSubmitTrait,
4587
+ resizeTrait,
2942
4588
  rowSpanTrait,
2943
4589
  rowsTrait,
4590
+ scrollToFirstErrorTrait,
2944
4591
  sectionDefinition,
2945
4592
  selectDefinition,
4593
+ showPreviewTrait,
4594
+ showSpinnerTrait,
2946
4595
  sortTraits,
2947
4596
  srcTrait,
4597
+ suffixIconTrait,
4598
+ switchDefinition,
4599
+ switchSizeTrait,
2948
4600
  tableCellDefinition,
2949
4601
  tableDefinition,
2950
4602
  tableRowDefinition,