@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.js CHANGED
@@ -575,6 +575,341 @@ function buttonTypeTrait(overrides) {
575
575
  overrides
576
576
  );
577
577
  }
578
+ function preventDefaultTrait(overrides) {
579
+ return withOverrides(
580
+ {
581
+ name: "preventDefault",
582
+ label: "Prevent Default",
583
+ type: "boolean",
584
+ defaultValue: true,
585
+ group: "form",
586
+ description: "Intercept the native browser submit and handle it via the KUBUILD action pipeline instead."
587
+ },
588
+ overrides
589
+ );
590
+ }
591
+ function scrollToFirstErrorTrait(overrides) {
592
+ return withOverrides(
593
+ {
594
+ name: "scrollToFirstError",
595
+ label: "Scroll to First Error",
596
+ type: "boolean",
597
+ defaultValue: true,
598
+ group: "form",
599
+ description: "Automatically scroll to and focus the first invalid field when submission fails validation."
600
+ },
601
+ overrides
602
+ );
603
+ }
604
+ function resetOnSubmitTrait(overrides) {
605
+ return withOverrides(
606
+ {
607
+ name: "resetOnSubmit",
608
+ label: "Reset on Submit",
609
+ type: "boolean",
610
+ defaultValue: false,
611
+ group: "form",
612
+ description: "Reset all fields to their initial values after a successful form submission."
613
+ },
614
+ overrides
615
+ );
616
+ }
617
+ function patternTrait(overrides) {
618
+ return withOverrides(
619
+ {
620
+ name: "pattern",
621
+ label: "Pattern (regex)",
622
+ type: "string",
623
+ attribute: "pattern",
624
+ group: "form",
625
+ description: "A regular expression the input value must match to pass validation."
626
+ },
627
+ overrides
628
+ );
629
+ }
630
+ function minLengthTrait(overrides) {
631
+ return withOverrides(
632
+ {
633
+ name: "minLength",
634
+ label: "Min Length",
635
+ type: "number",
636
+ attribute: "minlength",
637
+ group: "form",
638
+ description: "The minimum number of characters the user must enter."
639
+ },
640
+ overrides
641
+ );
642
+ }
643
+ function maxLengthTrait(overrides) {
644
+ return withOverrides(
645
+ {
646
+ name: "maxLength",
647
+ label: "Max Length",
648
+ type: "number",
649
+ attribute: "maxlength",
650
+ group: "form",
651
+ description: "The maximum number of characters the user is allowed to enter."
652
+ },
653
+ overrides
654
+ );
655
+ }
656
+ function prefixIconTrait(overrides) {
657
+ return withOverrides(
658
+ {
659
+ name: "prefixIcon",
660
+ label: "Prefix Icon",
661
+ type: "string",
662
+ group: "form",
663
+ description: 'Lucide icon name displayed before the input value (e.g. "mail", "search").'
664
+ },
665
+ overrides
666
+ );
667
+ }
668
+ function suffixIconTrait(overrides) {
669
+ return withOverrides(
670
+ {
671
+ name: "suffixIcon",
672
+ label: "Suffix Icon",
673
+ type: "string",
674
+ group: "form",
675
+ description: 'Lucide icon name displayed after the input value (e.g. "eye", "check").'
676
+ },
677
+ overrides
678
+ );
679
+ }
680
+ function helperTextTrait(overrides) {
681
+ return withOverrides(
682
+ {
683
+ name: "helperText",
684
+ label: "Helper Text",
685
+ type: "string",
686
+ group: "form",
687
+ description: 'A short message displayed below the input to guide the user (e.g. "Must be at least 8 characters").'
688
+ },
689
+ overrides
690
+ );
691
+ }
692
+ function resizeTrait(overrides) {
693
+ return withOverrides(
694
+ {
695
+ name: "resize",
696
+ label: "Resize",
697
+ type: "select",
698
+ defaultValue: "vertical",
699
+ group: "form",
700
+ options: [
701
+ { label: "Vertical only", value: "vertical" },
702
+ { label: "Horizontal only", value: "horizontal" },
703
+ { label: "Both", value: "both" },
704
+ { label: "None", value: "none" }
705
+ ],
706
+ description: "Controls whether and how the user can resize the textarea."
707
+ },
708
+ overrides
709
+ );
710
+ }
711
+ function autoGrowTrait(overrides) {
712
+ return withOverrides(
713
+ {
714
+ name: "autoGrow",
715
+ label: "Auto Grow",
716
+ type: "boolean",
717
+ defaultValue: false,
718
+ group: "form",
719
+ description: "Automatically expand the textarea height to fit the content without scrolling."
720
+ },
721
+ overrides
722
+ );
723
+ }
724
+ function maxCharCountTrait(overrides) {
725
+ return withOverrides(
726
+ {
727
+ name: "maxCharCount",
728
+ label: "Max Character Count",
729
+ type: "number",
730
+ group: "form",
731
+ description: 'Maximum character limit displayed as a counter below the textarea (e.g. "120 / 500").'
732
+ },
733
+ overrides
734
+ );
735
+ }
736
+ function optionsListTrait(overrides) {
737
+ return withOverrides(
738
+ {
739
+ name: "options",
740
+ label: "Options",
741
+ type: "string",
742
+ group: "form",
743
+ description: "The list of dropdown options, each with a label and value. Editable via the inspector trait panel."
744
+ },
745
+ overrides
746
+ );
747
+ }
748
+ function labelTextTrait(overrides) {
749
+ return withOverrides(
750
+ {
751
+ name: "label",
752
+ label: "Label Text",
753
+ type: "string",
754
+ group: "form",
755
+ description: "The visible text label displayed alongside the control."
756
+ },
757
+ overrides
758
+ );
759
+ }
760
+ function indeterminateTrait(overrides) {
761
+ return withOverrides(
762
+ {
763
+ name: "indeterminate",
764
+ label: "Indeterminate",
765
+ type: "boolean",
766
+ defaultValue: false,
767
+ group: "form",
768
+ description: "Renders the checkbox in a mixed/indeterminate visual state (neither checked nor unchecked)."
769
+ },
770
+ overrides
771
+ );
772
+ }
773
+ function switchSizeTrait(overrides) {
774
+ return withOverrides(
775
+ {
776
+ name: "switchSize",
777
+ label: "Size",
778
+ type: "select",
779
+ defaultValue: "md",
780
+ group: "form",
781
+ options: [
782
+ { label: "Small", value: "sm" },
783
+ { label: "Medium", value: "md" },
784
+ { label: "Large", value: "lg" }
785
+ ],
786
+ description: "The visual size of the switch toggle."
787
+ },
788
+ overrides
789
+ );
790
+ }
791
+ function orientationTrait(overrides) {
792
+ return withOverrides(
793
+ {
794
+ name: "orientation",
795
+ label: "Orientation",
796
+ type: "select",
797
+ defaultValue: "vertical",
798
+ group: "form",
799
+ options: [
800
+ { label: "Vertical", value: "vertical" },
801
+ { label: "Horizontal", value: "horizontal" }
802
+ ],
803
+ description: "The layout direction of the child controls (vertical stack or horizontal row)."
804
+ },
805
+ overrides
806
+ );
807
+ }
808
+ function defaultSelectedTrait(overrides) {
809
+ return withOverrides(
810
+ {
811
+ name: "defaultSelected",
812
+ label: "Default Selected",
813
+ type: "string",
814
+ group: "form",
815
+ description: "The value of the radio item that is selected by default."
816
+ },
817
+ overrides
818
+ );
819
+ }
820
+ function acceptTrait(overrides) {
821
+ return withOverrides(
822
+ {
823
+ name: "accept",
824
+ label: "Accepted File Types",
825
+ type: "string",
826
+ attribute: "accept",
827
+ defaultValue: "*/*",
828
+ group: "form",
829
+ description: 'Comma-separated list of MIME types or file extensions accepted (e.g. "image/*,.pdf,.docx").'
830
+ },
831
+ overrides
832
+ );
833
+ }
834
+ function maxFileSizeTrait(overrides) {
835
+ return withOverrides(
836
+ {
837
+ name: "maxFileSize",
838
+ label: "Max File Size (MB)",
839
+ type: "number",
840
+ defaultValue: 10,
841
+ group: "form",
842
+ description: "The maximum allowable file size in megabytes (MB)."
843
+ },
844
+ overrides
845
+ );
846
+ }
847
+ function multipleTrait(overrides) {
848
+ return withOverrides(
849
+ {
850
+ name: "multiple",
851
+ label: "Allow Multiple Files",
852
+ type: "boolean",
853
+ attribute: "multiple",
854
+ defaultValue: false,
855
+ group: "form",
856
+ description: "Allow multiple files to be selected and uploaded at once."
857
+ },
858
+ overrides
859
+ );
860
+ }
861
+ function showPreviewTrait(overrides) {
862
+ return withOverrides(
863
+ {
864
+ name: "showPreview",
865
+ label: "Show Preview",
866
+ type: "boolean",
867
+ defaultValue: true,
868
+ group: "form",
869
+ description: "Display an interactive preview (image thumbnail or file list with badges) for selected files."
870
+ },
871
+ overrides
872
+ );
873
+ }
874
+ function loadingTextTrait(overrides) {
875
+ return withOverrides(
876
+ {
877
+ name: "loadingText",
878
+ label: "Loading Text",
879
+ type: "string",
880
+ defaultValue: "Submitting...",
881
+ group: "behavior",
882
+ description: "Text displayed on the button while the form submission is in progress."
883
+ },
884
+ overrides
885
+ );
886
+ }
887
+ function showSpinnerTrait(overrides) {
888
+ return withOverrides(
889
+ {
890
+ name: "showSpinner",
891
+ label: "Show Loading Spinner",
892
+ type: "boolean",
893
+ defaultValue: true,
894
+ group: "behavior",
895
+ description: "Automatically show an animated loading spinner icon while form is submitting."
896
+ },
897
+ overrides
898
+ );
899
+ }
900
+ function autoDisableOnSubmitTrait(overrides) {
901
+ return withOverrides(
902
+ {
903
+ name: "autoDisableOnSubmit",
904
+ label: "Auto Disable on Submit",
905
+ type: "boolean",
906
+ defaultValue: true,
907
+ group: "behavior",
908
+ description: "Automatically disable the button to prevent duplicate submissions while the form is submitting."
909
+ },
910
+ overrides
911
+ );
912
+ }
578
913
  function sortTraits(traits) {
579
914
  const groupRank = (group) => {
580
915
  if (!group) return Number.MAX_SAFE_INTEGER;
@@ -608,12 +943,17 @@ var CONTENT_CHILD_TYPES = [
608
943
  "icon",
609
944
  "html-embed",
610
945
  "button",
946
+ "button-submit",
611
947
  "form",
612
948
  "input",
613
949
  "textarea",
614
950
  "select",
615
951
  "checkbox",
952
+ "switch",
953
+ "radio-group",
616
954
  "radio",
955
+ "radio-item",
956
+ "file-upload",
617
957
  "list",
618
958
  "table",
619
959
  "collection",
@@ -1705,7 +2045,10 @@ var formDefinition = {
1705
2045
  method: "POST",
1706
2046
  action: "",
1707
2047
  target: "_self",
1708
- autoComplete: "on"
2048
+ autoComplete: "on",
2049
+ preventDefault: true,
2050
+ scrollToFirstError: true,
2051
+ resetOnSubmit: false
1709
2052
  },
1710
2053
  defaultChildren: [
1711
2054
  { type: "input", props: { name: "name", type: "text", placeholder: "Your Name", required: true } },
@@ -1746,7 +2089,10 @@ var formDefinition = {
1746
2089
  { label: "On", value: "on" },
1747
2090
  { label: "Off", value: "off" }
1748
2091
  ]
1749
- }
2092
+ },
2093
+ { name: "preventDefault", label: "Prevent Default", type: "boolean", defaultValue: true },
2094
+ { name: "scrollToFirstError", label: "Scroll to First Error", type: "boolean", defaultValue: true },
2095
+ { name: "resetOnSubmit", label: "Reset on Submit", type: "boolean", defaultValue: false }
1750
2096
  ],
1751
2097
  traits: [
1752
2098
  fieldNameTrait({ defaultValue: "contact_form", required: false }),
@@ -1759,6 +2105,9 @@ var formDefinition = {
1759
2105
  { label: "Top (_top)", value: "_top" }
1760
2106
  ] }),
