@kodffe/ui 0.0.0-stage → 0.10.1

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 (304) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/accordion/accordion.d.ts +44 -0
  3. package/dist/accordion/accordion.js +84 -0
  4. package/dist/accordion/accordion.js.map +1 -0
  5. package/dist/alert/alert.d.ts +17 -0
  6. package/dist/alert/alert.js +59 -0
  7. package/dist/alert/alert.js.map +1 -0
  8. package/dist/app-shell/app-footer.d.ts +29 -0
  9. package/dist/app-shell/app-footer.js +39 -0
  10. package/dist/app-shell/app-footer.js.map +1 -0
  11. package/dist/app-shell/app-shell-context.d.ts +10 -0
  12. package/dist/app-shell/app-shell-context.js +12 -0
  13. package/dist/app-shell/app-shell-context.js.map +1 -0
  14. package/dist/app-shell/app-shell.d.ts +42 -0
  15. package/dist/app-shell/app-shell.js +191 -0
  16. package/dist/app-shell/app-shell.js.map +1 -0
  17. package/dist/app-shell/floating-actions.d.ts +19 -0
  18. package/dist/app-shell/floating-actions.js +59 -0
  19. package/dist/app-shell/floating-actions.js.map +1 -0
  20. package/dist/app-shell/workspace-switcher.d.ts +25 -0
  21. package/dist/app-shell/workspace-switcher.js +82 -0
  22. package/dist/app-shell/workspace-switcher.js.map +1 -0
  23. package/dist/badge/badge.d.ts +19 -0
  24. package/dist/badge/badge.js +59 -0
  25. package/dist/badge/badge.js.map +1 -0
  26. package/dist/banner/banner.d.ts +22 -0
  27. package/dist/banner/banner.js +80 -0
  28. package/dist/banner/banner.js.map +1 -0
  29. package/dist/breadcrumbs/breadcrumbs.d.ts +18 -0
  30. package/dist/breadcrumbs/breadcrumbs.js +45 -0
  31. package/dist/breadcrumbs/breadcrumbs.js.map +1 -0
  32. package/dist/button/button.d.ts +38 -0
  33. package/dist/button/button.js +83 -0
  34. package/dist/button/button.js.map +1 -0
  35. package/dist/card/card.d.ts +159 -0
  36. package/dist/card/card.js +390 -0
  37. package/dist/card/card.js.map +1 -0
  38. package/dist/card/insight-card.d.ts +19 -0
  39. package/dist/card/insight-card.js +51 -0
  40. package/dist/card/insight-card.js.map +1 -0
  41. package/dist/card/integration-card.d.ts +19 -0
  42. package/dist/card/integration-card.js +70 -0
  43. package/dist/card/integration-card.js.map +1 -0
  44. package/dist/charts/charts.d.ts +75 -0
  45. package/dist/charts/charts.js +453 -0
  46. package/dist/charts/charts.js.map +1 -0
  47. package/dist/choice/choice.d.ts +39 -0
  48. package/dist/choice/choice.js +143 -0
  49. package/dist/choice/choice.js.map +1 -0
  50. package/dist/combobox/combobox.d.ts +46 -0
  51. package/dist/combobox/combobox.js +196 -0
  52. package/dist/combobox/combobox.js.map +1 -0
  53. package/dist/command-palette/command-palette.d.ts +35 -0
  54. package/dist/command-palette/command-palette.js +164 -0
  55. package/dist/command-palette/command-palette.js.map +1 -0
  56. package/dist/confirm-dialog/confirm-dialog.d.ts +37 -0
  57. package/dist/confirm-dialog/confirm-dialog.js +106 -0
  58. package/dist/confirm-dialog/confirm-dialog.js.map +1 -0
  59. package/dist/content/assistant.d.ts +86 -0
  60. package/dist/content/assistant.js +213 -0
  61. package/dist/content/assistant.js.map +1 -0
  62. package/dist/content/content.d.ts +45 -0
  63. package/dist/content/content.js +136 -0
  64. package/dist/content/content.js.map +1 -0
  65. package/dist/data-display/avatar-sizes.d.ts +8 -0
  66. package/dist/data-display/avatar-sizes.js +12 -0
  67. package/dist/data-display/avatar-sizes.js.map +1 -0
  68. package/dist/data-display/avatar.d.ts +21 -0
  69. package/dist/data-display/avatar.js +53 -0
  70. package/dist/data-display/avatar.js.map +1 -0
  71. package/dist/data-display/chip.d.ts +20 -0
  72. package/dist/data-display/chip.js +64 -0
  73. package/dist/data-display/chip.js.map +1 -0
  74. package/dist/data-display/code-block.d.ts +14 -0
  75. package/dist/data-display/code-block.js +50 -0
  76. package/dist/data-display/code-block.js.map +1 -0
  77. package/dist/data-display/data-display.d.ts +73 -0
  78. package/dist/data-display/data-display.js +227 -0
  79. package/dist/data-display/data-display.js.map +1 -0
  80. package/dist/data-display/insights.d.ts +120 -0
  81. package/dist/data-display/insights.js +220 -0
  82. package/dist/data-display/insights.js.map +1 -0
  83. package/dist/data-table/cells.d.ts +86 -0
  84. package/dist/data-table/cells.js +163 -0
  85. package/dist/data-table/cells.js.map +1 -0
  86. package/dist/data-table/data-table.d.ts +112 -0
  87. package/dist/data-table/data-table.js +558 -0
  88. package/dist/data-table/data-table.js.map +1 -0
  89. package/dist/date-picker/date-picker.d.ts +61 -0
  90. package/dist/date-picker/date-picker.js +309 -0
  91. package/dist/date-picker/date-picker.js.map +1 -0
  92. package/dist/drawer/drawer.d.ts +32 -0
  93. package/dist/drawer/drawer.js +72 -0
  94. package/dist/drawer/drawer.js.map +1 -0
  95. package/dist/empty-state/empty-state.d.ts +25 -0
  96. package/dist/empty-state/empty-state.js +78 -0
  97. package/dist/empty-state/empty-state.js.map +1 -0
  98. package/dist/error-state/error-state.d.ts +19 -0
  99. package/dist/error-state/error-state.js +56 -0
  100. package/dist/error-state/error-state.js.map +1 -0
  101. package/dist/event-calendar/calendar-logic.test.d.ts +1 -0
  102. package/dist/event-calendar/dates.d.ts +35 -0
  103. package/dist/event-calendar/dates.js +55 -0
  104. package/dist/event-calendar/dates.js.map +1 -0
  105. package/dist/event-calendar/event-calendar.d.ts +125 -0
  106. package/dist/event-calendar/event-calendar.js +795 -0
  107. package/dist/event-calendar/event-calendar.js.map +1 -0
  108. package/dist/event-calendar/event-details.d.ts +50 -0
  109. package/dist/event-calendar/event-details.js +124 -0
  110. package/dist/event-calendar/event-details.js.map +1 -0
  111. package/dist/event-calendar/layout.d.ts +48 -0
  112. package/dist/event-calendar/layout.js +55 -0
  113. package/dist/event-calendar/layout.js.map +1 -0
  114. package/dist/file-upload/file-upload.d.ts +70 -0
  115. package/dist/file-upload/file-upload.js +307 -0
  116. package/dist/file-upload/file-upload.js.map +1 -0
  117. package/dist/filters/filters.d.ts +48 -0
  118. package/dist/filters/filters.js +103 -0
  119. package/dist/filters/filters.js.map +1 -0
  120. package/dist/form-field/form-field.d.ts +39 -0
  121. package/dist/form-field/form-field.js +88 -0
  122. package/dist/form-field/form-field.js.map +1 -0
  123. package/dist/hover-card/hover-card.d.ts +15 -0
  124. package/dist/hover-card/hover-card.js +27 -0
  125. package/dist/hover-card/hover-card.js.map +1 -0
  126. package/dist/hover-card/person-hover-card.d.ts +26 -0
  127. package/dist/hover-card/person-hover-card.js +85 -0
  128. package/dist/hover-card/person-hover-card.js.map +1 -0
  129. package/dist/icon/icon-tile.d.ts +20 -0
  130. package/dist/icon/icon-tile.js +55 -0
  131. package/dist/icon/icon-tile.js.map +1 -0
  132. package/dist/icon/icon.d.ts +14 -0
  133. package/dist/icon/icon.js +28 -0
  134. package/dist/icon/icon.js.map +1 -0
  135. package/dist/icon/icons.generated.d.ts +358 -0
  136. package/dist/icon/icons.generated.js +362 -0
  137. package/dist/icon/icons.generated.js.map +1 -0
  138. package/dist/index.d.ts +90 -0
  139. package/dist/index.js +88 -0
  140. package/dist/input/extra-inputs.d.ts +122 -0
  141. package/dist/input/extra-inputs.js +351 -0
  142. package/dist/input/extra-inputs.js.map +1 -0
  143. package/dist/input/field-styles.d.ts +5 -0
  144. package/dist/input/field-styles.js +14 -0
  145. package/dist/input/field-styles.js.map +1 -0
  146. package/dist/input/input.d.ts +50 -0
  147. package/dist/input/input.js +107 -0
  148. package/dist/input/input.js.map +1 -0
  149. package/dist/layout/layout.d.ts +41 -0
  150. package/dist/layout/layout.js +90 -0
  151. package/dist/layout/layout.js.map +1 -0
  152. package/dist/lib/control-styles.d.ts +9 -0
  153. package/dist/lib/control-styles.js +16 -0
  154. package/dist/lib/control-styles.js.map +1 -0
  155. package/dist/lib/cx.d.ts +2 -0
  156. package/dist/lib/cx.js +8 -0
  157. package/dist/lib/cx.js.map +1 -0
  158. package/dist/lib/glyphs.d.ts +13 -0
  159. package/dist/lib/glyphs.js +67 -0
  160. package/dist/lib/glyphs.js.map +1 -0
  161. package/dist/lib/segmented-styles.d.ts +8 -0
  162. package/dist/lib/segmented-styles.js +12 -0
  163. package/dist/lib/segmented-styles.js.map +1 -0
  164. package/dist/lib/select-on-arrow.d.ts +7 -0
  165. package/dist/lib/select-on-arrow.js +21 -0
  166. package/dist/lib/select-on-arrow.js.map +1 -0
  167. package/dist/lib/skip-link.d.ts +5 -0
  168. package/dist/lib/skip-link.js +13 -0
  169. package/dist/lib/skip-link.js.map +1 -0
  170. package/dist/lib/use-media-query.d.ts +4 -0
  171. package/dist/lib/use-media-query.js +15 -0
  172. package/dist/lib/use-media-query.js.map +1 -0
  173. package/dist/lists/lists.d.ts +76 -0
  174. package/dist/lists/lists.js +133 -0
  175. package/dist/lists/lists.js.map +1 -0
  176. package/dist/locale-switch/locale-switch.d.ts +29 -0
  177. package/dist/locale-switch/locale-switch.js +62 -0
  178. package/dist/locale-switch/locale-switch.js.map +1 -0
  179. package/dist/logo/logo.d.ts +31 -0
  180. package/dist/logo/logo.js +157 -0
  181. package/dist/logo/logo.js.map +1 -0
  182. package/dist/logo/product-logo.d.ts +19 -0
  183. package/dist/logo/product-logo.js +46 -0
  184. package/dist/logo/product-logo.js.map +1 -0
  185. package/dist/marketing/marketing.d.ts +176 -0
  186. package/dist/marketing/marketing.js +451 -0
  187. package/dist/marketing/marketing.js.map +1 -0
  188. package/dist/marketing/newsletter-form.d.ts +21 -0
  189. package/dist/marketing/newsletter-form.js +100 -0
  190. package/dist/marketing/newsletter-form.js.map +1 -0
  191. package/dist/mascot/mascot.d.ts +28 -0
  192. package/dist/mascot/mascot.js +28 -0
  193. package/dist/mascot/mascot.js.map +1 -0
  194. package/dist/mascot/mascots.generated.d.ts +284 -0
  195. package/dist/mascot/mascots.generated.js +287 -0
  196. package/dist/mascot/mascots.generated.js.map +1 -0
  197. package/dist/master-detail/master-detail.d.ts +30 -0
  198. package/dist/master-detail/master-detail.js +71 -0
  199. package/dist/master-detail/master-detail.js.map +1 -0
  200. package/dist/menu/account-menu.d.ts +44 -0
  201. package/dist/menu/account-menu.js +78 -0
  202. package/dist/menu/account-menu.js.map +1 -0
  203. package/dist/menu/context-menu.d.ts +31 -0
  204. package/dist/menu/context-menu.js +111 -0
  205. package/dist/menu/context-menu.js.map +1 -0
  206. package/dist/menu/dropdown-menu.d.ts +49 -0
  207. package/dist/menu/dropdown-menu.js +152 -0
  208. package/dist/menu/dropdown-menu.js.map +1 -0
  209. package/dist/menu/menu-styles.d.ts +8 -0
  210. package/dist/menu/menu-styles.js +6 -0
  211. package/dist/menu/menu-styles.js.map +1 -0
  212. package/dist/menu/menubar.d.ts +31 -0
  213. package/dist/menu/menubar.js +125 -0
  214. package/dist/menu/menubar.js.map +1 -0
  215. package/dist/modal/modal.d.ts +34 -0
  216. package/dist/modal/modal.js +58 -0
  217. package/dist/modal/modal.js.map +1 -0
  218. package/dist/notification-center/notification-center.d.ts +51 -0
  219. package/dist/notification-center/notification-center.js +244 -0
  220. package/dist/notification-center/notification-center.js.map +1 -0
  221. package/dist/otp-input/otp-input.d.ts +23 -0
  222. package/dist/otp-input/otp-input.js +61 -0
  223. package/dist/otp-input/otp-input.js.map +1 -0
  224. package/dist/overlay/overlay.d.ts +53 -0
  225. package/dist/overlay/overlay.js +103 -0
  226. package/dist/overlay/overlay.js.map +1 -0
  227. package/dist/page-header/page-header.d.ts +55 -0
  228. package/dist/page-header/page-header.js +114 -0
  229. package/dist/page-header/page-header.js.map +1 -0
  230. package/dist/page-header/record-headers.d.ts +51 -0
  231. package/dist/page-header/record-headers.js +134 -0
  232. package/dist/page-header/record-headers.js.map +1 -0
  233. package/dist/page-header/section-header.d.ts +21 -0
  234. package/dist/page-header/section-header.js +44 -0
  235. package/dist/page-header/section-header.js.map +1 -0
  236. package/dist/page-navigation/page-navigation.d.ts +59 -0
  237. package/dist/page-navigation/page-navigation.js +136 -0
  238. package/dist/page-navigation/page-navigation.js.map +1 -0
  239. package/dist/pagination/pagination.d.ts +28 -0
  240. package/dist/pagination/pagination.js +102 -0
  241. package/dist/pagination/pagination.js.map +1 -0
  242. package/dist/phone-input/phone-input.d.ts +34 -0
  243. package/dist/phone-input/phone-input.js +171 -0
  244. package/dist/phone-input/phone-input.js.map +1 -0
  245. package/dist/popover/popover.d.ts +23 -0
  246. package/dist/popover/popover.js +40 -0
  247. package/dist/popover/popover.js.map +1 -0
  248. package/dist/progress/progress.d.ts +21 -0
  249. package/dist/progress/progress.js +49 -0
  250. package/dist/progress/progress.js.map +1 -0
  251. package/dist/segmented-control/segmented-control.d.ts +32 -0
  252. package/dist/segmented-control/segmented-control.js +29 -0
  253. package/dist/segmented-control/segmented-control.js.map +1 -0
  254. package/dist/select/select.d.ts +48 -0
  255. package/dist/select/select.js +136 -0
  256. package/dist/select/select.js.map +1 -0
  257. package/dist/settings/permission-matrix.d.ts +29 -0
  258. package/dist/settings/permission-matrix.js +101 -0
  259. package/dist/settings/permission-matrix.js.map +1 -0
  260. package/dist/settings/settings-row.d.ts +32 -0
  261. package/dist/settings/settings-row.js +63 -0
  262. package/dist/settings/settings-row.js.map +1 -0
  263. package/dist/side-nav/side-nav.d.ts +36 -0
  264. package/dist/side-nav/side-nav.js +123 -0
  265. package/dist/side-nav/side-nav.js.map +1 -0
  266. package/dist/site-header/site-header.d.ts +32 -0
  267. package/dist/site-header/site-header.js +99 -0
  268. package/dist/site-header/site-header.js.map +1 -0
  269. package/dist/skeleton/skeleton.d.ts +16 -0
  270. package/dist/skeleton/skeleton.js +19 -0
  271. package/dist/skeleton/skeleton.js.map +1 -0
  272. package/dist/slider/slider.d.ts +15 -0
  273. package/dist/slider/slider.js +48 -0
  274. package/dist/slider/slider.js.map +1 -0
  275. package/dist/spinner/spinner.d.ts +15 -0
  276. package/dist/spinner/spinner.js +42 -0
  277. package/dist/spinner/spinner.js.map +1 -0
  278. package/dist/stepper/step-dots.d.ts +16 -0
  279. package/dist/stepper/step-dots.js +26 -0
  280. package/dist/stepper/step-dots.js.map +1 -0
  281. package/dist/stepper/stepper.d.ts +26 -0
  282. package/dist/stepper/stepper.js +113 -0
  283. package/dist/stepper/stepper.js.map +1 -0
  284. package/dist/tabs/tabs.d.ts +31 -0
  285. package/dist/tabs/tabs.js +66 -0
  286. package/dist/tabs/tabs.js.map +1 -0
  287. package/dist/templates/app-templates.d.ts +126 -0
  288. package/dist/templates/app-templates.js +153 -0
  289. package/dist/templates/app-templates.js.map +1 -0
  290. package/dist/templates/site-templates.d.ts +49 -0
  291. package/dist/templates/site-templates.js +110 -0
  292. package/dist/templates/site-templates.js.map +1 -0
  293. package/dist/toast/toast-store.d.ts +54 -0
  294. package/dist/toast/toast-store.js +49 -0
  295. package/dist/toast/toast-store.js.map +1 -0
  296. package/dist/toast/toaster.d.ts +15 -0
  297. package/dist/toast/toaster.js +124 -0
  298. package/dist/toast/toaster.js.map +1 -0
  299. package/dist/tooltip/tooltip.d.ts +29 -0
  300. package/dist/tooltip/tooltip.js +54 -0
  301. package/dist/tooltip/tooltip.js.map +1 -0
  302. package/package.json +88 -3
  303. package/styles.css +521 -0
  304. package/README.md +0 -3
