@rojaostudio/ds 1.0.2 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/README.md +75 -13
  2. package/dist/compat/generate.d.ts +0 -1
  3. package/dist/components/accordion.d.ts +30 -20
  4. package/dist/components/accordion.js +31 -93
  5. package/dist/components/action-bar.d.ts +24 -0
  6. package/dist/components/action-bar.js +55 -0
  7. package/dist/components/alert-dialog.d.ts +31 -0
  8. package/dist/components/alert-dialog.js +43 -0
  9. package/dist/components/alert.d.ts +31 -19
  10. package/dist/components/alert.js +67 -65
  11. package/dist/components/attachment.d.ts +37 -0
  12. package/dist/components/attachment.js +76 -0
  13. package/dist/components/avatar.d.ts +43 -36
  14. package/dist/components/avatar.js +59 -90
  15. package/dist/components/badge.d.ts +30 -41
  16. package/dist/components/badge.js +13 -110
  17. package/dist/components/banner.d.ts +27 -0
  18. package/dist/components/banner.js +66 -0
  19. package/dist/components/benefits.d.ts +30 -0
  20. package/dist/components/benefits.js +32 -0
  21. package/dist/components/breadcrumb.d.ts +25 -18
  22. package/dist/components/breadcrumb.js +38 -56
  23. package/dist/components/browser.d.ts +18 -0
  24. package/dist/components/browser.js +32 -0
  25. package/dist/components/bubble.d.ts +29 -0
  26. package/dist/components/bubble.js +33 -0
  27. package/dist/components/button-group.d.ts +19 -0
  28. package/dist/components/button-group.js +20 -0
  29. package/dist/components/button.d.ts +47 -20
  30. package/dist/components/button.js +45 -108
  31. package/dist/components/calendar.d.ts +29 -0
  32. package/dist/components/calendar.js +149 -0
  33. package/dist/components/card.d.ts +47 -19
  34. package/dist/components/card.js +31 -46
  35. package/dist/components/carousel.d.ts +28 -0
  36. package/dist/components/carousel.js +130 -0
  37. package/dist/components/chart.d.ts +49 -0
  38. package/dist/components/chart.js +258 -0
  39. package/dist/components/checkbox-group.d.ts +16 -0
  40. package/dist/components/checkbox-group.js +13 -0
  41. package/dist/components/checkbox.d.ts +25 -10
  42. package/dist/components/checkbox.js +87 -81
  43. package/dist/components/chip-input.d.ts +46 -20
  44. package/dist/components/chip-input.js +172 -176
  45. package/dist/components/chip.d.ts +28 -0
  46. package/dist/components/chip.js +73 -0
  47. package/dist/components/choice-card.d.ts +10 -13
  48. package/dist/components/choice-card.js +11 -62
  49. package/dist/components/choice-carousel.d.ts +9 -0
  50. package/dist/components/choice-carousel.js +28 -44
  51. package/dist/components/choice-preview-card.d.ts +10 -20
  52. package/dist/components/choice-preview-card.js +12 -40
  53. package/dist/components/color-input.d.ts +36 -11
  54. package/dist/components/color-input.js +131 -59
  55. package/dist/components/combobox.d.ts +60 -57
  56. package/dist/components/combobox.js +210 -213
  57. package/dist/components/command.d.ts +58 -0
  58. package/dist/components/command.js +177 -0
  59. package/dist/components/contact.d.ts +23 -0
  60. package/dist/components/contact.js +32 -0
  61. package/dist/components/context-menu.d.ts +34 -26
  62. package/dist/components/context-menu.js +41 -68
  63. package/dist/components/copy-field.d.ts +10 -5
  64. package/dist/components/copy-field.js +24 -29
  65. package/dist/components/currency-input.d.ts +25 -11
  66. package/dist/components/currency-input.js +29 -65
  67. package/dist/components/danger-zone.d.ts +10 -1
  68. package/dist/components/danger-zone.js +14 -18
  69. package/dist/components/data-table-header.d.ts +13 -2
  70. package/dist/components/data-table-header.js +114 -190
  71. package/dist/components/date-picker.d.ts +31 -32
  72. package/dist/components/date-picker.js +119 -254
  73. package/dist/components/delta.d.ts +26 -0
  74. package/dist/components/delta.js +24 -0
  75. package/dist/components/dialog.d.ts +21 -0
  76. package/dist/components/dialog.js +16 -0
  77. package/dist/components/drawer.d.ts +15 -23
  78. package/dist/components/drawer.js +57 -89
  79. package/dist/components/dropdown-menu.d.ts +63 -0
  80. package/dist/components/dropdown-menu.js +62 -0
  81. package/dist/components/dropzone.d.ts +10 -4
  82. package/dist/components/dropzone.js +30 -58
  83. package/dist/components/empty.d.ts +29 -0
  84. package/dist/components/empty.js +42 -0
  85. package/dist/components/fab.d.ts +29 -6
  86. package/dist/components/fab.js +51 -51
  87. package/dist/components/faq.d.ts +21 -0
  88. package/dist/components/faq.js +24 -0
  89. package/dist/components/file-input.d.ts +56 -0
  90. package/dist/components/file-input.js +244 -0
  91. package/dist/components/filter-chip.d.ts +34 -47
  92. package/dist/components/filter-chip.js +61 -61
  93. package/dist/components/floating-stepper.d.ts +7 -18
  94. package/dist/components/floating-stepper.js +27 -55
  95. package/dist/components/footer.d.ts +36 -0
  96. package/dist/components/footer.js +38 -0
  97. package/dist/components/form-actions.d.ts +28 -0
  98. package/dist/components/form-actions.js +24 -0
  99. package/dist/components/google-account-chooser.d.ts +25 -0
  100. package/dist/components/google-account-chooser.js +44 -0
  101. package/dist/components/google-button.d.ts +26 -0
  102. package/dist/components/google-button.js +38 -0
  103. package/dist/components/google-consent.d.ts +23 -0
  104. package/dist/components/google-consent.js +28 -0
  105. package/dist/components/google-sign-in.d.ts +26 -0
  106. package/dist/components/google-sign-in.js +36 -0
  107. package/dist/components/hover-card.d.ts +30 -0
  108. package/dist/components/hover-card.js +55 -0
  109. package/dist/components/icon-button.d.ts +41 -11
  110. package/dist/components/icon-button.js +44 -64
  111. package/dist/components/image-crop-modal.d.ts +3 -3
  112. package/dist/components/image-crop-modal.js +32 -39
  113. package/dist/components/image-upload.d.ts +21 -29
  114. package/dist/components/image-upload.js +55 -259
  115. package/dist/components/index.d.ts +105 -49
  116. package/dist/components/index.js +190 -68
  117. package/dist/components/input-otp.d.ts +35 -0
  118. package/dist/components/input-otp.js +119 -0
  119. package/dist/components/input.d.ts +23 -17
  120. package/dist/components/input.js +104 -137
  121. package/dist/components/insight-card.d.ts +25 -9
  122. package/dist/components/insight-card.js +42 -27
  123. package/dist/components/internal/announce.d.ts +3 -0
  124. package/dist/components/internal/announce.js +20 -0
  125. package/dist/components/internal/block.d.ts +15 -0
  126. package/dist/components/internal/block.js +14 -0
  127. package/dist/components/internal/button.d.ts +23 -0
  128. package/dist/components/internal/button.js +30 -0
  129. package/dist/components/internal/choice-card.d.ts +52 -0
  130. package/dist/components/internal/choice-card.js +117 -0
  131. package/dist/components/internal/choice.d.ts +25 -0
  132. package/dist/components/internal/choice.js +44 -0
  133. package/dist/components/internal/dates.d.ts +17 -0
  134. package/dist/components/internal/dates.js +59 -0
  135. package/dist/components/internal/field.d.ts +66 -0
  136. package/dist/components/internal/field.js +105 -0
  137. package/dist/components/internal/fieldset.d.ts +25 -0
  138. package/dist/components/internal/fieldset.js +56 -0
  139. package/dist/components/internal/focus-after.d.ts +3 -0
  140. package/dist/components/internal/focus-after.js +13 -0
  141. package/dist/components/internal/google.d.ts +47 -0
  142. package/dist/components/internal/google.js +73 -0
  143. package/dist/components/internal/icons.d.ts +108 -0
  144. package/dist/components/internal/icons.js +316 -0
  145. package/dist/components/internal/menu.d.ts +16 -0
  146. package/dist/components/internal/menu.js +14 -0
  147. package/dist/components/internal/modal.d.ts +50 -0
  148. package/dist/components/internal/modal.js +85 -0
  149. package/dist/components/internal/option-content.d.ts +10 -0
  150. package/dist/components/internal/option-content.js +13 -0
  151. package/dist/components/internal/radio-context.d.ts +16 -0
  152. package/dist/components/internal/radio-context.js +6 -0
  153. package/dist/components/internal/toggle.d.ts +7 -0
  154. package/dist/components/internal/toggle.js +13 -0
  155. package/dist/components/internal/use-listbox.d.ts +56 -0
  156. package/dist/components/internal/use-listbox.js +69 -0
  157. package/dist/components/internal/whatsapp.d.ts +8 -0
  158. package/dist/components/internal/whatsapp.js +12 -0
  159. package/dist/components/item.d.ts +32 -0
  160. package/dist/components/item.js +35 -0
  161. package/dist/components/kbd.d.ts +17 -0
  162. package/dist/components/kbd.js +18 -0
  163. package/dist/components/listbox.d.ts +34 -0
  164. package/dist/components/listbox.js +114 -0
  165. package/dist/components/marker.d.ts +24 -0
  166. package/dist/components/marker.js +28 -0
  167. package/dist/components/media-tile.d.ts +17 -14
  168. package/dist/components/media-tile.js +19 -27
  169. package/dist/components/message-scroller.d.ts +20 -0
  170. package/dist/components/message-scroller.js +108 -0
  171. package/dist/components/message.d.ts +33 -0
  172. package/dist/components/message.js +23 -0
  173. package/dist/components/navigation-menu.d.ts +42 -0
  174. package/dist/components/navigation-menu.js +30 -0
  175. package/dist/components/newsletter.d.ts +27 -0
  176. package/dist/components/newsletter.js +75 -0
  177. package/dist/components/number-input.d.ts +60 -0
  178. package/dist/components/number-input.js +234 -0
  179. package/dist/components/option-tile.d.ts +20 -19
  180. package/dist/components/option-tile.js +52 -137
  181. package/dist/components/page-header.d.ts +31 -0
  182. package/dist/components/page-header.js +25 -0
  183. package/dist/components/page-shell.d.ts +11 -1
  184. package/dist/components/page-shell.js +8 -34
  185. package/dist/components/page-skeleton.d.ts +15 -21
  186. package/dist/components/page-skeleton.js +28 -25
  187. package/dist/components/pagination.d.ts +32 -22
  188. package/dist/components/pagination.js +78 -76
  189. package/dist/components/password-input.d.ts +26 -0
  190. package/dist/components/password-input.js +112 -0
  191. package/dist/components/phone-input.d.ts +12 -8
  192. package/dist/components/phone-input.js +75 -64
  193. package/dist/components/phone.d.ts +27 -0
  194. package/dist/components/phone.js +35 -0
  195. package/dist/components/popover.d.ts +25 -36
  196. package/dist/components/popover.js +30 -131
  197. package/dist/components/pricing-card.d.ts +9 -25
  198. package/dist/components/pricing-card.js +9 -40
  199. package/dist/components/pricing.d.ts +48 -0
  200. package/dist/components/pricing.js +64 -0
  201. package/dist/components/progress.d.ts +30 -0
  202. package/dist/components/progress.js +57 -0
  203. package/dist/components/qr-display.d.ts +11 -6
  204. package/dist/components/qr-display.js +6 -22
  205. package/dist/components/questionnaire.d.ts +42 -0
  206. package/dist/components/questionnaire.js +107 -0
  207. package/dist/components/radio-group.d.ts +21 -0
  208. package/dist/components/radio-group.js +40 -0
  209. package/dist/components/radio.d.ts +15 -29
  210. package/dist/components/radio.js +45 -103
  211. package/dist/components/row-actions.d.ts +5 -0
  212. package/dist/components/row-actions.js +27 -34
  213. package/dist/components/saving-bar-context.d.ts +0 -5
  214. package/dist/components/saving-bar-context.js +16 -40
  215. package/dist/components/saving-bar.d.ts +26 -11
  216. package/dist/components/saving-bar.js +50 -65
  217. package/dist/components/section-card.d.ts +18 -4
  218. package/dist/components/section-card.js +29 -50
  219. package/dist/components/section-header.d.ts +8 -12
  220. package/dist/components/section-header.js +5 -10
  221. package/dist/components/select.d.ts +44 -16
  222. package/dist/components/select.js +83 -154
  223. package/dist/components/selectable-card.d.ts +11 -19
  224. package/dist/components/selectable-card.js +4 -28
  225. package/dist/components/separator.d.ts +20 -0
  226. package/dist/components/separator.js +19 -0
  227. package/dist/components/setting-row.d.ts +11 -15
  228. package/dist/components/setting-row.js +10 -23
  229. package/dist/components/settings-list.d.ts +10 -12
  230. package/dist/components/settings-list.js +7 -19
  231. package/dist/components/sheet.d.ts +21 -0
  232. package/dist/components/sheet.js +16 -0
  233. package/dist/components/sidebar.d.ts +79 -0
  234. package/dist/components/sidebar.js +111 -0
  235. package/dist/components/skeleton.d.ts +14 -20
  236. package/dist/components/skeleton.js +8 -37
  237. package/dist/components/slider.d.ts +21 -23
  238. package/dist/components/slider.js +59 -64
  239. package/dist/components/sparkline.d.ts +19 -0
  240. package/dist/components/sparkline.js +32 -0
  241. package/dist/components/spinner.d.ts +16 -8
  242. package/dist/components/spinner.js +34 -37
  243. package/dist/components/star-rating.d.ts +22 -0
  244. package/dist/components/star-rating.js +25 -0
  245. package/dist/components/stat.d.ts +33 -0
  246. package/dist/components/stat.js +29 -0
  247. package/dist/components/status.d.ts +27 -0
  248. package/dist/components/status.js +34 -0
  249. package/dist/components/step-progress.d.ts +13 -6
  250. package/dist/components/step-progress.js +18 -16
  251. package/dist/components/summary-bar.d.ts +20 -20
  252. package/dist/components/summary-bar.js +13 -55
  253. package/dist/components/switch.d.ts +20 -0
  254. package/dist/components/switch.js +46 -0
  255. package/dist/components/table.d.ts +56 -17
  256. package/dist/components/table.js +59 -58
  257. package/dist/components/tabs.d.ts +67 -0
  258. package/dist/components/tabs.js +56 -0
  259. package/dist/components/testimonial.d.ts +30 -0
  260. package/dist/components/testimonial.js +36 -0
  261. package/dist/components/textarea.d.ts +11 -16
  262. package/dist/components/textarea.js +55 -91
  263. package/dist/components/tile.d.ts +24 -0
  264. package/dist/components/tile.js +21 -0
  265. package/dist/components/time-picker.d.ts +40 -25
  266. package/dist/components/time-picker.js +185 -203
  267. package/dist/components/toast.d.ts +63 -0
  268. package/dist/components/toast.js +132 -0
  269. package/dist/components/toggle-card-compact.d.ts +15 -5
  270. package/dist/components/toggle-card-compact.js +19 -86
  271. package/dist/components/toggle-card.d.ts +11 -2
  272. package/dist/components/toggle-card.js +8 -77
  273. package/dist/components/toggle-group.d.ts +21 -59
  274. package/dist/components/toggle-group.js +31 -80
  275. package/dist/components/toggle.d.ts +19 -9
  276. package/dist/components/toggle.js +16 -61
  277. package/dist/components/tooltip.d.ts +25 -12
  278. package/dist/components/tooltip.js +15 -88
  279. package/dist/components/top-navigation.d.ts +33 -0
  280. package/dist/components/top-navigation.js +85 -0
  281. package/dist/components/typing-indicator.d.ts +6 -0
  282. package/dist/components/typing-indicator.js +3 -24
  283. package/dist/components/whatsapp-chat.d.ts +28 -0
  284. package/dist/components/whatsapp-chat.js +95 -0
  285. package/dist/components/whatsapp-message.d.ts +22 -0
  286. package/dist/components/whatsapp-message.js +34 -0
  287. package/dist/components/whatsapp-notification.d.ts +27 -0
  288. package/dist/components/whatsapp-notification.js +73 -0
  289. package/dist/components/whatsapp-template.d.ts +42 -0
  290. package/dist/components/whatsapp-template.js +69 -0
  291. package/dist/icons/index.d.ts +2 -0
  292. package/dist/icons/index.js +2 -0
  293. package/dist/icons/pix.d.ts +16 -0
  294. package/dist/targets/native/components/index.d.ts +0 -2
  295. package/dist/targets/native/components/index.js +0 -4
  296. package/dist/targets/native/preset.cjs +0 -1
  297. package/dist/targets/native/theme.css +58 -60
  298. package/dist/targets/native/theme.d.ts +58 -60
  299. package/dist/targets/native/theme.js +58 -60
  300. package/package.json +34 -12
  301. package/styles/_primitives.generated.css +40 -0
  302. package/styles/base.css +12 -18
  303. package/styles/rds/components-styles.css +11365 -0
  304. package/styles/rds/components.css +993 -0
  305. package/styles/rds/foundation.css +74 -0
  306. package/styles/rds/theme.css +261 -0
  307. package/styles/rds.css +6 -0
  308. package/styles/themes/rojao.css +46 -53
  309. package/dist/components/blocker-card.d.ts +0 -42
  310. package/dist/components/blocker-card.js +0 -54
  311. package/dist/components/bottom-sheet.d.ts +0 -31
  312. package/dist/components/bottom-sheet.js +0 -127
  313. package/dist/components/chat-bubble.d.ts +0 -16
  314. package/dist/components/chat-bubble.js +0 -56
  315. package/dist/components/chips.d.ts +0 -22
  316. package/dist/components/chips.js +0 -101
  317. package/dist/components/copilot-hint.d.ts +0 -18
  318. package/dist/components/copilot-hint.js +0 -72
  319. package/dist/components/divider.d.ts +0 -20
  320. package/dist/components/divider.js +0 -50
  321. package/dist/components/empty-state.d.ts +0 -48
  322. package/dist/components/empty-state.js +0 -94
  323. package/dist/components/form-card-header.d.ts +0 -13
  324. package/dist/components/form-card-header.js +0 -16
  325. package/dist/components/label.d.ts +0 -16
  326. package/dist/components/label.js +0 -48
  327. package/dist/components/menu.d.ts +0 -50
  328. package/dist/components/menu.js +0 -83
  329. package/dist/components/modal.d.ts +0 -25
  330. package/dist/components/modal.js +0 -86
  331. package/dist/components/notice.d.ts +0 -50
  332. package/dist/components/notice.js +0 -121
  333. package/dist/components/page-tabs.d.ts +0 -35
  334. package/dist/components/page-tabs.js +0 -68
  335. package/dist/components/paywall-banner.d.ts +0 -37
  336. package/dist/components/paywall-banner.js +0 -58
  337. package/dist/components/paywall.d.ts +0 -44
  338. package/dist/components/paywall.js +0 -65
  339. package/dist/components/phone-frame.d.ts +0 -9
  340. package/dist/components/phone-frame.js +0 -19
  341. package/dist/components/pix-icon.d.ts +0 -8
  342. package/dist/components/search.d.ts +0 -30
  343. package/dist/components/search.js +0 -86
  344. package/dist/components/themed.d.ts +0 -36
  345. package/dist/components/themed.js +0 -23
  346. package/dist/components/toaster.d.ts +0 -84
  347. package/dist/components/toaster.js +0 -290
  348. package/dist/components/use-dismiss.d.ts +0 -9
  349. package/dist/components/use-dismiss.js +0 -28
  350. package/dist/components/use-focus-trap.d.ts +0 -5
  351. package/dist/components/use-focus-trap.js +0 -54
  352. package/dist/targets/native/components/paywall-banner.d.ts +0 -11
  353. package/dist/targets/native/components/paywall-banner.js +0 -55
  354. package/dist/targets/native/components/paywall.d.ts +0 -18
  355. package/dist/targets/native/components/paywall.js +0 -71
  356. /package/dist/{components/pix-icon.js → icons/pix.js} +0 -0