1761
2107
  autoCompleteTrait(),
2108
+ preventDefaultTrait(),
2109
+ scrollToFirstErrorTrait(),
2110
+ resetOnSubmitTrait(),
1762
2111
  idTrait(),
1763
2112
  ariaLabelTrait({ description: "Accessible name for the form landmark." })
1764
2113
  ],
@@ -1785,6 +2134,15 @@ var formDefinition = {
1785
2134
  errors.push('Form "autoComplete" must be either "on" or "off".');
1786
2135
  }
1787
2136
  }
2137
+ if (props.preventDefault !== void 0 && typeof props.preventDefault !== "boolean" && !isVariableBinding(props.preventDefault)) {
2138
+ errors.push('Form "preventDefault" must be a boolean when provided.');
2139
+ }
2140
+ if (props.scrollToFirstError !== void 0 && typeof props.scrollToFirstError !== "boolean" && !isVariableBinding(props.scrollToFirstError)) {
2141
+ errors.push('Form "scrollToFirstError" must be a boolean when provided.');
2142
+ }
2143
+ if (props.resetOnSubmit !== void 0 && typeof props.resetOnSubmit !== "boolean" && !isVariableBinding(props.resetOnSubmit)) {
2144
+ errors.push('Form "resetOnSubmit" must be a boolean when provided.');
2145
+ }
1788
2146
  return errors.length > 0 ? errors : true;
1789
2147
  },