@@ -0,0 +1,171 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Glyph as t } from "../lib/glyphs.js";
4
+ import { controlClasses as n } from "../input/field-styles.js";
5
+ import { useFieldProps as r } from "../input/input.js";
6
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
7
+ import { useMemo as o, useState as s } from "react";
8
+ //#region src/phone-input/phone-input.tsx
9
+ var c = [
10
+ {
11
+ code: "US",
12
+ name: "United States",
13
+ dial: "1"
14
+ },
15
+ {
16
+ code: "CA",
17
+ name: "Canada",
18
+ dial: "1"
19
+ },
20
+ {
21
+ code: "MX",
22
+ name: "Mexico",
23
+ dial: "52"
24
+ },
25
+ {
26
+ code: "EC",
27
+ name: "Ecuador",
28
+ dial: "593"
29
+ },
30
+ {
31
+ code: "CO",
32
+ name: "Colombia",
33
+ dial: "57"
34
+ },
35
+ {
36
+ code: "PE",
37
+ name: "Peru",
38
+ dial: "51"
39
+ },
40
+ {
41
+ code: "CL",
42
+ name: "Chile",
43
+ dial: "56"
44
+ },
45
+ {
46
+ code: "AR",
47
+ name: "Argentina",
48
+ dial: "54"
49
+ },
50
+ {
51
+ code: "BR",
52
+ name: "Brazil",
53
+ dial: "55"
54
+ },
55
+ {
56
+ code: "UY",
57
+ name: "Uruguay",
58
+ dial: "598"
59
+ },
60
+ {
61
+ code: "PA",
62
+ name: "Panama",
63
+ dial: "507"
64
+ },
65
+ {
66
+ code: "CR",
67
+ name: "Costa Rica",
68
+ dial: "506"
69
+ },
70
+ {
71
+ code: "GT",
72
+ name: "Guatemala",
73
+ dial: "502"
74
+ },
75
+ {
76
+ code: "DO",
77
+ name: "Dominican Republic",
78
+ dial: "1"
79
+ },
80
+ {
81
+ code: "BO",
82
+ name: "Bolivia",
83
+ dial: "591"
84
+ },
85
+ {
86
+ code: "PY",
87
+ name: "Paraguay",
88
+ dial: "595"
89
+ },
90
+ {
91
+ code: "VE",
92
+ name: "Venezuela",
93
+ dial: "58"
94
+ },
95
+ {
96
+ code: "ES",
97
+ name: "Spain",
98
+ dial: "34"
99
+ },
100
+ {
101
+ code: "GB",
102
+ name: "United Kingdom",
103
+ dial: "44"
104
+ }
105
+ ], l = (e, t = c) => {
106
+ let n = t.find((t) => t.code === e.country);
107
+ return n && e.number ? `+${n.dial}${e.number.replace(/^0+/, "")}` : "";
108
+ };
109
+ function u({ value: l, onChange: u, countries: d = c, size: f = "md", placeholder: p, countryLabel: m = "Country code", className: h, ...g }) {
110
+ let { invalid: _, ...v } = r(g), [y, b] = s(!1), x = o(() => d.find((e) => e.code === l.country) ?? d[0], [d, l.country]);
111
+ return /* @__PURE__ */ a("div", {
112
+ className: e(n(f, _), "flex items-stretch", y && "border-primary", h),
113
+ children: [/* @__PURE__ */ a("div", {
114
+ className: "relative flex shrink-0 items-center border-r border-border",
115
+ children: [
116
+ /* @__PURE__ */ i("select", {
117
+ "aria-label": m,
118
+ value: x.code,
119
+ disabled: v.disabled,
120
+ onChange: (e) => u({
121
+ ...l,
122
+ country: e.target.value
123
+ }),
124
+ className: "h-full w-[6.75rem] cursor-pointer appearance-none rounded-l-sm border-0 bg-transparent py-0 pr-8 pl-3 font-[inherit] text-[length:inherit] font-medium text-transparent outline-none [&>option]:text-fg focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-focus",
125
+ children: d.map((e) => /* @__PURE__ */ a("option", {
126
+ value: e.code,
127
+ children: [
128
+ e.code,
129
+ " +",
130
+ e.dial,
131
+ " — ",
132
+ e.name
133
+ ]
134
+ }, e.code))
135
+ }),
136
+ /* @__PURE__ */ a("span", {
137
+ "aria-hidden": "true",
138
+ className: "pointer-events-none absolute inset-y-0 left-3 flex items-center bg-bg pr-1 font-medium",
139
+ children: [
140
+ x.code,
141
+ " +",
142
+ x.dial
143
+ ]
144
+ }),
145
+ /* @__PURE__ */ i(t, {
146
+ name: "chevron-down",
147
+ size: 14,
148
+ className: "pointer-events-none absolute right-2.5 text-fg-muted"
149
+ })
150
+ ]
151
+ }), /* @__PURE__ */ i("input", {
152
+ ...v,
153
+ type: "tel",
154
+ inputMode: "tel",
155
+ autoComplete: "tel-national",
156
+ placeholder: p,
157
+ value: l.number,
158
+ onFocus: () => b(!0),
159
+ onBlur: () => b(!1),
160
+ onChange: (e) => u({
161
+ ...l,
162
+ number: e.target.value.replace(/[^\d]/g, "").slice(0, 15)
163
+ }),
164
+ className: "min-w-0 flex-1 border-0 bg-transparent px-3 font-[inherit] text-[length:inherit] text-fg tabular-nums outline-none placeholder:text-fg-muted/80"
165
+ })]
166
+ });
167
+ }
168
+ //#endregion
169
+ export { c as DEFAULT_COUNTRIES, u as PhoneInput, l as toE164 };
170
+
171
+ //# sourceMappingURL=phone-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone-input.js","names":["DEFAULT_COUNTRIES","toE164","c","countries","x","value","PhoneInput","rest","field","useFieldProps","focused","setFocused","useState","country","useMemo","cx","controlClasses","size","invalid","className","countryLabel","onChange","Glyph"],"sources":["../../src/phone-input/phone-input.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo, useState } from 'react';\nimport { cx } from '../lib/cx';\nimport { Glyph } from '../lib/glyphs';\nimport { useFieldProps } from '../input/input';\nimport { controlClasses, type ControlSize } from '../input/field-styles';\n\nexport interface Country {\n /** ISO 3166-1 alpha-2. */\n code: string;\n name: string;\n dial: string;\n}\n\n/** Kodffe's markets first (US, LATAM, Spain). Pass `countries` to change the list. */\nexport const DEFAULT_COUNTRIES: Country[] = [\n { code: 'US', name: 'United States', dial: '1' },\n { code: 'CA', name: 'Canada', dial: '1' },\n { code: 'MX', name: 'Mexico', dial: '52' },\n { code: 'EC', name: 'Ecuador', dial: '593' },\n { code: 'CO', name: 'Colombia', dial: '57' },\n { code: 'PE', name: 'Peru', dial: '51' },\n { code: 'CL', name: 'Chile', dial: '56' },\n { code: 'AR', name: 'Argentina', dial: '54' },\n { code: 'BR', name: 'Brazil', dial: '55' },\n { code: 'UY', name: 'Uruguay', dial: '598' },\n { code: 'PA', name: 'Panama', dial: '507' },\n { code: 'CR', name: 'Costa Rica', dial: '506' },\n { code: 'GT', name: 'Guatemala', dial: '502' },\n { code: 'DO', name: 'Dominican Republic', dial: '1' },\n { code: 'BO', name: 'Bolivia', dial: '591' },\n { code: 'PY', name: 'Paraguay', dial: '595' },\n { code: 'VE', name: 'Venezuela', dial: '58' },\n { code: 'ES', name: 'Spain', dial: '34' },\n { code: 'GB', name: 'United Kingdom', dial: '44' },\n];\n\nexport interface PhoneValue {\n country: string;\n /** National number, digits only. */\n number: string;\n}\n\nexport interface PhoneInputProps {\n value: PhoneValue;\n onChange: (value: PhoneValue) => void;\n countries?: Country[];\n size?: ControlSize;\n id?: string;\n disabled?: boolean;\n required?: boolean;\n invalid?: boolean;\n placeholder?: string;\n countryLabel?: string;\n className?: string;\n}\n\n/** E.164 string for APIs (Brevo, WhatsApp, Twilio): `+593991234567`. */\nexport const toE164 = (value: PhoneValue, countries: Country[] = DEFAULT_COUNTRIES) => {\n const c = countries.find((x) => x.code === value.country);\n return c && value.number ? `+${c.dial}${value.number.replace(/^0+/, '')}` : '';\n};\n\n/**\n * Country code + national number. The country is a native select (fast on every device); the\n * number keeps digits only and uses the phone keypad (`type=\"tel\"`). Validate length on submit.\n */\nexport function PhoneInput({\n value,\n onChange,\n countries = DEFAULT_COUNTRIES,\n size = 'md',\n placeholder,\n countryLabel = 'Country code',\n className,\n ...rest\n}: PhoneInputProps) {\n const { invalid, ...field } = useFieldProps(rest);\n const [focused, setFocused] = useState(false);\n const country = useMemo(\n () => countries.find((c) => c.code === value.country) ?? countries[0]!,\n [countries, value.country],\n );\n return (\n <div className={cx(controlClasses(size, invalid), 'flex items-stretch', focused && 'border-primary', className)}>\n <div className=\"relative flex shrink-0 items-center border-r border-border\">\n <select\n aria-label={countryLabel}\n value={country.code}\n disabled={field.disabled}\n onChange={(e) => onChange({ ...value, country: e.target.value })}\n className=\"h-full w-[6.75rem] cursor-pointer appearance-none rounded-l-sm border-0 bg-transparent py-0 pr-8 pl-3 font-[inherit] text-[length:inherit] font-medium text-transparent outline-none [&>option]:text-fg focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-focus\"\n >\n {countries.map((c) => (\n <option key={c.code} value={c.code}>\n {c.code} +{c.dial} — {c.name}\n </option>\n ))}\n </select>\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-y-0 left-3 flex items-center bg-bg pr-1 font-medium\"\n >\n {country.code} +{country.dial}\n </span>\n <Glyph name=\"chevron-down\" size={14} className=\"pointer-events-none absolute right-2.5 text-fg-muted\" />\n </div>\n <input\n {...field}\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel-national\"\n placeholder={placeholder}\n value={value.number}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onChange={(e) => onChange({ ...value, number: e.target.value.replace(/[^\\d]/g, '').slice(0, 15) })}\n className=\"min-w-0 flex-1 border-0 bg-transparent px-3 font-[inherit] text-[length:inherit] text-fg tabular-nums outline-none placeholder:text-fg-muted/80\"\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import * as RadixPopover from '@radix-ui/react-popover';
2
+ import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
3
+ /** Shared surface for floating panels (Popover, HoverCard). */
4
+ export declare const floatingSurface = "z-50 rounded-md border border-border bg-surface font-sans text-fg shadow-overlay focus:outline-none max-w-[calc(100vw-2rem)]";
5
+ export declare const Popover: import("react").FC<RadixPopover.PopoverProps>;
6
+ /** Element that toggles the popover. Use `asChild` with a Button. */
7
+ export declare const PopoverTrigger: import("react").ForwardRefExoticComponent<RadixPopover.PopoverTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
8
+ export declare const PopoverClose: import("react").ForwardRefExoticComponent<RadixPopover.PopoverCloseProps & import("react").RefAttributes<HTMLButtonElement>>;
9
+ /** Positions the popover against another element than the trigger. */
10
+ export declare const PopoverAnchor: import("react").ForwardRefExoticComponent<RadixPopover.PopoverAnchorProps & import("react").RefAttributes<HTMLDivElement>>;
11
+ export interface PopoverContentProps extends Omit<ComponentPropsWithoutRef<typeof RadixPopover.Content>, 'title'> {
12
+ /** Optional heading; it also names the popover for screen readers. */
13
+ title?: ReactNode;
14
+ /** Width preset; content wraps inside it. */
15
+ size?: 'sm' | 'md' | 'lg';
16
+ /** Show the pointer arrow. */
17
+ arrow?: boolean;
18
+ }
19
+ /**
20
+ * Non-modal floating panel anchored to a trigger: help text, quick settings, small forms, pickers.
21
+ * Opens on click (and tap), closes on Escape or outside click, returns focus to the trigger.
22
+ */
23
+ export declare function PopoverContent({ title, size, arrow, side, align, sideOffset, collisionPadding, className, children, ...rest }: PopoverContentProps): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
+ import { useId as r } from "react";
5
+ import * as i from "@radix-ui/react-popover";
6
+ //#region src/popover/popover.tsx
7
+ var a = "z-50 rounded-md border border-border bg-surface font-sans text-fg shadow-overlay focus:outline-none max-w-[calc(100vw-2rem)]", o = i.Root, s = i.Trigger, c = i.Close, l = i.Anchor, u = {
8
+ sm: "w-64",
9
+ md: "w-80",
10
+ lg: "w-[26rem]"
11
+ };
12
+ function d({ title: o, size: s = "md", arrow: c = !1, side: l = "bottom", align: d = "center", sideOffset: f = 8, collisionPadding: p = 16, className: m, children: h, ...g }) {
13
+ let _ = r();
14
+ return /* @__PURE__ */ t(i.Portal, { children: /* @__PURE__ */ n(i.Content, {
15
+ side: l,
16
+ align: d,
17
+ sideOffset: f,
18
+ collisionPadding: p,
19
+ "aria-labelledby": o ? _ : void 0,
20
+ className: e("kf-popover p-4 text-sm", a, u[s], m),
21
+ ...g,
22
+ children: [
23
+ o && /* @__PURE__ */ t("p", {
24
+ id: _,
25
+ className: "m-0 mb-1.5 font-display text-[15px] font-bold",
26
+ children: o
27
+ }),
28
+ h,
29
+ c && /* @__PURE__ */ t(i.Arrow, {
30
+ width: 14,
31
+ height: 7,
32
+ className: "fill-surface"
33
+ })
34
+ ]
35
+ }) });
36
+ }
37
+ //#endregion
38
+ export { o as Popover, l as PopoverAnchor, c as PopoverClose, d as PopoverContent, s as PopoverTrigger, a as floatingSurface };
39
+
40
+ //# sourceMappingURL=popover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.js","names":["RadixPopover","floatingSurface","Popover","PopoverTrigger","PopoverClose","PopoverAnchor","SIZES","PopoverContent","rest","titleId","useId","title","cx","size","className","children","arrow"],"sources":["../../src/popover/popover.tsx"],"sourcesContent":["'use client';\n\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport { useId, type ComponentPropsWithoutRef, type ReactNode } from 'react';\nimport { cx } from '../lib/cx';\n\n/** Shared surface for floating panels (Popover, HoverCard). */\nexport const floatingSurface =\n 'z-50 rounded-md border border-border bg-surface font-sans text-fg shadow-overlay focus:outline-none max-w-[calc(100vw-2rem)]';\n\nexport const Popover = RadixPopover.Root;\n/** Element that toggles the popover. Use `asChild` with a Button. */\nexport const PopoverTrigger = RadixPopover.Trigger;\nexport const PopoverClose = RadixPopover.Close;\n/** Positions the popover against another element than the trigger. */\nexport const PopoverAnchor = RadixPopover.Anchor;\n\nexport interface PopoverContentProps extends Omit<ComponentPropsWithoutRef<typeof RadixPopover.Content>, 'title'> {\n /** Optional heading; it also names the popover for screen readers. */\n title?: ReactNode;\n /** Width preset; content wraps inside it. */\n size?: 'sm' | 'md' | 'lg';\n /** Show the pointer arrow. */\n arrow?: boolean;\n}\n\nconst SIZES = { sm: 'w-64', md: 'w-80', lg: 'w-[26rem]' };\n\n/**\n * Non-modal floating panel anchored to a trigger: help text, quick settings, small forms, pickers.\n * Opens on click (and tap), closes on Escape or outside click, returns focus to the trigger.\n */\nexport function PopoverContent({\n title,\n size = 'md',\n arrow = false,\n side = 'bottom',\n align = 'center',\n sideOffset = 8,\n collisionPadding = 16,\n className,\n children,\n ...rest\n}: PopoverContentProps) {\n const titleId = useId();\n return (\n <RadixPopover.Portal>\n <RadixPopover.Content\n side={side}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n aria-labelledby={title ? titleId : undefined}\n className={cx('kf-popover p-4 text-sm', floatingSurface, SIZES[size], className)}\n {...rest}\n >\n {title && <p id={titleId} className=\"m-0 mb-1.5 font-display text-[15px] font-bold\">{title}</p>}\n {children}\n {arrow && <RadixPopover.Arrow width={14} height={7} className=\"fill-surface\" />}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n );\n}\n"],"mappings":";;;;;;AAOA,IAAaC,IACX,gIAEWC,IAAUF,EAAa,MAEvBG,IAAiBH,EAAa,SAC9BI,IAAeJ,EAAa,OAE5BK,IAAgBL,EAAa,QAWpCM,IAAQ;CAAE,IAAI;CAAQ,IAAI;CAAQ,IAAI;AAAY;AAMxD,SAAgBC,EAAe,EAC7B,UACA,UAAO,MACP,WAAQ,IACR,UAAO,UACP,WAAQ,UACR,gBAAa,GACb,sBAAmB,IACnB,cACA,aACA,GAAGC,KACmB;CACtB,IAAMC,IAAUC,EAAM;CACtB,OACE,kBAACV,EAAa,QAAd,EAAA,UACE,kBAACA,EAAa,SAAd;EACQ;EACC;EACK;EACM;EAClB,mBAAiBW,IAAQF,IAAU,KAAA;EACnC,WAAWG,EAAG,0BAA0BX,GAAiBK,EAAMO,IAAOC,CAAS;EAC/E,GAAIN;EAPN,UAAA;GASGG,KAAS,kBAAC,KAAD;IAAG,IAAIF;IAAS,WAAU;IAAiD,UAAAE;GAAS,CAAA;GAC7FI;GACAC,KAAS,kBAAChB,EAAa,OAAd;IAAoB,OAAO;IAAI,QAAQ;IAAG,WAAU;GAAgB,CAAA;EAC1D;CACH,CAAA,EAAA,CAAA;AAEzB"}
@@ -0,0 +1,21 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ export type ProgressTone = 'primary' | 'accent' | 'success' | 'warning' | 'danger';
3
+ export type ProgressSize = 'sm' | 'md' | 'lg';
4
+ export interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
+ /** Current value. Omit (or `null`) for an indeterminate bar when the duration is unknown. */
6
+ value?: number | null;
7
+ max?: number;
8
+ /** Visible label above the bar; also its accessible name. */
9
+ label?: ReactNode;
10
+ /** Accessible name when there is no visible label. */
11
+ 'aria-label'?: string;
12
+ /** Text for the value, e.g. "3 of 12 files". Defaults to a percentage. Set `false` to hide it. */
13
+ valueText?: string | false;
14
+ tone?: ProgressTone;
15
+ size?: ProgressSize;
16
+ }
17
+ /**
18
+ * Linear progress for tasks that take more than ~2 seconds: imports, uploads, onboarding, quotas.
19
+ * Use `Spinner` for short waits inside buttons, and `Skeleton` for loading content.
20
+ */
21
+ export declare function Progress({ value, max, label, valueText, tone, size, className, ...rest }: ProgressProps): import("react").JSX.Element;
@@ -0,0 +1,49 @@
1
+ import { cx as e } from "../lib/cx.js";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ import { useId as r } from "react";
4
+ //#region src/progress/progress.tsx
5
+ var i = {
6
+ primary: "bg-primary",
7
+ accent: "bg-accent",
8
+ success: "bg-success-icon",
9
+ warning: "bg-warning-icon",
10
+ danger: "bg-danger-icon"
11
+ }, a = {
12
+ sm: "h-1",
13
+ md: "h-2",
14
+ lg: "h-3"
15
+ };
16
+ function o({ value: o = null, max: s = 100, label: c, valueText: l, tone: u = "primary", size: d = "md", className: f, ...p }) {
17
+ let m = r(), h = typeof o == "number", g = h ? Math.min(s, Math.max(0, o)) : 0, _ = h ? Math.round(g / s * 100) : 0, v = l === !1 ? void 0 : l ?? (h ? `${_}%` : void 0);
18
+ return /* @__PURE__ */ n("div", {
19
+ className: e("grid gap-1.5 font-sans", f),
20
+ children: [(c || v) && /* @__PURE__ */ n("div", {
21
+ className: "flex items-baseline justify-between gap-3 text-sm",
22
+ children: [c && /* @__PURE__ */ t("span", {
23
+ id: m,
24
+ className: "font-medium text-fg",
25
+ children: c
26
+ }), v && /* @__PURE__ */ t("span", {
27
+ className: "ml-auto text-fg-muted tabular-nums",
28
+ children: v
29
+ })]
30
+ }), /* @__PURE__ */ t("div", {
31
+ role: "progressbar",
32
+ "aria-valuemin": 0,
33
+ "aria-valuemax": s,
34
+ "aria-valuenow": h ? g : void 0,
35
+ "aria-valuetext": h ? v : void 0,
36
+ "aria-labelledby": c ? m : void 0,
37
+ ...p,
38
+ className: e("relative w-full overflow-hidden rounded-full bg-surface-muted", a[d]),
39
+ children: h ? /* @__PURE__ */ t("div", {
40
+ className: e("h-full rounded-full transition-[width] duration-300 ease-standard motion-reduce:transition-none", i[u]),
41
+ style: { width: `${_}%` }
42
+ }) : /* @__PURE__ */ t("div", { className: e("kf-progress-indeterminate absolute inset-y-0 left-0 w-full origin-left rounded-full", i[u]) })
43
+ })]
44
+ });
45
+ }
46
+ //#endregion
47
+ export { o as Progress };
48
+
49
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","names":["TONES","SIZES","Progress","rest","labelId","useId","determinate","value","clamped","max","percent","text","valueText","cx","className","label","size","tone"],"sources":["../../src/progress/progress.tsx"],"sourcesContent":["import { useId, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../lib/cx';\n\nexport type ProgressTone = 'primary' | 'accent' | 'success' | 'warning' | 'danger';\nexport type ProgressSize = 'sm' | 'md' | 'lg';\n\nconst TONES: Record<ProgressTone, string> = {\n primary: 'bg-primary',\n accent: 'bg-accent',\n success: 'bg-success-icon',\n warning: 'bg-warning-icon',\n danger: 'bg-danger-icon',\n};\n\nconst SIZES: Record<ProgressSize, string> = { sm: 'h-1', md: 'h-2', lg: 'h-3' };\n\nexport interface ProgressProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Current value. Omit (or `null`) for an indeterminate bar when the duration is unknown. */\n value?: number | null;\n max?: number;\n /** Visible label above the bar; also its accessible name. */\n label?: ReactNode;\n /** Accessible name when there is no visible label. */\n 'aria-label'?: string;\n /** Text for the value, e.g. \"3 of 12 files\". Defaults to a percentage. Set `false` to hide it. */\n valueText?: string | false;\n tone?: ProgressTone;\n size?: ProgressSize;\n}\n\n/**\n * Linear progress for tasks that take more than ~2 seconds: imports, uploads, onboarding, quotas.\n * Use `Spinner` for short waits inside buttons, and `Skeleton` for loading content.\n */\nexport function Progress({ value = null, max = 100, label, valueText, tone = 'primary', size = 'md', className, ...rest }: ProgressProps) {\n const labelId = useId();\n const determinate = typeof value === 'number';\n const clamped = determinate ? Math.min(max, Math.max(0, value)) : 0;\n const percent = determinate ? Math.round((clamped / max) * 100) : 0;\n const text = valueText === false ? undefined : (valueText ?? (determinate ? `${percent}%` : undefined));\n\n return (\n <div className={cx('grid gap-1.5 font-sans', className)}>\n {(label || text) && (\n <div className=\"flex items-baseline justify-between gap-3 text-sm\">\n {label && (\n <span id={labelId} className=\"font-medium text-fg\">\n {label}\n </span>\n )}\n {text && <span className=\"ml-auto text-fg-muted tabular-nums\">{text}</span>}\n </div>\n )}\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={max}\n aria-valuenow={determinate ? clamped : undefined}\n aria-valuetext={determinate ? text : undefined}\n aria-labelledby={label ? labelId : undefined}\n {...rest}\n className={cx('relative w-full overflow-hidden rounded-full bg-surface-muted', SIZES[size])}\n >\n {determinate ? (\n <div\n className={cx('h-full rounded-full transition-[width] duration-300 ease-standard motion-reduce:transition-none', TONES[tone])}\n style={{ width: `${percent}%` }}\n />\n ) : (\n <div className={cx('kf-progress-indeterminate absolute inset-y-0 left-0 w-full origin-left rounded-full', TONES[tone])} />\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AAMA,IAAMA,IAAsC;CAC1C,SAAS;CACT,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;AACV,GAEMC,IAAsC;CAAE,IAAI;CAAO,IAAI;CAAO,IAAI;AAAM;AAoB9E,SAAgBC,EAAS,EAAE,WAAQ,MAAM,SAAM,KAAK,UAAO,cAAW,UAAO,WAAW,UAAO,MAAM,cAAW,GAAGC,KAAuB;CACxI,IAAMC,IAAUC,EAAM,GAChBC,IAAc,OAAOC,KAAU,UAC/BC,IAAUF,IAAc,KAAK,IAAIG,GAAK,KAAK,IAAI,GAAGF,CAAK,CAAC,IAAI,GAC5DG,IAAUJ,IAAc,KAAK,MAAOE,IAAUC,IAAO,GAAG,IAAI,GAC5DE,IAAOC,MAAc,KAAQ,KAAA,IAAaA,MAAcN,IAAc,GAAGI,EAAQ,KAAK,KAAA;CAE5F,OACE,kBAAC,OAAD;EAAK,WAAWG,EAAG,0BAA0BC,CAAS;EAAtD,UAAA,EACIC,KAASJ,MACT,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACGI,KACC,kBAAC,QAAD;IAAM,IAAIX;IAAS,WAAU;IAC1B,UAAAW;GACG,CAAA,GAEPJ,KAAQ,kBAAC,QAAD;IAAM,WAAU;IAAsC,UAAAA;GAAW,CAAA,CACvE;EAEP,CAAA,GAAA,kBAAC,OAAD;GACE,MAAK;GACL,iBAAe;GACf,iBAAeF;GACf,iBAAeH,IAAcE,IAAU,KAAA;GACvC,kBAAgBF,IAAcK,IAAO,KAAA;GACrC,mBAAiBI,IAAQX,IAAU,KAAA;GACnC,GAAID;GACJ,WAAWU,EAAG,iEAAiEZ,EAAMe,EAAK;GAEzF,UAAAV,IACC,kBAAC,OAAD;IACE,WAAWO,EAAG,mGAAmGb,EAAMiB,EAAK;IAC5H,OAAO,EAAE,OAAO,GAAGP,EAAQ,GAAG;GAC/B,CAAA,IAED,kBAAC,OAAD,EAAK,WAAWG,EAAG,uFAAuFb,EAAMiB,EAAK,EAAI,CAAA;EAExH,CAAA,CACF;;AAET"}
@@ -0,0 +1,32 @@
1
+ import { type IconName } from '../icon/icon';
2
+ export interface SegmentedOption {
3
+ value: string;
4
+ label: string;
5
+ icon?: IconName;
6
+ disabled?: boolean;
7
+ }
8
+ export interface SegmentedControlProps {
9
+ /** Two to five mutually exclusive options. */
10
+ options: SegmentedOption[];
11
+ value?: string;
12
+ defaultValue?: string;
13
+ onValueChange?: (value: string) => void;
14
+ /** Required unless `aria-labelledby` is set (e.g. the label of a `SettingsRow`). */
15
+ 'aria-label'?: string;
16
+ 'aria-labelledby'?: string;
17
+ 'aria-describedby'?: string;
18
+ name?: string;
19
+ disabled?: boolean;
20
+ /** `sm` 32 px, `md` 40 px. Touch screens get at least 44 px. */
21
+ size?: 'sm' | 'md';
22
+ /** `inverse` on a brand surface (white active option). */
23
+ tone?: 'default' | 'inverse';
24
+ /** Stretch options to fill the width. */
25
+ fullWidth?: boolean;
26
+ className?: string;
27
+ }
28
+ /**
29
+ * Pick one of 2–5 options in a single pill ("Informative / Blocking", a language). Applies immediately; a radio
30
+ * group underneath, so arrow keys move the choice. For views of a page use `Tabs`; for longer lists, `Select`.
31
+ */
32
+ export declare function SegmentedControl({ options, size, tone, fullWidth, className, ...rest }: SegmentedControlProps): import("react").JSX.Element;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Icon as t } from "../icon/icon.js";
4
+ import { SEGMENTED_ITEM as n, SEGMENTED_TRACK as r } from "../lib/segmented-styles.js";
5
+ import { selectOnArrow as i } from "../lib/select-on-arrow.js";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ import * as s from "@radix-ui/react-radio-group";
8
+ //#region src/segmented-control/segmented-control.tsx
9
+ function c({ options: c, size: l = "md", tone: u = "default", fullWidth: d, className: f, ...p }) {
10
+ return /* @__PURE__ */ a(s.Root, {
11
+ orientation: "horizontal",
12
+ onKeyDown: i,
13
+ className: e("font-sans", d ? "flex w-full" : "inline-flex w-fit max-w-full overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", r[u], f),
14
+ ...p,
15
+ children: c.map((r) => /* @__PURE__ */ o(s.Item, {
16
+ value: r.value,
17
+ disabled: r.disabled,
18
+ className: e("inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-xs border-0 bg-transparent px-3 text-sm font-semibold whitespace-nowrap transition-colors duration-150", "focus-visible:outline-3 focus-visible:outline-offset-1 disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11", l === "sm" ? "h-8" : "h-10", d && "flex-1", n[u]),
19
+ children: [r.icon && /* @__PURE__ */ a(t, {
20
+ name: r.icon,
21
+ size: 16
22
+ }), r.label]
23
+ }, r.value))
24
+ });
25
+ }
26
+ //#endregion
27
+ export { c as SegmentedControl };
28
+
29
+ //# sourceMappingURL=segmented-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmented-control.js","names":["RadixRadio","SegmentedControl","rest","selectOnArrow","cx","fullWidth","SEGMENTED_TRACK","tone","className","options","o","size","SEGMENTED_ITEM","Icon"],"sources":["../../src/segmented-control/segmented-control.tsx"],"sourcesContent":["'use client';\n\nimport * as RadixRadio from '@radix-ui/react-radio-group';\nimport { cx } from '../lib/cx';\nimport { SEGMENTED_ITEM, SEGMENTED_TRACK } from '../lib/segmented-styles';\nimport { Icon, type IconName } from '../icon/icon';\nimport { selectOnArrow } from '../lib/select-on-arrow';\n\nexport interface SegmentedOption {\n value: string;\n label: string;\n icon?: IconName;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps {\n /** Two to five mutually exclusive options. */\n options: SegmentedOption[];\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n /** Required unless `aria-labelledby` is set (e.g. the label of a `SettingsRow`). */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n name?: string;\n disabled?: boolean;\n /** `sm` 32 px, `md` 40 px. Touch screens get at least 44 px. */\n size?: 'sm' | 'md';\n /** `inverse` on a brand surface (white active option). */\n tone?: 'default' | 'inverse';\n /** Stretch options to fill the width. */\n fullWidth?: boolean;\n className?: string;\n}\n\n\n/**\n * Pick one of 2–5 options in a single pill (\"Informative / Blocking\", a language). Applies immediately; a radio\n * group underneath, so arrow keys move the choice. For views of a page use `Tabs`; for longer lists, `Select`.\n */\nexport function SegmentedControl({\n options,\n size = 'md',\n tone = 'default',\n fullWidth,\n className,\n ...rest\n}: SegmentedControlProps) {\n return (\n <RadixRadio.Root\n orientation=\"horizontal\"\n onKeyDown={selectOnArrow}\n className={cx(\n 'font-sans',\n // Never wider than its container: scrolls sideways on narrow screens, like Tabs.\n fullWidth ? 'flex w-full' : 'inline-flex w-fit max-w-full overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',\n SEGMENTED_TRACK[tone],\n className,\n )}\n {...rest}\n >\n {options.map((o) => (\n <RadixRadio.Item\n key={o.value}\n value={o.value}\n disabled={o.disabled}\n className={cx(\n 'inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-xs border-0 bg-transparent px-3 text-sm font-semibold whitespace-nowrap transition-colors duration-150',\n 'focus-visible:outline-3 focus-visible:outline-offset-1 disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:min-h-11',\n size === 'sm' ? 'h-8' : 'h-10',\n fullWidth && 'flex-1',\n SEGMENTED_ITEM[tone],\n )}\n >\n {o.icon && <Icon name={o.icon} size={16} />}\n {o.label}\n </RadixRadio.Item>\n ))}\n </RadixRadio.Root>\n );\n}\n"],"mappings":";;;;;;;;AAyCA,SAAgBC,EAAiB,EAC/B,YACA,UAAO,MACP,UAAO,WACP,cACA,cACA,GAAGC,KACqB;CACxB,OACE,kBAACF,EAAW,MAAZ;EACE,aAAY;EACZ,WAAWG;EACX,WAAWC,EACT,aAEAC,IAAY,gBAAgB,qGAC5BC,EAAgBC,IAChBC,CACF;EACA,GAAIN;EAEH,UAAAO,EAAQ,KAAK,MACZ,kBAACT,EAAW,MAAZ;GAEE,OAAOU,EAAE;GACT,UAAUA,EAAE;GACZ,WAAWN,EACT,0LACA,kIACAO,MAAS,OAAO,QAAQ,QACxBN,KAAa,UACbO,EAAeL,EACjB;GAVF,UAAA,CAYGG,EAAE,QAAQ,kBAACG,GAAD;IAAM,MAAMH,EAAE;IAAM,MAAM;GAAK,CAAA,GACzCA,EAAE,KACY;EAbV,GAAAA,EAAE,KAaQ,CAClB;CACc,CAAA;AAErB"}
@@ -0,0 +1,48 @@
1
+ import type { SelectHTMLAttributes } from 'react';
2
+ import { type IconName } from '../icon/icon';
3
+ import { type ControlSize } from '../input/field-styles';
4
+ export interface SelectOption {
5
+ value: string;
6
+ label: string;
7
+ icon?: IconName;
8
+ /** Secondary text after the label, also in the closed select ("Guayaquil" + "UTC−05:00"). */
9
+ hint?: string;
10
+ disabled?: boolean;
11
+ }
12
+ export interface SelectGroup {
13
+ label: string;
14
+ options: SelectOption[];
15
+ }
16
+ export interface SelectProps {
17
+ options: (SelectOption | SelectGroup)[];
18
+ value?: string;
19
+ defaultValue?: string;
20
+ onValueChange?: (value: string) => void;
21
+ placeholder?: string;
22
+ size?: ControlSize;
23
+ /** Maximum width: `full` (default, fills the field), `xs` (currency, 7rem), `sm` (language, 11rem), `md` (18rem). */
24
+ width?: SelectWidth;
25
+ name?: string;
26
+ id?: string;
27
+ disabled?: boolean;
28
+ required?: boolean;
29
+ invalid?: boolean;
30
+ 'aria-label'?: string;
31
+ /** `auto` (default): native `<select>` on touch screens, custom listbox with a pointer. */
32
+ native?: 'auto' | boolean;
33
+ className?: string;
34
+ }
35
+ export type SelectWidth = 'full' | 'xs' | 'sm' | 'md';
36
+ /**
37
+ * Pick one option from a short list (up to ~15). Uses the OS picker on touch screens and a styled
38
+ * listbox (Radix Select) with a mouse. For long or searchable lists use `Combobox`.
39
+ */
40
+ export declare function Select({ options, value, defaultValue, onValueChange, placeholder, size, width, native, className, ...props }: SelectProps): import("react").JSX.Element;
41
+ export interface NativeSelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
42
+ size?: ControlSize;
43
+ invalid?: boolean;
44
+ /** Classes for the wrapper (e.g. a `max-w-*` to narrow it). */
45
+ wrapperClassName?: string;
46
+ }
47
+ /** Styled native `<select>`: best on mobile and for very simple forms. */
48
+ export declare function NativeSelect({ size, invalid: invalidProp, wrapperClassName, className, children, ...rest }: NativeSelectProps): import("react").JSX.Element;
@@ -0,0 +1,136 @@
1
+ "use client";
2
+ import { cx as e } from "../lib/cx.js";
3
+ import { Icon as t } from "../icon/icon.js";
4
+ import { useMediaQuery as n } from "../lib/use-media-query.js";
5
+ import { Glyph as r } from "../lib/glyphs.js";
6
+ import { controlClasses as i } from "../input/field-styles.js";
7
+ import { useFieldProps as a } from "../input/input.js";
8
+ import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
9
+ import * as l from "@radix-ui/react-select";
10
+ //#region src/select/select.tsx
11
+ var u = {
12
+ full: "",
13
+ xs: "max-w-28",
14
+ sm: "max-w-44",
15
+ md: "max-w-72"
16
+ }, d = (e) => "options" in e;
17
+ function f({ options: f, value: m, defaultValue: h, onValueChange: g, placeholder: _ = "Select…", size: v = "md", width: y = "full", native: b = "auto", className: x, ...S }) {
18
+ let C = n("(pointer: coarse)", !1), { invalid: w, ...T } = a(S), E = b === !0 || b === "auto" && C, D = f.flatMap((e) => d(e) ? e.options : [e]);
19
+ if (E) return /* @__PURE__ */ c(p, {
20
+ ...T,
21
+ name: S.name,
22
+ "aria-label": S["aria-label"],
23
+ value: m,
24
+ defaultValue: m === void 0 ? h ?? "" : void 0,
25
+ onChange: (e) => g?.(e.target.value),
26
+ size: v,
27
+ invalid: w,
28
+ wrapperClassName: u[y],
29
+ className: x,
30
+ children: [/* @__PURE__ */ s("option", {
31
+ value: "",
32
+ disabled: !0,
33
+ children: _
34
+ }), f.map((e) => d(e) ? /* @__PURE__ */ s("optgroup", {
35
+ label: e.label,
36
+ children: e.options.map((e) => /* @__PURE__ */ s("option", {
37
+ value: e.value,
38
+ disabled: e.disabled,
39
+ children: e.hint ? `${e.label} ${e.hint}` : e.label
40
+ }, e.value))
41
+ }, e.label) : /* @__PURE__ */ s("option", {
42
+ value: e.value,
43
+ disabled: e.disabled,
44
+ children: e.hint ? `${e.label} ${e.hint}` : e.label
45
+ }, e.value))]
46
+ });
47
+ let O = (e) => /* @__PURE__ */ c(l.Item, {
48
+ value: e.value,
49
+ disabled: e.disabled,
50
+ className: "relative flex min-h-9 cursor-pointer items-center gap-2.5 rounded-sm py-1.5 pr-8 pl-2.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-surface-muted data-[state=checked]:font-semibold",
51
+ children: [
52
+ e.icon && /* @__PURE__ */ s(t, {
53
+ name: e.icon,
54
+ size: 20
55
+ }),
56
+ /* @__PURE__ */ c(l.ItemText, { children: [e.label, e.hint && /* @__PURE__ */ c(o, { children: [" ", /* @__PURE__ */ s("span", {
57
+ className: "ml-0.5 font-normal text-fg-muted",
58
+ children: e.hint
59
+ })] })] }),
60
+ /* @__PURE__ */ s(l.ItemIndicator, {
61
+ className: "absolute right-2.5 inline-flex text-link",
62
+ children: /* @__PURE__ */ s(r, {
63
+ name: "check",
64
+ size: 16
65
+ })
66
+ })
67
+ ]
68
+ }, e.value);
69
+ return /* @__PURE__ */ c(l.Root, {
70
+ value: m,
71
+ defaultValue: h,
72
+ onValueChange: g,
73
+ name: S.name,
74
+ disabled: T.disabled,
75
+ required: T.required,
76
+ children: [/* @__PURE__ */ c(l.Trigger, {
77
+ id: T.id,
78
+ "aria-label": S["aria-label"],
79
+ "aria-invalid": T["aria-invalid"],
80
+ "aria-describedby": T["aria-describedby"],
81
+ className: e(i(v, w), "flex cursor-pointer items-center justify-between gap-2 px-3 text-left outline-none data-[placeholder]:text-fg-muted disabled:cursor-not-allowed disabled:bg-surface-muted", "focus:border-primary focus:shadow-[0_0_0_3px_color-mix(in_oklab,var(--color-focus),transparent_70%)]", u[y], x),
82
+ children: [/* @__PURE__ */ c("span", {
83
+ className: "flex min-w-0 items-center gap-2 truncate",
84
+ children: [(() => {
85
+ let e = D.find((e) => e.value === m);
86
+ return e?.icon ? /* @__PURE__ */ s(t, {
87
+ name: e.icon,
88
+ size: 20
89
+ }) : null;
90
+ })(), /* @__PURE__ */ s(l.Value, { placeholder: _ })]
91
+ }), /* @__PURE__ */ s(l.Icon, {
92
+ className: "shrink-0 text-fg-muted",
93
+ children: /* @__PURE__ */ s(r, {
94
+ name: "chevron-down",
95
+ size: 16
96
+ })
97
+ })]
98
+ }), /* @__PURE__ */ s(l.Portal, { children: /* @__PURE__ */ s(l.Content, {
99
+ position: "popper",
100
+ sideOffset: 6,
101
+ collisionPadding: 16,
102
+ className: "kf-menu z-50 max-h-[min(22rem,var(--radix-select-content-available-height))] min-w-[max(var(--radix-select-trigger-width),10rem)] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border border-border bg-surface font-sans text-fg shadow-overlay",
103
+ children: /* @__PURE__ */ s(l.Viewport, {
104
+ className: "p-1",
105
+ children: f.map((e) => d(e) ? /* @__PURE__ */ c(l.Group, { children: [/* @__PURE__ */ s(l.Label, {
106
+ className: "px-2.5 pt-2 pb-1 text-xs font-semibold tracking-wide text-fg-muted uppercase",
107
+ children: e.label
108
+ }), e.options.map(O)] }, e.label) : O(e))
109
+ })
110
+ }) })]
111
+ });
112
+ }
113
+ function p({ size: t = "md", invalid: n, wrapperClassName: o, className: l, children: u, ...d }) {
114
+ let { invalid: f, ...p } = a({
115
+ ...d,
116
+ invalid: n
117
+ });
118
+ return /* @__PURE__ */ c("div", {
119
+ className: e("relative", o),
120
+ children: [/* @__PURE__ */ s("select", {
121
+ ...d,
122
+ ...p,
123
+ "aria-invalid": f || d["aria-invalid"] || void 0,
124
+ className: e(i(t, f), "cursor-pointer appearance-none pr-10 pl-3 outline-none focus:border-primary focus:shadow-[0_0_0_3px_color-mix(in_oklab,var(--color-focus),transparent_70%)] disabled:cursor-not-allowed", l),
125
+ children: u
126
+ }), /* @__PURE__ */ s(r, {
127
+ name: "chevron-down",
128
+ size: 16,
129
+ className: "pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-fg-muted"
130
+ })]
131
+ });
132
+ }
133
+ //#endregion
134
+ export { p as NativeSelect, f as Select };
135
+
136
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","names":["_Fragment","RadixSelect","WIDTHS","isGroup","o","Select","props","coarse","useMediaQuery","field","useFieldProps","useNative","native","flat","options","NativeSelect","value","defaultValue","onValueChange","width","placeholder","opt","item","Icon","Fragment","Glyph","cx","controlClasses","size","invalid","className","selected","invalidProp","rest","wrapperClassName"],"sources":["../../src/select/select.tsx"],"sourcesContent":["'use client';\n\nimport * as RadixSelect from '@radix-ui/react-select';\nimport type { SelectHTMLAttributes } from 'react';\nimport { cx } from '../lib/cx';\nimport { Glyph } from '../lib/glyphs';\nimport { Icon, type IconName } from '../icon/icon';\nimport { useMediaQuery } from '../lib/use-media-query';\nimport { useFieldProps } from '../input/input';\nimport { controlClasses, type ControlSize } from '../input/field-styles';\n\nexport interface SelectOption {\n value: string;\n label: string;\n icon?: IconName;\n /** Secondary text after the label, also in the closed select (\"Guayaquil\" + \"UTC−05:00\"). */\n hint?: string;\n disabled?: boolean;\n}\n\nexport interface SelectGroup {\n label: string;\n options: SelectOption[];\n}\n\nexport interface SelectProps {\n options: (SelectOption | SelectGroup)[];\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n placeholder?: string;\n size?: ControlSize;\n /** Maximum width: `full` (default, fills the field), `xs` (currency, 7rem), `sm` (language, 11rem), `md` (18rem). */\n width?: SelectWidth;\n name?: string;\n id?: string;\n disabled?: boolean;\n required?: boolean;\n invalid?: boolean;\n 'aria-label'?: string;\n /** `auto` (default): native `<select>` on touch screens, custom listbox with a pointer. */\n native?: 'auto' | boolean;\n className?: string;\n}\n\nexport type SelectWidth = 'full' | 'xs' | 'sm' | 'md';\n// Caps the width instead of setting it, so it never conflicts with the control's `w-full`.\nconst WIDTHS: Record<SelectWidth, string> = { full: '', xs: 'max-w-28', sm: 'max-w-44', md: 'max-w-72' };\n\nconst isGroup = (o: SelectOption | SelectGroup): o is SelectGroup => 'options' in o;\n\n/**\n * Pick one option from a short list (up to ~15). Uses the OS picker on touch screens and a styled\n * listbox (Radix Select) with a mouse. For long or searchable lists use `Combobox`.\n */\nexport function Select({\n options,\n value,\n defaultValue,\n onValueChange,\n placeholder = 'Select…',\n size = 'md',\n width = 'full',\n native = 'auto',\n className,\n ...props\n}: SelectProps) {\n const coarse = useMediaQuery('(pointer: coarse)', false);\n const { invalid, ...field } = useFieldProps(props);\n const useNative = native === true || (native === 'auto' && coarse);\n const flat = options.flatMap((o) => (isGroup(o) ? o.options : [o]));\n\n if (useNative) {\n return (\n <NativeSelect\n {...field}\n name={props.name}\n aria-label={props['aria-label']}\n value={value}\n defaultValue={value === undefined ? (defaultValue ?? '') : undefined}\n onChange={(e) => onValueChange?.(e.target.value)}\n size={size}\n invalid={invalid}\n wrapperClassName={WIDTHS[width]}\n className={className}\n >\n <option value=\"\" disabled>\n {placeholder}\n </option>\n {options.map((o) =>\n isGroup(o) ? (\n <optgroup key={o.label} label={o.label}>\n {o.options.map((opt) => (\n <option key={opt.value} value={opt.value} disabled={opt.disabled}>\n {opt.hint ? `${opt.label} ${opt.hint}` : opt.label}\n </option>\n ))}\n </optgroup>\n ) : (\n <option key={o.value} value={o.value} disabled={o.disabled}>\n {o.hint ? `${o.label} ${o.hint}` : o.label}\n </option>\n ),\n )}\n </NativeSelect>\n );\n }\n\n const item = (opt: SelectOption) => (\n <RadixSelect.Item\n key={opt.value}\n value={opt.value}\n disabled={opt.disabled}\n className=\"relative flex min-h-9 cursor-pointer items-center gap-2.5 rounded-sm py-1.5 pr-8 pl-2.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-45 data-[highlighted]:bg-surface-muted data-[state=checked]:font-semibold\"\n >\n {opt.icon && <Icon name={opt.icon} size={20} />}\n <RadixSelect.ItemText>\n {opt.label}\n {opt.hint && (\n <>\n {' '}\n <span className=\"ml-0.5 font-normal text-fg-muted\">{opt.hint}</span>\n </>\n )}\n </RadixSelect.ItemText>\n <RadixSelect.ItemIndicator className=\"absolute right-2.5 inline-flex text-link\">\n <Glyph name=\"check\" size={16} />\n </RadixSelect.ItemIndicator>\n </RadixSelect.Item>\n );\n\n return (\n <RadixSelect.Root\n value={value}\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n name={props.name}\n disabled={field.disabled}\n required={field.required}\n >\n <RadixSelect.Trigger\n id={field.id}\n aria-label={props['aria-label']}\n aria-invalid={field['aria-invalid']}\n aria-describedby={field['aria-describedby']}\n className={cx(\n controlClasses(size, invalid),\n 'flex cursor-pointer items-center justify-between gap-2 px-3 text-left outline-none data-[placeholder]:text-fg-muted disabled:cursor-not-allowed disabled:bg-surface-muted',\n 'focus:border-primary focus:shadow-[0_0_0_3px_color-mix(in_oklab,var(--color-focus),transparent_70%)]',\n WIDTHS[width],\n className,\n )}\n >\n <span className=\"flex min-w-0 items-center gap-2 truncate\">\n {(() => {\n const selected = flat.find((o) => o.value === value);\n return selected?.icon ? <Icon name={selected.icon} size={20} /> : null;\n })()}\n <RadixSelect.Value placeholder={placeholder} />\n </span>\n <RadixSelect.Icon className=\"shrink-0 text-fg-muted\">\n <Glyph name=\"chevron-down\" size={16} />\n </RadixSelect.Icon>\n </RadixSelect.Trigger>\n <RadixSelect.Portal>\n <RadixSelect.Content\n position=\"popper\"\n sideOffset={6}\n collisionPadding={16}\n className=\"kf-menu z-50 max-h-[min(22rem,var(--radix-select-content-available-height))] min-w-[max(var(--radix-select-trigger-width),10rem)] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border border-border bg-surface font-sans text-fg shadow-overlay\"\n >\n <RadixSelect.Viewport className=\"p-1\">\n {options.map((o) =>\n isGroup(o) ? (\n <RadixSelect.Group key={o.label}>\n <RadixSelect.Label className=\"px-2.5 pt-2 pb-1 text-xs font-semibold tracking-wide text-fg-muted uppercase\">\n {o.label}\n </RadixSelect.Label>\n {o.options.map(item)}\n </RadixSelect.Group>\n ) : (\n item(o)\n ),\n )}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n );\n}\n\nexport interface NativeSelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {\n size?: ControlSize;\n invalid?: boolean;\n /** Classes for the wrapper (e.g. a `max-w-*` to narrow it). */\n wrapperClassName?: string;\n}\n\n/** Styled native `<select>`: best on mobile and for very simple forms. */\nexport function NativeSelect({\n size = 'md',\n invalid: invalidProp,\n wrapperClassName,\n className,\n children,\n ...rest\n}: NativeSelectProps) {\n // Reads the surrounding FormField (label, hint, error), like Input and Select.\n const { invalid, ...field } = useFieldProps({ ...rest, invalid: invalidProp });\n return (\n <div className={cx('relative', wrapperClassName)}>\n <select\n {...rest}\n {...field}\n aria-invalid={invalid || rest['aria-invalid'] || undefined}\n className={cx(\n controlClasses(size, invalid),\n 'cursor-pointer appearance-none pr-10 pl-3 outline-none focus:border-primary focus:shadow-[0_0_0_3px_color-mix(in_oklab,var(--color-focus),transparent_70%)] disabled:cursor-not-allowed',\n className,\n )}\n >\n {children}\n </select>\n <Glyph\n name=\"chevron-down\"\n size={16}\n className=\"pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-fg-muted\"\n />\n </div>\n );\n}\n"],"mappings":"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"}