@kubuild/components 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/blocks/index.cjs +601 -12
  2. package/dist/blocks/index.cjs.map +1 -1
  3. package/dist/blocks/index.d.ts +2 -1
  4. package/dist/blocks/index.d.ts.map +1 -1
  5. package/dist/blocks/index.js +3 -1
  6. package/dist/blocks/sales.d.ts +7 -0
  7. package/dist/blocks/sales.d.ts.map +1 -0
  8. package/dist/canonical-props.d.ts +8 -0
  9. package/dist/canonical-props.d.ts.map +1 -0
  10. package/dist/{chunk-3HU2KE2B.js → chunk-CJN5OHHX.js} +596 -9
  11. package/dist/chunk-CJN5OHHX.js.map +1 -0
  12. package/dist/{chunk-JTQ35OQQ.js → chunk-DIZKTXJI.js} +601 -13
  13. package/dist/chunk-DIZKTXJI.js.map +1 -0
  14. package/dist/definitions/constants.d.ts.map +1 -1
  15. package/dist/definitions/conversion/accordion.d.ts +8 -0
  16. package/dist/definitions/conversion/accordion.d.ts.map +1 -0
  17. package/dist/definitions/conversion/carousel.d.ts +7 -0
  18. package/dist/definitions/conversion/carousel.d.ts.map +1 -0
  19. package/dist/definitions/conversion/countdown.d.ts +19 -0
  20. package/dist/definitions/conversion/countdown.d.ts.map +1 -0
  21. package/dist/definitions/conversion/divider.d.ts +9 -0
  22. package/dist/definitions/conversion/divider.d.ts.map +1 -0
  23. package/dist/definitions/conversion/index.d.ts +7 -0
  24. package/dist/definitions/conversion/index.d.ts.map +1 -0
  25. package/dist/definitions/conversion/rating.d.ts +7 -0
  26. package/dist/definitions/conversion/rating.d.ts.map +1 -0
  27. package/dist/definitions/conversion/tabs.d.ts +9 -0
  28. package/dist/definitions/conversion/tabs.d.ts.map +1 -0
  29. package/dist/definitions/form/button.d.ts.map +1 -1
  30. package/dist/definitions/index.cjs +746 -147
  31. package/dist/definitions/index.cjs.map +1 -1
  32. package/dist/definitions/index.d.ts +1 -0
  33. package/dist/definitions/index.d.ts.map +1 -1
  34. package/dist/definitions/index.js +27 -1
  35. package/dist/definitions/types.d.ts +4 -1
  36. package/dist/definitions/types.d.ts.map +1 -1
  37. package/dist/definitions/typography/badge.d.ts.map +1 -1
  38. package/dist/definitions/typography/blockquote.d.ts.map +1 -1
  39. package/dist/definitions/typography/heading.d.ts.map +1 -1
  40. package/dist/definitions/typography/link.d.ts.map +1 -1
  41. package/dist/definitions/typography/paragraph.d.ts.map +1 -1
  42. package/dist/definitions/typography/text.d.ts.map +1 -1
  43. package/dist/index.cjs +1417 -227
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +32 -2
  48. package/dist/index.js.map +1 -1
  49. package/dist/registry.d.ts +12 -0
  50. package/dist/registry.d.ts.map +1 -1
  51. package/package.json +3 -3
  52. package/dist/chunk-3HU2KE2B.js.map +0 -1
  53. package/dist/chunk-JTQ35OQQ.js.map +0 -1
@@ -149,7 +149,20 @@ var ComponentRegistry = class {
149
149
  };
150
150
 
151
151
  // src/definitions/constants.ts