1790
2148
  defaultStyles: {
@@ -1810,7 +2168,13 @@ var inputDefinition = {
1810
2168
  defaultValue: "",
1811
2169
  required: false,
1812
2170
  disabled: false,
1813
- readOnly: false
2171
+ readOnly: false,
2172
+ pattern: "",
2173
+ minLength: void 0,
2174
+ maxLength: void 0,
2175
+ prefixIcon: "",
2176
+ suffixIcon: "",
2177
+ helperText: ""
1814
2178
  },
1815
2179
  propFields: [
1816
2180
  { name: "name", label: "Field Name", type: "string", defaultValue: "input_field" },
@@ -1834,7 +2198,13 @@ var inputDefinition = {
1834
2198
  { name: "defaultValue", label: "Default Value", type: "string" },
1835
2199
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
1836
2200
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1837
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
2201
+ { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false },
2202
+ { name: "pattern", label: "Pattern (regex)", type: "string" },
2203
+ { name: "minLength", label: "Min Length", type: "number" },
2204
+ { name: "maxLength", label: "Max Length", type: "number" },
2205
+ { name: "prefixIcon", label: "Prefix Icon", type: "string" },
2206
+ { name: "suffixIcon", label: "Suffix Icon", type: "string" },
2207
+ { name: "helperText", label: "Helper Text", type: "string" }
1838
2208
  ],
1839
2209
  traits: [
1840
2210
  inputTypeTrait({ options: [
@@ -1852,6 +2222,12 @@ var inputDefinition = {
1852
2222
  placeholderTrait({ defaultValue: "Enter text..." }),
1853
2223
  defaultValueTrait(),
1854
2224
  requiredTrait(),
2225
+ patternTrait(),
2226
+ minLengthTrait(),
2227
+ maxLengthTrait(),
2228
+ prefixIconTrait(),
2229
+ suffixIconTrait(),
2230
+ helperTextTrait(),
1855
2231
  disabledTrait(),
1856
2232
  readOnlyTrait(),
1857
2233
  idTrait(),
@@ -1880,6 +2256,28 @@ var inputDefinition = {
1880
2256
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !isVariableBinding(props.readOnly)) {
1881
2257
  errors.push('Input "readOnly" must be a boolean when provided.');
1882
2258
  }
2259
+ if (props.pattern !== void 0 && typeof props.pattern !== "string" && !isVariableBinding(props.pattern)) {
2260
+ errors.push('Input "pattern" must be a string when provided.');
2261
+ }
2262
+ if (props.minLength !== void 0 && !isVariableBinding(props.minLength)) {
2263
+ if (typeof props.minLength !== "number" || props.minLength < 0 || !Number.isInteger(props.minLength)) {
2264
+ errors.push('Input "minLength" must be a non-negative integer when provided.');
2265
+ }
2266
+ }
2267
+ if (props.maxLength !== void 0 && !isVariableBinding(props.maxLength)) {
2268
+ if (typeof props.maxLength !== "number" || props.maxLength < 0 || !Number.isInteger(props.maxLength)) {
2269
+ errors.push('Input "maxLength" must be a non-negative integer when provided.');
2270
+ }
2271
+ }
2272
+ if (props.prefixIcon !== void 0 && typeof props.prefixIcon !== "string" && !isVariableBinding(props.prefixIcon)) {
2273
+ errors.push('Input "prefixIcon" must be a string when provided.');
2274
+ }
2275
+ if (props.suffixIcon !== void 0 && typeof props.suffixIcon !== "string" && !isVariableBinding(props.suffixIcon)) {
2276
+ errors.push('Input "suffixIcon" must be a string when provided.');
2277
+ }
2278
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2279
+ errors.push('Input "helperText" must be a string when provided.');
2280
+ }
1883
2281
  return errors.length > 0 ? errors : true;
1884
2282
  },
1885
2283
  defaultStyles: {
@@ -1914,7 +2312,11 @@ var textareaDefinition = {
1914
2312
  rows: 4,
1915
2313
  required: false,
1916
2314
  disabled: false,
1917
- readOnly: false
2315
+ readOnly: false,
2316
+ resize: "vertical",
2317
+ autoGrow: false,
2318
+ maxCharCount: void 0,
2319
+ helperText: ""
1918
2320
  },
1919
2321
  propFields: [
1920
2322
  { name: "name", label: "Field Name", type: "string", defaultValue: "message" },
@@ -1923,13 +2325,32 @@ var textareaDefinition = {
1923
2325
  { name: "rows", label: "Rows", type: "number", defaultValue: 4 },
1924
2326
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
1925
2327
  { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
1926
- { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false }
2328
+ { name: "readOnly", label: "Read Only", type: "boolean", defaultValue: false },
2329
+ {
2330
+ name: "resize",
2331
+ label: "Resize",
2332
+ type: "select",
2333
+ defaultValue: "vertical",
2334
+ options: [
2335
+ { label: "Vertical only", value: "vertical" },
2336
+ { label: "Horizontal only", value: "horizontal" },
2337
+ { label: "Both", value: "both" },
2338
+ { label: "None", value: "none" }
2339
+ ]
2340
+ },
2341
+ { name: "autoGrow", label: "Auto Grow", type: "boolean", defaultValue: false },
2342
+ { name: "maxCharCount", label: "Max Character Count", type: "number" },
2343
+ { name: "helperText", label: "Helper Text", type: "string" }
1927
2344
  ],
1928
2345
  traits: [
1929
2346
  fieldNameTrait({ defaultValue: "message" }),
1930
2347
  placeholderTrait({ defaultValue: "Enter your message..." }),
1931
2348
  defaultValueTrait(),
1932
2349
  rowsTrait(),
2350
+ resizeTrait(),
2351
+ autoGrowTrait(),
2352
+ maxCharCountTrait(),
2353
+ helperTextTrait(),
1933
2354
  requiredTrait(),
1934
2355
  disabledTrait(),
1935
2356
  readOnlyTrait(),
@@ -1958,6 +2379,23 @@ var textareaDefinition = {
1958
2379
  if (props.readOnly !== void 0 && typeof props.readOnly !== "boolean" && !isVariableBinding(props.readOnly)) {
1959
2380
  errors.push('Textarea "readOnly" must be a boolean when provided.');
1960
2381
  }
2382
+ if (props.resize !== void 0 && !isVariableBinding(props.resize)) {
2383
+ const allowedResize = ["vertical", "horizontal", "both", "none"];
2384
+ if (typeof props.resize !== "string" || !allowedResize.includes(props.resize)) {
2385
+ errors.push(`Textarea "resize" must be one of: ${allowedResize.join(", ")}.`);
2386
+ }
2387
+ }
2388
+ if (props.autoGrow !== void 0 && typeof props.autoGrow !== "boolean" && !isVariableBinding(props.autoGrow)) {
2389
+ errors.push('Textarea "autoGrow" must be a boolean when provided.');
2390
+ }
2391
+ if (props.maxCharCount !== void 0 && !isVariableBinding(props.maxCharCount)) {
2392
+ if (typeof props.maxCharCount !== "number" || props.maxCharCount < 1 || !Number.isInteger(props.maxCharCount)) {
2393
+ errors.push('Textarea "maxCharCount" must be a positive integer (>= 1) when provided.');
2394
+ }
2395
+ }
2396
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2397
+ errors.push('Textarea "helperText" must be a string when provided.');
2398
+ }
1961
2399
  return errors.length > 0 ? errors : true;
1962
2400
  },
1963
2401
  defaultStyles: {
@@ -1995,7 +2433,8 @@ var selectDefinition = {
1995
2433
  ],
1996
2434
  defaultValue: "",
1997
2435
  required: false,
1998
- disabled: false
2436
+ disabled: false,
2437
+ helperText: ""
1999
2438
  },
2000
2439
  propFields: [
2001
2440
  { name: "name", label: "Field Name", type: "string", defaultValue: "select_field" },
@@ -2012,12 +2451,15 @@ var selectDefinition = {
2012
2451
  },
2013
2452
  { name: "defaultValue", label: "Default Selected Value", type: "string" },
2014
2453
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2015
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2454
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2455
+ { name: "helperText", label: "Helper Text", type: "string" }
2016
2456
  ],
2017
2457
  traits: [
2018
2458
  fieldNameTrait({ defaultValue: "select_field" }),
2019
2459
  placeholderTrait({ defaultValue: "Select an option..." }),
2460
+ optionsListTrait({ description: "The list of dropdown choices (label + value pairs). Editable via the inspector trait panel." }),
2020
2461
  defaultValueTrait({ description: "The initially selected option value (must match one of the option values)." }),
2462
+ helperTextTrait(),
2021
2463
  requiredTrait(),
2022
2464
  disabledTrait(),
2023
2465
  idTrait(),
@@ -2039,6 +2481,9 @@ var selectDefinition = {
2039
2481
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2040
2482
  errors.push('Select "disabled" must be a boolean when provided.');
2041
2483
  }
2484
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2485
+ errors.push('Select "helperText" must be a string when provided.');
2486
+ }
2042
2487
  return errors.length > 0 ? errors : true;
2043
2488
  },
2044
2489
  defaultStyles: {
@@ -2071,21 +2516,28 @@ var checkboxDefinition = {
2071
2516
  label: "I agree to the terms and conditions",
2072
2517
  value: "yes",
2073
2518
  defaultChecked: false,
2519
+ indeterminate: false,
2074
2520
  required: false,
2075
- disabled: false
2521
+ disabled: false,
2522
+ helperText: ""
2076
2523
  },
2077
2524
  propFields: [
2078
2525
  { name: "name", label: "Field Name", type: "string", defaultValue: "checkbox_field" },
2079
2526
  { name: "label", label: "Label Text", type: "string", defaultValue: "I agree to the terms and conditions" },
2080
2527
  { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2081
2528
  { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2529
+ { name: "indeterminate", label: "Indeterminate", type: "boolean", defaultValue: false },
2082
2530
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2083
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2531
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2532
+ { name: "helperText", label: "Helper Text", type: "string" }
2084
2533
  ],
2085
2534
  traits: [
2086
2535
  fieldNameTrait({ defaultValue: "checkbox_field" }),
2536
+ labelTextTrait({ defaultValue: "I agree to the terms and conditions" }),
2087
2537
  valueTrait({ defaultValue: "yes" }),
2088
2538
  defaultCheckedTrait(),
2539
+ indeterminateTrait(),
2540
+ helperTextTrait(),
2089
2541
  requiredTrait(),
2090
2542
  disabledTrait(),
2091
2543
  idTrait(),
@@ -2105,12 +2557,18 @@ var checkboxDefinition = {
2105
2557
  if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !isVariableBinding(props.defaultChecked)) {
2106
2558
  errors.push('Checkbox "defaultChecked" must be a boolean when provided.');
2107
2559
  }
2560
+ if (props.indeterminate !== void 0 && typeof props.indeterminate !== "boolean" && !isVariableBinding(props.indeterminate)) {
2561
+ errors.push('Checkbox "indeterminate" must be a boolean when provided.');
2562
+ }
2108
2563
  if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2109
2564
  errors.push('Checkbox "required" must be a boolean when provided.');
2110
2565
  }
2111
2566
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2112
2567
  errors.push('Checkbox "disabled" must be a boolean when provided.');
2113
2568
  }
2569
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2570
+ errors.push('Checkbox "helperText" must be a string when provided.');
2571
+ }
2114
2572
  return errors.length > 0 ? errors : true;
2115
2573
  },
2116
2574
  defaultStyles: {
@@ -2125,20 +2583,194 @@ var checkboxDefinition = {
2125
2583
  }
2126
2584
  }
2127
2585
  };
2128
- var radioDefinition = {
2129
- type: "radio",
2130
- label: "Radio",
2586
+ var switchDefinition = {
2587
+ type: "switch",
2588
+ label: "Switch",
2131
2589
  category: "form",
2132
- icon: "radio",
2590
+ icon: "switch",
2133
2591
  acceptsChildren: false,
2134
2592
  disallowedParents: ["page"],
2135
2593
  defaultProps: {
2136
- name: "radio_group",
2137
- label: "Option 1",
2138
- value: "option1",
2594
+ name: "switch_field",
2595
+ label: "Enable feature",
2596
+ value: "yes",
2139
2597
  defaultChecked: false,
2598
+ switchSize: "md",
2140
2599
  required: false,
2141
- disabled: false
2600
+ disabled: false,
2601
+ helperText: ""
2602
+ },
2603
+ propFields: [
2604
+ { name: "name", label: "Field Name", type: "string", defaultValue: "switch_field" },
2605
+ { name: "label", label: "Label Text", type: "string", defaultValue: "Enable feature" },
2606
+ { name: "value", label: "Checked Value", type: "string", defaultValue: "yes" },
2607
+ { name: "defaultChecked", label: "Default Checked", type: "boolean", defaultValue: false },
2608
+ {
2609
+ name: "switchSize",
2610
+ label: "Size",
2611
+ type: "select",
2612
+ defaultValue: "md",
2613
+ options: [
2614
+ { label: "Small", value: "sm" },
2615
+ { label: "Medium", value: "md" },
2616
+ { label: "Large", value: "lg" }
2617
+ ]
2618
+ },
2619
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2620
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2621
+ { name: "helperText", label: "Helper Text", type: "string" }
2622
+ ],
2623
+ traits: [
2624
+ fieldNameTrait({ defaultValue: "switch_field" }),
2625
+ labelTextTrait({ defaultValue: "Enable feature" }),
2626
+ valueTrait({ defaultValue: "yes" }),
2627
+ defaultCheckedTrait(),
2628
+ switchSizeTrait(),
2629
+ helperTextTrait(),
2630
+ requiredTrait(),
2631
+ disabledTrait(),
2632
+ idTrait(),
2633
+ ariaLabelTrait()
2634
+ ],
2635
+ validateProps: (props) => {
2636
+ const errors = [];
2637
+ if (props.label !== void 0 && typeof props.label !== "string" && !isVariableBinding(props.label)) {
2638
+ errors.push('Switch "label" must be a string when provided.');
2639
+ }
2640
+ if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2641
+ errors.push('Switch "name" must be a string when provided.');
2642
+ }
2643
+ if (props.value !== void 0 && typeof props.value !== "string" && !isVariableBinding(props.value)) {
2644
+ errors.push('Switch "value" must be a string when provided.');
2645
+ }
2646
+ if (props.defaultChecked !== void 0 && typeof props.defaultChecked !== "boolean" && !isVariableBinding(props.defaultChecked)) {
2647
+ errors.push('Switch "defaultChecked" must be a boolean when provided.');
2648
+ }
2649
+ if (props.switchSize !== void 0 && !isVariableBinding(props.switchSize)) {
2650
+ const allowedSizes = ["sm", "md", "lg"];
2651
+ if (typeof props.switchSize !== "string" || !allowedSizes.includes(props.switchSize)) {
2652
+ errors.push(`Switch "switchSize" must be one of: ${allowedSizes.join(", ")}.`);
2653
+ }
2654
+ }
2655
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2656
+ errors.push('Switch "required" must be a boolean when provided.');
2657
+ }
2658
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2659
+ errors.push('Switch "disabled" must be a boolean when provided.');
2660
+ }
2661
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2662
+ errors.push('Switch "helperText" must be a string when provided.');
2663
+ }
2664
+ return errors.length > 0 ? errors : true;
2665
+ },
2666
+ defaultStyles: {
2667
+ base: {
2668
+ display: "inline-flex",
2669
+ alignItems: "center",
2670
+ gap: "8px",
2671
+ fontSize: "14px",
2672
+ color: "#1e293b",
2673
+ cursor: "pointer",
2674
+ userSelect: "none"
2675
+ }
2676
+ }
2677
+ };
2678
+ var radioGroupDefinition = {
2679
+ type: "radio-group",
2680
+ label: "Radio Group",
2681
+ category: "form",
2682
+ icon: "radio-group",
2683
+ acceptsChildren: true,
2684
+ allowedChildren: ["radio", "radio-item", "custom"],
2685
+ disallowedParents: ["page"],
2686
+ defaultProps: {
2687
+ name: "radio_group",
2688
+ defaultSelected: "option1",
2689
+ orientation: "vertical",
2690
+ required: false,
2691
+ disabled: false,
2692
+ helperText: ""
2693
+ },
2694
+ defaultChildren: [
2695
+ { type: "radio", props: { name: "radio_group", label: "Option 1", value: "option1", defaultChecked: true } },
2696
+ { type: "radio", props: { name: "radio_group", label: "Option 2", value: "option2", defaultChecked: false } },
2697
+ { type: "radio", props: { name: "radio_group", label: "Option 3", value: "option3", defaultChecked: false } }
2698
+ ],
2699
+ propFields: [
2700
+ { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
2701
+ { name: "defaultSelected", label: "Default Selected", type: "string", defaultValue: "option1" },
2702
+ {
2703
+ name: "orientation",
2704
+ label: "Orientation",
2705
+ type: "select",
2706
+ defaultValue: "vertical",
2707
+ options: [
2708
+ { label: "Vertical", value: "vertical" },
2709
+ { label: "Horizontal", value: "horizontal" }
2710
+ ]
2711
+ },
2712
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2713
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2714
+ { name: "helperText", label: "Helper Text", type: "string" }
2715
+ ],
2716
+ traits: [
2717
+ fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2718
+ defaultSelectedTrait({ defaultValue: "option1" }),
2719
+ orientationTrait(),
2720
+ helperTextTrait(),
2721
+ requiredTrait(),
2722
+ disabledTrait(),
2723
+ idTrait(),
2724
+ ariaLabelTrait()
2725
+ ],
2726
+ validateProps: (props) => {
2727
+ const errors = [];
2728
+ if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2729
+ errors.push('RadioGroup "name" must be a string when provided.');
2730
+ }
2731
+ if (props.defaultSelected !== void 0 && typeof props.defaultSelected !== "string" && !isVariableBinding(props.defaultSelected)) {
2732
+ errors.push('RadioGroup "defaultSelected" must be a string when provided.');
2733
+ }
2734
+ if (props.orientation !== void 0 && !isVariableBinding(props.orientation)) {
2735
+ const allowedOrientations = ["vertical", "horizontal"];
2736
+ if (typeof props.orientation !== "string" || !allowedOrientations.includes(props.orientation)) {
2737
+ errors.push(`RadioGroup "orientation" must be one of: ${allowedOrientations.join(", ")}.`);
2738
+ }
2739
+ }
2740
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2741
+ errors.push('RadioGroup "required" must be a boolean when provided.');
2742
+ }
2743
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2744
+ errors.push('RadioGroup "disabled" must be a boolean when provided.');
2745
+ }
2746
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2747
+ errors.push('RadioGroup "helperText" must be a string when provided.');
2748
+ }
2749
+ return errors.length > 0 ? errors : true;
2750
+ },
2751
+ defaultStyles: {
2752
+ base: {
2753
+ display: "flex",
2754
+ flexDirection: "column",
2755
+ gap: "8px"
2756
+ }
2757
+ }
2758
+ };
2759
+ var radioDefinition = {
2760
+ type: "radio",
2761
+ label: "Radio",
2762
+ category: "form",
2763
+ icon: "radio",
2764
+ acceptsChildren: false,
2765
+ disallowedParents: ["page"],
2766
+ defaultProps: {
2767
+ name: "radio_group",
2768
+ label: "Option 1",
2769
+ value: "option1",
2770
+ defaultChecked: false,
2771
+ required: false,
2772
+ disabled: false,
2773
+ helperText: ""
2142
2774
  },
2143
2775
  propFields: [
2144
2776
  { name: "name", label: "Group Name", type: "string", defaultValue: "radio_group" },
@@ -2146,12 +2778,15 @@ var radioDefinition = {
2146
2778
  { name: "value", label: "Radio Value", type: "string", defaultValue: "option1" },
2147
2779
  { name: "defaultChecked", label: "Default Selected", type: "boolean", defaultValue: false },
2148
2780
  { name: "required", label: "Required", type: "boolean", defaultValue: false },
2149
- { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false }
2781
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2782
+ { name: "helperText", label: "Helper Text", type: "string" }
2150
2783
  ],
2151
2784
  traits: [
2152
2785
  fieldNameTrait({ defaultValue: "radio_group", label: "Group Name" }),
2786
+ labelTextTrait({ defaultValue: "Option 1" }),
2153
2787
  valueTrait({ defaultValue: "option1" }),
2154
2788
  defaultCheckedTrait(),
2789
+ helperTextTrait(),
2155
2790
  requiredTrait(),
2156
2791
  disabledTrait(),
2157
2792
  idTrait(),
@@ -2177,6 +2812,9 @@ var radioDefinition = {
2177
2812
  if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2178
2813
  errors.push('Radio "disabled" must be a boolean when provided.');
2179
2814
  }
2815
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2816
+ errors.push('Radio "helperText" must be a string when provided.');
2817
+ }
2180
2818
  return errors.length > 0 ? errors : true;
2181
2819
  },
2182
2820
  defaultStyles: {
@@ -2191,6 +2829,206 @@ var radioDefinition = {
2191
2829
  }
2192
2830
  }
2193
2831
  };