@@ -1,235 +1,232 @@
1
1
  "use client";
2
- import "../chunk-ORMEWXMH.js";
3
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
- import { forwardRef, useState, useRef, useEffect, useId, useImperativeHandle } from "react";
5
- import { ChevronDown, Check, Search as SearchIcon, X, Plus } from "lucide-react";
6
- import { Popover } from "./popover.js";
7
- const SIZE_CLASS = {
8
- sm: "h-8 text-caption px-2.5",
9
- md: "h-10 text-label px-3"
10
- };
11
- function defaultFilter(opt, q) {
12
- var _a, _b;
13
- if (!q) return true;
14
- const lower = q.toLowerCase();
15
- return opt.label.toLowerCase().includes(lower) || ((_b = (_a = opt.description) == null ? void 0 : _a.toLowerCase().includes(lower)) != null ? _b : false);
16
- }
17
- const Combobox = forwardRef(function Combobox2(props, ref) {
18
- var _a;
2
+ import {
3
+ __spreadProps,
4
+ __spreadValues
5
+ } from "../chunk-ORMEWXMH.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useMemo, useRef, useState } from "react";
8
+ import { Chip } from "./chip.js";
9
+ import { announce } from "./internal/announce.js";
10
+ import { FieldShell, useFieldIds, warnIfUnlabelled } from "./internal/field.js";
11
+ import { ChevronDownIcon, PlusIcon } from "./internal/icons.js";
12
+ import { OptionContent } from "./internal/option-content.js";
13
+ import { toggleValue, useListbox } from "./internal/use-listbox.js";
14
+ const CREATE = "\0create";
15
+ const normalize = (text) => text.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").toLowerCase();
16
+ function Combobox(props) {
17
+ var _a, _b, _c, _d;
19
18
  const {
20
- options,
21
- placeholder = "Selecione\u2026",
22
- filter = defaultFilter,
23
- emptyMessage = "Nada encontrado",
24
- width = "full",
25
- size = "md",
26
- disabled = false,
27
- className = "",
28
- triggerContent,
29
- dropdownMinWidth,
19
+ label,
20
+ labelPosition,
21
+ hint,
22
+ error,
23
+ errorMessage,
24
+ required,
25
+ options: rawOptions,
26
+ emptyMessage = "Nenhum resultado",
27
+ resultsMessage = (count) => `${count} ${count === 1 ? "resultado" : "resultados"}`,
30
28
  onCreate,
31
- createLabel = (q) => `+ "${q}"`
29
+ creatable = onCreate !== void 0,
30
+ createLabel = (text) => `Cadastrar "${text}"`,
31
+ placeholder,
32
+ leadingIcon,
33
+ name,
34
+ disabled,
35
+ id,
36
+ className,
37
+ style,
38
+ "aria-label": ariaLabel,
39
+ "aria-labelledby": ariaLabelledBy
32
40
  } = props;
33
- const isMulti = props.multi === true;
34
- const [open, setOpen] = useState(false);
41
+ const multiple = props.multiple === true;
42
+ warnIfUnlabelled("Combobox", label, ariaLabel, ariaLabelledBy);
43
+ const { controlId, hintId, errorId, invalid, describedBy } = useFieldIds(id, hint, error, errorMessage);
44
+ const [created, setCreated] = useState([]);
45
+ const options = useMemo(
46
+ () => [...rawOptions.map((o) => typeof o === "string" ? { value: o, label: o } : o), ...created],
47
+ [rawOptions, created]
48
+ );
49
+ const labelOf = (v) => {
50
+ var _a2, _b2;
51
+ return (_b2 = (_a2 = options.find((o) => o.value === v)) == null ? void 0 : _a2.label) != null ? _b2 : v;
52
+ };
53
+ const [ownSingle, setOwnSingle] = useState(multiple ? "" : (_a = props.defaultValue) != null ? _a : "");
54
+ const [ownMany, setOwnMany] = useState(multiple ? (_b = props.defaultValue) != null ? _b : [] : []);
55
+ const chosen = multiple ? (_c = props.value) != null ? _c : ownMany : [(_d = props.value) != null ? _d : ownSingle].filter(Boolean);
56
+ const chosenLabel = !multiple && chosen[0] ? labelOf(chosen[0]) : "";
57
+ const input = useRef(null);
35
58
  const [query, setQuery] = useState("");
36
- const [activeIdx, setActiveIdx] = useState(0);
37
- const [dropdownWidth, setDropdownWidth] = useState(0);
38
- const triggerRef = useRef(null);
39
- const inputRef = useRef(null);
40
- const id = useId();
41
- useImperativeHandle(ref, () => triggerRef.current);
42
- useEffect(() => {
43
- if (open && triggerRef.current) {
44
- setDropdownWidth(triggerRef.current.offsetWidth);
45
- }
46
- }, [open]);
47
- useEffect(() => {
48
- if (open) {
49
- requestAnimationFrame(() => {
50
- var _a2;
51
- return (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
52
- });
53
- setActiveIdx(0);
54
- } else {
55
- setQuery("");
56
- }
57
- }, [open]);
58
- const filtered = options.filter((o) => filter(o, query));
59
- const trimmed = query.trim();
60
- const showCreate = !!onCreate && trimmed.length > 0 && !options.some((o) => o.label.toLowerCase() === trimmed.toLowerCase());
61
- function doCreate() {
62
- if (!onCreate || !trimmed) return;
63
- onCreate(trimmed);
64
- setOpen(false);
59
+ const [typing, setTyping] = useState(false);
60
+ const [open, setOpen] = useState(false);
61
+ function listFor(text, filtering2) {
62
+ const matches2 = filtering2 ? options.filter((o) => normalize(o.label).includes(normalize(text))) : options;
63
+ const typed = text.trim();
64
+ const exact = options.some((o) => normalize(o.label) === normalize(typed));
65
+ const rows2 = creatable && filtering2 && typed && !exact ? [...matches2, { value: CREATE, label: createLabel(typed), create: typed }] : matches2;
66
+ return { matches: matches2, rows: rows2 };
65
67
  }
66
- function isSelected(opt) {
67
- return isMulti ? props.value.includes(opt.value) : props.value === opt.value;
68
+ const onlyCreate = (rows2) => rows2.length === 1 && rows2[0].create !== void 0;
69
+ const filtering = multiple ? query !== "" : typing && query !== "";
70
+ const { matches, rows } = listFor(query, filtering);
71
+ const showList = open && rows.length > 0;
72
+ const empty = open && rows.length === 0;
73
+ function commitSingle(next) {
74
+ var _a2;
75
+ if (props.value === void 0) setOwnSingle(next);
76
+ (_a2 = props.onValueChange) == null ? void 0 : _a2.call(props, next);
68
77
  }
69
- function selectedOption() {
78
+ function commitMany(next) {
70
79
  var _a2;
71
- if (isMulti) return null;
72
- return (_a2 = options.find((o) => o.value === props.value)) != null ? _a2 : null;
80
+ if (props.value === void 0) setOwnMany(next);
81
+ (_a2 = props.onValueChange) == null ? void 0 : _a2.call(props, next);
73
82
  }
74
- function handleSelect(opt) {
75
- if (opt.disabled) return;
76
- if (isMulti) {
77
- const current = props.value;
78
- const next = current.includes(opt.value) ? current.filter((v) => v !== opt.value) : [...current, opt.value];
79
- props.onChange(next);
80
- } else {
81
- props.onChange(opt.value);
82
- setOpen(false);
83
- }
83
+ function create(text) {
84
+ const made = onCreate == null ? void 0 : onCreate(text);
85
+ const option = typeof made === "string" ? { value: made, label: text } : made != null ? made : { value: text, label: text };
86
+ if (!options.some((o) => o.value === option.value)) setCreated((all) => [...all, option]);
87
+ return option;
84
88
  }
85
- function handleKey(e) {
86
- if (e.key === "ArrowDown") {
87
- e.preventDefault();
88
- setActiveIdx((i) => Math.min(i + 1, filtered.length - 1));
89
- } else if (e.key === "ArrowUp") {
90
- e.preventDefault();
91
- setActiveIdx((i) => Math.max(i - 1, 0));
92
- } else if (e.key === "Enter") {
93
- e.preventDefault();
94
- const opt = filtered[activeIdx];
95
- if (opt) handleSelect(opt);
96
- else if (showCreate) doCreate();
97
- } else if (e.key === "Escape") {
98
- setOpen(false);
89
+ const { setActive, isSelected, onKeyDown: listKeyDown, controlProps, listProps, optionProps } = useListbox({
90
+ items: rows,
91
+ showing: showList,
92
+ selected: chosen,
93
+ multiple,
94
+ onOpen: () => setOpen(true),
95
+ onChoose: (row) => {
96
+ if (multiple) {
97
+ if (row.create) {
98
+ const option = create(row.create);
99
+ commitMany([...chosen, option.value]);
100
+ announce(`${option.label} adicionado`);
101
+ } else {
102
+ const adding = !chosen.includes(row.value);
103
+ commitMany(toggleValue(chosen, row.value));
104
+ announce(`${row.label} ${adding ? "adicionado" : "removido"}`);
105
+ }
106
+ if (query !== "") {
107
+ setQuery("");
108
+ setActive(-1);
109
+ }
110
+ } else {
111
+ commitSingle(row.create ? create(row.create).value : row.value);
112
+ setTyping(false);
113
+ setOpen(false);
114
+ setActive(-1);
115
+ }
116
+ }
117
+ });
118
+ function keyDown(event) {
119
+ if (listKeyDown(event)) return;
120
+ if (event.key === "Escape") {
121
+ if (open) {
122
+ event.preventDefault();
123
+ setOpen(false);
124
+ setActive(-1);
125
+ } else if (!multiple) {
126
+ setTyping(false);
127
+ }
128
+ } else if (multiple && event.key === "Backspace" && query === "" && chosen.length) {
129
+ const last = chosen[chosen.length - 1];
130
+ commitMany(chosen.slice(0, -1));
131
+ announce(`${labelOf(last)} removido`);
99
132
  }
100
133
  }
101
- const sel = selectedOption();
102
- const triggerLabel = isMulti ? props.value.length === 0 ? placeholder : `${props.value.length} selecionado(s)` : (_a = sel == null ? void 0 : sel.label) != null ? _a : placeholder;
103
- const isPlaceholder = isMulti ? props.value.length === 0 : !sel;
104
- const dropdown = /* @__PURE__ */ jsxs(
105
- "div",
134
+ function remove(v) {
135
+ const next = chosen.filter((x) => x !== v);
136
+ commitMany(next);
137
+ if (next.length === 0) requestAnimationFrame(() => {
138
+ var _a2;
139
+ return (_a2 = input.current) == null ? void 0 : _a2.focus();
140
+ });
141
+ }
142
+ const listName = typeof label === "string" ? label : ariaLabel;
143
+ return /* @__PURE__ */ jsxs(
144
+ FieldShell,
106
145
  {
107
- id,
108
- role: "listbox",
109
- style: { width: Math.max(dropdownWidth, dropdownMinWidth != null ? dropdownMinWidth : 0) || void 0 },
110
- className: "max-h-72 overflow-hidden rounded-(--radius-control) border border-stroke-control bg-surface-default shadow-lg flex flex-col",
146
+ kind: "rds-combobox",
147
+ controlId,
148
+ hintId,
149
+ errorId,
150
+ label,
151
+ labelPosition,
152
+ hint,
153
+ errorMessage,
154
+ invalid,
155
+ required,
156
+ disabled,
157
+ boxClassName: multiple ? "rds-combobox__box--multiple" : void 0,
158
+ className,
159
+ style,
111
160
  children: [
112
- /* @__PURE__ */ jsxs("div", { className: "relative shrink-0 border-b border-stroke-subtle", children: [
113
- /* @__PURE__ */ jsx(SearchIcon, { size: 14, className: "absolute left-3 top-1/2 -translate-y-1/2 text-fg-muted pointer-events-none" }),
114
- /* @__PURE__ */ jsx(
115
- "input",
116
- {
117
- ref: inputRef,
118
- type: "text",
119
- value: query,
120
- onChange: (e) => {
121
- setQuery(e.target.value);
122
- setActiveIdx(0);
123
- },
124
- onKeyDown: handleKey,
125
- placeholder: "Buscar\u2026",
126
- className: "w-full pl-9 pr-8 py-2 text-label bg-transparent outline-none text-fg-primary placeholder:text-fg-placeholder",
127
- "aria-label": "Buscar op\xE7\xF5es"
161
+ leadingIcon && /* @__PURE__ */ jsx("span", { className: "rds-field__icon", "aria-hidden": "true", children: leadingIcon }),
162
+ multiple && chosen.length > 0 && /* @__PURE__ */ jsx("ul", { className: "rds-combobox__chips", "aria-label": `Escolhidos: ${chosen.length}`, children: chosen.map((v) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Chip, { disabled, onRemove: () => remove(v), children: labelOf(v) }) }, v)) }),
163
+ /* @__PURE__ */ jsx(
164
+ "input",
165
+ __spreadProps(__spreadValues({
166
+ ref: input,
167
+ id: controlId,
168
+ className: "rds-field__control",
169
+ type: "text",
170
+ role: "combobox",
171
+ autoComplete: "off",
172
+ "aria-autocomplete": "list"
173
+ }, controlProps), {
174
+ "aria-label": ariaLabel,
175
+ "aria-labelledby": ariaLabelledBy,
176
+ "aria-invalid": invalid || void 0,
177
+ "aria-describedby": describedBy,
178
+ "aria-required": required || void 0,
179
+ disabled,
180
+ placeholder: multiple && chosen.length ? void 0 : labelPosition === "floating" && label ? " " : placeholder,
181
+ value: multiple ? query : typing ? query : chosenLabel,
182
+ onChange: (event) => {
183
+ const text = event.target.value;
184
+ setQuery(text);
185
+ setTyping(true);
186
+ setOpen(true);
187
+ setActive(onlyCreate(listFor(text, text !== "").rows) ? 0 : -1);
188
+ if (!multiple && text === "" && chosen.length) commitSingle("");
189
+ },
190
+ onClick: () => setOpen((current) => !current),
191
+ onKeyDown: keyDown,
192
+ onBlur: () => {
193
+ setOpen(false);
194
+ setTyping(false);
195
+ setQuery("");
196
+ setActive(-1);
128
197
  }
129
- ),
130
- query && /* @__PURE__ */ jsx(
131
- "button",
132
- {
133
- type: "button",
134
- onClick: () => {
135
- var _a2;
136
- setQuery("");
137
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
138
- },
139
- "aria-label": "Limpar",
140
- className: "absolute right-2 top-1/2 -translate-y-1/2 text-fg-muted hover:text-fg-primary p-1",
141
- children: /* @__PURE__ */ jsx(X, { size: 12 })
142
- }
143
- )
144
- ] }),
145
- /* @__PURE__ */ jsx("div", { className: "overflow-y-auto py-1 max-h-60", children: filtered.length === 0 && !showCreate ? /* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-label text-fg-muted text-center", children: emptyMessage }) : /* @__PURE__ */ jsxs(Fragment, { children: [
146
- filtered.map((opt, idx) => {
147
- const selected = isSelected(opt);
148
- const active = idx === activeIdx;
149
- return /* @__PURE__ */ jsxs(
150
- "button",
151
- {
152
- type: "button",
153
- role: "option",
154
- "aria-selected": selected,
155
- disabled: opt.disabled,
156
- onClick: () => handleSelect(opt),
157
- onMouseEnter: () => setActiveIdx(idx),
158
- className: [
159
- "w-full flex items-start gap-2.5 px-3 py-2 text-label text-left transition-colors",
160
- "disabled:cursor-not-allowed disabled:opacity-50",
161
- active ? "bg-surface-raised" : "hover:bg-surface-raised"
162
- ].join(" "),
163
- children: [
164
- opt.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-fg-muted mt-0.5 [&_svg]:size-4", children: opt.icon }),
165
- /* @__PURE__ */ jsxs("span", { className: "flex-1 min-w-0", children: [
166
- /* @__PURE__ */ jsx("span", { className: "block text-fg-primary truncate", children: opt.label }),
167
- opt.description && /* @__PURE__ */ jsx("span", { className: "block text-caption text-fg-muted truncate", children: opt.description })
168
- ] }),
169
- selected && /* @__PURE__ */ jsx(Check, { size: 14, className: "shrink-0 text-fg-muted mt-0.5" })
170
- ]
171
- },
172
- opt.value
173
- );
198
+ })
199
+ ),
200
+ /* @__PURE__ */ jsx(
201
+ "span",
202
+ {
203
+ className: ["rds-field__icon", "rds-combobox__chevron", open && "rds-combobox__chevron--open"].filter(Boolean).join(" "),
204
+ "aria-hidden": "true",
205
+ onMouseDown: (event) => {
206
+ var _a2;
207
+ event.preventDefault();
208
+ if (disabled) return;
209
+ (_a2 = input.current) == null ? void 0 : _a2.focus();
210
+ setOpen((current) => !current);
211
+ },
212
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
213
+ }
214
+ ),
215
+ name && (chosen.length ? chosen : multiple ? [] : [""]).map((v) => /* @__PURE__ */ jsx("input", { type: "hidden", name, value: v }, v)),
216
+ showList && /* @__PURE__ */ jsx("ul", __spreadProps(__spreadValues({}, listProps), { "aria-label": listName, className: "rds-listbox rds-combobox__list", children: rows.map((row, index) => /* @__PURE__ */ jsx(
217
+ "li",
218
+ __spreadProps(__spreadValues({}, optionProps(row, index)), {
219
+ className: row.create ? "rds-listbox__option rds-combobox__create" : "rds-listbox__option",
220
+ children: /* @__PURE__ */ jsx(OptionContent, { icon: row.create ? /* @__PURE__ */ jsx(PlusIcon, {}) : row.icon, selected: !row.create && isSelected(row.value), children: row.label })
174
221
  }),
175
- showCreate && /* @__PURE__ */ jsxs(
176
- "button",
177
- {
178
- type: "button",
179
- onClick: doCreate,
180
- className: "w-full flex items-center gap-2.5 px-3 py-2 text-label text-left text-fg-primary transition-colors hover:bg-surface-raised border-t border-stroke-subtle",
181
- children: [
182
- /* @__PURE__ */ jsx(Plus, { size: 14, className: "shrink-0 text-fg-muted" }),
183
- /* @__PURE__ */ jsx("span", { className: "truncate", children: createLabel(trimmed) })
184
- ]
185
- }
186
- )
187
- ] }) })
222
+ row.value
223
+ )) })),
224
+ empty && /* @__PURE__ */ jsx("div", { className: "rds-listbox rds-combobox__list rds-combobox__empty", "aria-hidden": "true", children: emptyMessage }),
225
+ /* @__PURE__ */ jsx("span", { className: "rds-visually-hidden", "aria-live": "polite", children: open && filtering ? matches.length ? resultsMessage(matches.length) : emptyMessage : "" })
188
226
  ]
189
227
  }
190
228
  );
191
- return /* @__PURE__ */ jsx("div", { className: ["relative inline-block", width === "full" ? "w-full" : "w-auto", className].join(" "), children: /* @__PURE__ */ jsx(
192
- Popover,
193
- {
194
- trigger: /* @__PURE__ */ jsxs(
195
- "button",
196
- {
197
- ref: triggerRef,
198
- type: "button",
199
- onClick: (e) => {
200
- e.stopPropagation();
201
- if (!disabled) setOpen((o) => !o);
202
- },
203
- disabled,
204
- "aria-haspopup": "listbox",
205
- "aria-expanded": open,
206
- "aria-controls": id,
207
- className: [
208
- "w-full flex items-center justify-between gap-2 rounded-(--radius-control) border border-stroke-control bg-surface-default",
209
- "transition-colors focus:outline-none focus:border-stroke-focus focus:ring-2 focus:ring-stroke-focus/20",
210
- "disabled:opacity-50 disabled:cursor-not-allowed",
211
- SIZE_CLASS[size]
212
- ].join(" "),
213
- children: [
214
- /* @__PURE__ */ jsx("span", { className: ["truncate inline-flex items-center", isPlaceholder ? "text-fg-placeholder" : "text-fg-primary"].join(" "), children: triggerContent ? triggerContent(sel) : /* @__PURE__ */ jsxs(Fragment, { children: [
215
- (sel == null ? void 0 : sel.icon) && /* @__PURE__ */ jsx("span", { className: "inline-flex mr-2 align-middle [&_svg]:size-4", children: sel.icon }),
216
- triggerLabel
217
- ] }) }),
218
- /* @__PURE__ */ jsx(ChevronDown, { size: 16, className: "text-fg-muted shrink-0" })
219
- ]
220
- }
221
- ),
222
- triggerClassName: width === "full" ? "block w-full" : "inline-block",
223
- placement: "bottom-start",
224
- offset: 4,
225
- open,
226
- onOpenChange: (v) => {
227
- if (!disabled) setOpen(v);
228
- },
229
- children: () => dropdown
230
- }
231
- ) });
232
- });
229
+ }
233
230
  export {
234
231
  Combobox
235
232
  };
@@ -0,0 +1,58 @@
1
+ import * as react from 'react';
2
+ import { ReactElement, ReactNode } from 'react';
3
+ import { MenuItemContentProps } from './internal/menu.js';
4
+
5
+ interface CommandProps {
6
+ /** The element that opens it (a Button). Ctrl K (⌘ K on a Mac) opens it too, unless `hotkey` is off. */
7
+ trigger?: ReactElement;
8
+ open?: boolean;
9
+ defaultOpen?: boolean;
10
+ onOpenChange?: (open: boolean) => void;
11
+ /** Controlled: what is typed in the search (Figma: `query`). */
12
+ query?: string;
13
+ /** Uncontrolled: what the search starts with. */
14
+ defaultQuery?: string;
15
+ onQueryChange?: (query: string) => void;
16
+ /** What the person can search for, shown while the search is empty. */
17
+ placeholder?: string;
18
+ /** The results (Figma: the `results` slot): CommandGroups of CommandItems. They filter by the search. */
19
+ children: ReactNode;
20
+ /** Shown when nothing matches the search. */
21
+ emptyMessage?: string;
22
+ /** Ctrl K (⌘ K) opens and closes it. On by default. */
23
+ hotkey?: boolean;
24
+ /** The window's name for screen readers. */
25
+ label?: string;
26
+ /** Where the layer is portaled (default document.body). */
27
+ container?: HTMLElement | null;
28
+ }
29
+ /**
30
+ * Command — Figma [RDS] Overlays/Command. The command palette: search, then go anywhere or run an action. A modal
31
+ * window (Radix Dialog) with a search field (role="combobox", aria-activedescendant) over a listbox of results in
32
+ * groups. Typing filters (accents and case don't matter, `keywords` count too), the arrows move, Enter runs the
33
+ * highlighted result, Escape closes and gives the focus back. Everything in it also exists on the screen.
34
+ * Styles: internal/menu.css and command.css.
35
+ */
36
+ declare function Command({ trigger, open, defaultOpen, onOpenChange, query: queryProp, defaultQuery, onQueryChange, placeholder, children, emptyMessage, hotkey, label, container, }: CommandProps): react.JSX.Element;
37
+ interface CommandGroupProps {
38
+ /** The group's visible name ("Ir para", "Ações"). */
39
+ label: string;
40
+ /** The CommandItems. The group hides when none matches. */
41
+ children: ReactNode;
42
+ }
43
+ /** A group of results under a name (Figma: the `group` and its `group-label`). */
44
+ declare function CommandGroup({ label, children }: CommandGroupProps): react.JSX.Element;
45
+ interface CommandItemProps extends MenuItemContentProps {
46
+ /** Runs when chosen (Enter or a click); the palette closes first. */
47
+ onSelect?: () => void;
48
+ /** The text the search matches. Defaults to the label when it is plain text. */
49
+ value?: string;
50
+ /** Other words that find it ("envio" finds "Novo disparo"). */
51
+ keywords?: string[];
52
+ /** Shown but can't be chosen; the arrows skip it. */
53
+ disabled?: boolean;
54
+ }
55
+ /** One result (Figma .menu/item): role="option". It shows only while it matches the search. */
56
+ declare function CommandItem({ children, icon, shortcut, onSelect, value, keywords, disabled }: CommandItemProps): react.JSX.Element | null;
57
+
58
+ export { Command, CommandGroup, type CommandGroupProps, CommandItem, type CommandItemProps, type CommandProps };