152
- var LAYOUT_PARENTS = ["page", "section", "container", "columns", "flex", "grid", "modal", "drawer", "collapsible"];
152
+ var LAYOUT_PARENTS = [
153
+ "page",
154
+ "section",
155
+ "container",
156
+ "columns",
157
+ "flex",
158
+ "grid",
159
+ "modal",
160
+ "drawer",
161
+ "collapsible",
162
+ "accordion-item",
163
+ "tab-panel",
164
+ "carousel"
165
+ ];
153
166
  var CONTENT_CHILD_TYPES = [
154
167
  "heading",
155
168
  "text",
@@ -180,7 +193,14 @@ var CONTENT_CHILD_TYPES = [
180
193
  "custom",
181
194
  "modal",
182
195
  "drawer",
183
- "collapsible"
196
+ "collapsible",
197
+ "countdown",
198
+ "accordion",
199
+ "tabs",
200
+ "carousel",
201
+ "rating",
202
+ "divider",
203
+ "spacer"
184
204
  ];
185
205
 
186
206
  // src/definitions/layout/page.ts
@@ -350,12 +370,26 @@ var gridDefinition = {
350
370
 
351
371
  // src/definitions/typography/heading.ts
352
372
  import { isVariableBinding } from "@kubuild/schema";
373
+
374
+ // src/canonical-props.ts
375
+ import { getCanonicalTextPropRule } from "@kubuild/schema";
376
+ function canonicalTextPropFields(componentType) {
377
+ const rule = getCanonicalTextPropRule(componentType);
378
+ if (!rule) return {};
379
+ return {
380
+ canonicalTextProp: rule.canonical,
381
+ deprecatedPropAliases: Object.fromEntries(rule.aliases.map((alias) => [alias, rule.canonical]))
382
+ };
383
+ }
384
+
385
+ // src/definitions/typography/heading.ts
353
386
  var headingDefinition = {
354
387
  type: "heading",
355
388
  label: "Heading",
356
389
  category: "typography",
357
390
  icon: "heading",
358
391
  acceptsChildren: false,
392
+ ...canonicalTextPropFields("heading"),
359
393
  defaultProps: { text: "Heading Text", level: 2 },
360
394
  propFields: [
361
395
  { name: "text", label: "Text", type: "string", defaultValue: "Heading Text" },
@@ -381,7 +415,8 @@ var headingDefinition = {
381
415
  ],
382
416
  validateProps: (props) => {
383
417
  const errors = [];
384
- if (!isVariableBinding(props.text) && (typeof props.text !== "string" || props.text.trim().length === 0)) {
418
+ const text = props.text ?? props.content;
419
+ if (!isVariableBinding(text) && (typeof text !== "string" || text.trim().length === 0)) {
385
420
  errors.push('Heading requires a non-empty "text".');
386
421
  }
387
422
  if (props.level !== void 0 && (typeof props.level !== "number" || props.level < 1 || props.level > 6)) {
@@ -407,9 +442,11 @@ var textDefinition = {
407
442
  category: "typography",
408
443
  icon: "type",
409
444
  acceptsChildren: false,
410
- defaultProps: { content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." },
445
+ ...canonicalTextPropFields("text"),
446
+ // `as: 'p'` keeps the block-level rendering the old `content` default produced (STORA-550).
447
+ defaultProps: { text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", as: "p" },
411
448
  propFields: [
412
- { name: "content", label: "Content", type: "string", defaultValue: "Lorem ipsum dolor sit amet." }
449
+ { name: "text", label: "Content", type: "string", defaultValue: "Lorem ipsum dolor sit amet." }
413
450
  ],
414
451
  traits: [
415
452
  idTrait(),
@@ -417,8 +454,9 @@ var textDefinition = {
417
454
  ariaLabelTrait()
418
455
  ],
419
456
  validateProps: (props) => {
420
- if (!isVariableBinding2(props.content) && (typeof props.content !== "string" || props.content.trim().length === 0)) {
421
- return ['Text requires a non-empty "content".'];
457
+ const value = props.text ?? props.content;
458
+ if (!isVariableBinding2(value) && (typeof value !== "string" || value.trim().length === 0)) {
459
+ return ['Text requires a non-empty "text".'];
422
460
  }
423
461
  return true;
424
462
  },
@@ -439,6 +477,7 @@ var paragraphDefinition = {
439
477
  category: "typography",
440
478
  icon: "paragraph",
441
479
  acceptsChildren: false,
480
+ ...canonicalTextPropFields("paragraph"),
442
481
  defaultProps: {
443
482
  text: "A paragraph of text with clean semantic typography."
444
483
  },
@@ -481,6 +520,7 @@ var linkDefinition = {
481
520
  category: "typography",
482
521
  icon: "link",
483
522
  acceptsChildren: false,
523
+ ...canonicalTextPropFields("link"),
484
524
  defaultProps: {
485
525
  text: "Click here",
486
526
  href: "#",
@@ -561,6 +601,7 @@ var blockquoteDefinition = {
561
601
  "html-embed",
562
602
  "custom"
563
603
  ],
604
+ ...canonicalTextPropFields("blockquote"),
564
605
  defaultProps: {
565
606
  text: "\u201CSimplicity is the soul of efficiency.\u201D"
566
607
  },
@@ -614,6 +655,7 @@ var badgeDefinition = {
614
655
  category: "typography",
615
656
  icon: "badge",
616
657
  acceptsChildren: false,
658
+ ...canonicalTextPropFields("badge"),
617
659
  defaultProps: {
618
660
  text: "Badge",
619
661
  variant: "default"
@@ -1286,6 +1328,7 @@ var buttonDefinition = {
1286
1328
  icon: "mouse-pointer",
1287
1329
  acceptsChildren: false,
1288
1330
  capabilities: ["actionRegistry"],
1331
+ ...canonicalTextPropFields("button"),
1289
1332
  defaultProps: {
1290
1333
  label: "Click Me",
1291
1334
  variant: "primary"
@@ -2616,6 +2659,526 @@ var collapsibleDefinition = {
2616
2659
  }
2617
2660
  };
2618
2661
 
2662
+ // src/definitions/conversion/countdown.ts
2663
+ import { isVariableBinding as isVariableBinding23 } from "@kubuild/schema";
2664
+ var COUNTDOWN_MODES = ["evergreen", "fixed"];
2665
+ var COUNTDOWN_FORMATS = ["mm:ss", "hh:mm:ss", "d h m s"];
2666
+ var COUNTDOWN_EXPIRE_BEHAVIORS = ["text", "hide", "zero"];
2667
+ var COUNTDOWN_STORAGE_TYPES = ["session", "local"];
2668
+ var countdownDefinition = {
2669
+ type: "countdown",
2670
+ label: "Countdown",
2671
+ category: "interactive",
2672
+ icon: "clock",
2673
+ description: "Urgency timer for limited offers (evergreen per-visitor or fixed deadline).",
2674
+ acceptsChildren: false,
2675
+ defaultProps: {
2676
+ mode: "evergreen",
2677
+ durationMinutes: 15,
2678
+ targetDate: "",
2679
+ timezone: "UTC",
2680
+ format: "hh:mm:ss",
2681
+ label: "",
2682
+ labelDays: "Days",
2683
+ labelHours: "Hours",
2684
+ labelMinutes: "Minutes",
2685
+ labelSeconds: "Seconds",
2686
+ expireBehavior: "text",
2687
+ expiredText: "This offer has expired.",
2688
+ storage: "session",
2689
+ storageKey: ""
2690
+ },
2691
+ propFields: [
2692
+ {
2693
+ name: "mode",
2694
+ label: "Mode",
2695
+ type: "select",
2696
+ defaultValue: "evergreen",
2697
+ options: [
2698
+ { label: "Evergreen (per visitor)", value: "evergreen" },
2699
+ { label: "Fixed date", value: "fixed" }
2700
+ ]
2701
+ },
2702
+ {
2703
+ name: "durationMinutes",
2704
+ label: "Duration (minutes)",
2705
+ type: "number",
2706
+ defaultValue: 15,
2707
+ description: "Evergreen mode: how long each visitor gets from their first view."
2708
+ },
2709
+ {
2710
+ name: "targetDate",
2711
+ label: "Target Date/Time",
2712
+ type: "string",
2713
+ defaultValue: "",
2714
+ description: 'Fixed mode: wall-clock time "YYYY-MM-DDTHH:mm" in the selected timezone.'
2715
+ },
2716
+ {
2717
+ name: "timezone",
2718
+ label: "Timezone",
2719
+ type: "string",
2720
+ defaultValue: "UTC",
2721
+ description: 'Fixed mode: IANA timezone name, e.g. "Asia/Jakarta" or "Europe/London".'
2722
+ },
2723
+ {
2724
+ name: "format",
2725
+ label: "Format",
2726
+ type: "select",
2727
+ defaultValue: "hh:mm:ss",
2728
+ options: [
2729
+ { label: "mm:ss", value: "mm:ss" },
2730
+ { label: "hh:mm:ss", value: "hh:mm:ss" },
2731
+ { label: "d h m s (unit blocks)", value: "d h m s" }
2732
+ ]
2733
+ },
2734
+ {
2735
+ name: "label",
2736
+ label: "Label",
2737
+ type: "string",
2738
+ defaultValue: "",
2739
+ description: 'Optional text shown before the timer, e.g. "Offer ends in".'
2740
+ },
2741
+ { name: "labelDays", label: "Days Label", type: "string", defaultValue: "Days" },
2742
+ { name: "labelHours", label: "Hours Label", type: "string", defaultValue: "Hours" },
2743
+ { name: "labelMinutes", label: "Minutes Label", type: "string", defaultValue: "Minutes" },
2744
+ { name: "labelSeconds", label: "Seconds Label", type: "string", defaultValue: "Seconds" },
2745
+ {
2746
+ name: "expireBehavior",
2747
+ label: "When Expired",
2748
+ type: "select",
2749
+ defaultValue: "text",
2750
+ options: [
2751
+ { label: "Show expired text", value: "text" },
2752
+ { label: "Hide timer", value: "hide" },
2753
+ { label: "Keep showing zeros", value: "zero" }
2754
+ ],
2755
+ description: 'Add an "On Expire" action pipeline to redirect, show a toast, open a modal, etc.'
2756
+ },
2757
+ {
2758
+ name: "expiredText",
2759
+ label: "Expired Text",
2760
+ type: "string",
2761
+ defaultValue: "This offer has expired."
2762
+ },
2763
+ {
2764
+ name: "storage",
2765
+ label: "Evergreen Storage",
2766
+ type: "select",
2767
+ defaultValue: "session",
2768
+ options: [
2769
+ { label: "Session (per browser session)", value: "session" },
2770
+ { label: "Local (persists across visits)", value: "local" }
2771
+ ]
2772
+ },
2773
+ {
2774
+ name: "storageKey",
2775
+ label: "Storage Key",
2776
+ type: "string",
2777
+ defaultValue: "",
2778
+ description: "Share one deadline across pages by using the same key (defaults to the node id)."
2779
+ }
2780
+ ],
2781
+ traits: [
2782
+ idTrait(),
2783
+ ariaLabelTrait({ description: 'Accessible name for the timer, e.g. "Offer ends in".' })
2784
+ ],
2785
+ defaultStyles: {
2786
+ base: {
2787
+ display: "flex",
2788
+ alignItems: "center",
2789
+ justifyContent: "center",
2790
+ gap: "12px",
2791
+ fontSize: "28px",
2792
+ fontWeight: "700",
2793
+ fontVariantNumeric: "tabular-nums"
2794
+ }
2795
+ },
2796
+ validateProps: (props) => {
2797
+ const errors = [];
2798
+ const checkEnum = (name, allowed) => {
2799
+ const value = props[name];
2800
+ if (value === void 0 || isVariableBinding23(value)) return;
2801
+ if (typeof value !== "string" || !allowed.includes(value)) {
2802
+ errors.push(`Countdown "${name}" must be one of: ${allowed.join(", ")}.`);
2803
+ }
2804
+ };
2805
+ checkEnum("mode", COUNTDOWN_MODES);
2806
+ checkEnum("format", COUNTDOWN_FORMATS);
2807
+ checkEnum("expireBehavior", COUNTDOWN_EXPIRE_BEHAVIORS);
2808
+ checkEnum("storage", COUNTDOWN_STORAGE_TYPES);
2809
+ const duration = props.durationMinutes;
2810
+ if (duration !== void 0 && !isVariableBinding23(duration)) {
2811
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0) {
2812
+ errors.push('Countdown "durationMinutes" must be a non-negative number.');
2813
+ }
2814
+ }
2815
+ return errors;
2816
+ }
2817
+ };
2818
+
2819
+ // src/definitions/conversion/accordion.ts
2820
+ import { isVariableBinding as isVariableBinding24 } from "@kubuild/schema";
2821
+ var accordionDefinition = {
2822
+ type: "accordion",
2823
+ label: "Accordion",
2824
+ category: "interactive",
2825
+ icon: "chevron-down",
2826
+ description: "Group of expandable items (FAQ) with single- or multi-open behavior.",
2827
+ acceptsChildren: true,
2828
+ allowedChildren: ["accordion-item"],
2829
+ defaultProps: {
2830
+ allowMultiple: false,
2831
+ defaultOpenIndex: 0,
2832
+ icon: "chevron",
2833
+ faqSchema: false
2834
+ },
2835
+ defaultChildren: [
2836
+ {
2837
+ type: "accordion-item",
2838
+ props: { title: "What is included?" },
2839
+ children: [{ type: "paragraph", props: { text: "Everything you need to get started." } }]
2840
+ },
2841
+ {
2842
+ type: "accordion-item",
2843
+ props: { title: "Can I get a refund?" },
2844
+ children: [{ type: "paragraph", props: { text: "Yes, within 30 days of purchase." } }]
2845
+ },
2846
+ {
2847
+ type: "accordion-item",
2848
+ props: { title: "How do I get access?" },
2849
+ children: [
2850
+ { type: "paragraph", props: { text: "You receive an email right after checkout." } }
2851
+ ]
2852
+ }
2853
+ ],
2854
+ propFields: [
2855
+ {
2856
+ name: "allowMultiple",
2857
+ label: "Allow Multiple Open",
2858
+ type: "boolean",
2859
+ defaultValue: false,
2860
+ description: "When off, opening an item closes the others."
2861
+ },
2862
+ {
2863
+ name: "defaultOpenIndex",
2864
+ label: "Default Open Item",
2865
+ type: "number",
2866
+ defaultValue: 0,
2867
+ description: "Zero-based index of the item open on first render (-1 = all closed)."
2868
+ },
2869
+ {
2870
+ name: "icon",
2871
+ label: "Icon",
2872
+ type: "select",
2873
+ defaultValue: "chevron",
2874
+ options: [
2875
+ { label: "Chevron", value: "chevron" },
2876
+ { label: "Plus / Minus", value: "plus" },
2877
+ { label: "None", value: "none" }
2878
+ ]
2879
+ },
2880
+ {
2881
+ name: "faqSchema",
2882
+ label: "Output FAQPage JSON-LD",
2883
+ type: "boolean",
2884
+ defaultValue: false,
2885
+ description: "Emits schema.org FAQPage structured data on the published page for SEO."
2886
+ }
2887
+ ],
2888
+ traits: [idTrait(), ariaLabelTrait({ description: "Accessible name for the accordion group." })],
2889
+ defaultStyles: {
2890
+ base: {
2891
+ display: "flex",
2892
+ flexDirection: "column",
2893
+ width: "100%",
2894
+ borderTop: "1px solid #e2e8f0"
2895
+ }
2896
+ },
2897
+ validateProps: (props) => {
2898
+ const errors = [];
2899
+ const idx = props.defaultOpenIndex;
2900
+ if (idx !== void 0 && !isVariableBinding24(idx) && (typeof idx !== "number" || !Number.isInteger(idx))) {
2901
+ errors.push('Accordion "defaultOpenIndex" must be an integer.');
2902
+ }
2903
+ return errors;
2904
+ }
2905
+ };
2906
+ var accordionItemDefinition = {
2907
+ type: "accordion-item",
2908
+ label: "Accordion Item",
2909
+ category: "interactive",
2910
+ icon: "chevron-right",
2911
+ description: "One question/answer row of an accordion: a title header plus content children.",
2912
+ acceptsChildren: true,
2913
+ allowedChildren: ["container", "columns", "flex", "grid", ...CONTENT_CHILD_TYPES],
2914
+ defaultProps: {
2915
+ title: "Question"
2916
+ },
2917
+ defaultChildren: [{ type: "paragraph", props: { text: "Answer goes here." } }],
2918
+ propFields: [{ name: "title", label: "Title", type: "string", defaultValue: "Question" }],
2919
+ traits: [idTrait()],
2920
+ defaultStyles: {
2921
+ base: {
2922
+ borderBottom: "1px solid #e2e8f0"
2923
+ }
2924
+ }
2925
+ };
2926
+
2927
+ // src/definitions/conversion/tabs.ts
2928
+ import { isVariableBinding as isVariableBinding25 } from "@kubuild/schema";
2929
+ var tabsDefinition = {
2930
+ type: "tabs",
2931
+ label: "Tabs",
2932
+ category: "interactive",
2933
+ icon: "tabs",
2934
+ description: "Tabbed content for product variants, specifications, or plan comparison.",
2935
+ acceptsChildren: true,
2936
+ allowedChildren: ["tab-panel"],
2937
+ defaultProps: {
2938
+ activeIndex: 0
2939
+ },
2940
+ defaultChildren: [
2941
+ {
2942
+ type: "tab-panel",
2943
+ props: { label: "Tab 1" },
2944
+ children: [{ type: "paragraph", props: { text: "Content for the first tab." } }]
2945
+ },
2946
+ {
2947
+ type: "tab-panel",
2948
+ props: { label: "Tab 2" },
2949
+ children: [{ type: "paragraph", props: { text: "Content for the second tab." } }]
2950
+ }
2951
+ ],
2952
+ propFields: [
2953
+ {
2954
+ name: "activeIndex",
2955
+ label: "Active Tab",
2956
+ type: "number",
2957
+ defaultValue: 0,
2958
+ description: "Zero-based index of the tab shown initially."
2959
+ }
2960
+ ],
2961
+ traits: [idTrait(), ariaLabelTrait({ description: "Accessible name for the tab list." })],
2962
+ defaultStyles: {
2963
+ base: {
2964
+ display: "flex",
2965
+ flexDirection: "column",
2966
+ width: "100%"
2967
+ }
2968
+ },
2969
+ validateProps: (props) => {
2970
+ const errors = [];
2971
+ const idx = props.activeIndex;
2972
+ if (idx !== void 0 && !isVariableBinding25(idx) && (typeof idx !== "number" || !Number.isInteger(idx) || idx < 0)) {
2973
+ errors.push('Tabs "activeIndex" must be a non-negative integer.');
2974
+ }
2975
+ return errors;
2976
+ }
2977
+ };
2978
+ var tabPanelDefinition = {
2979
+ type: "tab-panel",
2980
+ label: "Tab Panel",
2981
+ category: "interactive",
2982
+ icon: "layout",
2983
+ description: "Content of a single tab; its label is shown in the tab list.",
2984
+ acceptsChildren: true,
2985
+ allowedChildren: ["container", "columns", "flex", "grid", ...CONTENT_CHILD_TYPES],
2986
+ defaultProps: {
2987
+ label: "Tab"
2988
+ },
2989
+ defaultChildren: [{ type: "paragraph", props: { text: "Tab content." } }],
2990
+ propFields: [{ name: "label", label: "Tab Label", type: "string", defaultValue: "Tab" }],
2991
+ traits: [idTrait()],
2992
+ defaultStyles: {
2993
+ base: {
2994
+ paddingTop: "16px"
2995
+ }
2996
+ }
2997
+ };
2998
+
2999
+ // src/definitions/conversion/carousel.ts
3000
+ import { isVariableBinding as isVariableBinding26 } from "@kubuild/schema";
3001
+ var carouselDefinition = {
3002
+ type: "carousel",
3003
+ label: "Carousel",
3004
+ category: "interactive",
3005
+ icon: "carousel",
3006
+ description: "Slider for product galleries and testimonials; each child is a slide.",
3007
+ acceptsChildren: true,
3008
+ allowedChildren: ["*"],
3009
+ defaultProps: {
3010
+ autoplay: false,
3011
+ interval: 5e3,
3012
+ loop: true,
3013
+ showDots: true,
3014
+ showArrows: true
3015
+ },
3016
+ defaultChildren: [
3017
+ { type: "container", children: [{ type: "paragraph", props: { text: "Slide 1" } }] },
3018
+ { type: "container", children: [{ type: "paragraph", props: { text: "Slide 2" } }] },
3019
+ { type: "container", children: [{ type: "paragraph", props: { text: "Slide 3" } }] }
3020
+ ],
3021
+ propFields: [
3022
+ { name: "autoplay", label: "Autoplay", type: "boolean", defaultValue: false },
3023
+ { name: "interval", label: "Autoplay Interval (ms)", type: "number", defaultValue: 5e3 },
3024
+ { name: "loop", label: "Loop", type: "boolean", defaultValue: true },
3025
+ { name: "showDots", label: "Show Dots", type: "boolean", defaultValue: true },
3026
+ { name: "showArrows", label: "Show Arrows", type: "boolean", defaultValue: true }
3027
+ ],
3028
+ traits: [
3029
+ idTrait(),
3030
+ ariaLabelTrait({ description: 'Accessible name for the carousel, e.g. "Testimonials".' })
3031
+ ],
3032
+ defaultStyles: {
3033
+ base: {
3034
+ position: "relative",
3035
+ width: "100%",
3036
+ overflow: "hidden"
3037
+ }
3038
+ },
3039
+ validateProps: (props) => {
3040
+ const errors = [];
3041
+ const interval = props.interval;
3042
+ if (interval !== void 0 && !isVariableBinding26(interval) && (typeof interval !== "number" || !(interval > 0))) {
3043
+ errors.push('Carousel "interval" must be a positive number of milliseconds.');
3044
+ }
3045
+ return errors;
3046
+ }
3047
+ };
3048
+
3049
+ // src/definitions/conversion/rating.ts
3050
+ import { isVariableBinding as isVariableBinding27 } from "@kubuild/schema";
3051
+ var ratingDefinition = {
3052
+ type: "rating",
3053
+ label: "Rating",
3054
+ category: "media",
3055
+ icon: "star",
3056
+ description: "Read-only star rating with half-star support.",
3057
+ acceptsChildren: false,
3058
+ defaultProps: {
3059
+ value: 5,
3060
+ max: 5,
3061
+ size: 20,
3062
+ color: "#f59e0b",
3063
+ emptyColor: "#e2e8f0",
3064
+ labelTemplate: "{value} out of {max}"
3065
+ },
3066
+ propFields: [
3067
+ {
3068
+ name: "value",
3069
+ label: "Value",
3070
+ type: "number",
3071
+ defaultValue: 5,
3072
+ description: "Rounded to the nearest half star."
3073
+ },
3074
+ { name: "max", label: "Max Stars", type: "number", defaultValue: 5 },
3075
+ { name: "size", label: "Star Size (px)", type: "number", defaultValue: 20 },
3076
+ { name: "color", label: "Color", type: "color", defaultValue: "#f59e0b" },
3077
+ { name: "emptyColor", label: "Empty Color", type: "color", defaultValue: "#e2e8f0" },
3078
+ {
3079
+ name: "labelTemplate",
3080
+ label: "Accessible Label",
3081
+ type: "string",
3082
+ defaultValue: "{value} out of {max}",
3083
+ description: 'Screen reader text; {value} and {max} are replaced (e.g. "{value} dari {max}").'
3084
+ }
3085
+ ],
3086
+ traits: [idTrait()],
3087
+ defaultStyles: {
3088
+ base: {
3089
+ display: "inline-flex",
3090
+ alignItems: "center",
3091
+ gap: "2px"
3092
+ }
3093
+ },
3094
+ validateProps: (props) => {
3095
+ const errors = [];
3096
+ for (const name of ["value", "max", "size"]) {
3097
+ const v = props[name];
3098
+ if (v !== void 0 && !isVariableBinding27(v) && (typeof v !== "number" || !Number.isFinite(v) || v < 0)) {
3099
+ errors.push(`Rating "${name}" must be a non-negative number.`);
3100
+ }
3101
+ }
3102
+ return errors;
3103
+ }
3104
+ };
3105
+
3106
+ // src/definitions/conversion/divider.ts
3107
+ import { isVariableBinding as isVariableBinding28 } from "@kubuild/schema";
3108
+ var dividerDefinition = {
3109
+ type: "divider",
3110
+ label: "Divider",
3111
+ category: "layout",
3112
+ icon: "divider",
3113
+ description: "Horizontal rule (solid/dashed/dotted) with an optional centered label.",
3114
+ acceptsChildren: false,
3115
+ defaultProps: {
3116
+ lineStyle: "solid",
3117
+ thickness: 1,
3118
+ color: "#e2e8f0",
3119
+ label: ""
3120
+ },
3121
+ propFields: [
3122
+ {
3123
+ name: "lineStyle",
3124
+ label: "Line Style",
3125
+ type: "select",
3126
+ defaultValue: "solid",
3127
+ options: [
3128
+ { label: "Solid", value: "solid" },
3129
+ { label: "Dashed", value: "dashed" },
3130
+ { label: "Dotted", value: "dotted" }
3131
+ ]
3132
+ },
3133
+ { name: "thickness", label: "Thickness (px)", type: "number", defaultValue: 1 },
3134
+ { name: "color", label: "Color", type: "color", defaultValue: "#e2e8f0" },
3135
+ {
3136
+ name: "label",
3137
+ label: "Center Label",
3138
+ type: "string",
3139
+ defaultValue: "",
3140
+ description: 'Optional text in the middle of the line, e.g. "OR".'
3141
+ }
3142
+ ],
3143
+ traits: [idTrait()],
3144
+ defaultStyles: {
3145
+ base: {
3146
+ width: "100%",
3147
+ marginTop: "16px",
3148
+ marginBottom: "16px"
3149
+ }
3150
+ },
3151
+ validateProps: (props) => {
3152
+ const v = props.lineStyle;
3153
+ if (v !== void 0 && !isVariableBinding28(v) && !["solid", "dashed", "dotted"].includes(v)) {
3154
+ return ['Divider "lineStyle" must be one of: solid, dashed, dotted.'];
3155
+ }
3156
+ return [];
3157
+ }
3158
+ };
3159
+ var spacerDefinition = {
3160
+ type: "spacer",
3161
+ label: "Spacer",
3162
+ category: "layout",
3163
+ icon: "dimension",
3164
+ description: "Empty vertical space; height is responsive per breakpoint.",
3165
+ acceptsChildren: false,
3166
+ defaultProps: {},
3167
+ traits: [idTrait()],
3168
+ defaultStyles: {
3169
+ base: {
3170
+ width: "100%",
3171
+ height: "48px"
3172
+ },
3173
+ tablet: {
3174
+ height: "32px"
3175
+ },
3176
+ mobile: {
3177
+ height: "24px"
3178
+ }
3179
+ }
3180
+ };
3181
+
2619
3182
  // src/definitions/index.ts
2620
3183
  var coreComponentDefinitions = [
2621
3184
  pageDefinition,
@@ -2655,7 +3218,17 @@ var coreComponentDefinitions = [
2655
3218
  tableCellDefinition,
2656
3219
  modalDefinition,
2657
3220
  drawerDefinition,
2658
- collapsibleDefinition
3221
+ collapsibleDefinition,
3222
+ // Conversion components (Epic 60)
3223
+ countdownDefinition,
3224
+ accordionDefinition,
3225
+ accordionItemDefinition,
3226
+ tabsDefinition,
3227
+ tabPanelDefinition,
3228
+ carouselDefinition,
3229
+ ratingDefinition,
3230
+ dividerDefinition,
3231
+ spacerDefinition
2659
3232
  ];
2660
3233
  function createDefaultComponentRegistry() {
2661
3234
  const registry = new ComponentRegistry();
@@ -2675,6 +3248,7 @@ export {
2675
3248
  columnsDefinition,
2676
3249
  flexDefinition,
2677
3250
  gridDefinition,
3251
+ canonicalTextPropFields,
2678
3252
  headingDefinition,
2679
3253
  textDefinition,
2680
3254
  paragraphDefinition,
@@ -2707,7 +3281,20 @@ export {
2707
3281
  modalDefinition,
2708
3282
  drawerDefinition,
2709
3283
  collapsibleDefinition,
3284
+ COUNTDOWN_MODES,
3285
+ COUNTDOWN_FORMATS,
3286
+ COUNTDOWN_EXPIRE_BEHAVIORS,
3287
+ COUNTDOWN_STORAGE_TYPES,
3288
+ countdownDefinition,
3289
+ accordionDefinition,
3290
+ accordionItemDefinition,
3291
+ tabsDefinition,
3292
+ tabPanelDefinition,
3293
+ carouselDefinition,
3294
+ ratingDefinition,
3295
+ dividerDefinition,
3296
+ spacerDefinition,
2710
3297
  coreComponentDefinitions,
2711
3298
  createDefaultComponentRegistry
2712
3299
  };
2713
- //# sourceMappingURL=chunk-3HU2KE2B.js.map
3300
+ //# sourceMappingURL=chunk-CJN5OHHX.js.map