2832
+ var radioItemDefinition = {
2833
+ ...radioDefinition,
2834
+ type: "radio-item",
2835
+ label: "Radio Item"
2836
+ };
2837
+ var fileUploadDefinition = {
2838
+ type: "file-upload",
2839
+ label: "File Upload",
2840
+ category: "form",
2841
+ icon: "upload",
2842
+ acceptsChildren: false,
2843
+ disallowedParents: ["page"],
2844
+ defaultProps: {
2845
+ name: "file_upload",
2846
+ label: "Upload File",
2847
+ accept: "*/*",
2848
+ maxFileSize: 10,
2849
+ multiple: false,
2850
+ showPreview: true,
2851
+ required: false,
2852
+ disabled: false,
2853
+ helperText: ""
2854
+ },
2855
+ propFields: [
2856
+ { name: "name", label: "Field Name", type: "string", defaultValue: "file_upload" },
2857
+ { name: "label", label: "Label Text", type: "string", defaultValue: "Upload File" },
2858
+ { name: "accept", label: "Accepted File Types", type: "string", defaultValue: "*/*" },
2859
+ { name: "maxFileSize", label: "Max File Size (MB)", type: "number", defaultValue: 10 },
2860
+ { name: "multiple", label: "Allow Multiple Files", type: "boolean", defaultValue: false },
2861
+ { name: "showPreview", label: "Show Preview", type: "boolean", defaultValue: true },
2862
+ { name: "required", label: "Required", type: "boolean", defaultValue: false },
2863
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2864
+ { name: "helperText", label: "Helper Text", type: "string" }
2865
+ ],
2866
+ traits: [
2867
+ fieldNameTrait({ defaultValue: "file_upload" }),
2868
+ labelTextTrait({ defaultValue: "Upload File" }),
2869
+ acceptTrait(),
2870
+ maxFileSizeTrait(),
2871
+ multipleTrait(),
2872
+ showPreviewTrait(),
2873
+ helperTextTrait(),
2874
+ requiredTrait(),
2875
+ disabledTrait(),
2876
+ idTrait(),
2877
+ ariaLabelTrait()
2878
+ ],
2879
+ validateProps: (props) => {
2880
+ const errors = [];
2881
+ if (props.label !== void 0 && typeof props.label !== "string" && !isVariableBinding(props.label)) {
2882
+ errors.push('FileUpload "label" must be a string when provided.');
2883
+ }
2884
+ if (props.name !== void 0 && typeof props.name !== "string" && !isVariableBinding(props.name)) {
2885
+ errors.push('FileUpload "name" must be a string when provided.');
2886
+ }
2887
+ if (props.accept !== void 0 && typeof props.accept !== "string" && !isVariableBinding(props.accept)) {
2888
+ errors.push('FileUpload "accept" must be a string when provided.');
2889
+ }
2890
+ if (props.maxFileSize !== void 0 && !isVariableBinding(props.maxFileSize)) {
2891
+ if (typeof props.maxFileSize !== "number" || props.maxFileSize <= 0) {
2892
+ errors.push('FileUpload "maxFileSize" must be a positive number when provided.');
2893
+ }
2894
+ }
2895
+ if (props.multiple !== void 0 && typeof props.multiple !== "boolean" && !isVariableBinding(props.multiple)) {
2896
+ errors.push('FileUpload "multiple" must be a boolean when provided.');
2897
+ }
2898
+ if (props.showPreview !== void 0 && typeof props.showPreview !== "boolean" && !isVariableBinding(props.showPreview)) {
2899
+ errors.push('FileUpload "showPreview" must be a boolean when provided.');
2900
+ }
2901
+ if (props.required !== void 0 && typeof props.required !== "boolean" && !isVariableBinding(props.required)) {
2902
+ errors.push('FileUpload "required" must be a boolean when provided.');
2903
+ }
2904
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
2905
+ errors.push('FileUpload "disabled" must be a boolean when provided.');
2906
+ }
2907
+ if (props.helperText !== void 0 && typeof props.helperText !== "string" && !isVariableBinding(props.helperText)) {
2908
+ errors.push('FileUpload "helperText" must be a string when provided.');
2909
+ }
2910
+ return errors.length > 0 ? errors : true;
2911
+ },
2912
+ defaultStyles: {
2913
+ base: {
2914
+ display: "flex",
2915
+ flexDirection: "column",
2916
+ gap: "8px",
2917
+ fontSize: "14px",
2918
+ color: "#1e293b"
2919
+ }
2920
+ }
2921
+ };
2922
+ var buttonSubmitDefinition = {
2923
+ type: "button-submit",
2924
+ label: "Submit Button",
2925
+ category: "form",
2926
+ icon: "send",
2927
+ acceptsChildren: false,
2928
+ capabilities: ["actionRegistry"],
2929
+ disallowedParents: ["page"],
2930
+ defaultProps: {
2931
+ label: "Submit",
2932
+ loadingText: "Submitting...",
2933
+ showSpinner: true,
2934
+ autoDisableOnSubmit: true,
2935
+ variant: "primary",
2936
+ disabled: false,
2937
+ buttonType: "submit"
2938
+ },
2939
+ propFields: [
2940
+ { name: "label", label: "Label", type: "string", defaultValue: "Submit" },
2941
+ { name: "loadingText", label: "Loading Text", type: "string", defaultValue: "Submitting..." },
2942
+ { name: "showSpinner", label: "Show Loading Spinner", type: "boolean", defaultValue: true },
2943
+ { name: "autoDisableOnSubmit", label: "Auto Disable on Submit", type: "boolean", defaultValue: true },
2944
+ {
2945
+ name: "buttonType",
2946
+ label: "Button Type",
2947
+ type: "select",
2948
+ defaultValue: "submit",
2949
+ options: [
2950
+ { label: "Submit Form (submit)", value: "submit" },
2951
+ { label: "Reset Form (reset)", value: "reset" }
2952
+ ]
2953
+ },
2954
+ {
2955
+ name: "variant",
2956
+ label: "Variant",
2957
+ type: "select",
2958
+ defaultValue: "primary",
2959
+ options: [
2960
+ { label: "Primary", value: "primary" },
2961
+ { label: "Secondary", value: "secondary" }
2962
+ ]
2963
+ },
2964
+ { name: "disabled", label: "Disabled", type: "boolean", defaultValue: false },
2965
+ { name: "prefixIcon", label: "Prefix Icon", type: "string" },
2966
+ { name: "suffixIcon", label: "Suffix Icon", type: "string" }
2967
+ ],
2968
+ traits: [
2969
+ buttonTypeTrait({
2970
+ defaultValue: "submit",
2971
+ options: [
2972
+ { label: "Submit Form (submit)", value: "submit" },
2973
+ { label: "Reset Form (reset)", value: "reset" }
2974
+ ]
2975
+ }),
2976
+ labelTextTrait({ defaultValue: "Submit", label: "Label" }),
2977
+ loadingTextTrait(),
2978
+ showSpinnerTrait(),
2979
+ autoDisableOnSubmitTrait(),
2980
+ disabledTrait(),
2981
+ prefixIconTrait(),
2982
+ suffixIconTrait(),
2983
+ idTrait(),
2984
+ titleTrait(),
2985
+ ariaLabelTrait()
2986
+ ],
2987
+ validateProps: (props) => {
2988
+ const errors = [];
2989
+ const hasLabel = typeof props.label === "string" && props.label.trim().length > 0 || isVariableBinding(props.label);
2990
+ if (!hasLabel) {
2991
+ errors.push('Submit Button requires a non-empty "label".');
2992
+ }
2993
+ if (props.loadingText !== void 0 && typeof props.loadingText !== "string" && !isVariableBinding(props.loadingText)) {
2994
+ errors.push('Submit Button "loadingText" must be a string when provided.');
2995
+ }
2996
+ if (props.showSpinner !== void 0 && typeof props.showSpinner !== "boolean" && !isVariableBinding(props.showSpinner)) {
2997
+ errors.push('Submit Button "showSpinner" must be a boolean when provided.');
2998
+ }
2999
+ if (props.autoDisableOnSubmit !== void 0 && typeof props.autoDisableOnSubmit !== "boolean" && !isVariableBinding(props.autoDisableOnSubmit)) {
3000
+ errors.push('Submit Button "autoDisableOnSubmit" must be a boolean when provided.');
3001
+ }
3002
+ if (props.buttonType !== void 0 && !isVariableBinding(props.buttonType)) {
3003
+ if (!["submit", "reset", "button"].includes(props.buttonType)) {
3004
+ errors.push('Submit Button "buttonType" must be one of: "submit", "reset", "button".');
3005
+ }
3006
+ }
3007
+ if (props.disabled !== void 0 && typeof props.disabled !== "boolean" && !isVariableBinding(props.disabled)) {
3008
+ errors.push('Submit Button "disabled" must be a boolean when provided.');
3009
+ }
3010
+ return errors.length > 0 ? errors : true;
3011
+ },
3012
+ defaultStyles: {
3013
+ base: {
3014
+ backgroundColor: "#2563eb",
3015
+ color: "#ffffff",
3016
+ paddingTop: "10px",
3017
+ paddingBottom: "10px",
3018
+ paddingLeft: "20px",
3019
+ paddingRight: "20px",
3020
+ borderRadius: "6px",
3021
+ fontWeight: "500",
3022
+ fontSize: "15px",
3023
+ border: "none",
3024
+ cursor: "pointer",
3025
+ display: "inline-flex",
3026
+ alignItems: "center",
3027
+ justifyContent: "center",
3028
+ gap: "8px"
3029
+ }
3030
+ }
3031
+ };
2194
3032
  var coreComponentDefinitions = [
2195
3033
  pageDefinition,
2196
3034
  sectionDefinition,
@@ -2208,12 +3046,17 @@ var coreComponentDefinitions = [
2208
3046
  iconDefinition,
2209
3047
  htmlEmbedDefinition,
2210
3048
  buttonDefinition,
3049
+ buttonSubmitDefinition,
2211
3050
  formDefinition,
2212
3051
  inputDefinition,
2213
3052
  textareaDefinition,
2214
3053
  selectDefinition,
2215
3054
  checkboxDefinition,
3055
+ switchDefinition,
3056
+ radioGroupDefinition,
2216
3057
  radioDefinition,
3058
+ radioItemDefinition,
3059
+ fileUploadDefinition,
2217
3060
  collectionDefinition,
2218
3061
  listDefinition,
2219
3062
  listItemDefinition,
@@ -2784,6 +3627,755 @@ var STARTER_BLOCKS = [
2784
3627
  }
2785
3628
  ]
2786
3629
  })
