@cloudflare/kumo 2.0.2 → 2.0.4

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 (161) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/ai/component-registry.json +17 -3
  3. package/ai/component-registry.md +34 -4
  4. package/ai/schemas.ts +5 -2
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +10 -4
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/ai/schemas.js +510 -504
  9. package/dist/ai/schemas.js.map +1 -1
  10. package/dist/chunks/{autocomplete-48aq0d244bs2e8zv.js → autocomplete-hbs51xgjf9iglbmq.js} +27 -26
  11. package/dist/chunks/autocomplete-hbs51xgjf9iglbmq.js.map +1 -0
  12. package/dist/chunks/{badge-dan90i0rzy4pwa1j.js → badge-kqox9toi0sygfbno.js} +16 -16
  13. package/dist/chunks/badge-kqox9toi0sygfbno.js.map +1 -0
  14. package/dist/chunks/{banner-eiwcnk7ts21s3bnb.js → banner-eux4y8xaogjg64af.js} +32 -31
  15. package/dist/chunks/banner-eux4y8xaogjg64af.js.map +1 -0
  16. package/dist/chunks/{breadcrumbs-cxcwf2l1ki3ffg5d.js → breadcrumbs-er08s9swoctwoj69.js} +33 -32
  17. package/dist/chunks/breadcrumbs-er08s9swoctwoj69.js.map +1 -0
  18. package/dist/chunks/{button-6by9ntsa3nj553mq.js → button-fe5rvewji3e5xd7m.js} +79 -63
  19. package/dist/chunks/button-fe5rvewji3e5xd7m.js.map +1 -0
  20. package/dist/chunks/{checkbox-hvxfvhtx1qjo2mww.js → checkbox-l7kc0vcs0o7a6fgn.js} +2 -2
  21. package/dist/chunks/checkbox-l7kc0vcs0o7a6fgn.js.map +1 -0
  22. package/dist/chunks/{clipboard-text-hswydzx3iql369sd.js → clipboard-text-je4e2q880wngmmuc.js} +57 -56
  23. package/dist/chunks/clipboard-text-je4e2q880wngmmuc.js.map +1 -0
  24. package/dist/chunks/{cloudflare-logo-pbavoe1wu8nr5c4n.js → cloudflare-logo-fya2cd2ljozkzjh8.js} +84 -75
  25. package/dist/chunks/cloudflare-logo-fya2cd2ljozkzjh8.js.map +1 -0
  26. package/dist/chunks/{code-f9v1ikwhekqw274q.js → code-bbnjm8vk9hxl129r.js} +20 -19
  27. package/dist/chunks/code-bbnjm8vk9hxl129r.js.map +1 -0
  28. package/dist/chunks/{combobox-fq36ye0hstote16x.js → combobox-ck95wketqoqbxjwb.js} +11 -10
  29. package/dist/chunks/combobox-ck95wketqoqbxjwb.js.map +1 -0
  30. package/dist/chunks/{command-palette-md65owxt5hv4rt9r.js → command-palette-kgiso245exdons4r.js} +2 -2
  31. package/dist/chunks/{command-palette-md65owxt5hv4rt9r.js.map → command-palette-kgiso245exdons4r.js.map} +1 -1
  32. package/dist/chunks/{dialog-k3f1fbam6nt96k8x.js → dialog-mqpvaidy0vnjwrfp.js} +16 -15
  33. package/dist/chunks/dialog-mqpvaidy0vnjwrfp.js.map +1 -0
  34. package/dist/chunks/{dropdown-zbax0zowy6m9zhmt.js → dropdown-gp5iptj1niq14lpv.js} +76 -75
  35. package/dist/chunks/dropdown-gp5iptj1niq14lpv.js.map +1 -0
  36. package/dist/chunks/{empty-b82oer7npkhtkx7k.js → empty-bmacg9ap2gjmyqiw.js} +27 -26
  37. package/dist/chunks/empty-bmacg9ap2gjmyqiw.js.map +1 -0
  38. package/dist/chunks/{field-c0wf94plit2gci59.js → field-hmucpi6d4sqci1zu.js} +2 -2
  39. package/dist/chunks/{field-c0wf94plit2gci59.js.map → field-hmucpi6d4sqci1zu.js.map} +1 -1
  40. package/dist/chunks/{grid-hj1ylz16p7g5uelh.js → grid-do93dv1rjggqxx7p.js} +30 -29
  41. package/dist/chunks/grid-do93dv1rjggqxx7p.js.map +1 -0
  42. package/dist/chunks/{input-area-bkyzu6f7gsck479h.js → input-area-dpgn5810c269jwbu.js} +3 -3
  43. package/dist/chunks/{input-area-bkyzu6f7gsck479h.js.map → input-area-dpgn5810c269jwbu.js.map} +1 -1
  44. package/dist/chunks/{input-group-bidweffa0zyg8gt0.js → input-group-k1xa9cu8ochl1arh.js} +4 -4
  45. package/dist/chunks/{input-group-bidweffa0zyg8gt0.js.map → input-group-k1xa9cu8ochl1arh.js.map} +1 -1
  46. package/dist/chunks/{input-ncfowphv81yq7fyy.js → input-k2ychlh2zo6hsocz.js} +51 -50
  47. package/dist/chunks/input-k2ychlh2zo6hsocz.js.map +1 -0
  48. package/dist/chunks/{label-c3h9i3y4wiccelt7.js → label-ni6chzu01wns3cs2.js} +2 -2
  49. package/dist/chunks/{label-c3h9i3y4wiccelt7.js.map → label-ni6chzu01wns3cs2.js.map} +1 -1
  50. package/dist/chunks/{link-kt74pxkud4olmcer.js → link-m9hlspftl34nseme.js} +28 -27
  51. package/dist/chunks/link-m9hlspftl34nseme.js.map +1 -0
  52. package/dist/chunks/{loader-hr2w7cpqeev3p3vl.js → loader-g8a6j76ue5nq0lr8.js} +15 -14
  53. package/dist/chunks/loader-g8a6j76ue5nq0lr8.js.map +1 -0
  54. package/dist/chunks/{pagination-jb3mncivbwsoi1se.js → pagination-l9inbujoqp5swmyg.js} +3 -3
  55. package/dist/chunks/pagination-l9inbujoqp5swmyg.js.map +1 -0
  56. package/dist/chunks/{radio-datzh3pilz8ojak1.js → radio-f95mt237ru8fyc03.js} +44 -43
  57. package/dist/chunks/radio-f95mt237ru8fyc03.js.map +1 -0
  58. package/dist/chunks/resolve-variant-gw6eh7fa4st8ej7m.js +11 -0
  59. package/dist/chunks/resolve-variant-gw6eh7fa4st8ej7m.js.map +1 -0
  60. package/dist/chunks/{select-g261chvosodu22i8.js → select-n6u3p44qgtb0in3z.js} +4 -4
  61. package/dist/chunks/{select-g261chvosodu22i8.js.map → select-n6u3p44qgtb0in3z.js.map} +1 -1
  62. package/dist/chunks/{sensitive-input-cijagk551mesdtk4.js → sensitive-input-yoawqvvvmtdod430.js} +3 -3
  63. package/dist/chunks/{sensitive-input-cijagk551mesdtk4.js.map → sensitive-input-yoawqvvvmtdod430.js.map} +1 -1
  64. package/dist/chunks/{sidebar-kb9kykqfgy5yzqwr.js → sidebar-jjptencqv1jgztgu.js} +85 -84
  65. package/dist/chunks/sidebar-jjptencqv1jgztgu.js.map +1 -0
  66. package/dist/chunks/surface-k0e8mq1x00b7i8r6.js.map +1 -1
  67. package/dist/chunks/{switch-jdfsr3j3oa1qxegw.js → switch-dsnh8onvu1sxzdoe.js} +2 -2
  68. package/dist/chunks/switch-dsnh8onvu1sxzdoe.js.map +1 -0
  69. package/dist/chunks/{table-iudje0lva0z68jto.js → table-ngrghrfy9qsk6091.js} +56 -55
  70. package/dist/chunks/table-ngrghrfy9qsk6091.js.map +1 -0
  71. package/dist/chunks/{text-f7t467waymhb30sx.js → text-be7ehenoyldhyjma.js} +32 -28
  72. package/dist/chunks/text-be7ehenoyldhyjma.js.map +1 -0
  73. package/dist/chunks/{toast-h573o0tc7tefivk2.js → toast-ksnnyrf2o8yfvc3m.js} +75 -74
  74. package/dist/chunks/toast-ksnnyrf2o8yfvc3m.js.map +1 -0
  75. package/dist/chunks/tooltip-odudhkxe282wxinq.js.map +1 -1
  76. package/dist/code.js +1 -1
  77. package/dist/components/autocomplete.js +1 -1
  78. package/dist/components/badge.js +1 -1
  79. package/dist/components/banner.js +1 -1
  80. package/dist/components/breadcrumbs.js +1 -1
  81. package/dist/components/button.js +1 -1
  82. package/dist/components/checkbox.js +1 -1
  83. package/dist/components/clipboard-text.js +1 -1
  84. package/dist/components/cloudflare-logo.js +1 -1
  85. package/dist/components/code.js +1 -1
  86. package/dist/components/combobox.js +1 -1
  87. package/dist/components/command-palette.js +1 -1
  88. package/dist/components/dialog.js +1 -1
  89. package/dist/components/dropdown.js +1 -1
  90. package/dist/components/empty.js +1 -1
  91. package/dist/components/field.js +1 -1
  92. package/dist/components/grid.js +1 -1
  93. package/dist/components/input-group.js +1 -1
  94. package/dist/components/input.js +3 -3
  95. package/dist/components/label.js +1 -1
  96. package/dist/components/link.js +1 -1
  97. package/dist/components/loader.js +1 -1
  98. package/dist/components/pagination.js +1 -1
  99. package/dist/components/radio.js +1 -1
  100. package/dist/components/select.js +1 -1
  101. package/dist/components/sensitive-input.js +1 -1
  102. package/dist/components/sidebar.js +1 -1
  103. package/dist/components/switch.js +1 -1
  104. package/dist/components/table.js +1 -1
  105. package/dist/components/text.js +1 -1
  106. package/dist/components/toast.js +1 -1
  107. package/dist/index.js +35 -35
  108. package/dist/src/components/autocomplete/autocomplete.d.ts.map +1 -1
  109. package/dist/src/components/badge/badge.d.ts.map +1 -1
  110. package/dist/src/components/banner/banner.d.ts.map +1 -1
  111. package/dist/src/components/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  112. package/dist/src/components/button/button.d.ts.map +1 -1
  113. package/dist/src/components/checkbox/checkbox.d.ts.map +1 -1
  114. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  115. package/dist/src/components/cloudflare-logo/cloudflare-logo.d.ts.map +1 -1
  116. package/dist/src/components/code/code.d.ts.map +1 -1
  117. package/dist/src/components/combobox/combobox.d.ts.map +1 -1
  118. package/dist/src/components/dialog/dialog.d.ts.map +1 -1
  119. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  120. package/dist/src/components/empty/empty.d.ts.map +1 -1
  121. package/dist/src/components/grid/grid.d.ts.map +1 -1
  122. package/dist/src/components/input/input.d.ts.map +1 -1
  123. package/dist/src/components/link/link.d.ts.map +1 -1
  124. package/dist/src/components/loader/loader.d.ts.map +1 -1
  125. package/dist/src/components/pagination/pagination.d.ts.map +1 -1
  126. package/dist/src/components/radio/radio.d.ts.map +1 -1
  127. package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
  128. package/dist/src/components/surface/surface.d.ts.map +1 -1
  129. package/dist/src/components/switch/switch.d.ts.map +1 -1
  130. package/dist/src/components/table/table.d.ts.map +1 -1
  131. package/dist/src/components/text/text.d.ts.map +1 -1
  132. package/dist/src/components/toast/toast.d.ts.map +1 -1
  133. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  134. package/dist/src/utils/resolve-variant.d.ts +27 -0
  135. package/dist/src/utils/resolve-variant.d.ts.map +1 -0
  136. package/package.json +1 -1
  137. package/scripts/component-registry/metadata.ts +18 -3
  138. package/dist/chunks/autocomplete-48aq0d244bs2e8zv.js.map +0 -1
  139. package/dist/chunks/badge-dan90i0rzy4pwa1j.js.map +0 -1
  140. package/dist/chunks/banner-eiwcnk7ts21s3bnb.js.map +0 -1
  141. package/dist/chunks/breadcrumbs-cxcwf2l1ki3ffg5d.js.map +0 -1
  142. package/dist/chunks/button-6by9ntsa3nj553mq.js.map +0 -1
  143. package/dist/chunks/checkbox-hvxfvhtx1qjo2mww.js.map +0 -1
  144. package/dist/chunks/clipboard-text-hswydzx3iql369sd.js.map +0 -1
  145. package/dist/chunks/cloudflare-logo-pbavoe1wu8nr5c4n.js.map +0 -1
  146. package/dist/chunks/code-f9v1ikwhekqw274q.js.map +0 -1
  147. package/dist/chunks/combobox-fq36ye0hstote16x.js.map +0 -1
  148. package/dist/chunks/dialog-k3f1fbam6nt96k8x.js.map +0 -1
  149. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js.map +0 -1
  150. package/dist/chunks/empty-b82oer7npkhtkx7k.js.map +0 -1
  151. package/dist/chunks/grid-hj1ylz16p7g5uelh.js.map +0 -1
  152. package/dist/chunks/input-ncfowphv81yq7fyy.js.map +0 -1
  153. package/dist/chunks/link-kt74pxkud4olmcer.js.map +0 -1
  154. package/dist/chunks/loader-hr2w7cpqeev3p3vl.js.map +0 -1
  155. package/dist/chunks/pagination-jb3mncivbwsoi1se.js.map +0 -1
  156. package/dist/chunks/radio-datzh3pilz8ojak1.js.map +0 -1
  157. package/dist/chunks/sidebar-kb9kykqfgy5yzqwr.js.map +0 -1
  158. package/dist/chunks/switch-jdfsr3j3oa1qxegw.js.map +0 -1
  159. package/dist/chunks/table-iudje0lva0z68jto.js.map +0 -1
  160. package/dist/chunks/text-f7t467waymhb30sx.js.map +0 -1
  161. package/dist/chunks/toast-h573o0tc7tefivk2.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  "use client";