3630
+ },
3631
+ // --- Starter Form Templates (STORA-350) ---
3632
+ {
3633
+ id: "form-contact-us",
3634
+ name: "Contact Us Form",
3635
+ category: "forms",
3636
+ categoryLabel: "Form Templates",
3637
+ description: "Contact form with Name, Email, Subject, Message, and submit action pipeline with API request and toast notifications",
3638
+ icon: "form",
3639
+ createNodeTree: (gen = defaultGenId) => ({
3640
+ id: gen("section"),
3641
+ type: "section",
3642
+ styles: {
3643
+ base: {
3644
+ padding: "64px 20px",
3645
+ backgroundColor: "#f8fafc",
3646
+ width: "100%"
3647
+ }
3648
+ },
3649
+ children: [
3650
+ {
3651
+ id: gen("container"),
3652
+ type: "container",
3653
+ props: { tag: "div", maxWidth: "640px" },
3654
+ styles: {
3655
+ base: {
3656
+ maxWidth: "640px",
3657
+ margin: "0 auto",
3658
+ width: "100%",
3659
+ backgroundColor: "#ffffff",
3660
+ padding: "36px",
3661
+ borderRadius: "16px",
3662
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05)",
3663
+ border: "1px solid #e2e8f0"
3664
+ }
3665
+ },
3666
+ children: [
3667
+ {
3668
+ id: gen("heading"),
3669
+ type: "heading",
3670
+ props: { text: "Contact Us", level: 2 },
3671
+ styles: {
3672
+ base: {
3673
+ fontSize: "28px",
3674
+ fontWeight: "700",
3675
+ color: "#0f172a",
3676
+ marginBottom: "8px",
3677
+ textAlign: "center"
3678
+ }
3679
+ }
3680
+ },
3681
+ {
3682
+ id: gen("paragraph"),
3683
+ type: "paragraph",
3684
+ props: {
3685
+ content: "Have questions or need assistance? Fill out the form below and we will get back to you shortly."
3686
+ },
3687
+ styles: {
3688
+ base: {
3689
+ fontSize: "15px",
3690
+ color: "#64748b",
3691
+ marginBottom: "28px",
3692
+ textAlign: "center",
3693
+ lineHeight: "1.5"
3694
+ }
3695
+ }
3696
+ },
3697
+ {
3698
+ id: gen("form"),
3699
+ type: "form",
3700
+ props: {
3701
+ name: "contact_us_form",
3702
+ method: "POST",
3703
+ preventDefault: true,
3704
+ scrollToFirstError: true,
3705
+ resetOnSubmit: true
3706
+ },
3707
+ styles: {
3708
+ base: {
3709
+ display: "flex",
3710
+ flexDirection: "column",
3711
+ gap: "20px",
3712
+ width: "100%"
3713
+ }
3714
+ },
3715
+ actions: [
3716
+ {
3717
+ id: gen("pipeline"),
3718
+ trigger: "submit",
3719
+ label: "Submit Contact Form",
3720
+ enabled: true,
3721
+ steps: [
3722
+ {
3723
+ id: gen("step"),
3724
+ type: "api_request",
3725
+ label: "Send Contact Message",
3726
+ payload: {
3727
+ url: "/api/mock/submit-lead",
3728
+ method: "POST",
3729
+ bodyFormat: "json"
3730
+ },
3731
+ onSuccess: [
3732
+ {
3733
+ id: gen("step"),
3734
+ type: "show_toast",
3735
+ label: "Show Success Toast",
3736
+ payload: {
3737
+ message: "Thank you! Your message has been sent successfully.",
3738
+ type: "success",
3739
+ title: "Message Sent",
3740
+ duration: 4e3
3741
+ }
3742
+ },
3743
+ {
3744
+ id: gen("step"),
3745
+ type: "reset_form",
3746
+ label: "Reset Form",
3747
+ payload: {}
3748
+ }
3749
+ ],
3750
+ onError: [
3751
+ {
3752
+ id: gen("step"),
3753
+ type: "show_toast",
3754
+ label: "Show Error Toast",
3755
+ payload: {
3756
+ message: "Failed to send message. Please check your connection and try again.",
3757
+ type: "error",
3758
+ title: "Submission Failed",
3759
+ duration: 5e3
3760
+ }
3761
+ }
3762
+ ]
3763
+ }
3764
+ ]
3765
+ }
3766
+ ],
3767
+ children: [
3768
+ {
3769
+ id: gen("input"),
3770
+ type: "input",
3771
+ props: {
3772
+ name: "name",
3773
+ label: "Your Name",
3774
+ type: "text",
3775
+ placeholder: "Jane Doe",
3776
+ required: true,
3777
+ rules: [
3778
+ { type: "required", message: "Please enter your name" },
3779
+ { type: "min_length", value: 2, message: "Name must be at least 2 characters" }
3780
+ ]
3781
+ },
3782
+ styles: {
3783
+ base: {
3784
+ width: "100%",
3785
+ padding: "10px 14px",
3786
+ borderRadius: "8px",
3787
+ border: "1px solid #cbd5e1",
3788
+ fontSize: "14px"
3789
+ }
3790
+ }
3791
+ },
3792
+ {
3793
+ id: gen("input"),
3794
+ type: "input",
3795
+ props: {
3796
+ name: "email",
3797
+ label: "Email Address",
3798
+ type: "email",
3799
+ placeholder: "jane@example.com",
3800
+ required: true,
3801
+ rules: [
3802
+ { type: "required", message: "Please enter your email" },
3803
+ { type: "email", message: "Please enter a valid email address" }
3804
+ ]
3805
+ },
3806
+ styles: {
3807
+ base: {
3808
+ width: "100%",
3809
+ padding: "10px 14px",
3810
+ borderRadius: "8px",
3811
+ border: "1px solid #cbd5e1",
3812
+ fontSize: "14px"
3813
+ }
3814
+ }
3815
+ },
3816
+ {
3817
+ id: gen("input"),
3818
+ type: "input",
3819
+ props: {
3820
+ name: "subject",
3821
+ label: "Subject",
3822
+ type: "text",
3823
+ placeholder: "How can we help you?",
3824
+ required: true,
3825
+ rules: [
3826
+ { type: "required", message: "Please enter a subject" }
3827
+ ]
3828
+ },
3829
+ styles: {
3830
+ base: {
3831
+ width: "100%",
3832
+ padding: "10px 14px",
3833
+ borderRadius: "8px",
3834
+ border: "1px solid #cbd5e1",
3835
+ fontSize: "14px"
3836
+ }
3837
+ }
3838
+ },
3839
+ {
3840
+ id: gen("textarea"),
3841
+ type: "textarea",
3842
+ props: {
3843
+ name: "message",
3844
+ label: "Message",
3845
+ placeholder: "Write your message here...",
3846
+ rows: 4,
3847
+ required: true,
3848
+ rules: [
3849
+ { type: "required", message: "Please enter your message" },
3850
+ { type: "min_length", value: 10, message: "Message must be at least 10 characters" }
3851
+ ]
3852
+ },
3853
+ styles: {
3854
+ base: {
3855
+ width: "100%",
3856
+ padding: "10px 14px",
3857
+ borderRadius: "8px",
3858
+ border: "1px solid #cbd5e1",
3859
+ fontSize: "14px"
3860
+ }
3861
+ }
3862
+ },
3863
+ {
3864
+ id: gen("button"),
3865
+ type: "button",
3866
+ props: {
3867
+ label: "Send Message",
3868
+ variant: "primary",
3869
+ buttonType: "submit"
3870
+ },
3871
+ styles: {
3872
+ base: {
3873
+ width: "100%",
3874
+ backgroundColor: "#2563eb",
3875
+ color: "#ffffff",
3876
+ padding: "12px",
3877
+ borderRadius: "8px",
3878
+ fontWeight: "600",
3879
+ fontSize: "15px",
3880
+ display: "inline-block",
3881
+ textAlign: "center"
3882
+ },
3883
+ states: {
3884
+ ":hover": { backgroundColor: "#1d4ed8" }
3885
+ }
3886
+ }
3887
+ }
3888
+ ]
3889
+ }
3890
+ ]
3891
+ }
3892
+ ]
3893
+ })
3894
+ },
3895
+ {
3896
+ id: "form-newsletter",
3897
+ name: "Newsletter Subscribe Form",
3898
+ category: "forms",
3899
+ categoryLabel: "Form Templates",
3900
+ description: "Inline email newsletter subscription form with real-time feedback",
3901
+ icon: "mail",
3902
+ createNodeTree: (gen = defaultGenId) => ({
3903
+ id: gen("section"),
3904
+ type: "section",
3905
+ styles: {
3906
+ base: {
3907
+ padding: "48px 20px",
3908
+ backgroundColor: "#f1f5f9",
3909
+ width: "100%"
3910
+ }
3911
+ },
3912
+ children: [
3913
+ {
3914
+ id: gen("container"),
3915
+ type: "container",
3916
+ props: { tag: "div", maxWidth: "580px" },
3917
+ styles: {
3918
+ base: {
3919
+ maxWidth: "580px",
3920
+ margin: "0 auto",
3921
+ width: "100%",
3922
+ textAlign: "center"
3923
+ }
3924
+ },
3925
+ children: [
3926
+ {
3927
+ id: gen("heading"),
3928
+ type: "heading",
3929
+ props: { text: "Stay in the Loop", level: 3 },
3930
+ styles: {
3931
+ base: {
3932
+ fontSize: "26px",
3933
+ fontWeight: "700",
3934
+ color: "#0f172a",
3935
+ marginBottom: "8px"
3936
+ }
3937
+ }
3938
+ },
3939
+ {
3940
+ id: gen("paragraph"),
3941
+ type: "paragraph",
3942
+ props: {
3943
+ content: "Subscribe to our newsletter for weekly curated insights, updates, and best practices."
3944
+ },
3945
+ styles: {
3946
+ base: {
3947
+ fontSize: "15px",
3948
+ color: "#64748b",
3949
+ marginBottom: "24px",
3950
+ lineHeight: "1.5"
3951
+ }
3952
+ }
3953
+ },
3954
+ {
3955
+ id: gen("form"),
3956
+ type: "form",
3957
+ props: {
3958
+ name: "newsletter_form",
3959
+ method: "POST",
3960
+ preventDefault: true,
3961
+ resetOnSubmit: true
3962
+ },
3963
+ styles: {
3964
+ base: {
3965
+ display: "flex",
3966
+ flexDirection: "row",
3967
+ gap: "8px",
3968
+ alignItems: "center",
3969
+ width: "100%"
3970
+ },
3971
+ mobile: {
3972
+ flexDirection: "column"
3973
+ }
3974
+ },
3975
+ actions: [
3976
+ {
3977
+ id: gen("pipeline"),
3978
+ trigger: "submit",
3979
+ label: "Subscribe to Newsletter",
3980
+ enabled: true,
3981
+ steps: [
3982
+ {
3983
+ id: gen("step"),
3984
+ type: "api_request",
3985
+ label: "Submit Subscription",
3986
+ payload: {
3987
+ url: "/api/mock/submit-lead",
3988
+ method: "POST",
3989
+ bodyFormat: "json"
3990
+ },
3991
+ onSuccess: [
3992
+ {
3993
+ id: gen("step"),
3994
+ type: "show_toast",
3995
+ label: "Show Success Toast",
3996
+ payload: {
3997
+ message: "Thank you for subscribing to our newsletter!",
3998
+ type: "success",
3999
+ title: "Subscription Confirmed",
4000
+ duration: 4e3
4001
+ }
4002
+ },
4003
+ {
4004
+ id: gen("step"),
4005
+ type: "reset_form",
4006
+ label: "Reset Form",
4007
+ payload: {}
4008
+ }
4009
+ ],
4010
+ onError: [
4011
+ {
4012
+ id: gen("step"),
4013
+ type: "show_toast",
4014
+ label: "Show Error Toast",
4015
+ payload: {
4016
+ message: "Unable to subscribe right now. Please try again later.",
4017
+ type: "error",
4018
+ title: "Error",
4019
+ duration: 5e3
4020
+ }
4021
+ }
4022
+ ]
4023
+ }
4024
+ ]
4025
+ }
4026
+ ],
4027
+ children: [
4028
+ {
4029
+ id: gen("input"),
4030
+ type: "input",
4031
+ props: {
4032
+ name: "email",
4033
+ type: "email",
4034
+ placeholder: "Enter your email address...",
4035
+ required: true,
4036
+ rules: [
4037
+ { type: "required", message: "Email address is required" },
4038
+ { type: "email", message: "Please enter a valid email address" }
4039
+ ]
4040
+ },
4041
+ styles: {
4042
+ base: {
4043
+ flex: "1 1 0%",
4044
+ minWidth: "0",
4045
+ padding: "12px 16px",
4046
+ borderRadius: "8px",
4047
+ border: "1px solid #cbd5e1",
4048
+ backgroundColor: "#ffffff",
4049
+ fontSize: "14px"
4050
+ }
4051
+ }
4052
+ },
4053
+ {
4054
+ id: gen("button"),
4055
+ type: "button",
4056
+ props: {
4057
+ label: "Subscribe",
4058
+ variant: "primary",
4059
+ buttonType: "submit"
4060
+ },
4061
+ styles: {
4062
+ base: {
4063
+ backgroundColor: "#2563eb",
4064
+ color: "#ffffff",
4065
+ padding: "12px 24px",
4066
+ borderRadius: "8px",
4067
+ fontWeight: "600",
4068
+ fontSize: "14px",
4069
+ whiteSpace: "nowrap"
4070
+ },
4071
+ states: {
4072
+ ":hover": { backgroundColor: "#1d4ed8" }
4073
+ }
4074
+ }
4075
+ }
4076
+ ]
4077
+ }
4078
+ ]
4079
+ }
4080
+ ]
4081
+ })
4082
+ },
4083
+ {
4084
+ id: "form-lead-gen",
4085
+ name: "Lead Generation Form",
4086
+ category: "forms",
4087
+ categoryLabel: "Form Templates",
4088
+ description: "Multi-field lead generation form with phone validation, interest dropdown, and API submission pipeline",
4089
+ icon: "users",
4090
+ createNodeTree: (gen = defaultGenId) => ({
4091
+ id: gen("section"),
4092
+ type: "section",
4093
+ styles: {
4094
+ base: {
4095
+ padding: "64px 20px",
4096
+ backgroundColor: "#ffffff",
4097
+ width: "100%"
4098
+ }
4099
+ },
4100
+ children: [
4101
+ {
4102
+ id: gen("container"),
4103
+ type: "container",
4104
+ props: { tag: "div", maxWidth: "640px" },
4105
+ styles: {
4106
+ base: {
4107
+ maxWidth: "640px",
4108
+ margin: "0 auto",
4109
+ width: "100%",
4110
+ backgroundColor: "#ffffff",
4111
+ padding: "36px",
4112
+ borderRadius: "16px",
4113
+ border: "1px solid #e2e8f0",
4114
+ boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.05)"
4115
+ }
4116
+ },
4117
+ children: [
4118
+ {
4119
+ id: gen("badge"),
4120
+ type: "badge",
4121
+ props: { label: "FREE CONSULTATION", variant: "primary" },
4122
+ styles: { base: { marginBottom: "12px", display: "inline-block" } }
4123
+ },
4124
+ {
4125
+ id: gen("heading"),
4126
+ type: "heading",
4127
+ props: { text: "Schedule a Consultation", level: 2 },
4128
+ styles: {
4129
+ base: {
4130
+ fontSize: "28px",
4131
+ fontWeight: "700",
4132
+ color: "#0f172a",
4133
+ marginBottom: "8px"
4134
+ }
4135
+ }
4136
+ },
4137
+ {
4138
+ id: gen("paragraph"),
4139
+ type: "paragraph",
4140
+ props: {
4141
+ content: "Share your project details with our solutions team. We will analyze your needs and provide a personalized roadmap."
4142
+ },
4143
+ styles: {
4144
+ base: {
4145
+ fontSize: "15px",
4146
+ color: "#64748b",
4147
+ marginBottom: "28px",
4148
+ lineHeight: "1.5"
4149
+ }
4150
+ }
4151
+ },
4152
+ {
4153
+ id: gen("form"),
4154
+ type: "form",
4155
+ props: {
4156
+ name: "lead_generation_form",
4157
+ method: "POST",
4158
+ preventDefault: true,
4159
+ scrollToFirstError: true,
4160
+ resetOnSubmit: true
4161
+ },
4162
+ styles: {
4163
+ base: {
4164
+ display: "flex",
4165
+ flexDirection: "column",
4166
+ gap: "18px",
4167
+ width: "100%"
4168
+ }
4169
+ },
4170
+ actions: [
4171
+ {
4172
+ id: gen("pipeline"),
4173
+ trigger: "submit",
4174
+ label: "Submit Lead Form",
4175
+ enabled: true,
4176
+ steps: [
4177
+ {
4178
+ id: gen("step"),
4179
+ type: "api_request",
4180
+ label: "Send Lead Data",
4181
+ payload: {
4182
+ url: "/api/mock/submit-lead",
4183
+ method: "POST",
4184
+ bodyFormat: "json"
4185
+ },
4186
+ onSuccess: [
4187
+ {
4188
+ id: gen("step"),
4189
+ type: "show_toast",
4190
+ label: "Show Success Toast",
4191
+ payload: {
4192
+ message: "Thank you! Your request has been received. Our team will contact you shortly.",
4193
+ type: "success",
4194
+ title: "Request Submitted",
4195
+ duration: 4e3
4196
+ }
4197
+ },
4198
+ {
4199
+ id: gen("step"),
4200
+ type: "reset_form",
4201
+ label: "Reset Form",
4202
+ payload: {}
4203
+ }
4204
+ ],
4205
+ onError: [
4206
+ {
4207
+ id: gen("step"),
4208
+ type: "show_toast",
4209
+ label: "Show Error Toast",
4210
+ payload: {
4211
+ message: "Submission failed. Please verify your information and try again.",
4212
+ type: "error",
4213
+ title: "Submission Error",
4214
+ duration: 5e3
4215
+ }
4216
+ }
4217
+ ]
4218
+ }
4219
+ ]
4220
+ }
4221
+ ],
4222
+ children: [
4223
+ {
4224
+ id: gen("input"),
4225
+ type: "input",
4226
+ props: {
4227
+ name: "full_name",
4228
+ label: "Full Name",
4229
+ type: "text",
4230
+ placeholder: "Alex Morgan",
4231
+ required: true,
4232
+ rules: [
4233
+ { type: "required", message: "Full name is required" },
4234
+ { type: "min_length", value: 2, message: "Name must be at least 2 characters" }
4235
+ ]
4236
+ },
4237
+ styles: {
4238
+ base: {
4239
+ width: "100%",
4240
+ padding: "10px 14px",
4241
+ borderRadius: "8px",
4242
+ border: "1px solid #cbd5e1",
4243
+ fontSize: "14px"
4244
+ }
4245
+ }
4246
+ },
4247
+ {
4248
+ id: gen("input"),
4249
+ type: "input",
4250
+ props: {
4251
+ name: "email",
4252
+ label: "Business Email",
4253
+ type: "email",
4254
+ placeholder: "alex@company.com",
4255
+ required: true,
4256
+ rules: [
4257
+ { type: "required", message: "Business email is required" },
4258
+ { type: "email", message: "Please enter a valid email address" }
4259
+ ]
4260
+ },
4261
+ styles: {
4262
+ base: {
4263
+ width: "100%",
4264
+ padding: "10px 14px",
4265
+ borderRadius: "8px",
4266
+ border: "1px solid #cbd5e1",
4267
+ fontSize: "14px"
4268
+ }
4269
+ }
4270
+ },
4271
+ {
4272
+ id: gen("input"),
4273
+ type: "input",
4274
+ props: {
4275
+ name: "phone",
4276
+ label: "Phone Number",
4277
+ type: "tel",
4278
+ placeholder: "+62 812-3456-7890",
4279
+ required: true,
4280
+ rules: [
4281
+ { type: "required", message: "Phone number is required" },
4282
+ {
4283
+ type: "custom_regex",
4284
+ value: "^[+]?[0-9\\s-()]{8,20}$",
4285
+ message: "Please enter a valid phone number (min 8 digits)"
4286
+ }
4287
+ ]
4288
+ },
4289
+ styles: {
4290
+ base: {
4291
+ width: "100%",
4292
+ padding: "10px 14px",
4293
+ borderRadius: "8px",
4294
+ border: "1px solid #cbd5e1",
4295
+ fontSize: "14px"
4296
+ }
4297
+ }
4298
+ },
4299
+ {
4300
+ id: gen("select"),
4301
+ type: "select",
4302
+ props: {
4303
+ name: "interest",
4304
+ label: "Area of Interest",
4305
+ placeholder: "Select your interest / service...",
4306
+ required: true,
4307
+ defaultValue: "",
4308
+ options: [
4309
+ { label: "Web Platform Development", value: "web_platform" },
4310
+ { label: "Mobile Application", value: "mobile_app" },
4311
+ { label: "Cloud Architecture & DevOps", value: "cloud_devops" },
4312
+ { label: "UI/UX Product Design", value: "product_design" },
4313
+ { label: "General Inquiry", value: "general" }
4314
+ ],
4315
+ rules: [
4316
+ { type: "required", message: "Please select an area of interest" }
4317
+ ]
4318
+ },
4319
+ styles: {
4320
+ base: {
4321
+ width: "100%",
4322
+ padding: "10px 14px",
4323
+ borderRadius: "8px",
4324
+ border: "1px solid #cbd5e1",
4325
+ fontSize: "14px",
4326
+ backgroundColor: "#ffffff"
4327
+ }
4328
+ }
4329
+ },
4330
+ {
4331
+ id: gen("input"),
4332
+ type: "input",
4333
+ props: {
4334
+ name: "company",
4335
+ label: "Company Name (Optional)",
4336
+ type: "text",
4337
+ placeholder: "Company / Organization"
4338
+ },
4339
+ styles: {
4340
+ base: {
4341
+ width: "100%",
4342
+ padding: "10px 14px",
4343
+ borderRadius: "8px",
4344
+ border: "1px solid #cbd5e1",
4345
+ fontSize: "14px"
4346
+ }
4347
+ }
4348
+ },
4349
+ {
4350
+ id: gen("button"),
4351
+ type: "button",
4352
+ props: {
4353
+ label: "Request Consultation",
4354
+ variant: "primary",
4355
+ buttonType: "submit"
4356
+ },
4357
+ styles: {
4358
+ base: {
4359
+ width: "100%",
4360
+ backgroundColor: "#2563eb",
4361
+ color: "#ffffff",
4362
+ padding: "12px 24px",
4363
+ borderRadius: "8px",
4364
+ fontWeight: "600",
4365
+ fontSize: "15px",
4366
+ marginTop: "4px"
4367
+ },
4368
+ states: {
4369
+ ":hover": { backgroundColor: "#1d4ed8" }
4370
+ }
4371
+ }
4372
+ }
4373
+ ]
4374
+ }
4375
+ ]
4376
+ }
4377
+ ]
4378
+ })
2787
4379
  }
2788
4380
  ];
2789
4381
  export {
@@ -2791,14 +4383,18 @@ export {
2791
4383
  STARTER_BLOCKS,
2792
4384
  TRAIT_GROUP_LABELS,
2793
4385
  TRAIT_GROUP_ORDER,
4386
+ acceptTrait,
2794
4387
  actionTrait,
2795
4388
  altTrait,
2796
4389
  ariaLabelTrait,
2797
4390
  autoCompleteTrait,
4391
+ autoDisableOnSubmitTrait,
4392
+ autoGrowTrait,
2798
4393
  autoplayTrait,
2799
4394
  badgeDefinition,
2800
4395
  blockquoteDefinition,
2801
4396
  buttonDefinition,
4397
+ buttonSubmitDefinition,
2802
4398
  buttonTypeTrait,
2803
4399
  checkboxDefinition,
2804
4400
  citeTrait,
@@ -2812,42 +4408,68 @@ export {
2812
4408
  coreComponentDefinitions,
2813
4409
  createDefaultComponentRegistry,
2814
4410
  defaultCheckedTrait,
4411
+ defaultSelectedTrait,
2815
4412
  defaultValueTrait,
2816
4413
  disabledTrait,
2817
4414
  extractComponentRequirements,
2818
4415
  fieldNameTrait,
4416
+ fileUploadDefinition,
2819
4417
  formDefinition,
2820
4418
  headingDefinition,
4419
+ helperTextTrait,
2821
4420
  hrefTrait,
2822
4421
  htmlEmbedDefinition,
2823
4422
  iconDefinition,
2824
4423
  idTrait,
2825
4424
  imageDefinition,
4425
+ indeterminateTrait,
2826
4426
  inputDefinition,
2827
4427
  inputTypeTrait,
2828
4428
  isBindableField,
4429
+ labelTextTrait,
2829
4430
  linkDefinition,
2830
4431
  listDefinition,
2831
4432
  listItemDefinition,
4433
+ loadingTextTrait,
2832
4434
  loadingTrait,
2833
4435
  loopTrait,
4436
+ maxCharCountTrait,
4437
+ maxFileSizeTrait,
4438
+ maxLengthTrait,
2834
4439
  methodTrait,
4440
+ minLengthTrait,
4441
+ multipleTrait,
2835
4442
  mutedTrait,
4443
+ optionsListTrait,
4444
+ orientationTrait,
2836
4445
  pageDefinition,
2837
4446
  paragraphDefinition,
4447
+ patternTrait,
2838
4448
  placeholderTrait,
2839
4449
  posterTrait,
4450
+ prefixIconTrait,
4451
+ preventDefaultTrait,
2840
4452
  primitiveTypeForField,
2841
4453
  radioDefinition,
4454
+ radioGroupDefinition,
4455
+ radioItemDefinition,
2842
4456
  readOnlyTrait,
2843
4457
  relTrait,
2844
4458
  requiredTrait,
4459
+ resetOnSubmitTrait,
4460
+ resizeTrait,
2845
4461
  rowSpanTrait,
2846
4462
  rowsTrait,
4463
+ scrollToFirstErrorTrait,
2847
4464
  sectionDefinition,
2848
4465
  selectDefinition,
4466
+ showPreviewTrait,
4467
+ showSpinnerTrait,
2849
4468
  sortTraits,
2850
4469
  srcTrait,
4470
+ suffixIconTrait,
4471
+ switchDefinition,
4472
+ switchSizeTrait,
2851
4473
  tableCellDefinition,
2852
4474
  tableDefinition,
2853
4475
  tableRowDefinition,