2
- import { jsxs as i, jsx as t } from "react/jsx-runtime";
3
- const n = {
2
+ import { jsxs as a, jsx as t } from "react/jsx-runtime";
3
+ import { r as n } from "./resolve-variant-gw6eh7fa4st8ej7m.js";
4
+ const l = {
4
5
  size: {
5
6
  sm: {
6
7
  value: 16,
@@ -15,21 +16,21 @@ const n = {
15
16
  description: "Large loader for prominent loading states"
16
17
  }
17
18
  }
18
- }, a = {
19
+ }, r = {
19
20
  size: "base"
20
21
  };
21
- function l({
22
- size: e = a.size
22
+ function u({
23
+ size: e = r.size
23
24
  } = {}) {
24
- return typeof e == "number" ? e : n.size[e].value;
25
+ return typeof e == "number" ? e : n(l.size, e, r.size).value;
25
26
  }
26
- const d = ({
27
+ const m = ({
27
28
  className: e,
28
- size: s = a.size,
29
+ size: s = r.size,
29
30
  "aria-label": o = "Loading"
30
31
  }) => {
31
- const r = l({ size: s });
32
- return /* @__PURE__ */ i(
32
+ const i = u({ size: s });
33
+ return /* @__PURE__ */ a(
33
34
  "svg",
34
35
  {
35
36
  width: "24",
@@ -38,11 +39,11 @@ const d = ({
38
39
  xmlns: "http://www.w3.org/2000/svg",
39
40
  stroke: "currentColor",
40
41
  className: e,
41
- style: { height: r, width: r },
42
+ style: { height: i, width: i },
42
43
  role: "status",
43
44
  "aria-label": o,
44
45
  children: [
45
- /* @__PURE__ */ i(
46
+ /* @__PURE__ */ a(
46
47
  "circle",
47
48
  {
48
49
  cx: "12",
@@ -103,6 +104,6 @@ const d = ({
103
104
  );
104
105
  };
105
106
  export {
106
- d as L
107
+ m as L
107
108
  };
108
- //# sourceMappingURL=loader-hr2w7cpqeev3p3vl.js.map
109
+ //# sourceMappingURL=loader-g8a6j76ue5nq0lr8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-g8a6j76ue5nq0lr8.js","sources":["../../src/components/loader/loader.tsx"],"sourcesContent":["import { resolveVariant } from \"../../utils/resolve-variant\";\n\n/** Loader size variant definitions mapping sizes to their pixel values. */\nexport const KUMO_LOADER_VARIANTS = {\n size: {\n sm: {\n value: 16,\n description: \"Small loader for inline use\",\n },\n base: {\n value: 24,\n description: \"Default loader size\",\n },\n lg: {\n value: 32,\n description: \"Large loader for prominent loading states\",\n },\n },\n} as const;\n\nexport const KUMO_LOADER_DEFAULT_VARIANTS = {\n size: \"base\",\n} as const;\n\n// Derived types from KUMO_LOADER_VARIANTS\nexport type KumoLoaderSize = keyof typeof KUMO_LOADER_VARIANTS.size;\n\nexport interface KumoLoaderVariantsProps {\n /**\n * Size of the loader. Use a preset name or a custom pixel number.\n * - `\"sm\"` — 16px, small loader for inline use\n * - `\"base\"` — 24px, default loader size\n * - `\"lg\"` — 32px, large loader for prominent loading states\n * @default \"base\"\n */\n size?: KumoLoaderSize | number;\n}\n\nexport function loaderVariants({\n size = KUMO_LOADER_DEFAULT_VARIANTS.size,\n}: KumoLoaderVariantsProps = {}): number {\n if (typeof size === \"number\") return size;\n return resolveVariant(KUMO_LOADER_VARIANTS.size, size, KUMO_LOADER_DEFAULT_VARIANTS.size).value;\n}\n\n/**\n * Loader component props.\n *\n * @example\n * ```tsx\n * <Loader />\n * <Loader size=\"sm\" />\n * <Loader size={24} />\n * ```\n */\nexport interface LoaderProps {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /**\n * Size of the spinner. Use a preset name or a custom pixel number.\n * - `\"sm\"` — 16px, for inline use\n * - `\"base\"` — 24px, default size\n * - `\"lg\"` — 32px, for prominent loading states\n * @default \"base\"\n */\n size?: KumoLoaderSize | number;\n /**\n * Accessible label for the loader, announced by screen readers.\n * Pass a translated string for internationalization.\n * @default \"Loading\"\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Animated circular spinner for indicating loading states.\n *\n * @example\n * ```tsx\n * <Loader />\n * ```\n */\nexport const Loader = ({\n className,\n size = KUMO_LOADER_DEFAULT_VARIANTS.size,\n \"aria-label\": ariaLabel = \"Loading\",\n}: LoaderProps) => {\n const sizeValue = loaderVariants({ size });\n return (\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n stroke=\"currentColor\"\n className={className}\n style={{ height: sizeValue, width: sizeValue }}\n role=\"status\"\n aria-label={ariaLabel}\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"9.5\"\n fill=\"none\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"2s\"\n repeatCount=\"indefinite\"\n />\n <animate\n attributeName=\"stroke-dasharray\"\n values=\"0 150;42 150;42 150\"\n keyTimes=\"0;0.5;1\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"\n />\n <animate\n attributeName=\"stroke-dashoffset\"\n values=\"0;-16;-59\"\n keyTimes=\"0;0.5;1\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"9.5\"\n fill=\"none\"\n opacity={0.1}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n};\n"],"names":["KUMO_LOADER_VARIANTS","KUMO_LOADER_DEFAULT_VARIANTS","loaderVariants","size","resolveVariant","Loader","className","ariaLabel","sizeValue","jsxs","jsx"],"mappings":";;;AAGO,MAAMA,IAAuB;AAAA,EAClC,MAAM;AAAA,IACJ,IAAI;AAAA,MACF,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,IAAI;AAAA,MACF,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ,GAEaC,IAA+B;AAAA,EAC1C,MAAM;AACR;AAgBO,SAASC,EAAe;AAAA,EAC7B,MAAAC,IAAOF,EAA6B;AACtC,IAA6B,IAAY;AACvC,SAAI,OAAOE,KAAS,WAAiBA,IAC9BC,EAAeJ,EAAqB,MAAMG,GAAMF,EAA6B,IAAI,EAAE;AAC5F;AAuCO,MAAMI,IAAS,CAAC;AAAA,EACrB,WAAAC;AAAA,EACA,MAAAH,IAAOF,EAA6B;AAAA,EACpC,cAAcM,IAAY;AAC5B,MAAmB;AACjB,QAAMC,IAAYN,EAAe,EAAE,MAAAC,GAAM;AACzC,SACE,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,OAAM;AAAA,MACN,QAAO;AAAA,MACP,WAAAH;AAAA,MACA,OAAO,EAAE,QAAQE,GAAW,OAAOA,EAAA;AAAA,MACnC,MAAK;AAAA,MACL,cAAYD;AAAA,MAEZ,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,MAAK;AAAA,YACL,aAAY;AAAA,YACZ,eAAc;AAAA,YAEd,UAAA;AAAA,cAAA,gBAAAC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,IAAG;AAAA,kBACH,KAAI;AAAA,kBACJ,aAAY;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEd,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,QAAO;AAAA,kBACP,UAAS;AAAA,kBACT,KAAI;AAAA,kBACJ,aAAY;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEd,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,QAAO;AAAA,kBACP,UAAS;AAAA,kBACT,KAAI;AAAA,kBACJ,aAAY;AAAA,gBAAA;AAAA,cAAA;AAAA,YACd;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,MAAK;AAAA,YACL,SAAS;AAAA,YACT,aAAY;AAAA,YACZ,eAAc;AAAA,UAAA;AAAA,QAAA;AAAA,MAChB;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as a, jsxs as p, Fragment as E } from "react/jsx-runtime";
3
3
  import { useState as T, useMemo as N, useEffect as B, createContext as D, useContext as R } from "react";
4
- import { I as m } from "./input-group-bidweffa0zyg8gt0.js";
4
+ import { I as m } from "./input-group-k1xa9cu8ochl1arh.js";
5
5
  import { CaretDoubleLeftIcon as F, CaretLeftIcon as V, CaretRightIcon as U, CaretDoubleRightIcon as j } from "@phosphor-icons/react";
6
6
  import { c as d } from "./cn-ct4n7r74mh8y0f48.js";
7
- import { S as P } from "./select-g261chvosodu22i8.js";
7
+ import { S as P } from "./select-n6u3p44qgtb0in3z.js";
8
8
  const G = [25, 50, 100, 250], y = (n, l, o) => Math.min(Math.max(n, l), o), K = {
9
9
  navigation: "Pagination",
10
10
  firstPage: "First page",
@@ -263,4 +263,4 @@ const W = Object.assign(L, {
263
263
  export {
264
264
  W as P
265
265
  };
266
- //# sourceMappingURL=pagination-jb3mncivbwsoi1se.js.map
266
+ //# sourceMappingURL=pagination-l9inbujoqp5swmyg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination-l9inbujoqp5swmyg.js","sources":["../../src/components/pagination/pagination.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useState,\n type KeyboardEvent,\n type ReactNode,\n} from \"react\";\nimport { InputGroup } from \"../input-group\";\nimport {\n CaretDoubleLeftIcon,\n CaretDoubleRightIcon,\n CaretLeftIcon,\n CaretRightIcon,\n} from \"@phosphor-icons/react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant } from \"../../utils/resolve-variant\";\nimport { Select } from \"../select\";\n\nconst DEFAULT_PAGE_SIZE_OPTIONS = [25, 50, 100, 250] as const;\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max);\n\n// ============================================================================\n// i18n Labels\n// ============================================================================\n\n/**\n * Labels for internationalization of Pagination component.\n * All labels have English defaults and can be overridden for other locales.\n *\n * Note: To customize the \"Showing X-Y of Z\" text, use the `children` render prop\n * on `Pagination.Info` instead. To customize the \"Per page:\" label, use the\n * `label` prop on `Pagination.PageSize`.\n */\nexport interface PaginationLabels {\n /** Aria label for the navigation landmark. @default \"Pagination\" */\n navigation?: string;\n /** Aria label for the first page button. @default \"First page\" */\n firstPage?: string;\n /** Aria label for the previous page button. @default \"Previous page\" */\n previousPage?: string;\n /** Aria label for the next page button. @default \"Next page\" */\n nextPage?: string;\n /** Aria label for the last page button. @default \"Last page\" */\n lastPage?: string;\n /** Aria label for the page number input/select. @default \"Page number\" */\n pageNumber?: string;\n /** Aria label for the page size select. @default \"Page size\" */\n pageSize?: string;\n}\n\nconst DEFAULT_LABELS: Required<PaginationLabels> = {\n navigation: \"Pagination\",\n firstPage: \"First page\",\n previousPage: \"Previous page\",\n nextPage: \"Next page\",\n lastPage: \"Last page\",\n pageNumber: \"Page number\",\n pageSize: \"Page size\",\n};\n\n/** Pagination controls variant definitions. */\nexport const KUMO_PAGINATION_VARIANTS = {\n controls: {\n full: {\n classes: \"\",\n description:\n \"Full pagination controls with first, previous, page input, next, and last buttons\",\n },\n simple: {\n classes: \"\",\n description:\n \"Simple pagination controls with only previous and next buttons\",\n },\n },\n} as const;\n\nexport type KumoPaginationControls =\n keyof typeof KUMO_PAGINATION_VARIANTS.controls;\n\nexport const KUMO_PAGINATION_DEFAULT_VARIANTS = {\n controls: \"full\",\n} as const;\n\nexport interface KumoPaginationVariantsProps {\n controls?: KumoPaginationControls;\n}\n\nexport function paginationVariants({\n controls = KUMO_PAGINATION_DEFAULT_VARIANTS.controls,\n}: KumoPaginationVariantsProps = {}) {\n return cn(\n \"flex items-center justify-between gap-2\",\n resolveVariant(KUMO_PAGINATION_VARIANTS.controls, controls, KUMO_PAGINATION_DEFAULT_VARIANTS.controls).classes,\n );\n}\n\n// ============================================================================\n// Pagination Context\n// ============================================================================\n\ninterface PaginationContextValue {\n page: number;\n perPage?: number;\n totalCount?: number;\n maxPage: number;\n pageShowingRange: string;\n setPage: (page: number) => void;\n editingPage: number;\n setEditingPage: (page: number) => void;\n labels: Required<PaginationLabels>;\n}\n\nconst PaginationContext = createContext<PaginationContextValue | null>(null);\n\nfunction usePaginationContext() {\n const context = useContext(PaginationContext);\n if (!context) {\n throw new Error(\n \"Pagination compound components must be used within a Pagination component\",\n );\n }\n return context;\n}\n\n// ============================================================================\n// Pagination.Info\n// ============================================================================\n\nexport interface PaginationInfoProps {\n /** Custom render function for the info text */\n children?: (props: {\n page: number;\n perPage?: number;\n totalCount?: number;\n pageShowingRange: string;\n }) => ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\nfunction PaginationInfo({ children, className }: PaginationInfoProps) {\n const { page, perPage, totalCount, pageShowingRange } =\n usePaginationContext();\n\n const content = children ? (\n children({ page, perPage, totalCount, pageShowingRange })\n ) : totalCount && totalCount > 0 ? (\n <>\n Showing <span className=\"tabular-nums\">{pageShowingRange}</span> of{\" \"}\n <span className=\"tabular-nums\">{totalCount}</span>\n </>\n ) : null;\n\n return (\n <div\n data-slot=\"pagination-info\"\n className={cn(\"text-sm text-kumo-subtle\", className)}\n >\n {content}\n </div>\n );\n}\n\nPaginationInfo.displayName = \"Pagination.Info\";\n\n// ============================================================================\n// Pagination.PageSize\n// ============================================================================\n\nexport interface PaginationPageSizeProps {\n /** Current page size value */\n value: number;\n /** Callback when page size changes */\n onChange: (size: number) => void;\n /** Available page size options */\n options?: number[];\n /**\n * Label text shown before the selector.\n * @default \"Per page:\"\n */\n label?: ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\nfunction PaginationPageSize({\n value,\n onChange,\n options = DEFAULT_PAGE_SIZE_OPTIONS as unknown as number[],\n label = \"Per page:\",\n className,\n}: PaginationPageSizeProps) {\n const { labels } = usePaginationContext();\n\n return (\n <div\n data-slot=\"pagination-page-size\"\n className={cn(\"flex items-center gap-2\", className)}\n >\n {label && <span className=\"text-sm text-kumo-subtle\">{label}</span>}\n <Select\n aria-label={labels.pageSize}\n value={value}\n onValueChange={(v) => onChange(v as number)}\n >\n {options.map((size) => (\n <Select.Option key={size} value={size}>\n {size}\n </Select.Option>\n ))}\n </Select>\n </div>\n );\n}\n\nPaginationPageSize.displayName = \"Pagination.PageSize\";\n\n// ============================================================================\n// Pagination.Controls\n// ============================================================================\n\nexport interface PaginationControlsProps extends KumoPaginationVariantsProps {\n /**\n * How the page number selector is rendered in \"full\" controls mode.\n * - `\"input\"` (default): A text input where users type a page number.\n * - `\"dropdown\"`: A dropdown select with all page numbers as options.\n *\n * **Note:** `\"dropdown\"` renders an option for every page, so it is best\n * suited for small page counts. For large datasets (hundreds of pages or\n * more) prefer `\"input\"` to avoid rendering performance overhead.\n */\n pageSelector?: \"input\" | \"dropdown\";\n /** Additional CSS classes */\n className?: string;\n}\n\nfunction PaginationControls({\n controls = KUMO_PAGINATION_DEFAULT_VARIANTS.controls,\n pageSelector = \"input\",\n className,\n}: PaginationControlsProps) {\n const { page, maxPage, setPage, editingPage, setEditingPage, labels } =\n usePaginationContext();\n\n return (\n <div\n data-slot=\"pagination-controls\"\n className={cn(\"grow flex flex-col items-end\", className)}\n >\n <nav aria-label={labels.navigation}>\n <InputGroup>\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label={labels.firstPage}\n disabled={page <= 1}\n onClick={() => {\n setPage(1);\n setEditingPage(1);\n }}\n >\n <CaretDoubleLeftIcon size={16} />\n </InputGroup.Button>\n )}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label={labels.previousPage}\n disabled={page <= 1}\n onClick={() => {\n const previousPage = Math.max(page - 1, 1);\n setPage(previousPage);\n setEditingPage(previousPage);\n }}\n >\n <CaretLeftIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" &&\n (pageSelector === \"dropdown\" ? (\n <Select\n aria-label={labels.pageNumber}\n className=\"rounded-none ring-kumo-hairline\"\n value={page}\n onValueChange={(value) => {\n const num = value as number;\n setPage(num);\n setEditingPage(num);\n }}\n >\n {Array.from({ length: maxPage }, (_, i) => i + 1).map((p) => (\n <Select.Option key={p} value={p}>\n {p}\n </Select.Option>\n ))}\n </Select>\n ) : (\n <InputGroup.Input\n style={{ width: 50 }}\n className=\"text-center\"\n aria-label={labels.pageNumber}\n value={editingPage}\n onValueChange={(value: string) => {\n setEditingPage(Number(value));\n }}\n onBlur={() => {\n const clamped = clamp(editingPage, 1, maxPage);\n setPage(clamped);\n setEditingPage(clamped);\n }}\n onKeyDown={(e: KeyboardEvent) => {\n if (e.key === \"Enter\") {\n const clamped = clamp(editingPage, 1, maxPage);\n setPage(clamped);\n setEditingPage(clamped);\n }\n }}\n // Prevent password managers from auto-filling\n autoComplete=\"off\"\n data-1p-ignore\n data-lpignore=\"true\"\n data-form-type=\"other\"\n />\n ))}\n <InputGroup.Button\n variant=\"secondary\"\n aria-label={labels.nextPage}\n disabled={page === maxPage}\n onClick={() => {\n const nextPage = Math.min(page + 1, maxPage);\n setPage(nextPage);\n setEditingPage(nextPage);\n }}\n >\n <CaretRightIcon size={16} />\n </InputGroup.Button>\n {controls === \"full\" && (\n <InputGroup.Button\n variant=\"secondary\"\n aria-label={labels.lastPage}\n disabled={page === maxPage}\n onClick={() => {\n setPage(maxPage);\n setEditingPage(maxPage);\n }}\n >\n <CaretDoubleRightIcon size={16} />\n </InputGroup.Button>\n )}\n </InputGroup>\n </nav>\n </div>\n );\n}\n\nPaginationControls.displayName = \"Pagination.Controls\";\n\n// ============================================================================\n// Pagination.Separator\n// ============================================================================\n\nexport interface PaginationSeparatorProps {\n /** Additional CSS classes */\n className?: string;\n}\n\nfunction PaginationSeparator({ className }: PaginationSeparatorProps) {\n return (\n <div\n data-slot=\"pagination-separator\"\n className={cn(\"mx-2 h-6 border-l border-kumo-hairline\", className)}\n />\n );\n}\n\nPaginationSeparator.displayName = \"Pagination.Separator\";\n\n// ============================================================================\n// Pagination Root\n// ============================================================================\n\n/** Base props shared by both compound and legacy Pagination APIs */\ninterface PaginationBaseProps {\n /** Callback fired when the current page changes. */\n setPage: (page: number) => void;\n /**\n * Current page number (1-indexed).\n * @default 1\n */\n page?: number;\n /** Number of items displayed per page. */\n perPage?: number;\n /** Total number of items across all pages. */\n totalCount?: number;\n /** Additional CSS classes for the container */\n className?: string;\n /**\n * Labels for internationalization of aria-labels. All labels have English defaults.\n *\n * For visible text like \"Showing X of Y\", use render props on sub-components:\n * - `Pagination.Info` children for the info text\n * - `Pagination.PageSize` label prop for the \"Per page:\" text\n *\n * @example\n * ```tsx\n * <Pagination\n * labels={{\n * firstPage: \"Première page\",\n * previousPage: \"Page précédente\",\n * nextPage: \"Page suivante\",\n * lastPage: \"Dernière page\",\n * pageNumber: \"Numéro de page\",\n * pageSize: \"Taille de page\",\n * }}\n * // ...\n * />\n * ```\n */\n labels?: PaginationLabels;\n}\n\n/**\n * Props for the compound component API (recommended).\n *\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={perPage} totalCount={500}>\n * <Pagination.Info />\n * <Pagination.PageSize value={perPage} onChange={setPerPage} />\n * <Pagination.Controls />\n * </Pagination>\n * ```\n */\nexport interface PaginationCompoundProps extends PaginationBaseProps {\n /**\n * Compound component children for custom layouts.\n * Use Pagination.Info, Pagination.PageSize, Pagination.Controls, and Pagination.Separator.\n */\n children: ReactNode;\n controls?: never;\n text?: never;\n}\n\n/**\n * Props for the legacy API (deprecated, use compound components instead).\n *\n * @deprecated Use the compound component API with children instead:\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={perPage} totalCount={500}>\n * <Pagination.Info />\n * <Pagination.Controls />\n * </Pagination>\n * ```\n *\n * @example\n * ```tsx\n * // Legacy usage (deprecated)\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * ```\n */\nexport interface PaginationLegacyProps\n extends PaginationBaseProps, KumoPaginationVariantsProps {\n children?: never;\n /** @deprecated Use Pagination.Info with children prop instead */\n text?: (props: {\n page?: number;\n perPage?: number;\n totalCount?: number;\n pageShowingRange: string;\n }) => ReactNode;\n}\n\n/**\n * Pagination component props.\n *\n * Prefer the compound component API for new code:\n * @example\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={perPage} totalCount={500}>\n * <Pagination.Info />\n * <Pagination.PageSize value={perPage} onChange={setPerPage} />\n * <Pagination.Controls />\n * </Pagination>\n * ```\n */\nexport type PaginationProps = PaginationCompoundProps | PaginationLegacyProps;\n\n/**\n * Page navigation controls with page count display.\n *\n * Supports both compound component and legacy patterns. Prefer compound components for new code:\n *\n * @example\n * // Compound component (recommended)\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={perPage} totalCount={500}>\n * <Pagination.Info />\n * <Pagination.Separator />\n * <Pagination.PageSize value={perPage} onChange={setPerPage} />\n * <Pagination.Controls />\n * </Pagination>\n * ```\n *\n * @example\n * // Legacy (deprecated)\n * ```tsx\n * <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />\n * ```\n */\nfunction PaginationRoot(props: PaginationProps) {\n const {\n page = 1,\n perPage,\n totalCount,\n setPage,\n children,\n className,\n labels: labelsProp,\n } = props;\n\n // Extract legacy props (only present when children is not provided)\n const text = \"text\" in props ? props.text : undefined;\n const controls =\n \"controls\" in props\n ? (props.controls ?? KUMO_PAGINATION_DEFAULT_VARIANTS.controls)\n : KUMO_PAGINATION_DEFAULT_VARIANTS.controls;\n const [editingPage, setEditingPage] = useState<number>(1);\n\n // Merge provided labels with defaults\n const labels = useMemo<Required<PaginationLabels>>(\n () => ({ ...DEFAULT_LABELS, ...labelsProp }),\n [labelsProp],\n );\n\n useEffect(() => {\n setEditingPage(page);\n }, [page]);\n\n const pageShowingRange = useMemo(() => {\n let lower = page * (perPage ?? 1) - (perPage ?? 0) + 1;\n let upper = Math.min(page * (perPage ?? 0), totalCount ?? 0);\n\n if (Number.isNaN(lower)) lower = 0;\n if (Number.isNaN(upper)) upper = 0;\n\n return `${lower}-${upper}`;\n }, [page, perPage, totalCount]);\n\n const maxPage = useMemo(() => {\n return Math.ceil((totalCount ?? 1) / (perPage ?? 1));\n }, [totalCount, perPage]);\n\n const contextValue: PaginationContextValue = {\n page,\n perPage,\n totalCount,\n maxPage,\n pageShowingRange,\n setPage,\n editingPage,\n setEditingPage,\n labels,\n };\n\n // Compound component mode: render children within context\n if (children) {\n return (\n <PaginationContext.Provider value={contextValue}>\n <div\n data-slot=\"pagination\"\n className={cn(\"flex items-center gap-2 w-full\", className)}\n >\n {children}\n </div>\n </PaginationContext.Provider>\n );\n }\n\n // Legacy mode: render default layout for backwards compatibility\n const getPaginationText = () => {\n if (text) {\n return text({ page, perPage, totalCount, pageShowingRange });\n } else if (totalCount && totalCount > 0) {\n return (\n <>\n Showing <span className=\"tabular-nums\">{pageShowingRange}</span> of{\" \"}\n <span className=\"tabular-nums\">{totalCount}</span>\n </>\n );\n }\n return null;\n };\n\n return (\n <PaginationContext.Provider value={contextValue}>\n <div\n data-slot=\"pagination\"\n className={cn(\"flex items-center gap-2 w-full\", className)}\n >\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n data-slot=\"pagination-info\"\n className=\"grow text-sm text-kumo-subtle\"\n >\n {getPaginationText()}\n </div>\n <PaginationControls controls={controls} />\n </div>\n </PaginationContext.Provider>\n );\n}\n\nPaginationRoot.displayName = \"Pagination\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\nexport const Pagination = Object.assign(PaginationRoot, {\n Info: PaginationInfo,\n PageSize: PaginationPageSize,\n Controls: PaginationControls,\n Separator: PaginationSeparator,\n});\n\nexport {\n PaginationInfo,\n PaginationPageSize,\n PaginationControls,\n PaginationSeparator,\n};\n"],"names":["DEFAULT_PAGE_SIZE_OPTIONS","clamp","value","min","max","DEFAULT_LABELS","KUMO_PAGINATION_DEFAULT_VARIANTS","PaginationContext","createContext","usePaginationContext","context","useContext","PaginationInfo","children","className","page","perPage","totalCount","pageShowingRange","content","jsxs","Fragment","jsx","cn","PaginationPageSize","onChange","options","label","labels","Select","v","size","PaginationControls","controls","pageSelector","maxPage","setPage","editingPage","setEditingPage","InputGroup","CaretDoubleLeftIcon","previousPage","CaretLeftIcon","num","_","i","p","clamped","e","nextPage","CaretRightIcon","CaretDoubleRightIcon","PaginationSeparator","PaginationRoot","props","labelsProp","text","useState","useMemo","useEffect","lower","upper","contextValue","getPaginationText","Pagination"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  "use client";
2
- import { jsx as e, jsxs as f } from "react/jsx-runtime";
3
- import { forwardRef as j, createContext as I, useContext as C } from "react";
2
+ import { jsx as e, jsxs as p } from "react/jsx-runtime";
3
+ import { forwardRef as I, createContext as C, useContext as G } from "react";
4
4
  import { c as o } from "./cn-ct4n7r74mh8y0f48.js";
5
- import { R as G, U as L, Q as R, br as k, bs as x } from "./vendor-base-ui-ie71jahf0czyf58j.js";
6
- const v = {
5
+ import { r as x } from "./resolve-variant-gw6eh7fa4st8ej7m.js";
6
+ import { R as L, U as O, Q as w, br as v, bs as N } from "./vendor-base-ui-ie71jahf0czyf58j.js";
7
+ const R = {
7
8
  variant: {
8
9
  default: {
9
10
  classes: "ring-kumo-hairline",
@@ -24,23 +25,23 @@ const v = {
24
25
  description: "Choice card appearance with border, padding, and highlighted selection state"
25
26
  }
26
27
  }
27
- }, N = {
28
+ }, f = {
28
29
  variant: "default",
29
30
  appearance: "default"
30
31
  };
31
- function M({
32
- variant: t = N.variant,
33
- appearance: r = N.appearance
32
+ function P({
33
+ variant: t = f.variant,
34
+ appearance: r = f.appearance
34
35
  } = {}) {
35
36
  return o(
36
- v.variant[t].classes,
37
- v.appearance[r].classes
37
+ x(R.variant, t, f.variant).classes,
38
+ x(R.appearance, r, f.appearance).classes
38
39
  );
39
40
  }
40
- const w = I({
41
+ const y = C({
41
42
  controlPosition: void 0,
42
43
  appearance: "default"
43
- }), y = j(
44
+ }), A = I(
44
45
  ({
45
46
  className: t,
46
47
  disabled: r,
@@ -50,8 +51,8 @@ const w = I({
50
51
  description: i,
51
52
  value: c
52
53
  }, l) => {
53
- const { controlPosition: g, appearance: u } = C(w), d = (s ?? u) === "card", m = g ?? (d ? "end" : "start");
54
- return d ? /* @__PURE__ */ f(
54
+ const { controlPosition: g, appearance: u } = G(y), d = (s ?? u) === "card", m = g ?? (d ? "end" : "start");
55
+ return d ? /* @__PURE__ */ p(
55
56
  "label",
56
57
  {
57
58
  className: o(
@@ -65,12 +66,12 @@ const w = I({
65
66
  t
66
67
  ),
67
68
  children: [
68
- /* @__PURE__ */ f("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
69
+ /* @__PURE__ */ p("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
69
70
  /* @__PURE__ */ e("span", { className: "text-base font-medium text-kumo-default", children: n }),
70
71
  i && /* @__PURE__ */ e("span", { className: "text-sm text-kumo-subtle", children: i })
71
72
  ] }),
72
73
  /* @__PURE__ */ e(
73
- k,
74
+ v,
74
75
  {
75
76
  ref: l,
76
77
  value: c,
@@ -83,7 +84,7 @@ const w = I({
83
84
  "data-[checked]:bg-kumo-contrast"
84
85
  ),
85
86
  children: /* @__PURE__ */ e(
86
- x,
87
+ N,
87
88
  {
88
89
  keepMounted: !0,
89
90
  className: "flex items-center justify-center",
@@ -94,7 +95,7 @@ const w = I({
94
95
  )
95
96
  ]
96
97
  }
97
- ) : /* @__PURE__ */ f(
98
+ ) : /* @__PURE__ */ p(
98
99
  "label",
99
100
  {
100
101
  className: o(
@@ -107,7 +108,7 @@ const w = I({
107
108
  ),
108
109
  children: [
109
110
  /* @__PURE__ */ e(
110
- k,
111
+ v,
111
112
  {
112
113
  ref: l,
113
114
  value: c,
@@ -120,7 +121,7 @@ const w = I({
120
121
  "data-[checked]:bg-kumo-contrast"
121
122
  ),
122
123
  children: /* @__PURE__ */ e(
123
- x,
124
+ N,
124
125
  {
125
126
  keepMounted: !0,
126
127
  className: "flex items-center justify-center",
@@ -135,18 +136,18 @@ const w = I({
135
136
  );
136
137
  }
137
138
  );
138
- y.displayName = "Radio.Item";
139
- function A({ children: t, className: r }) {
139
+ A.displayName = "Radio.Item";
140
+ function j({ children: t, className: r }) {
140
141
  return /* @__PURE__ */ e(
141
- R,
142
+ w,
142
143
  {
143
144
  className: o("text-base font-medium text-kumo-default", r),
144
145
  children: t
145
146
  }
146
147
  );
147
148
  }
148
- A.displayName = "Radio.Legend";
149
- function p({
149
+ j.displayName = "Radio.Legend";
150
+ function h({
150
151
  legend: t,
151
152
  children: r,
152
153
  orientation: a = "vertical",
@@ -157,25 +158,25 @@ function p({
157
158
  value: l,
158
159
  onValueChange: g,
159
160
  disabled: u,
160
- controlPosition: h,
161
+ controlPosition: b,
161
162
  name: d,
162
163
  className: m
163
164
  }) {
164
- return /* @__PURE__ */ e(w.Provider, { value: { controlPosition: h, appearance: s }, children: /* @__PURE__ */ e(
165
- G,
165
+ return /* @__PURE__ */ e(y.Provider, { value: { controlPosition: b, appearance: s }, children: /* @__PURE__ */ e(
166
+ L,
166
167
  {
167
168
  defaultValue: c,
168
169
  value: l,
169
- onValueChange: (b) => g?.(b),
170
+ onValueChange: (k) => g?.(k),
170
171
  disabled: u,
171
172
  name: d,
172
- children: /* @__PURE__ */ f(
173
- L,
173
+ children: /* @__PURE__ */ p(
174
+ O,
174
175
  {
175
176
  disabled: u,
176
177
  className: o("flex flex-col gap-4", m),
177
178
  children: [
178
- t && /* @__PURE__ */ e(R, { className: "text-base font-medium text-kumo-default", children: t }),
179
+ t && /* @__PURE__ */ e(w, { className: "text-base font-medium text-kumo-default", children: t }),
179
180
  /* @__PURE__ */ e(
180
181
  "div",
181
182
  {
@@ -193,17 +194,17 @@ function p({
193
194
  }
194
195
  ) });
195
196
  }
196
- p.displayName = "Radio.Group";
197
- const P = Object.assign(p, {
198
- Item: y,
199
- Group: p,
200
- Legend: A
197
+ h.displayName = "Radio.Group";
198
+ const U = Object.assign(h, {
199
+ Item: A,
200
+ Group: h,
201
+ Legend: j
201
202
  });
202
203
  export {
203
- v as K,
204
- P as R,
205
- p as a,
206
- N as b,
207
- M as r
204
+ R as K,
205
+ U as R,
206
+ h as a,
207
+ f as b,
208
+ P as r
208
209
  };
209
- //# sourceMappingURL=radio-datzh3pilz8ojak1.js.map
210
+ //# sourceMappingURL=radio-f95mt237ru8fyc03.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-f95mt237ru8fyc03.js","sources":["../../src/components/radio/radio.tsx"],"sourcesContent":["import { forwardRef, createContext, useContext, type ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant } from \"../../utils/resolve-variant\";\nimport { Fieldset } from \"@base-ui/react/fieldset\";\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\";\nimport { Radio as BaseRadio } from \"@base-ui/react/radio\";\n\n/** Radio variant definitions mapping variant names to their Tailwind classes. */\nexport const KUMO_RADIO_VARIANTS = {\n variant: {\n default: {\n classes: \"ring-kumo-hairline\",\n description: \"Default radio appearance\",\n },\n error: {\n classes: \"ring-kumo-danger\",\n description: \"Error state for validation failures\",\n },\n },\n appearance: {\n default: {\n classes: \"\",\n description: \"Standard inline radio item\",\n },\n card: {\n classes:\n \"rounded-lg border border-kumo-hairline bg-kumo-base p-3 transition-colors hover:bg-kumo-tint has-[[data-checked]]:border-kumo-interact has-[[data-checked]]:bg-kumo-tint\",\n description:\n \"Choice card appearance with border, padding, and highlighted selection state\",\n },\n },\n} as const;\n\nexport const KUMO_RADIO_DEFAULT_VARIANTS = {\n variant: \"default\",\n appearance: \"default\",\n} as const;\n\n// Derived types from KUMO_RADIO_VARIANTS\nexport type KumoRadioVariant = keyof typeof KUMO_RADIO_VARIANTS.variant;\nexport type KumoRadioAppearance = keyof typeof KUMO_RADIO_VARIANTS.appearance;\n\nexport interface KumoRadioVariantsProps {\n /**\n * Visual variant.\n * - `\"default\"` — Standard radio appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: KumoRadioVariant;\n /**\n * Visual appearance.\n * - `\"default\"` — Standard inline radio item\n * - `\"card\"` — Choice card with border, padding, and highlighted selection state\n * @default \"default\"\n */\n appearance?: KumoRadioAppearance;\n}\n\nexport function radioVariants({\n variant = KUMO_RADIO_DEFAULT_VARIANTS.variant,\n appearance = KUMO_RADIO_DEFAULT_VARIANTS.appearance,\n}: KumoRadioVariantsProps = {}) {\n return cn(\n resolveVariant(KUMO_RADIO_VARIANTS.variant, variant, KUMO_RADIO_DEFAULT_VARIANTS.variant).classes,\n resolveVariant(KUMO_RADIO_VARIANTS.appearance, appearance, KUMO_RADIO_DEFAULT_VARIANTS.appearance).classes,\n );\n}\n\n// Legacy type alias for backwards compatibility\nexport type RadioVariant = KumoRadioVariant;\n\n/** Position of the radio control relative to its label */\nexport type RadioControlPosition = \"start\" | \"end\";\n\n// Context for passing controlPosition and appearance from Group to Items.\n// `controlPosition` may be undefined so each item can fall back to an\n// appearance-appropriate default (start for default, end for card).\nconst RadioGroupContext = createContext<{\n controlPosition: RadioControlPosition | undefined;\n appearance: KumoRadioAppearance;\n}>({\n controlPosition: undefined,\n appearance: \"default\",\n});\n\n/**\n * Radio group component props (with built-in Fieldset and RadioGroup)\n *\n * @example\n * // Basic usage\n * ```tsx\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Horizontal layout\n * ```tsx\n * <Radio.Group legend=\"Size\" orientation=\"horizontal\" defaultValue=\"md\">\n * <Radio.Item label=\"Small\" value=\"sm\" />\n * <Radio.Item label=\"Medium\" value=\"md\" />\n * <Radio.Item label=\"Large\" value=\"lg\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // With error and description\n * ```tsx\n * <Radio.Group\n * legend=\"Payment method\"\n * error=\"Please select a payment method\"\n * description=\"Choose how you'd like to pay\"\n * >\n * <Radio.Item label=\"Credit Card\" value=\"card\" />\n * <Radio.Item label=\"PayPal\" value=\"paypal\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Controlled\n * ```tsx\n * const [value, setValue] = useState(\"email\");\n * <Radio.Group legend=\"Contact\" value={value} onValueChange={setValue}>\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"Phone\" value=\"phone\" />\n * </Radio.Group>\n * ```\n *\n * @example\n * // Label before radio (controlPosition=\"end\")\n * ```tsx\n * <Radio.Group legend=\"Options\" controlPosition=\"end\" defaultValue=\"a\">\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * <Radio.Item label=\"Option B\" value=\"b\" />\n * </Radio.Group>\n * ```\n */\n/**\n * Props for Radio.Legend — a composable sub-component for labeling a Radio.Group.\n *\n * Place as a direct child of `<Radio.Group>` to provide a styled, accessible legend.\n * Accepts `className` for full styling control (e.g. `className=\"sr-only\"` to visually hide).\n *\n * @example\n * ```tsx\n * <Radio.Group>\n * <Radio.Legend className=\"sr-only\">Paths</Radio.Legend>\n * <Radio.Item label=\"Allow all paths\" value=\"all\" />\n * </Radio.Group>\n * ```\n */\nexport interface RadioLegendProps {\n /** Legend content */\n children: ReactNode;\n /** Additional CSS classes (e.g. \"sr-only\" to visually hide the legend) */\n className?: string;\n}\n\nexport interface RadioGroupProps {\n /**\n * Legend text for the group (required for accessibility).\n * For more control over legend styling, omit this prop and use `<Radio.Legend>` as a child instead.\n */\n legend?: string;\n /** Child Radio.Item components (and optionally a Radio.Legend) */\n children: ReactNode;\n /** Layout direction of the radio items */\n orientation?: \"vertical\" | \"horizontal\";\n /**\n * Visual appearance applied to all Radio.Item children.\n * - `\"default\"` — Standard inline radio items\n * - `\"card\"` — Choice card with border, padding, and highlighted selection state\n *\n * Individual items can override this with their own `appearance` prop.\n * @default \"default\"\n */\n appearance?: KumoRadioAppearance;\n /** Error message for the group */\n error?: string;\n /** Helper text for the group */\n description?: ReactNode;\n /** Value of the radio that should be initially selected (uncontrolled) */\n defaultValue?: string;\n /** Value of the radio that should be selected (controlled) */\n value?: string;\n /** Event handler called when radio value changes */\n onValueChange?: (value: string) => void;\n /** Whether all radios in the group are disabled */\n disabled?: boolean;\n /** Position of radio control relative to label: \"start\" puts radio before label, \"end\" puts label before radio. Defaults to \"start\" for default appearance and \"end\" for card appearance. */\n controlPosition?: RadioControlPosition;\n /** Form submission name for the radio group */\n name?: string;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Individual radio item within a group\n *\n * @example\n * ```tsx\n * <Radio.Item label=\"Option A\" value=\"a\" />\n * ```\n *\n * @example\n * // Disabled item\n * ```tsx\n * <Radio.Item label=\"Unavailable\" value=\"unavailable\" disabled />\n * ```\n */\nexport type RadioItemProps = {\n /** Visual variant: \"default\" or \"error\" for validation failures */\n variant?: RadioVariant;\n /**\n * Visual appearance of the radio item.\n * - `\"default\"` — Standard inline radio item\n * - `\"card\"` — Choice card with border, padding, and highlighted selection state\n *\n * When set on an individual item, overrides the group-level `appearance`.\n * @default \"default\"\n */\n appearance?: KumoRadioAppearance;\n /** Label content displayed next to radio (required). Accepts strings or React nodes for rich content. */\n label: ReactNode;\n /** Description text displayed below the label (only visible in card appearance) */\n description?: ReactNode;\n /** Value of the radio (required) */\n value: string;\n /** Additional CSS classes for the label wrapper */\n className?: string;\n /** Whether the radio is disabled */\n disabled?: boolean;\n};\n\n// Radio.Item for use within Radio.Group\nconst RadioItem = forwardRef<HTMLButtonElement, RadioItemProps>(\n (\n {\n className,\n disabled,\n variant = \"default\",\n appearance: appearanceProp,\n label,\n description,\n value,\n },\n ref,\n ) => {\n const { controlPosition, appearance: groupAppearance } =\n useContext(RadioGroupContext);\n const appearance = appearanceProp ?? groupAppearance;\n const isCard = appearance === \"card\";\n\n // Fall back to an appearance-appropriate default when controlPosition is\n // not provided: card defaults to \"end\" (radio on the right), default\n // appearance defaults to \"start\" (radio on the left).\n const effectiveControlPosition: RadioControlPosition =\n controlPosition ?? (isCard ? \"end\" : \"start\");\n\n if (isCard) {\n const controlAtStart = effectiveControlPosition === \"start\";\n return (\n <label\n className={cn(\n \"m-0 group relative flex items-start gap-3 rounded-lg border border-kumo-hairline bg-kumo-base p-3 transition-colors has-[[data-checked]]:border-kumo-interact has-[[data-checked]]:bg-kumo-tint\",\n controlAtStart && \"flex-row-reverse\",\n variant === \"error\" &&\n \"border-kumo-danger has-[[data-checked]]:border-kumo-danger has-[[data-checked]]:bg-kumo-base\",\n disabled\n ? \"cursor-not-allowed opacity-50\"\n : cn(\n \"has-[[data-disabled]]:cursor-not-allowed has-[[data-disabled]]:opacity-50 cursor-pointer\",\n variant !== \"error\" &&\n \"hover:not-has-[[data-disabled]]:bg-kumo-tint\",\n ),\n className,\n )}\n >\n <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"text-base font-medium text-kumo-default\">\n {label}\n </span>\n {description && (\n <span className=\"text-sm text-kumo-subtle\">{description}</span>\n )}\n </div>\n <BaseRadio.Root\n ref={ref}\n value={value}\n disabled={disabled}\n className={cn(\n \"relative mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full border-0 bg-kumo-base ring ring-2 focus:outline-none focus:ring-kumo-focus focus-visible:ring-2 focus-visible:ring-kumo-brand\",\n variant === \"error\" ? \"ring-kumo-danger\" : \"ring-kumo-line\",\n !disabled &&\n variant !== \"error\" &&\n \"group-hover:ring-kumo-hairline focus-visible:outline-offset-3\",\n !disabled &&\n variant === \"error\" &&\n \"focus-visible:outline-offset-3\",\n \"data-[checked]:bg-kumo-contrast\",\n )}\n >\n <BaseRadio.Indicator\n keepMounted\n className=\"flex items-center justify-center\"\n >\n <span className=\"h-2 w-2 rounded-full bg-kumo-base\" />\n </BaseRadio.Indicator>\n </BaseRadio.Root>\n </label>\n );\n }\n\n return (\n <label\n className={cn(\n \"m-0 group relative inline-flex items-center gap-2\",\n // \"start\" (default): radio before label\n // \"end\": label before radio using flex-row-reverse\n effectiveControlPosition === \"end\" && \"flex-row-reverse justify-end\",\n disabled ? \"cursor-not-allowed opacity-50\" : \"cursor-pointer\",\n className,\n )}\n >\n <BaseRadio.Root\n ref={ref}\n value={value}\n disabled={disabled}\n className={cn(\n \"relative flex h-4 w-4 items-center justify-center rounded-full border-0 bg-kumo-base ring focus:outline-none after:absolute after:-inset-x-3 after:-inset-y-2\",\n variant === \"error\" ? \"ring-kumo-danger\" : \"ring-kumo-line\",\n !disabled &&\n variant !== \"error\" &&\n \"group-hover:ring-kumo-hairline focus:ring-kumo-focus focus:ring-2 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:outline-offset-3\",\n !disabled &&\n variant === \"error\" &&\n \"focus:ring-kumo-focus focus:ring-2 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:outline-offset-3\",\n \"data-[checked]:bg-kumo-contrast\",\n )}\n >\n <BaseRadio.Indicator\n keepMounted\n className=\"flex items-center justify-center\"\n >\n <span className=\"h-2 w-2 rounded-full bg-kumo-base\" />\n </BaseRadio.Indicator>\n </BaseRadio.Root>\n <span className=\"text-base text-kumo-default\">{label}</span>\n </label>\n );\n },\n);\n\nRadioItem.displayName = \"Radio.Item\";\n\n// Radio.Legend — composable legend sub-component for Radio.Group\nfunction RadioLegend({ children, className }: RadioLegendProps) {\n return (\n <Fieldset.Legend\n className={cn(\"text-base font-medium text-kumo-default\", className)}\n >\n {children}\n </Fieldset.Legend>\n );\n}\n\nRadioLegend.displayName = \"Radio.Legend\";\n\n// Radio.Group with built-in Fieldset and RadioGroup\nfunction RadioGroup({\n legend,\n children,\n orientation = \"vertical\",\n appearance = \"default\",\n error,\n description,\n defaultValue,\n value,\n onValueChange,\n disabled,\n controlPosition,\n name,\n className,\n}: RadioGroupProps) {\n return (\n <RadioGroupContext.Provider value={{ controlPosition, appearance }}>\n <BaseRadioGroup\n defaultValue={defaultValue}\n value={value}\n onValueChange={(newValue) => onValueChange?.(newValue)}\n disabled={disabled}\n name={name}\n >\n <Fieldset.Root\n disabled={disabled}\n className={cn(\"flex flex-col gap-4\", className)}\n >\n {legend && (\n <Fieldset.Legend className=\"text-base font-medium text-kumo-default\">\n {legend}\n </Fieldset.Legend>\n )}\n <div\n className={cn(\n orientation === \"vertical\"\n ? cn(\"flex flex-col\", appearance === \"card\" ? \"gap-3\" : \"gap-2\")\n : appearance === \"card\"\n ? \"grid grid-cols-2 gap-3\"\n : \"flex flex-row flex-wrap gap-2\",\n )}\n >\n {children}\n </div>\n {error && <p className=\"text-sm text-kumo-danger\">{error}</p>}\n {description && (\n <p className=\"text-sm text-kumo-subtle\">{description}</p>\n )}\n </Fieldset.Root>\n </BaseRadioGroup>\n </RadioGroupContext.Provider>\n );\n}\n\nRadioGroup.displayName = \"Radio.Group\";\n\n// Export RadioGroup directly for external usage\nexport { RadioGroup };\n\n/**\n * Radio — radio button group for single-select choices.\n *\n * Compound component: `Radio.Group` (with built-in Fieldset), `Radio.Item`, and `Radio.Legend`.\n * Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.\n *\n * @example\n * ```tsx\n * // Simple: legend as a string prop\n * <Radio.Group legend=\"Notification preference\" defaultValue=\"email\">\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * <Radio.Item label=\"Push\" value=\"push\" />\n * </Radio.Group>\n *\n * // Composable: Radio.Legend for full styling control (e.g. visually hidden)\n * <Radio.Group defaultValue=\"email\">\n * <Radio.Legend className=\"sr-only\">Notification preference</Radio.Legend>\n * <Radio.Item label=\"Email\" value=\"email\" />\n * <Radio.Item label=\"SMS\" value=\"sms\" />\n * </Radio.Group>\n * ```\n */\nexport const Radio = Object.assign(RadioGroup, {\n Item: RadioItem,\n Group: RadioGroup,\n Legend: RadioLegend,\n});\n"],"names":["KUMO_RADIO_VARIANTS","KUMO_RADIO_DEFAULT_VARIANTS","radioVariants","variant","appearance","cn","resolveVariant","RadioGroupContext","createContext","RadioItem","forwardRef","className","disabled","appearanceProp","label","description","value","ref","controlPosition","groupAppearance","useContext","isCard","effectiveControlPosition","jsxs","jsx","BaseRadio.Root","BaseRadio.Indicator","RadioLegend","children","Fieldset.Legend","RadioGroup","legend","orientation","error","defaultValue","onValueChange","name","BaseRadioGroup","newValue","Fieldset.Root","Radio"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ function t(n, o, e) {
3
+ const r = n[o];
4
+ return r !== void 0 ? r : (process.env.NODE_ENV !== "production" && console.warn(
5
+ `[kumo] Unknown variant "${o}". Expected one of: ${Object.keys(n).join(", ")}. Falling back to "${e}".`
6
+ ), n[e]);
7
+ }
8
+ export {
9
+ t as r
10
+ };
11
+ //# sourceMappingURL=resolve-variant-gw6eh7fa4st8ej7m.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-variant-gw6eh7fa4st8ej7m.js","sources":["../../src/utils/resolve-variant.ts"],"sourcesContent":["/**\n * Safely resolve a variant config from a variants map, falling back\n * to a known-good default when the key doesn't match any entry.\n *\n * This prevents `TypeError: Cannot read properties of undefined`\n * when a component receives an invalid variant value at runtime\n * (e.g. from untyped JS consumers, server data, or stale props).\n *\n * @param variants – A dimension of a KUMO_*_VARIANTS object\n * (e.g. `KUMO_BUTTON_VARIANTS.variant`)\n * @param key – The runtime value of the variant prop\n * @param fallback – A key guaranteed to exist (typically from\n * KUMO_*_DEFAULT_VARIANTS)\n * @returns The matched config entry, or the fallback entry\n *\n * @example\n * ```ts\n * const config = resolveVariant(\n * KUMO_BUTTON_VARIANTS.variant,\n * variant,\n * KUMO_BUTTON_DEFAULT_VARIANTS.variant,\n * );\n * // config.classes is always safe to access\n * ```\n */\nexport function resolveVariant<T extends Record<string, unknown>>(\n variants: T,\n key: string,\n fallback: keyof T & string,\n): T[keyof T] {\n const config = (variants as Record<string, unknown>)[key] as\n | T[keyof T]\n | undefined;\n\n if (config !== undefined) return config;\n\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[kumo] Unknown variant \"${key}\". Expected one of: ${Object.keys(variants).join(\", \")}. Falling back to \"${fallback}\".`,\n );\n }\n\n return variants[fallback];\n}\n"],"names":["resolveVariant","variants","key","fallback","config"],"mappings":";AAyBO,SAASA,EACdC,GACAC,GACAC,GACY;AACZ,QAAMC,IAAUH,EAAqCC,CAAG;AAIxD,SAAIE,MAAW,SAAkBA,KAE7B,QAAQ,IAAI,aAAa,gBAC3B,QAAQ;AAAA,IACN,2BAA2BF,CAAG,uBAAuB,OAAO,KAAKD,CAAQ,EAAE,KAAK,IAAI,CAAC,sBAAsBE,CAAQ;AAAA,EAAA,GAIhHF,EAASE,CAAQ;AAC1B;"}
@@ -3,10 +3,10 @@ import { jsxs as m, jsx as a } from "react/jsx-runtime";
3
3
  import { CaretUpDownIcon as R, CheckIcon as B } from "@phosphor-icons/react";
4
4
  import { useId as W, forwardRef as p } from "react";
5
5
  import { c as o } from "./cn-ct4n7r74mh8y0f48.js";
6
- import { b as q } from "./button-6by9ntsa3nj553mq.js";
7
- import { K as H } from "./input-ncfowphv81yq7fyy.js";
6
+ import { b as q } from "./button-fe5rvewji3e5xd7m.js";
7
+ import { K as H } from "./input-k2ychlh2zo6hsocz.js";
8
8
  import { S as J } from "./skeleton-line-epxenksfesr2fkcv.js";
9
- import { F as Q } from "./field-c0wf94plit2gci59.js";
9
+ import { F as Q } from "./field-hmucpi6d4sqci1zu.js";
10
10
  import { u as X } from "./portal-provider-hwmkdmkpvct0cb76.js";
11
11
  import { a$ as Y, b0 as Z, b1 as ee, b2 as te, b3 as ae, b4 as se, b5 as le, b6 as oe, b7 as ie, b8 as ne, b9 as re, ba as ce, bb as de, S as ue } from "./vendor-base-ui-ie71jahf0czyf58j.js";
12
12
  H.size;
@@ -212,4 +212,4 @@ d.Option.displayName = "Select.Option";
212
212
  export {
213
213
  d as S
214
214
  };
215
- //# sourceMappingURL=select-g261chvosodu22i8.js.map
215
+ //# sourceMappingURL=select-n6u3p44qgtb0in3z.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-g261chvosodu22i8.js","sources":["../../src/components/select/select.tsx"],"sourcesContent":["import { Select as SelectBase } from \"@base-ui/react/select\";\nimport { CaretUpDownIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, useId } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { buttonVariants } from \"../button\";\nimport { KUMO_INPUT_VARIANTS, type KumoInputSize } from \"../input/input\";\nimport { SkeletonLine } from \"../loader\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\nimport {\n usePortalContainer,\n type PortalContainer,\n} from \"../../utils/portal-provider\";\n\n/** Select variant definitions. */\nexport const KUMO_SELECT_VARIANTS = {\n size: KUMO_INPUT_VARIANTS.size,\n} as const;\n\nexport const KUMO_SELECT_DEFAULT_VARIANTS = {\n size: \"base\",\n} as const;\n\n/**\n * Select component styling metadata for Figma plugin code generation\n * Extracted from select.tsx implementation (source of truth)\n */\nexport const KUMO_SELECT_STYLING = {\n trigger: {\n height: 36, // h-9\n paddingX: 12, // px-3\n borderRadius: 8, // rounded-lg\n background: \"bg-kumo-elevated\",\n text: \"text-color-surface\",\n ring: \"color-border\",\n fontSize: 16, // text-base\n fontWeight: 400, // font-normal\n },\n stateTokens: {\n focus: { ring: \"color-active\" },\n disabled: { opacity: 0.5 },\n },\n icons: {\n caret: { name: \"ph-caret-up-down\", size: 20 },\n check: { name: \"ph-check\", size: 20 },\n },\n popup: {\n background: \"bg-kumo-elevated\",\n ring: \"border-kumo-line\",\n borderRadius: 8, // rounded-lg\n padding: 6, // p-1.5\n },\n option: {\n paddingX: 8, // px-2\n paddingY: 6, // py-1.5\n borderRadius: 4, // rounded\n fontSize: 16, // text-base\n highlightBackground: \"color-surface-secondary\",\n },\n} as const;\n\n// Derived types from KUMO_SELECT_VARIANTS\nexport type KumoSelectSize = keyof typeof KUMO_SELECT_VARIANTS.size;\n\nexport interface KumoSelectVariantsProps {\n /**\n * Size of the select trigger. Matches Input component sizes.\n * - `\"xs\"` — Extra small for compact UIs (h-5 / 20px)\n * - `\"sm\"` — Small for secondary fields (h-6.5 / 26px)\n * - `\"base\"` — Default size (h-9 / 36px)\n * - `\"lg\"` — Large for prominent fields (h-10 / 40px)\n * @default \"base\"\n */\n size?: KumoSelectSize;\n}\n\nexport function selectVariants({\n size = KUMO_SELECT_DEFAULT_VARIANTS.size,\n}: KumoSelectVariantsProps = {}) {\n return cn(\n buttonVariants({ size }),\n \"justify-between font-normal\",\n \"focus:opacity-100 focus:ring-kumo-focus/50 focus-visible:ring-inset *:in-focus:opacity-100\",\n );\n}\n\nconst triggerIconStyles: Record<\n KumoInputSize,\n { iconSize: number; className: string }\n> = {\n xs: { iconSize: 12, className: \"text-kumo-subtle\" },\n sm: { iconSize: 14, className: \"text-kumo-subtle\" },\n base: { iconSize: 16, className: \"text-kumo-subtle\" },\n lg: { iconSize: 18, className: \"text-kumo-subtle\" },\n};\n\n/**\n * Shape for items that carry extra metadata (disabled state, tooltip).\n * Plain `ReactNode` values are still supported for backward compatibility.\n */\nexport interface SelectItemDescriptor {\n /** Display label for the option. */\n label: ReactNode;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n}\n\n/** Value type accepted by the `items` object-map prop. */\nexport type SelectItemValue = ReactNode | SelectItemDescriptor;\n\nfunction isItemDescriptor(\n value: SelectItemValue,\n): value is SelectItemDescriptor {\n if (value === null || value === undefined) return false;\n if (typeof value !== \"object\" || Array.isArray(value)) return false;\n // React elements have $$typeof — exclude them\n if (\"$$typeof\" in (value as object)) return false;\n // Promises are not descriptors\n if (value instanceof Promise) return false;\n // Must have a defined label (not just the key existing)\n const candidate = value as unknown as Record<string, unknown>;\n return \"label\" in candidate && candidate.label !== undefined;\n}\n\n/**\n * Normalizes items to array format for Base UI.\n * Object maps are converted to array format so Base UI can properly\n * handle value matching and placeholder display.\n */\nfunction normalizeItems<T>(\n items:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>,\n): ReadonlyArray<{ label: ReactNode; value: T }> {\n if (Array.isArray(items)) {\n return items;\n }\n // Convert object map to array format\n return Object.entries(items).map(([key, entry]) => ({\n value: key as T,\n label: isItemDescriptor(entry) ? entry.label : entry,\n }));\n}\n\n/**\n * Auto-generates Select.Option elements from items prop.\n * Only used when children are not explicitly provided.\n * Filters out null values (typically used for placeholders).\n */\nfunction renderOptionsFromItems<T>(\n items:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>,\n): ReactNode {\n const normalizedItems = normalizeItems(items);\n\n // Build a lookup for disabled metadata from object-map items.\n // Object-map keys are always strings (Record<string, ...>), so the lookup\n // uses string keys. The array form ({ label, value }[]) does not support\n // descriptors — consumers should use the children API for that case.\n const disabledLookup = new Map<string, { disabled?: boolean }>();\n if (!Array.isArray(items)) {\n for (const [key, entry] of Object.entries(items)) {\n if (isItemDescriptor(entry)) {\n disabledLookup.set(key, { disabled: entry.disabled });\n }\n }\n }\n\n // Filter out null values and render options\n return normalizedItems\n .filter((item) => item.value !== null)\n .map((item, index) => {\n const key =\n typeof item.value === \"string\" ? item.value : `option-${index}`;\n // When items is an object-map, value is always a string key from\n // Object.entries. When items is an array, disabledLookup is empty.\n const meta =\n typeof item.value === \"string\"\n ? disabledLookup.get(item.value)\n : undefined;\n\n return (\n <Option key={key} value={item.value} disabled={meta?.disabled}>\n {item.label}\n </Option>\n );\n });\n}\n\ntype SelectPropsGeneric<T, Multiple extends boolean | undefined = false> = Omit<\n SelectBase.Root.Props<T, Multiple>,\n \"items\"\n> &\n KumoSelectVariantsProps & {\n multiple?: Multiple;\n /**\n * A function that returns a `ReactNode` to format the selected value.\n * Only called when a value is selected — use `placeholder` for the empty state.\n * @example\n * ```tsx\n * <Select\n * placeholder=\"Select a user...\"\n * renderValue={(user) => user.name}\n * />\n * ```\n */\n renderValue?: (value: Multiple extends true ? T[] : T) => ReactNode;\n className?: string;\n /**\n * Data structure of items rendered in the popup.\n * Accepts a plain object map (`{ key: \"Label\" }`) or an array of `{ label, value }`.\n *\n * Object-map values can be a `ReactNode` (backward-compatible) **or** a\n * `SelectItemDescriptor` for extra metadata:\n *\n * ```tsx\n * items={{\n * apple: \"Apple\",\n * banana: { label: \"Banana\", disabled: true, disabledReason: \"Out of season\" },\n * }}\n * ```\n */\n items?:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>;\n /**\n * Label content for the select.\n * When provided, enables the Field wrapper with a visible label.\n * For accessibility without a visible label, use `aria-label` instead.\n */\n label?: ReactNode;\n /**\n * @deprecated Use `aria-label` for hidden labels instead of `label` + `hideLabel={true}`.\n * When `label` is provided without `hideLabel`, the label is now visible by default (matching Input behavior).\n * This prop will be removed in a future version.\n */\n hideLabel?: boolean;\n placeholder?: string;\n loading?: boolean;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the select */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n /**\n * Container element for the portal. Use this to render the select inside\n * a Shadow DOM or custom container. Overrides `KumoPortalProvider` context.\n * @default document.body (or KumoPortalProvider container if set)\n */\n container?: PortalContainer;\n };\n\n/**\n * Select component props.\n *\n * **Accessible Name Required:** Select should have one of:\n * 1. `label` prop (recommended) - enables Field wrapper with visible label\n * 2. `aria-label` - for selects without visible label (accessibility-only)\n * 3. `aria-labelledby` - for custom label association\n *\n * @example\n * ```tsx\n * // With visible label (recommended)\n * <Select label=\"Country\" onValueChange={setValue}>\n * <Select.Option value=\"us\">United States</Select.Option>\n * <Select.Option value=\"uk\">United Kingdom</Select.Option>\n * </Select>\n *\n * // Without visible label (use aria-label for accessibility)\n * <Select aria-label=\"Select a country\" onValueChange={setValue}>\n * <Select.Option value=\"us\">United States</Select.Option>\n * </Select>\n * ```\n */\nexport interface SelectProps {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Size of the select trigger. Matches Input component sizes. */\n size?: KumoSelectSize;\n /**\n * Label content for the select.\n * When provided, enables the Field wrapper with a visible label above the select.\n * For accessibility without a visible label, use `aria-label` instead.\n */\n label?: ReactNode;\n /**\n * @deprecated Use `aria-label` for hidden labels instead of `label` + `hideLabel={true}`.\n * When `label` is provided without `hideLabel`, the label is now visible by default (matching Input behavior).\n * This prop will be removed in a future version.\n */\n hideLabel?: boolean;\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** When `true`, shows a skeleton loader in place of the selected value. */\n loading?: boolean;\n /** Whether the select is disabled. */\n disabled?: boolean;\n /** Whether the select is required. When `false`, shows \"(optional)\" text. */\n required?: boolean;\n /** Tooltip content displayed next to the label via an info icon. */\n labelTooltip?: ReactNode;\n /** Currently selected value (controlled mode). */\n value?: unknown;\n /** Initial value for uncontrolled mode. */\n defaultValue?: unknown;\n /** Callback fired when the selected value changes. */\n onValueChange?: (value: unknown) => void;\n /** Enable multi-select mode. */\n multiple?: boolean;\n /** `Select.Option` elements to render in the dropdown. */\n children?: ReactNode;\n /** Helper text displayed below the select. */\n description?: ReactNode;\n /** Error message string or validation error object with `match` key. */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\n/**\n * Select.Option component props.\n */\nexport interface SelectOptionProps {\n /** The option content. */\n children: ReactNode;\n /** The value associated with this option. */\n value: unknown;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n}\n\n/**\n * Dropdown for selecting a value from a list of options.\n * Wraps Base UI Select with Kumo styling and optional Field integration.\n *\n * @example\n * ```tsx\n * <Select label=\"Fruit\" onValueChange={setFruit}>\n * <Select.Option value=\"apple\">Apple</Select.Option>\n * <Select.Option value=\"banana\">Banana</Select.Option>\n * </Select>\n * ```\n */\nexport function Select<T, Multiple extends boolean | undefined = false>({\n children,\n className,\n renderValue,\n label,\n hideLabel,\n placeholder,\n loading,\n size = KUMO_SELECT_DEFAULT_VARIANTS.size,\n labelTooltip,\n description,\n error,\n required,\n container: containerProp,\n ...props\n}: SelectPropsGeneric<T, Multiple> & { required?: boolean }) {\n const labelId = useId();\n const contextContainer = usePortalContainer();\n const container = containerProp ?? contextContainer ?? undefined;\n const propLookup = props as Record<string, unknown>;\n const ariaLabel = propLookup[\"aria-label\"] as string | undefined;\n const ariaLabelledby = propLookup[\"aria-labelledby\"] as string | undefined;\n // For aria-label, use string label or placeholder (ReactNode labels can't be used for aria-label)\n const fallbackLabel = typeof label === \"string\" ? label : placeholder;\n\n // Deprecation warning for hideLabel\n if (process.env.NODE_ENV !== \"production\" && hideLabel !== undefined) {\n console.warn(\n \"[Kumo Select]: `hideLabel` is deprecated. For hidden labels, use `aria-label` instead of `label` + `hideLabel={true}`.\\n\" +\n \" Migration:\\n\" +\n ' - For visible labels: <Select label=\"Country\" /> (hideLabel no longer needed)\\n' +\n ' - For hidden labels: <Select aria-label=\"Select a country\" /> (remove label and hideLabel)',\n );\n }\n\n // New behavior: label presence determines Field wrapper visibility (like Input)\n // hideLabel is only respected for backward compatibility when explicitly set to true\n const useFieldWrapper = label && hideLabel !== true;\n const triggerLabelledBy = useFieldWrapper\n ? undefined\n : (ariaLabelledby ?? (label ? labelId : undefined));\n const triggerAriaLabel =\n ariaLabel ?? (!triggerLabelledBy ? fallbackLabel : undefined);\n\n // Normalize items to array format for Base UI compatibility\n // This fixes placeholder not showing with object map items\n const normalizedItems = props.items ? normalizeItems(props.items) : undefined;\n\n // Auto-render children from items if no explicit children provided\n const renderedChildren = children\n ? children\n : props.items\n ? renderOptionsFromItems(props.items)\n : null;\n\n // Wrap renderValue to handle null values properly:\n // - When value is null, show placeholder (Base UI ignores placeholder when children fn provided)\n // - When value is non-null, call user's renderValue\n const valueChildrenFn = renderValue\n ? (value: unknown) => {\n if (value == null) {\n // If no placeholder provided, return null to show nothing (same as no renderValue)\n if (placeholder == null) {\n return null;\n }\n return <span className=\"text-kumo-placeholder\">{placeholder}</span>;\n }\n // Cast through `any` as a deliberate type boundary: Base UI passes `unknown`,\n // but our renderValue expects the generic T (or T[] for multiple)\n return renderValue(value as any);\n }\n : undefined;\n\n // Exclude Kumo-extended `items` from Base UI spread — we pass `normalizedItems` instead\n const { items: _items, ...baseProps } = props;\n\n const selectControl = (\n <SelectBase.Root\n {...baseProps}\n items={normalizedItems}\n disabled={loading || props.disabled}\n >\n <SelectBase.Trigger\n className={cn(\n selectVariants({ size }),\n props.disabled && \"cursor-not-allowed opacity-50\",\n className,\n )}\n aria-label={triggerAriaLabel}\n aria-labelledby={triggerLabelledBy}\n >\n {loading ? (\n <SkeletonLine className=\"w-32\" />\n ) : (\n <SelectBase.Value\n placeholder={placeholder}\n className=\"min-w-0 truncate data-[placeholder]:text-kumo-placeholder\"\n >\n {valueChildrenFn}\n </SelectBase.Value>\n )}\n <SelectBase.Icon\n className={cn(\n \"flex shrink-0 items-center\",\n triggerIconStyles[size].className,\n )}\n >\n <CaretUpDownIcon\n size={triggerIconStyles[size].iconSize}\n className=\"fill-current\"\n />\n </SelectBase.Icon>\n </SelectBase.Trigger>\n <SelectBase.Portal container={container}>\n <SelectBase.Positioner>\n <SelectBase.Popup\n className={cn(\n \"flex flex-col\",\n \"max-h-[var(--available-height)] bg-kumo-base text-kumo-default\",\n \"rounded-lg shadow-lg ring ring-kumo-line\",\n \"min-w-[calc(var(--anchor-width)+3px)] py-1.5\",\n )}\n >\n <SelectBase.List\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto overscroll-none scroll-pt-2 scroll-pb-2\",\n )}\n >\n {renderedChildren}\n </SelectBase.List>\n </SelectBase.Popup>\n </SelectBase.Positioner>\n </SelectBase.Portal>\n </SelectBase.Root>\n );\n\n // Use Field wrapper when label is provided and not hidden\n if (useFieldWrapper) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {selectControl}\n </Field>\n );\n }\n\n // Render with standalone label when label is hidden (sr-only)\n // Still show description/error for accessibility and UX\n const normalizedError = error\n ? typeof error === \"string\"\n ? { message: error, match: true as const }\n : error\n : undefined;\n\n return (\n <div className=\"grid gap-2\">\n {label && (\n <span id={labelId} className=\"sr-only\">\n {label}\n </span>\n )}\n {selectControl}\n {normalizedError ? (\n <span className=\"text-sm text-kumo-danger\">\n {normalizedError.message}\n </span>\n ) : (\n description && (\n <span className=\"text-sm leading-snug text-kumo-subtle\">\n {description}\n </span>\n )\n )}\n </div>\n );\n}\n\ntype OptionProps<T> = {\n children: ReactNode;\n value: T;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\nfunction Option<T>({ children, value, disabled, className }: OptionProps<T>) {\n return (\n <SelectBase.Item\n value={value}\n disabled={disabled}\n className={cn(\n \"group mx-1.5 flex cursor-pointer items-center justify-between gap-2 rounded px-2 py-1.5 text-base outline-none\",\n \"focus-visible:z-50 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:ring-inset\",\n \"data-highlighted:bg-kumo-tint\",\n \"data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n className,\n )}\n >\n <SelectBase.ItemText>{children}</SelectBase.ItemText>\n <SelectBase.ItemIndicator>\n <CheckIcon />\n </SelectBase.ItemIndicator>\n </SelectBase.Item>\n );\n}\n\n// --- Select.Group ---\n\ntype GroupProps = {\n children: ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * Groups related options together with an accessible `role=\"group\"`.\n * Use with `Select.GroupLabel` to provide a visible heading for the group.\n *\n * @example\n * ```tsx\n * <Select.Group>\n * <Select.GroupLabel>Fruits</Select.GroupLabel>\n * <Select.Option value=\"apple\">Apple</Select.Option>\n * </Select.Group>\n * ```\n */\nconst Group = forwardRef<HTMLDivElement, GroupProps>(\n ({ children, className }, ref) => (\n <SelectBase.Group ref={ref} className={cn(className)}>\n {children}\n </SelectBase.Group>\n ),\n);\nGroup.displayName = \"Select.Group\";\n\n// --- Select.GroupLabel ---\n\ntype GroupLabelProps = {\n children: ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * A visible heading for a `Select.Group`.\n * Automatically associated with its parent group for accessibility.\n *\n * @example\n * ```tsx\n * <Select.Group>\n * <Select.GroupLabel>Available</Select.GroupLabel>\n * <Select.Option value=\"a\">Option A</Select.Option>\n * </Select.Group>\n * ```\n */\nconst GroupLabel = forwardRef<HTMLDivElement, GroupLabelProps>(\n ({ children, className }, ref) => (\n <SelectBase.GroupLabel\n ref={ref}\n className={cn(\n \"px-3.5 py-1.5 text-sm font-semibold text-kumo-subtle\",\n className,\n )}\n >\n {children}\n </SelectBase.GroupLabel>\n ),\n);\nGroupLabel.displayName = \"Select.GroupLabel\";\n\n// --- Select.Separator ---\n\ntype SeparatorProps = {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * A visual divider between option groups.\n *\n * @example\n * ```tsx\n * <Select.Option value=\"a\">Option A</Select.Option>\n * <Select.Separator />\n * <Select.Option value=\"b\">Option B</Select.Option>\n * ```\n */\nconst Separator = forwardRef<HTMLDivElement, SeparatorProps>(\n ({ className }, ref) => (\n <SelectBase.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-kumo-hairline\", className)}\n />\n ),\n);\nSeparator.displayName = \"Select.Separator\";\n\n// --- Assign sub-components ---\n\nSelect.Option = Option;\nSelect.Group = Group;\nSelect.GroupLabel = GroupLabel;\nSelect.Separator = Separator;\n\n(Select.Option as { displayName?: string }).displayName = \"Select.Option\";\n"],"names":["KUMO_INPUT_VARIANTS","KUMO_SELECT_DEFAULT_VARIANTS","selectVariants","size","cn","buttonVariants","triggerIconStyles","isItemDescriptor","value","candidate","normalizeItems","items","key","entry","renderOptionsFromItems","normalizedItems","disabledLookup","item","index","meta","jsx","Option","Select","children","className","renderValue","label","hideLabel","placeholder","loading","labelTooltip","description","error","required","containerProp","props","labelId","useId","contextContainer","usePortalContainer","container","propLookup","ariaLabel","ariaLabelledby","fallbackLabel","useFieldWrapper","triggerLabelledBy","triggerAriaLabel","renderedChildren","valueChildrenFn","_items","baseProps","selectControl","jsxs","SelectBase.Root","SelectBase.Trigger","SkeletonLine","SelectBase.Value","SelectBase.Icon","CaretUpDownIcon","SelectBase.Portal","SelectBase.Positioner","SelectBase.Popup","SelectBase.List","Field","normalizedError","disabled","SelectBase.Item","SelectBase.ItemText","SelectBase.ItemIndicator","CheckIcon","Group","forwardRef","ref","SelectBase.Group","GroupLabel","SelectBase.GroupLabel","Separator","SelectBase.Separator"],"mappings":"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"}
1
+ {"version":3,"file":"select-n6u3p44qgtb0in3z.js","sources":["../../src/components/select/select.tsx"],"sourcesContent":["import { Select as SelectBase } from \"@base-ui/react/select\";\nimport { CaretUpDownIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport { forwardRef, useId } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { buttonVariants } from \"../button\";\nimport { KUMO_INPUT_VARIANTS, type KumoInputSize } from \"../input/input\";\nimport { SkeletonLine } from \"../loader\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\nimport {\n usePortalContainer,\n type PortalContainer,\n} from \"../../utils/portal-provider\";\n\n/** Select variant definitions. */\nexport const KUMO_SELECT_VARIANTS = {\n size: KUMO_INPUT_VARIANTS.size,\n} as const;\n\nexport const KUMO_SELECT_DEFAULT_VARIANTS = {\n size: \"base\",\n} as const;\n\n/**\n * Select component styling metadata for Figma plugin code generation\n * Extracted from select.tsx implementation (source of truth)\n */\nexport const KUMO_SELECT_STYLING = {\n trigger: {\n height: 36, // h-9\n paddingX: 12, // px-3\n borderRadius: 8, // rounded-lg\n background: \"bg-kumo-elevated\",\n text: \"text-color-surface\",\n ring: \"color-border\",\n fontSize: 16, // text-base\n fontWeight: 400, // font-normal\n },\n stateTokens: {\n focus: { ring: \"color-active\" },\n disabled: { opacity: 0.5 },\n },\n icons: {\n caret: { name: \"ph-caret-up-down\", size: 20 },\n check: { name: \"ph-check\", size: 20 },\n },\n popup: {\n background: \"bg-kumo-elevated\",\n ring: \"border-kumo-line\",\n borderRadius: 8, // rounded-lg\n padding: 6, // p-1.5\n },\n option: {\n paddingX: 8, // px-2\n paddingY: 6, // py-1.5\n borderRadius: 4, // rounded\n fontSize: 16, // text-base\n highlightBackground: \"color-surface-secondary\",\n },\n} as const;\n\n// Derived types from KUMO_SELECT_VARIANTS\nexport type KumoSelectSize = keyof typeof KUMO_SELECT_VARIANTS.size;\n\nexport interface KumoSelectVariantsProps {\n /**\n * Size of the select trigger. Matches Input component sizes.\n * - `\"xs\"` — Extra small for compact UIs (h-5 / 20px)\n * - `\"sm\"` — Small for secondary fields (h-6.5 / 26px)\n * - `\"base\"` — Default size (h-9 / 36px)\n * - `\"lg\"` — Large for prominent fields (h-10 / 40px)\n * @default \"base\"\n */\n size?: KumoSelectSize;\n}\n\nexport function selectVariants({\n size = KUMO_SELECT_DEFAULT_VARIANTS.size,\n}: KumoSelectVariantsProps = {}) {\n return cn(\n buttonVariants({ size }),\n \"justify-between font-normal\",\n \"focus:opacity-100 focus:ring-kumo-focus/50 focus-visible:ring-inset *:in-focus:opacity-100\",\n );\n}\n\nconst triggerIconStyles: Record<\n KumoInputSize,\n { iconSize: number; className: string }\n> = {\n xs: { iconSize: 12, className: \"text-kumo-subtle\" },\n sm: { iconSize: 14, className: \"text-kumo-subtle\" },\n base: { iconSize: 16, className: \"text-kumo-subtle\" },\n lg: { iconSize: 18, className: \"text-kumo-subtle\" },\n};\n\n/**\n * Shape for items that carry extra metadata (disabled state, tooltip).\n * Plain `ReactNode` values are still supported for backward compatibility.\n */\nexport interface SelectItemDescriptor {\n /** Display label for the option. */\n label: ReactNode;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n}\n\n/** Value type accepted by the `items` object-map prop. */\nexport type SelectItemValue = ReactNode | SelectItemDescriptor;\n\nfunction isItemDescriptor(\n value: SelectItemValue,\n): value is SelectItemDescriptor {\n if (value === null || value === undefined) return false;\n if (typeof value !== \"object\" || Array.isArray(value)) return false;\n // React elements have $$typeof — exclude them\n if (\"$$typeof\" in (value as object)) return false;\n // Promises are not descriptors\n if (value instanceof Promise) return false;\n // Must have a defined label (not just the key existing)\n const candidate = value as unknown as Record<string, unknown>;\n return \"label\" in candidate && candidate.label !== undefined;\n}\n\n/**\n * Normalizes items to array format for Base UI.\n * Object maps are converted to array format so Base UI can properly\n * handle value matching and placeholder display.\n */\nfunction normalizeItems<T>(\n items:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>,\n): ReadonlyArray<{ label: ReactNode; value: T }> {\n if (Array.isArray(items)) {\n return items;\n }\n // Convert object map to array format\n return Object.entries(items).map(([key, entry]) => ({\n value: key as T,\n label: isItemDescriptor(entry) ? entry.label : entry,\n }));\n}\n\n/**\n * Auto-generates Select.Option elements from items prop.\n * Only used when children are not explicitly provided.\n * Filters out null values (typically used for placeholders).\n */\nfunction renderOptionsFromItems<T>(\n items:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>,\n): ReactNode {\n const normalizedItems = normalizeItems(items);\n\n // Build a lookup for disabled metadata from object-map items.\n // Object-map keys are always strings (Record<string, ...>), so the lookup\n // uses string keys. The array form ({ label, value }[]) does not support\n // descriptors — consumers should use the children API for that case.\n const disabledLookup = new Map<string, { disabled?: boolean }>();\n if (!Array.isArray(items)) {\n for (const [key, entry] of Object.entries(items)) {\n if (isItemDescriptor(entry)) {\n disabledLookup.set(key, { disabled: entry.disabled });\n }\n }\n }\n\n // Filter out null values and render options\n return normalizedItems\n .filter((item) => item.value !== null)\n .map((item, index) => {\n const key =\n typeof item.value === \"string\" ? item.value : `option-${index}`;\n // When items is an object-map, value is always a string key from\n // Object.entries. When items is an array, disabledLookup is empty.\n const meta =\n typeof item.value === \"string\"\n ? disabledLookup.get(item.value)\n : undefined;\n\n return (\n <Option key={key} value={item.value} disabled={meta?.disabled}>\n {item.label}\n </Option>\n );\n });\n}\n\ntype SelectPropsGeneric<T, Multiple extends boolean | undefined = false> = Omit<\n SelectBase.Root.Props<T, Multiple>,\n \"items\"\n> &\n KumoSelectVariantsProps & {\n multiple?: Multiple;\n /**\n * A function that returns a `ReactNode` to format the selected value.\n * Only called when a value is selected — use `placeholder` for the empty state.\n * @example\n * ```tsx\n * <Select\n * placeholder=\"Select a user...\"\n * renderValue={(user) => user.name}\n * />\n * ```\n */\n renderValue?: (value: Multiple extends true ? T[] : T) => ReactNode;\n className?: string;\n /**\n * Data structure of items rendered in the popup.\n * Accepts a plain object map (`{ key: \"Label\" }`) or an array of `{ label, value }`.\n *\n * Object-map values can be a `ReactNode` (backward-compatible) **or** a\n * `SelectItemDescriptor` for extra metadata:\n *\n * ```tsx\n * items={{\n * apple: \"Apple\",\n * banana: { label: \"Banana\", disabled: true, disabledReason: \"Out of season\" },\n * }}\n * ```\n */\n items?:\n | Record<string, SelectItemValue>\n | ReadonlyArray<{ label: ReactNode; value: T }>;\n /**\n * Label content for the select.\n * When provided, enables the Field wrapper with a visible label.\n * For accessibility without a visible label, use `aria-label` instead.\n */\n label?: ReactNode;\n /**\n * @deprecated Use `aria-label` for hidden labels instead of `label` + `hideLabel={true}`.\n * When `label` is provided without `hideLabel`, the label is now visible by default (matching Input behavior).\n * This prop will be removed in a future version.\n */\n hideLabel?: boolean;\n placeholder?: string;\n loading?: boolean;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the select */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n /**\n * Container element for the portal. Use this to render the select inside\n * a Shadow DOM or custom container. Overrides `KumoPortalProvider` context.\n * @default document.body (or KumoPortalProvider container if set)\n */\n container?: PortalContainer;\n };\n\n/**\n * Select component props.\n *\n * **Accessible Name Required:** Select should have one of:\n * 1. `label` prop (recommended) - enables Field wrapper with visible label\n * 2. `aria-label` - for selects without visible label (accessibility-only)\n * 3. `aria-labelledby` - for custom label association\n *\n * @example\n * ```tsx\n * // With visible label (recommended)\n * <Select label=\"Country\" onValueChange={setValue}>\n * <Select.Option value=\"us\">United States</Select.Option>\n * <Select.Option value=\"uk\">United Kingdom</Select.Option>\n * </Select>\n *\n * // Without visible label (use aria-label for accessibility)\n * <Select aria-label=\"Select a country\" onValueChange={setValue}>\n * <Select.Option value=\"us\">United States</Select.Option>\n * </Select>\n * ```\n */\nexport interface SelectProps {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n /** Size of the select trigger. Matches Input component sizes. */\n size?: KumoSelectSize;\n /**\n * Label content for the select.\n * When provided, enables the Field wrapper with a visible label above the select.\n * For accessibility without a visible label, use `aria-label` instead.\n */\n label?: ReactNode;\n /**\n * @deprecated Use `aria-label` for hidden labels instead of `label` + `hideLabel={true}`.\n * When `label` is provided without `hideLabel`, the label is now visible by default (matching Input behavior).\n * This prop will be removed in a future version.\n */\n hideLabel?: boolean;\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** When `true`, shows a skeleton loader in place of the selected value. */\n loading?: boolean;\n /** Whether the select is disabled. */\n disabled?: boolean;\n /** Whether the select is required. When `false`, shows \"(optional)\" text. */\n required?: boolean;\n /** Tooltip content displayed next to the label via an info icon. */\n labelTooltip?: ReactNode;\n /** Currently selected value (controlled mode). */\n value?: unknown;\n /** Initial value for uncontrolled mode. */\n defaultValue?: unknown;\n /** Callback fired when the selected value changes. */\n onValueChange?: (value: unknown) => void;\n /** Enable multi-select mode. */\n multiple?: boolean;\n /** `Select.Option` elements to render in the dropdown. */\n children?: ReactNode;\n /** Helper text displayed below the select. */\n description?: ReactNode;\n /** Error message string or validation error object with `match` key. */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\n/**\n * Select.Option component props.\n */\nexport interface SelectOptionProps {\n /** The option content. */\n children: ReactNode;\n /** The value associated with this option. */\n value: unknown;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n}\n\n/**\n * Dropdown for selecting a value from a list of options.\n * Wraps Base UI Select with Kumo styling and optional Field integration.\n *\n * @example\n * ```tsx\n * <Select label=\"Fruit\" onValueChange={setFruit}>\n * <Select.Option value=\"apple\">Apple</Select.Option>\n * <Select.Option value=\"banana\">Banana</Select.Option>\n * </Select>\n * ```\n */\nexport function Select<T, Multiple extends boolean | undefined = false>({\n children,\n className,\n renderValue,\n label,\n hideLabel,\n placeholder,\n loading,\n size = KUMO_SELECT_DEFAULT_VARIANTS.size,\n labelTooltip,\n description,\n error,\n required,\n container: containerProp,\n ...props\n}: SelectPropsGeneric<T, Multiple> & { required?: boolean }) {\n const labelId = useId();\n const contextContainer = usePortalContainer();\n const container = containerProp ?? contextContainer ?? undefined;\n const propLookup = props as Record<string, unknown>;\n const ariaLabel = propLookup[\"aria-label\"] as string | undefined;\n const ariaLabelledby = propLookup[\"aria-labelledby\"] as string | undefined;\n // For aria-label, use string label or placeholder (ReactNode labels can't be used for aria-label)\n const fallbackLabel = typeof label === \"string\" ? label : placeholder;\n\n // Deprecation warning for hideLabel\n if (process.env.NODE_ENV !== \"production\" && hideLabel !== undefined) {\n console.warn(\n \"[Kumo Select]: `hideLabel` is deprecated. For hidden labels, use `aria-label` instead of `label` + `hideLabel={true}`.\\n\" +\n \" Migration:\\n\" +\n ' - For visible labels: <Select label=\"Country\" /> (hideLabel no longer needed)\\n' +\n ' - For hidden labels: <Select aria-label=\"Select a country\" /> (remove label and hideLabel)',\n );\n }\n\n // New behavior: label presence determines Field wrapper visibility (like Input)\n // hideLabel is only respected for backward compatibility when explicitly set to true\n const useFieldWrapper = label && hideLabel !== true;\n const triggerLabelledBy = useFieldWrapper\n ? undefined\n : (ariaLabelledby ?? (label ? labelId : undefined));\n const triggerAriaLabel =\n ariaLabel ?? (!triggerLabelledBy ? fallbackLabel : undefined);\n\n // Normalize items to array format for Base UI compatibility\n // This fixes placeholder not showing with object map items\n const normalizedItems = props.items ? normalizeItems(props.items) : undefined;\n\n // Auto-render children from items if no explicit children provided\n const renderedChildren = children\n ? children\n : props.items\n ? renderOptionsFromItems(props.items)\n : null;\n\n // Wrap renderValue to handle null values properly:\n // - When value is null, show placeholder (Base UI ignores placeholder when children fn provided)\n // - When value is non-null, call user's renderValue\n const valueChildrenFn = renderValue\n ? (value: unknown) => {\n if (value == null) {\n // If no placeholder provided, return null to show nothing (same as no renderValue)\n if (placeholder == null) {\n return null;\n }\n return <span className=\"text-kumo-placeholder\">{placeholder}</span>;\n }\n // Cast through `any` as a deliberate type boundary: Base UI passes `unknown`,\n // but our renderValue expects the generic T (or T[] for multiple)\n return renderValue(value as any);\n }\n : undefined;\n\n // Exclude Kumo-extended `items` from Base UI spread — we pass `normalizedItems` instead\n const { items: _items, ...baseProps } = props;\n\n const selectControl = (\n <SelectBase.Root\n {...baseProps}\n items={normalizedItems}\n disabled={loading || props.disabled}\n >\n <SelectBase.Trigger\n className={cn(\n selectVariants({ size }),\n props.disabled && \"cursor-not-allowed opacity-50\",\n className,\n )}\n aria-label={triggerAriaLabel}\n aria-labelledby={triggerLabelledBy}\n >\n {loading ? (\n <SkeletonLine className=\"w-32\" />\n ) : (\n <SelectBase.Value\n placeholder={placeholder}\n className=\"min-w-0 truncate data-[placeholder]:text-kumo-placeholder\"\n >\n {valueChildrenFn}\n </SelectBase.Value>\n )}\n <SelectBase.Icon\n className={cn(\n \"flex shrink-0 items-center\",\n triggerIconStyles[size].className,\n )}\n >\n <CaretUpDownIcon\n size={triggerIconStyles[size].iconSize}\n className=\"fill-current\"\n />\n </SelectBase.Icon>\n </SelectBase.Trigger>\n <SelectBase.Portal container={container}>\n <SelectBase.Positioner>\n <SelectBase.Popup\n className={cn(\n \"flex flex-col\",\n \"max-h-[var(--available-height)] bg-kumo-base text-kumo-default\",\n \"rounded-lg shadow-lg ring ring-kumo-line\",\n \"min-w-[calc(var(--anchor-width)+3px)] py-1.5\",\n )}\n >\n <SelectBase.List\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto overscroll-none scroll-pt-2 scroll-pb-2\",\n )}\n >\n {renderedChildren}\n </SelectBase.List>\n </SelectBase.Popup>\n </SelectBase.Positioner>\n </SelectBase.Portal>\n </SelectBase.Root>\n );\n\n // Use Field wrapper when label is provided and not hidden\n if (useFieldWrapper) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {selectControl}\n </Field>\n );\n }\n\n // Render with standalone label when label is hidden (sr-only)\n // Still show description/error for accessibility and UX\n const normalizedError = error\n ? typeof error === \"string\"\n ? { message: error, match: true as const }\n : error\n : undefined;\n\n return (\n <div className=\"grid gap-2\">\n {label && (\n <span id={labelId} className=\"sr-only\">\n {label}\n </span>\n )}\n {selectControl}\n {normalizedError ? (\n <span className=\"text-sm text-kumo-danger\">\n {normalizedError.message}\n </span>\n ) : (\n description && (\n <span className=\"text-sm leading-snug text-kumo-subtle\">\n {description}\n </span>\n )\n )}\n </div>\n );\n}\n\ntype OptionProps<T> = {\n children: ReactNode;\n value: T;\n /** When `true`, the option cannot be selected. */\n disabled?: boolean;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\nfunction Option<T>({ children, value, disabled, className }: OptionProps<T>) {\n return (\n <SelectBase.Item\n value={value}\n disabled={disabled}\n className={cn(\n \"group mx-1.5 flex cursor-pointer items-center justify-between gap-2 rounded px-2 py-1.5 text-base outline-none\",\n \"focus-visible:z-50 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:ring-inset\",\n \"data-highlighted:bg-kumo-tint\",\n \"data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n className,\n )}\n >\n <SelectBase.ItemText>{children}</SelectBase.ItemText>\n <SelectBase.ItemIndicator>\n <CheckIcon />\n </SelectBase.ItemIndicator>\n </SelectBase.Item>\n );\n}\n\n// --- Select.Group ---\n\ntype GroupProps = {\n children: ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * Groups related options together with an accessible `role=\"group\"`.\n * Use with `Select.GroupLabel` to provide a visible heading for the group.\n *\n * @example\n * ```tsx\n * <Select.Group>\n * <Select.GroupLabel>Fruits</Select.GroupLabel>\n * <Select.Option value=\"apple\">Apple</Select.Option>\n * </Select.Group>\n * ```\n */\nconst Group = forwardRef<HTMLDivElement, GroupProps>(\n ({ children, className }, ref) => (\n <SelectBase.Group ref={ref} className={cn(className)}>\n {children}\n </SelectBase.Group>\n ),\n);\nGroup.displayName = \"Select.Group\";\n\n// --- Select.GroupLabel ---\n\ntype GroupLabelProps = {\n children: ReactNode;\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * A visible heading for a `Select.Group`.\n * Automatically associated with its parent group for accessibility.\n *\n * @example\n * ```tsx\n * <Select.Group>\n * <Select.GroupLabel>Available</Select.GroupLabel>\n * <Select.Option value=\"a\">Option A</Select.Option>\n * </Select.Group>\n * ```\n */\nconst GroupLabel = forwardRef<HTMLDivElement, GroupLabelProps>(\n ({ children, className }, ref) => (\n <SelectBase.GroupLabel\n ref={ref}\n className={cn(\n \"px-3.5 py-1.5 text-sm font-semibold text-kumo-subtle\",\n className,\n )}\n >\n {children}\n </SelectBase.GroupLabel>\n ),\n);\nGroupLabel.displayName = \"Select.GroupLabel\";\n\n// --- Select.Separator ---\n\ntype SeparatorProps = {\n /** Additional CSS classes merged via `cn()`. */\n className?: string;\n};\n\n/**\n * A visual divider between option groups.\n *\n * @example\n * ```tsx\n * <Select.Option value=\"a\">Option A</Select.Option>\n * <Select.Separator />\n * <Select.Option value=\"b\">Option B</Select.Option>\n * ```\n */\nconst Separator = forwardRef<HTMLDivElement, SeparatorProps>(\n ({ className }, ref) => (\n <SelectBase.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-kumo-hairline\", className)}\n />\n ),\n);\nSeparator.displayName = \"Select.Separator\";\n\n// --- Assign sub-components ---\n\nSelect.Option = Option;\nSelect.Group = Group;\nSelect.GroupLabel = GroupLabel;\nSelect.Separator = Separator;\n\n(Select.Option as { displayName?: string }).displayName = \"Select.Option\";\n"],"names":["KUMO_INPUT_VARIANTS","KUMO_SELECT_DEFAULT_VARIANTS","selectVariants","size","cn","buttonVariants","triggerIconStyles","isItemDescriptor","value","candidate","normalizeItems","items","key","entry","renderOptionsFromItems","normalizedItems","disabledLookup","item","index","meta","jsx","Option","Select","children","className","renderValue","label","hideLabel","placeholder","loading","labelTooltip","description","error","required","containerProp","props","labelId","useId","contextContainer","usePortalContainer","container","propLookup","ariaLabel","ariaLabelledby","fallbackLabel","useFieldWrapper","triggerLabelledBy","triggerAriaLabel","renderedChildren","valueChildrenFn","_items","baseProps","selectControl","jsxs","SelectBase.Root","SelectBase.Trigger","SkeletonLine","SelectBase.Value","SelectBase.Icon","CaretUpDownIcon","SelectBase.Portal","SelectBase.Positioner","SelectBase.Popup","SelectBase.List","Field","normalizedError","disabled","SelectBase.Item","SelectBase.ItemText","SelectBase.ItemIndicator","CheckIcon","Group","forwardRef","ref","SelectBase.Group","GroupLabel","SelectBase.GroupLabel","Separator","SelectBase.Separator"],"mappings":"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"}
@@ -3,8 +3,8 @@ import { jsxs as y, Fragment as ce, jsx as a } from "react/jsx-runtime";
3
3
  import { EyeSlash as ue, Eye as pe } from "@phosphor-icons/react";
4
4
  import { forwardRef as de, useState as C, useRef as N, useId as T, useCallback as c, useEffect as fe } from "react";
5
5
  import { c as p } from "./cn-ct4n7r74mh8y0f48.js";
6
- import { K as me, i as he } from "./input-ncfowphv81yq7fyy.js";
7
- import { F as ge } from "./field-c0wf94plit2gci59.js";
6
+ import { K as me, i as he } from "./input-k2ychlh2zo6hsocz.js";
7
+ import { F as ge } from "./field-hmucpi6d4sqci1zu.js";
8
8
  import { I as ve } from "./vendor-base-ui-ie71jahf0czyf58j.js";
9
9
  const Te = me, M = {
10
10
  size: "base",
@@ -261,4 +261,4 @@ export {
261
261
  be as S,
262
262
  M as a
263
263
  };
264
- //# sourceMappingURL=sensitive-input-cijagk551mesdtk4.js.map
264
+ //# sourceMappingURL=sensitive-input-yoawqvvvmtdod430.js.map