@1doc/1ds-react 2.8.0 → 2.10.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 (287) hide show
  1. package/CHANGELOG.md +1540 -0
  2. package/dist/components/AILabel/AILabel.js +1 -1
  3. package/dist/components/Accordion/Accordion.css +13 -0
  4. package/dist/components/Accordion/Accordion.d.ts +9 -2
  5. package/dist/components/Accordion/Accordion.js +1 -0
  6. package/dist/components/AppSubheader/AppSubheader.css +10 -1
  7. package/dist/components/AttachmentCard/AttachmentCard.css +26 -8
  8. package/dist/components/AttachmentCard/AttachmentCard.d.ts +22 -2
  9. package/dist/components/AttachmentCard/AttachmentCard.js +47 -3
  10. package/dist/components/Avatar/Avatar.css +7 -2
  11. package/dist/components/Avatar/AvatarGroup.d.ts +17 -0
  12. package/dist/components/Avatar/AvatarGroup.js +22 -8
  13. package/dist/components/Badge/Badge.css +67 -2
  14. package/dist/components/Badge/Badge.d.ts +23 -4
  15. package/dist/components/Badge/Badge.js +4 -0
  16. package/dist/components/Box/Box.css +83 -0
  17. package/dist/components/Box/Box.d.ts +82 -2
  18. package/dist/components/Box/Box.js +42 -2
  19. package/dist/components/Button/Button.css +29 -0
  20. package/dist/components/Button/Button.d.ts +4 -4
  21. package/dist/components/Button/Button.js +4 -1
  22. package/dist/components/Calendar/Calendar.css +245 -0
  23. package/dist/components/Calendar/Calendar.d.ts +126 -0
  24. package/dist/components/Calendar/Calendar.js +320 -0
  25. package/dist/components/Chips/Chips.css +38 -0
  26. package/dist/components/Chips/Chips.d.ts +5 -2
  27. package/dist/components/Chips/Chips.js +2 -1
  28. package/dist/components/Coachmark/Coachmark.css +128 -0
  29. package/dist/components/Coachmark/Coachmark.d.ts +87 -0
  30. package/dist/components/Coachmark/Coachmark.js +362 -0
  31. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  32. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  33. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  34. package/dist/components/ColorPicker/ColorPicker.css +140 -0
  35. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  36. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  37. package/dist/components/Combobox/Combobox.css +8 -0
  38. package/dist/components/DataTable/DataTable.css +254 -0
  39. package/dist/components/DataTable/DataTable.d.ts +81 -5
  40. package/dist/components/DataTable/DataTable.js +335 -19
  41. package/dist/components/DatePicker/DatePicker.css +8 -0
  42. package/dist/components/DatePicker/DatePicker.js +10 -1
  43. package/dist/components/DescriptionList/DescriptionList.css +127 -0
  44. package/dist/components/DescriptionList/DescriptionList.d.ts +62 -0
  45. package/dist/components/DescriptionList/DescriptionList.js +52 -0
  46. package/dist/components/EmptyState/EmptyState.d.ts +4 -2
  47. package/dist/components/EmptyState/EmptyState.js +2 -2
  48. package/dist/components/FileInput/FileInput.css +16 -0
  49. package/dist/components/FileInput/FileInput.d.ts +4 -2
  50. package/dist/components/FileInput/FileInput.js +8 -2
  51. package/dist/components/Grid/Grid.js +5 -5
  52. package/dist/components/IconPicker/IconPicker.css +107 -0
  53. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  54. package/dist/components/IconPicker/IconPicker.js +194 -0
  55. package/dist/components/Input/Input.css +59 -0
  56. package/dist/components/Input/Input.d.ts +17 -1
  57. package/dist/components/Input/Input.js +67 -5
  58. package/dist/components/Kanban/Kanban.css +4 -0
  59. package/dist/components/Kbd/Kbd.css +66 -0
  60. package/dist/components/Kbd/Kbd.d.ts +32 -0
  61. package/dist/components/Kbd/Kbd.js +40 -0
  62. package/dist/components/List/List.css +136 -0
  63. package/dist/components/List/List.d.ts +82 -0
  64. package/dist/components/List/List.js +53 -0
  65. package/dist/components/List/ListItem.d.ts +97 -0
  66. package/dist/components/List/ListItem.js +82 -0
  67. package/dist/components/Modal/Modal.css +80 -0
  68. package/dist/components/Modal/Modal.d.ts +33 -6
  69. package/dist/components/Modal/Modal.js +101 -6
  70. package/dist/components/MultiSelect/MultiSelect.css +8 -0
  71. package/dist/components/MultiSelect/MultiSelect.js +10 -1
  72. package/dist/components/OrgChart/OrgChart.css +149 -0
  73. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  74. package/dist/components/OrgChart/OrgChart.js +297 -0
  75. package/dist/components/OtpInput/OtpInput.css +93 -0
  76. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  77. package/dist/components/OtpInput/OtpInput.js +215 -0
  78. package/dist/components/PhoneInput/PhoneInput.css +8 -0
  79. package/dist/components/Popover/Popover.d.ts +7 -0
  80. package/dist/components/Popover/Popover.js +11 -1
  81. package/dist/components/RichTextEditor/RichTextEditor.css +250 -0
  82. package/dist/components/RichTextEditor/RichTextEditor.d.ts +97 -0
  83. package/dist/components/RichTextEditor/RichTextEditor.js +951 -0
  84. package/dist/components/SegmentedControl/SegmentedControl.css +24 -0
  85. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  86. package/dist/components/SegmentedControl/SegmentedControl.js +10 -2
  87. package/dist/components/Select/Select.css +164 -0
  88. package/dist/components/Select/Select.d.ts +34 -0
  89. package/dist/components/Select/Select.js +258 -28
  90. package/dist/components/Stack/Stack.css +49 -0
  91. package/dist/components/Stack/Stack.d.ts +65 -7
  92. package/dist/components/Stack/Stack.js +30 -2
  93. package/dist/components/StatCard/StatCard.css +138 -0
  94. package/dist/components/StatCard/StatCard.d.ts +26 -0
  95. package/dist/components/StatCard/StatCard.js +13 -1
  96. package/dist/components/Tabs/Tab.d.ts +15 -0
  97. package/dist/components/Tabs/Tab.js +30 -1
  98. package/dist/components/Tabs/Tabs.css +132 -0
  99. package/dist/components/Tabs/Tabs.d.ts +7 -0
  100. package/dist/components/Tabs/Tabs.js +13 -2
  101. package/dist/components/Tag/Tag.css +85 -2
  102. package/dist/components/Tag/Tag.d.ts +13 -6
  103. package/dist/components/Tag/Tag.js +1 -0
  104. package/dist/components/Text/Text.js +2 -2
  105. package/dist/components/Textarea/Textarea.css +8 -0
  106. package/dist/components/TimePicker/TimePicker.css +8 -0
  107. package/dist/components/Toast/Toast.css +32 -0
  108. package/dist/components/Toast/Toast.d.ts +18 -0
  109. package/dist/components/Toast/Toast.js +14 -1
  110. package/dist/components/Toast/ToastStack.js +8 -1
  111. package/dist/components/Tooltip/Tooltip.css +25 -0
  112. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  113. package/dist/components/Tooltip/Tooltip.js +18 -3
  114. package/dist/index.d.ts +25 -0
  115. package/dist/index.js +14 -0
  116. package/dist/teste/AILabel.test.d.ts +1 -0
  117. package/dist/teste/AILabel.test.js +33 -0
  118. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  119. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  120. package/dist/teste/AccordionTituloNeutro.test.d.ts +1 -0
  121. package/dist/teste/AccordionTituloNeutro.test.js +23 -0
  122. package/dist/teste/AppSubheaderRegiao.test.d.ts +1 -0
  123. package/dist/teste/AppSubheaderRegiao.test.js +13 -0
  124. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  125. package/dist/teste/AtributosRepassados.test.js +52 -0
  126. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  127. package/dist/teste/AttachmentCardIA.test.js +89 -0
  128. package/dist/teste/AttachmentCardLista.test.d.ts +1 -0
  129. package/dist/teste/AttachmentCardLista.test.js +49 -0
  130. package/dist/teste/AttachmentCardSm.test.d.ts +1 -0
  131. package/dist/teste/AttachmentCardSm.test.js +26 -0
  132. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  133. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  134. package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
  135. package/dist/teste/BadgeNeutroColado.test.js +11 -0
  136. package/dist/teste/BadgeTag.test.d.ts +1 -0
  137. package/dist/teste/BadgeTag.test.js +55 -0
  138. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  139. package/dist/teste/BoxItemFlex.test.js +54 -0
  140. package/dist/teste/BoxLayout.test.d.ts +1 -0
  141. package/dist/teste/BoxLayout.test.js +35 -0
  142. package/dist/teste/Button.test.d.ts +1 -0
  143. package/dist/teste/Button.test.js +27 -0
  144. package/dist/teste/Calendar.test.d.ts +1 -0
  145. package/dist/teste/Calendar.test.js +221 -0
  146. package/dist/teste/CalendarCabecalho.test.d.ts +1 -0
  147. package/dist/teste/CalendarCabecalho.test.js +11 -0
  148. package/dist/teste/ChipsXs.test.d.ts +1 -0
  149. package/dist/teste/ChipsXs.test.js +31 -0
  150. package/dist/teste/Coachmark.test.d.ts +1 -0
  151. package/dist/teste/Coachmark.test.js +149 -0
  152. package/dist/teste/CoachmarkSemVeu.test.d.ts +1 -0
  153. package/dist/teste/CoachmarkSemVeu.test.js +85 -0
  154. package/dist/teste/ColorPicker.test.d.ts +1 -0
  155. package/dist/teste/ColorPicker.test.js +132 -0
  156. package/dist/teste/ColorPickerXs.test.d.ts +1 -0
  157. package/dist/teste/ColorPickerXs.test.js +21 -0
  158. package/dist/teste/DataTableArvoreEVariantes.test.d.ts +1 -0
  159. package/dist/teste/DataTableArvoreEVariantes.test.js +190 -0
  160. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  161. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  162. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  163. package/dist/teste/DataTableDocumento.test.js +92 -0
  164. package/dist/teste/DatePicker.test.js +23 -0
  165. package/dist/teste/DescriptionListCompacta.test.d.ts +1 -0
  166. package/dist/teste/DescriptionListCompacta.test.js +22 -0
  167. package/dist/teste/EmptyStateTituloRico.test.d.ts +1 -0
  168. package/dist/teste/EmptyStateTituloRico.test.js +23 -0
  169. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  170. package/dist/teste/FileInputTrigger.test.js +53 -0
  171. package/dist/teste/IconPicker.test.d.ts +1 -0
  172. package/dist/teste/IconPicker.test.js +130 -0
  173. package/dist/teste/InputAgrupado.test.d.ts +1 -0
  174. package/dist/teste/InputAgrupado.test.js +24 -0
  175. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  176. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  177. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  178. package/dist/teste/KbdCodeBlock.test.js +95 -0
  179. package/dist/teste/List.test.d.ts +1 -0
  180. package/dist/teste/List.test.js +153 -0
  181. package/dist/teste/ListItemTooltipStandalone.test.d.ts +1 -0
  182. package/dist/teste/ListItemTooltipStandalone.test.js +39 -0
  183. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  184. package/dist/teste/ModalVariantes.test.js +151 -0
  185. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  186. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  187. package/dist/teste/OrgChart.test.d.ts +1 -0
  188. package/dist/teste/OrgChart.test.js +162 -0
  189. package/dist/teste/OtpInput.test.d.ts +1 -0
  190. package/dist/teste/OtpInput.test.js +143 -0
  191. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  192. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  193. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  194. package/dist/teste/RichTextEditor.test.js +287 -0
  195. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.d.ts +1 -0
  196. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.js +212 -0
  197. package/dist/teste/RichTextEditorEstiloDeTexto.test.d.ts +1 -0
  198. package/dist/teste/RichTextEditorEstiloDeTexto.test.js +120 -0
  199. package/dist/teste/SegmentedControlContador.test.d.ts +1 -0
  200. package/dist/teste/SegmentedControlContador.test.js +39 -0
  201. package/dist/teste/SelectAbertoControladoEFlutuante.test.d.ts +1 -0
  202. package/dist/teste/SelectAbertoControladoEFlutuante.test.js +145 -0
  203. package/dist/teste/SelectFiltroCorETamanho.test.d.ts +1 -0
  204. package/dist/teste/SelectFiltroCorETamanho.test.js +77 -0
  205. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  206. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  207. package/dist/teste/Stack.test.d.ts +1 -0
  208. package/dist/teste/Stack.test.js +57 -0
  209. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  210. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  211. package/dist/teste/StatCardSecundariaETom.test.d.ts +1 -0
  212. package/dist/teste/StatCardSecundariaETom.test.js +45 -0
  213. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  214. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  215. package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
  216. package/dist/teste/ToastAcaoEDetalhes.test.js +94 -0
  217. package/dist/teste/TooltipDark.test.d.ts +1 -0
  218. package/dist/teste/TooltipDark.test.js +31 -0
  219. package/dist/utils/calendario.d.ts +28 -0
  220. package/dist/utils/calendario.js +73 -0
  221. package/dist/utils/html-seguro.d.ts +45 -0
  222. package/dist/utils/html-seguro.js +208 -0
  223. package/dist/utils/paleta-de-cores.d.ts +26 -0
  224. package/dist/utils/paleta-de-cores.js +10 -0
  225. package/dist/utils/texto.d.ts +5 -0
  226. package/dist/utils/texto.js +5 -0
  227. package/dist/utils/toast.d.ts +10 -1
  228. package/dist/utils/toast.js +2 -1
  229. package/package.json +3 -3
  230. package/src/index.ts +26 -0
  231. package/src/teste/AILabel.test.tsx +41 -0
  232. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  233. package/src/teste/AccordionTituloNeutro.test.tsx +25 -0
  234. package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
  235. package/src/teste/AtributosRepassados.test.tsx +73 -0
  236. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  237. package/src/teste/AttachmentCardLista.test.tsx +53 -0
  238. package/src/teste/AttachmentCardSm.test.tsx +29 -0
  239. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  240. package/src/teste/BadgeNeutroColado.test.tsx +15 -0
  241. package/src/teste/BadgeTag.test.tsx +85 -0
  242. package/src/teste/BoxItemFlex.test.tsx +81 -0
  243. package/src/teste/BoxLayout.test.tsx +50 -0
  244. package/src/teste/Button.test.tsx +39 -0
  245. package/src/teste/Calendar.test.tsx +282 -0
  246. package/src/teste/CalendarCabecalho.test.tsx +11 -0
  247. package/src/teste/ChipsXs.test.tsx +41 -0
  248. package/src/teste/Coachmark.test.tsx +198 -0
  249. package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
  250. package/src/teste/ColorPicker.test.tsx +153 -0
  251. package/src/teste/ColorPickerXs.test.tsx +22 -0
  252. package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -0
  253. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  254. package/src/teste/DataTableDocumento.test.tsx +102 -0
  255. package/src/teste/DatePicker.test.tsx +38 -0
  256. package/src/teste/DescriptionListCompacta.test.tsx +24 -0
  257. package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
  258. package/src/teste/FileInputTrigger.test.tsx +89 -0
  259. package/src/teste/IconPicker.test.tsx +145 -0
  260. package/src/teste/InputAgrupado.test.tsx +26 -0
  261. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  262. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  263. package/src/teste/List.test.tsx +269 -0
  264. package/src/teste/ListItemTooltipStandalone.test.tsx +64 -0
  265. package/src/teste/ModalVariantes.test.tsx +173 -0
  266. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  267. package/src/teste/OrgChart.test.tsx +183 -0
  268. package/src/teste/OtpInput.test.tsx +163 -0
  269. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  270. package/src/teste/RichTextEditor.test.tsx +329 -0
  271. package/src/teste/RichTextEditorAlinhaImagemTabela.test.tsx +238 -0
  272. package/src/teste/RichTextEditorEstiloDeTexto.test.tsx +137 -0
  273. package/src/teste/SegmentedControlContador.test.tsx +43 -0
  274. package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
  275. package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -0
  276. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  277. package/src/teste/Stack.test.tsx +80 -0
  278. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  279. package/src/teste/StatCardSecundariaETom.test.tsx +51 -0
  280. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  281. package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
  282. package/src/teste/TooltipDark.test.tsx +51 -0
  283. package/src/utils/calendario.ts +78 -0
  284. package/src/utils/html-seguro.ts +197 -0
  285. package/src/utils/paleta-de-cores.ts +34 -0
  286. package/src/utils/texto.ts +5 -0
  287. package/src/utils/toast.ts +12 -2
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import './Select.css';
4
4
  import { useState, useRef, useEffect } from "react";
5
5
  import { faChevronUp, faChevronDown, faMagnifyingGlass, faXmark, faCheck, faTrash, } from "@fortawesome/free-solid-svg-icons";
6
+ import { computePosition, autoUpdate, offset, flip, size, } from "@floating-ui/dom";
6
7
  import Text from "../Text/Text";
7
8
  import Icon from "../Icon/Icon";
8
9
  import Spinner from "../Spinner/Spinner";
@@ -15,6 +16,10 @@ function Select(props) {
15
16
  const searchInputRef = useRef(null);
16
17
  const outsideWatcherRef = useRef(null);
17
18
  const searchTimeoutRef = useRef(null);
19
+ const dropdownRef = useRef(null);
20
+ const floatCleanupRef = useRef(null);
21
+ const latestOpenRef = useRef(false);
22
+ const latestOpenChangeRef = useRef(null);
18
23
  function textoDeApoio() {
19
24
  return props.helperText || props.description || "";
20
25
  }
@@ -25,16 +30,43 @@ function Select(props) {
25
30
  return props.readOnly ? "true" : undefined;
26
31
  }
27
32
  const [isOpen, setIsOpen] = useState(() => false);
33
+ const [prepared, setPrepared] = useState(() => false);
34
+ const [floatMode, setFloatMode] = useState(() => false);
35
+ const [floatReady, setFloatReady] = useState(() => false);
36
+ const [floatX, setFloatX] = useState(() => 0);
37
+ const [floatY, setFloatY] = useState(() => 0);
38
+ const [floatW, setFloatW] = useState(() => 0);
39
+ const [floatMaxH, setFloatMaxH] = useState(() => 0);
40
+ const [listMaxH, setListMaxH] = useState(() => 0);
28
41
  const [searchTerm, setSearchTerm] = useState(() => "");
29
42
  const [internalSelected, setInternalSelected] = useState(() => Array.isArray(props.defaultValue)
30
43
  ? props.defaultValue
31
44
  : props.defaultValue !== undefined && props.defaultValue !== null
32
45
  ? [props.defaultValue]
33
46
  : Array());
47
+ const [opensUp, setOpensUp] = useState(() => false);
34
48
  const [shouldFocusSearch, setShouldFocusSearch] = useState(() => false);
35
49
  const [shouldFocusTrigger, setShouldFocusTrigger] = useState(() => false);
36
50
  const [activeIndex, setActiveIndex] = useState(() => -1);
37
51
  const [uid, setUid] = useState(() => "");
52
+ function opened() {
53
+ if (props.open !== undefined)
54
+ return props.open === "" ? true : !!props.open;
55
+ return isOpen;
56
+ }
57
+ function isFilter() {
58
+ return (props.variant === "filter" ||
59
+ props.variant === "search" ||
60
+ props.variant === "combo");
61
+ }
62
+ function setOpen(next) {
63
+ if (next === opened())
64
+ return;
65
+ if (props.open === undefined)
66
+ setIsOpen(next);
67
+ if (props.onOpenChange)
68
+ props.onOpenChange(next);
69
+ }
38
70
  function baseId() {
39
71
  return props.id || uid;
40
72
  }
@@ -47,6 +79,9 @@ function Select(props) {
47
79
  function isInvalid() {
48
80
  return !!props.invalid || !!props.errorMessage;
49
81
  }
82
+ function ariaRequiredText() {
83
+ return props.required ? "true" : undefined;
84
+ }
50
85
  function ariaInvalidText() {
51
86
  return isInvalid() ? "true" : undefined;
52
87
  }
@@ -92,6 +127,12 @@ function Select(props) {
92
127
  : internalSelected || [];
93
128
  if (currentVal.length === 0)
94
129
  return props.placeholder || "Selecione...";
130
+ // Opção "sem filtro" escolhida: volta a mostrar o nome do filtro.
131
+ if (props.emptyOptionLabel &&
132
+ !props.multiple &&
133
+ currentVal.length === 1 &&
134
+ currentVal[0] === "")
135
+ return props.placeholder || "Selecione...";
95
136
  if (props.multiple) {
96
137
  if (props.selectionDisplay === "tags")
97
138
  return "";
@@ -109,6 +150,14 @@ function Select(props) {
109
150
  }
110
151
  return String(currentVal[0]);
111
152
  }
153
+ function triggerSwatchColor() {
154
+ if (props.triggerSwatch)
155
+ return props.triggerSwatch;
156
+ if (props.multiple || isPlaceholder())
157
+ return undefined;
158
+ const escolhida = selectedOptionsList()[0];
159
+ return escolhida ? escolhida.color : undefined;
160
+ }
112
161
  function isPlaceholder() {
113
162
  const currentVal = props.value !== undefined
114
163
  ? Array.isArray(props.value)
@@ -117,6 +166,11 @@ function Select(props) {
117
166
  ? []
118
167
  : [props.value]
119
168
  : internalSelected || [];
169
+ if (props.emptyOptionLabel &&
170
+ !props.multiple &&
171
+ currentVal.length === 1 &&
172
+ currentVal[0] === "")
173
+ return true;
120
174
  return currentVal.length === 0;
121
175
  }
122
176
  function formValue() {
@@ -132,22 +186,40 @@ function Select(props) {
132
186
  function filteredOptionsList() {
133
187
  if (!props.options)
134
188
  return [];
189
+ // Opção "sem filtro" no topo (seleção única), sempre visível sem busca.
190
+ const vazia = props.emptyOptionLabel && !props.multiple && !searchTerm
191
+ ? [
192
+ {
193
+ label: props.emptyOptionLabel,
194
+ value: "",
195
+ },
196
+ ]
197
+ : [];
135
198
  // If it's remote search (onSearchChange provided), we don't filter locally
136
199
  if (!props.searchable || !searchTerm || props.onSearchChange)
137
- return props.options;
200
+ return vazia.concat(props.options);
138
201
  const term = searchTerm.toLowerCase();
139
202
  return props.options.filter((opt) => opt.label.toLowerCase().includes(term));
140
203
  }
141
204
  function wrapperClassesList() {
142
205
  return [
143
206
  "umds-select",
144
- `umds-select--${props.size || "md"}`,
207
+ `umds-select--${props.size || (isFilter() ? "sm" : "md")}`,
208
+ isFilter() && !isPlaceholder() ? "umds-select--has-value" : "",
145
209
  props.fullWidth ? "umds-select--full-width" : "",
146
210
  props.disabled ? "umds-select--disabled" : "",
147
211
  props.readOnly ? "umds-select--readonly" : "",
148
212
  props.invalid ? "umds-select--invalid" : "",
149
- isOpen ? "umds-select--open" : "",
213
+ opened() ? "umds-select--open" : "",
150
214
  props.searchVariant === "inline" ? "umds-select--search-inline" : "",
215
+ isFilter() ? "umds-select--filter" : "",
216
+ props.variant === "search" ? "umds-select--filter-search" : "",
217
+ props.variant === "combo" ? "umds-select--filter-combo" : "",
218
+ opened() && floatMode ? "umds-select--floating" : "",
219
+ props.triggerIcon ? "umds-select--has-trigger-icon" : "",
220
+ opensUp && props.searchVariant !== "inline"
221
+ ? "umds-select--placement-top"
222
+ : "",
151
223
  props.multiple &&
152
224
  props.selectionDisplay === "tags" &&
153
225
  selectedOptionsList().length > 0
@@ -164,8 +236,16 @@ function Select(props) {
164
236
  function labelIdText() {
165
237
  return baseId() ? baseId() + "-label" : undefined;
166
238
  }
239
+ function comboboxLabelledBy() {
240
+ return props.label && baseId() ? labelIdText() : undefined;
241
+ }
242
+ function comboboxAriaLabel() {
243
+ if (props.ariaLabel)
244
+ return props.ariaLabel;
245
+ return props.label && !baseId() ? props.label : undefined;
246
+ }
167
247
  function activeDescendantText() {
168
- if (!isOpen || activeIndex < 0 || !baseId())
248
+ if (!opened() || activeIndex < 0 || !baseId())
169
249
  return undefined;
170
250
  return baseId() + "-option-" + activeIndex;
171
251
  }
@@ -175,23 +255,133 @@ function Select(props) {
175
255
  function removeItemAriaLabelText(label) {
176
256
  return (props.removeAriaLabel || "Remover") + " " + label;
177
257
  }
258
+ function insideDialog() {
259
+ if (typeof document === "undefined" ||
260
+ !triggerRef.current ||
261
+ props.searchVariant === "inline")
262
+ return false;
263
+ if (typeof triggerRef.current.closest !== "function")
264
+ return false;
265
+ return !!triggerRef.current.closest('[role="dialog"], [aria-modal="true"]');
266
+ }
267
+ function shouldOpenUp(flutuante) {
268
+ const pedido = props.placement || "bottom";
269
+ setListMaxH(0);
270
+ if (pedido === "top")
271
+ return true;
272
+ if (pedido !== "auto")
273
+ return false;
274
+ if (typeof window === "undefined" || !triggerRef.current)
275
+ return false;
276
+ const caixa = triggerRef.current.getBoundingClientRect();
277
+ let topo = 0;
278
+ let base = window.innerHeight;
279
+ if (!flutuante) {
280
+ let pai = triggerRef.current.parentElement;
281
+ while (pai && pai !== document.body) {
282
+ const corte = window.getComputedStyle(pai).overflowY;
283
+ if (corte === "auto" ||
284
+ corte === "scroll" ||
285
+ corte === "hidden" ||
286
+ corte === "clip") {
287
+ const area = pai.getBoundingClientRect();
288
+ topo = Math.max(topo, area.top);
289
+ base = Math.min(base, area.bottom);
290
+ }
291
+ pai = pai.parentElement;
292
+ }
293
+ }
294
+ const abaixo = base - caixa.bottom;
295
+ const acima = caixa.top - topo;
296
+ const opcoes = filteredOptionsList().length;
297
+ const estimada = Math.min(300, opcoes * 36 + 8 + (props.searchable ? 44 : 0) + (props.footer ? 44 : 0));
298
+ const sobe = abaixo < estimada && acima > abaixo;
299
+ const espaco = (sobe ? acima : abaixo) - 8;
300
+ if (espaco < 300)
301
+ setListMaxH(Math.max(96, Math.floor(espaco)));
302
+ return sobe;
303
+ }
304
+ function prepareOpen() {
305
+ setPrepared(true);
306
+ // Local: no React gerado o setState é assíncrono e o estado leria STALE.
307
+ const flutuante = insideDialog();
308
+ setFloatMode(flutuante);
309
+ setFloatReady(false);
310
+ setOpensUp(shouldOpenUp(flutuante));
311
+ // Abre com a opção já selecionada ativa (padrão combobox).
312
+ setActiveIndex(filteredOptionsList().findIndex((opt) => isOptionSelected(opt.value)));
313
+ if (props.searchable &&
314
+ (props.autoFocusSearch || props.searchVariant === "inline" || isFilter())) {
315
+ setShouldFocusSearch(true);
316
+ }
317
+ }
318
+ function updateFloat() {
319
+ if (!triggerRef.current || !dropdownRef.current)
320
+ return;
321
+ computePosition(triggerRef.current, dropdownRef.current, {
322
+ strategy: "fixed",
323
+ placement: opensUp ? "top-start" : "bottom-start",
324
+ middleware: [
325
+ offset(4),
326
+ flip({
327
+ fallbackStrategy: "bestFit",
328
+ }),
329
+ size({
330
+ apply({ availableHeight, rects }) {
331
+ setFloatW(rects.reference.width);
332
+ setFloatMaxH(Math.max(96, Math.min(300, Math.floor(availableHeight - 8))));
333
+ },
334
+ }),
335
+ ],
336
+ }).then((posicao) => {
337
+ setFloatX(Math.round(posicao.x));
338
+ setFloatY(Math.round(posicao.y));
339
+ setFloatReady(true);
340
+ });
341
+ }
342
+ function dropdownStyle() {
343
+ if (props.searchVariant === "inline")
344
+ return {
345
+ top: "0",
346
+ };
347
+ if (opened() && floatMode) {
348
+ const estilo = {
349
+ position: "fixed",
350
+ top: "0",
351
+ left: "0",
352
+ bottom: "auto",
353
+ transform: "translate(" + floatX + "px, " + floatY + "px)",
354
+ visibility: floatReady ? "visible" : "hidden",
355
+ };
356
+ if (isFilter()) {
357
+ estilo.minWidth =
358
+ "max(" + floatW + "px, calc(var(--umds-primitive-spacing-xxl) * 3))";
359
+ }
360
+ else {
361
+ estilo.width = floatW + "px";
362
+ }
363
+ if (floatMaxH)
364
+ estilo.maxHeight = floatMaxH + "px";
365
+ return estilo;
366
+ }
367
+ return listMaxH
368
+ ? {
369
+ maxHeight: listMaxH + "px",
370
+ }
371
+ : {};
372
+ }
178
373
  function toggle() {
179
374
  if (props.disabled || props.readOnly)
180
375
  return;
181
- // NUNCA ler isOpen logo após atribuí-lo: no React gerado o
182
- // setState é assíncrono e a leitura vem STALE. Decidir os ramos pela
183
- // variável local (mesmo padrão do toggle do Switch).
184
- const next = !isOpen;
185
- setIsOpen(next);
376
+ // Decide pela variável local: no React gerado o setState é assíncrono e
377
+ // ler o estado logo após atribuí-lo vem STALE.
378
+ const next = !opened();
379
+ setOpen(next);
186
380
  if (next) {
187
- // Abre com a opção já selecionada ativa (padrão combobox).
188
- setActiveIndex(filteredOptionsList().findIndex((opt) => isOptionSelected(opt.value)));
189
- if (props.searchable &&
190
- (props.autoFocusSearch || props.searchVariant === "inline")) {
191
- setShouldFocusSearch(true);
192
- }
381
+ prepareOpen();
193
382
  }
194
383
  else {
384
+ setPrepared(false);
195
385
  setActiveIndex(-1);
196
386
  }
197
387
  }
@@ -224,7 +414,8 @@ function Select(props) {
224
414
  }
225
415
  }
226
416
  function closeSearch() {
227
- setIsOpen(false);
417
+ setOpen(false);
418
+ setPrepared(false);
228
419
  setSearchTerm("");
229
420
  setActiveIndex(-1);
230
421
  if (props.onSearchChange) {
@@ -247,7 +438,7 @@ function Select(props) {
247
438
  return;
248
439
  const key = event.key;
249
440
  if (key === "Escape") {
250
- if (isOpen) {
441
+ if (opened()) {
251
442
  event.preventDefault();
252
443
  closeSearch();
253
444
  }
@@ -260,7 +451,7 @@ function Select(props) {
260
451
  return;
261
452
  }
262
453
  event.preventDefault();
263
- if (!isOpen) {
454
+ if (!opened()) {
264
455
  toggle();
265
456
  return;
266
457
  }
@@ -326,7 +517,8 @@ function Select(props) {
326
517
  else {
327
518
  newValue = option.value;
328
519
  setInternalSelected([newValue]);
329
- setIsOpen(false);
520
+ setOpen(false);
521
+ setPrepared(false);
330
522
  setActiveIndex(-1);
331
523
  }
332
524
  if (props.onChange) {
@@ -368,17 +560,31 @@ function Select(props) {
368
560
  ? []
369
561
  : [props.value]
370
562
  : internalSelected || [];
563
+ // "Sem filtro" aparece marcada enquanto nada está escolhido.
564
+ if (props.emptyOptionLabel && !props.multiple && val === "") {
565
+ return currentVal.length === 0 || currentVal.includes("");
566
+ }
371
567
  return currentVal.includes(val);
372
568
  }
373
569
  useEffect(() => {
374
570
  if (!props.id)
375
571
  setUid(gerarId("umds-select"));
572
+ // No Vue o onUpdate só roda depois de uma atualização: a lista que já nasce
573
+ // aberta (open controlado) é preparada aqui.
574
+ latestOpenRef.current = opened();
575
+ latestOpenChangeRef.current = props.onOpenChange;
576
+ if (opened() && !prepared)
577
+ prepareOpen();
376
578
  if (typeof document === "undefined")
377
579
  return;
378
580
  const handleClickOutside = (event) => {
379
581
  if (selectRef.current &&
380
582
  !selectRef.current.contains(event.target)) {
583
+ // Só avisa quando a lista está aberta: o ouvinte vive no document inteiro.
584
+ if (latestOpenRef.current && latestOpenChangeRef.current)
585
+ latestOpenChangeRef.current(false);
381
586
  setIsOpen(false);
587
+ setPrepared(false);
382
588
  setActiveIndex(-1);
383
589
  }
384
590
  };
@@ -386,7 +592,27 @@ function Select(props) {
386
592
  document.addEventListener("mousedown", handleClickOutside);
387
593
  }, []);
388
594
  useEffect(() => {
389
- if (isOpen && shouldFocusSearch) {
595
+ // Guarda o estado visto neste render para o ouvinte de clique fora.
596
+ latestOpenRef.current = opened();
597
+ latestOpenChangeRef.current = props.onOpenChange;
598
+ // Aberta de fora (open controlado): aplica os efeitos de abrir uma vez.
599
+ if (opened() && !prepared)
600
+ prepareOpen();
601
+ if (!opened() && prepared)
602
+ setPrepared(false);
603
+ // Lista flutuante: segue o gatilho (scroll, resize) enquanto aberta.
604
+ if (opened() &&
605
+ floatMode &&
606
+ triggerRef.current &&
607
+ dropdownRef.current &&
608
+ !floatCleanupRef.current) {
609
+ floatCleanupRef.current = autoUpdate(triggerRef.current, dropdownRef.current, () => updateFloat());
610
+ }
611
+ if ((!opened() || !floatMode) && floatCleanupRef.current) {
612
+ floatCleanupRef.current();
613
+ floatCleanupRef.current = null;
614
+ }
615
+ if (opened() && shouldFocusSearch) {
390
616
  // Retry a few times if ref is not yet ready (though onUpdate usually implies rendered)
391
617
  // We use a small timeout to ensure browser paints or simply check ref
392
618
  if (searchInputRef.current) {
@@ -395,7 +621,7 @@ function Select(props) {
395
621
  }
396
622
  }
397
623
  // Devolve o foco ao trigger após fechar por Esc/seleção via teclado.
398
- if (!isOpen && shouldFocusTrigger) {
624
+ if (!opened() && shouldFocusTrigger) {
399
625
  if (triggerRef.current) {
400
626
  triggerRef.current.focus();
401
627
  setShouldFocusTrigger(false);
@@ -404,6 +630,10 @@ function Select(props) {
404
630
  });
405
631
  useEffect(() => {
406
632
  return () => {
633
+ if (floatCleanupRef.current) {
634
+ floatCleanupRef.current();
635
+ floatCleanupRef.current = null;
636
+ }
407
637
  // Cancela o debounce pendente da busca — evita callback após unmount.
408
638
  if (searchTimeoutRef.current) {
409
639
  clearTimeout(searchTimeoutRef.current);
@@ -417,13 +647,11 @@ function Select(props) {
417
647
  }
418
648
  };
419
649
  }, []);
420
- return (_jsxs("div", { ref: selectRef, className: wrapperClassesList(), children: [props.label ? (_jsxs(Text, { as: "label", variant: "label", className: "umds-select__label", id: labelIdText(), children: [props.label, props.required ? (_jsx("span", { className: "umds-select__required", children: " *" })) : null] })) : null, _jsxs("div", { className: "umds-select__container", children: [!(isOpen && props.searchVariant === "inline") ? (_jsxs("div", { role: "combobox", "aria-haspopup": "listbox", className: "umds-select__trigger", ref: triggerRef, onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeyDown(event), "aria-readonly": ariaReadonly(), "aria-expanded": isOpen, "aria-controls": listboxIdText(), "aria-activedescendant": activeDescendantText(), "aria-labelledby": props.label ? labelIdText() : undefined, "aria-label": props.ariaLabel, "aria-invalid": ariaInvalidText(), "aria-describedby": describedByText(), "aria-disabled": props.disabled ? "true" : undefined, tabIndex: props.disabled ? -1 : 0, children: [_jsxs("div", { className: "umds-select__values", children: [displayLabelText() ? (_jsx(Text, { as: "span", variant: "body2", className: isPlaceholder() ? "umds-select__placeholder" : "", children: displayLabelText() })) : null, props.multiple &&
650
+ return (_jsxs("div", { ref: selectRef, className: wrapperClassesList(), children: [props.label ? (_jsxs(Text, { as: "label", variant: "label", className: "umds-select__label", id: labelIdText(), children: [props.label, props.required ? (_jsx("span", { className: "umds-select__required", children: " *" })) : null] })) : null, _jsxs("div", { className: "umds-select__container", children: [!(opened() && props.searchVariant === "inline") ? (_jsxs("div", { role: "combobox", "aria-haspopup": "listbox", className: "umds-select__trigger", ref: triggerRef, onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeyDown(event), "aria-readonly": ariaReadonly(), "aria-expanded": opened(), "aria-controls": listboxIdText(), "aria-activedescendant": activeDescendantText(), "aria-labelledby": comboboxLabelledBy(), "aria-label": comboboxAriaLabel(), "aria-invalid": ariaInvalidText(), "aria-required": ariaRequiredText(), "aria-describedby": describedByText(), "aria-disabled": props.disabled ? "true" : undefined, tabIndex: props.disabled ? -1 : 0, children: [_jsxs("div", { className: "umds-select__values", children: [props.triggerIcon ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__trigger-icon", children: _jsx(Icon, { variant: "inherit", customSize: "12px", icon: props.triggerIcon }) })) : null, triggerSwatchColor() ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__swatch", style: {
651
+ background: triggerSwatchColor(),
652
+ } })) : null, displayLabelText() ? (_jsx(Text, { as: "span", variant: "body2", className: isPlaceholder() ? "umds-select__placeholder" : "", children: displayLabelText() })) : null, props.multiple &&
421
653
  props.selectionDisplay === "tags" &&
422
- selectedOptionsList().length > 0 ? (_jsx("div", { className: "umds-select__tags", children: selectedOptionsList()?.map((opt) => (_jsx(Tag, { size: "sm", label: opt.label, closable: true, disabled: props.disabled, onClose: (e) => removeValue(opt.value, e) }, opt.value))) })) : null] }), _jsxs("div", { className: "umds-select__actions", children: [props.loading ? _jsx(Spinner, { size: "sm", variant: "secondary" }) : null, _jsx("div", { className: "umds-select__arrow", children: _jsx(Icon, { size: "sm", icon: isOpen ? faChevronUp : faChevronDown }) })] })] })) : null, isOpen ? (_jsxs("div", { className: "umds-select__dropdown", style: props.searchVariant === "inline"
423
- ? {
424
- top: "0",
425
- }
426
- : {}, onKeyDown: (event) => handleDropdownKeyDown(event), children: [props.searchable ? (_jsxs("div", { className: "umds-select__search-container", children: [_jsx("div", { className: "umds-select__search-icon", children: _jsx(Icon, { size: "sm", icon: faMagnifyingGlass }) }), _jsx("input", { type: "text", className: "umds-select__search-input", ref: searchInputRef, placeholder: props.searchPlaceholder || "Buscar...", "aria-label": props.searchAriaLabel || "Buscar", value: searchTerm, onInput: (e) => handleSearch(e) }), props.searchVariant === "inline" ? (_jsx("button", { type: "button", className: "umds-select__search-close", "aria-label": props.closeSearchAriaLabel || "Fechar busca", onClick: (event) => closeSearch(), onKeyDown: (event) => handleSearchCloseKeyDown(event), children: _jsx(Icon, { size: "sm", icon: faXmark }) })) : null] })) : null, _jsxs("div", { role: "listbox", className: "umds-select__options", id: listboxIdText(), "aria-multiselectable": props.multiple ? "true" : undefined, onScroll: (e) => onScrollList(e), children: [filteredOptionsList().length === 0 && !props.loading ? (_jsx("div", { className: "umds-select__no-options", children: _jsx(Text, { variant: "body2", color: "secondary", children: props.emptyLabel || "Nenhum item encontrado" }) })) : null, filteredOptionsList()?.map((option, index) => (_jsxs("div", { role: "option", id: optionIdText(index), "aria-selected": isOptionSelected(option.value), onClick: (event) => selectOption(option), className: [
654
+ selectedOptionsList().length > 0 ? (_jsx("div", { className: "umds-select__tags", children: selectedOptionsList()?.map((opt) => (_jsx(Tag, { size: "sm", label: opt.label, closable: true, disabled: props.disabled, onClose: (e) => removeValue(opt.value, e) }, opt.value))) })) : null] }), _jsxs("div", { className: "umds-select__actions", children: [props.loading ? _jsx(Spinner, { size: "sm", variant: "secondary" }) : null, _jsx("div", { className: "umds-select__arrow", children: _jsx(Icon, { size: "sm", icon: opened() ? faChevronUp : faChevronDown }) })] })] })) : null, opened() ? (_jsxs("div", { className: "umds-select__dropdown", ref: dropdownRef, style: dropdownStyle(), onKeyDown: (event) => handleDropdownKeyDown(event), children: [props.searchable ? (_jsxs("div", { className: "umds-select__search-container", children: [_jsx("div", { className: "umds-select__search-icon", children: _jsx(Icon, { size: "sm", icon: faMagnifyingGlass }) }), _jsx("input", { type: "text", className: "umds-select__search-input", ref: searchInputRef, placeholder: props.searchPlaceholder || "Buscar...", "aria-label": props.searchAriaLabel || "Buscar", value: searchTerm, onInput: (e) => handleSearch(e) }), props.searchVariant === "inline" ? (_jsx("button", { type: "button", className: "umds-select__search-close", "aria-label": props.closeSearchAriaLabel || "Fechar busca", onClick: (event) => closeSearch(), onKeyDown: (event) => handleSearchCloseKeyDown(event), children: _jsx(Icon, { size: "sm", icon: faXmark }) })) : null] })) : null, _jsxs("div", { role: "listbox", className: "umds-select__options", id: listboxIdText(), "aria-multiselectable": props.multiple ? "true" : undefined, onScroll: (e) => onScrollList(e), children: [filteredOptionsList().length === 0 && !props.loading ? (_jsx("div", { className: "umds-select__no-options", children: _jsx(Text, { variant: "body2", color: "secondary", children: props.emptyLabel || "Nenhum item encontrado" }) })) : null, filteredOptionsList()?.map((option, index) => (_jsxs("div", { role: "option", id: optionIdText(index), "aria-selected": isOptionSelected(option.value), onClick: (event) => selectOption(option), className: [
427
655
  "umds-select__option",
428
656
  isOptionSelected(option.value)
429
657
  ? "umds-select__option--selected"
@@ -431,7 +659,9 @@ function Select(props) {
431
659
  index === activeIndex ? "umds-select__option--active" : "",
432
660
  ]
433
661
  .filter(Boolean)
434
- .join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null, _jsx("div", { className: "umds-select__option-content", children: _jsx(_Fragment, { children: props.item || (_jsx(Text, { variant: "body2", children: option.label })) }) }), !props.multiple && isOptionSelected(option.value) ? (_jsx("div", { className: "umds-select__option-check", children: _jsx(Icon, { size: "sm", icon: faCheck }) })) : null] }, option.value))), props.loading && props.pagination ? (_jsxs("div", { className: "umds-select__loading-more", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { variant: "caption", children: props.loadingLabel || "Carregando mais..." })] })) : null] })] })) : null] }), props.name ? (_jsx("input", { type: "hidden", name: props.name, value: formValue() || "" })) : null, props.errorMessage ? (_jsx(Text, { variant: "caption", color: "negative", className: "umds-select__error-message", id: errorIdText(), children: props.errorMessage })) : null, mostraApoio() ? (_jsx(Text, { variant: "caption", color: "secondary", className: "umds-select__description", id: helperIdText(), children: textoDeApoio() })) : null, props.multiple &&
662
+ .join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null, option.color ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__swatch", style: {
663
+ background: option.color,
664
+ } })) : null, _jsx("div", { className: "umds-select__option-content", children: _jsx(_Fragment, { children: props.item || (_jsx(Text, { variant: "body2", children: option.label })) }) }), !props.multiple && isOptionSelected(option.value) ? (_jsx("div", { className: "umds-select__option-check", children: _jsx(Icon, { size: "sm", icon: faCheck }) })) : null] }, option.value))), props.loading && props.pagination ? (_jsxs("div", { className: "umds-select__loading-more", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { variant: "caption", children: props.loadingLabel || "Carregando mais..." })] })) : null] }), props.footer ? (_jsx("div", { className: "umds-select__footer", children: _jsx(_Fragment, { children: props.footer }) })) : null] })) : null] }), props.name ? (_jsx("input", { type: "hidden", name: props.name, value: formValue() || "" })) : null, props.errorMessage ? (_jsx(Text, { variant: "caption", color: "negative", className: "umds-select__error-message", id: errorIdText(), children: props.errorMessage })) : null, mostraApoio() ? (_jsx(Text, { variant: "caption", color: "secondary", className: "umds-select__description", id: helperIdText(), children: textoDeApoio() })) : null, props.multiple &&
435
665
  props.selectionDisplay === "list" &&
436
666
  selectedOptionsList().length > 0 ? (_jsx("div", { className: "umds-select__selected-list", children: selectedOptionsList()?.map((opt) => (_jsxs("div", { className: "umds-select__selected-list-item", children: [_jsx(Text, { variant: "body2", children: opt.label }), _jsx("button", { type: "button", className: "umds-select__list-remove", "aria-label": removeItemAriaLabelText(opt.label), onClick: (e) => removeValue(opt.value, e), children: _jsx(Icon, { size: "sm", icon: faTrash }) })] }, opt.value))) })) : null] }));
437
667
  }
@@ -55,3 +55,52 @@
55
55
  .umds-stack--justify-between { justify-content: space-between; }
56
56
  .umds-stack--justify-around { justify-content: space-around; }
57
57
  .umds-stack--justify-evenly { justify-content: space-evenly; }
58
+
59
+ /* ── Sem espaço ── */
60
+ .umds-stack--gap-none { gap: 0; }
61
+
62
+ /* ── Lista: ul/ol sem marcador, margem nem recuo do navegador ── */
63
+ ul.umds-stack,
64
+ ol.umds-stack {
65
+ list-style: none;
66
+ margin: 0;
67
+ padding: 0;
68
+ }
69
+
70
+ /* ── Como item de outro Stack/flex ── */
71
+ .umds-stack--grow { flex-grow: 1; }
72
+ .umds-stack--shrink-0 { flex-shrink: 0; }
73
+ .umds-stack--shrink-1 { flex-shrink: 1; }
74
+
75
+ .umds-stack--basis-auto { flex-basis: auto; }
76
+ .umds-stack--basis-0 { flex-basis: 0; }
77
+ .umds-stack--basis-25 { flex-basis: 25%; }
78
+ .umds-stack--basis-33 { flex-basis: 33.3333%; }
79
+ .umds-stack--basis-50 { flex-basis: 50%; }
80
+ .umds-stack--basis-66 { flex-basis: 66.6667%; }
81
+ .umds-stack--basis-75 { flex-basis: 75%; }
82
+ .umds-stack--basis-100 { flex-basis: 100%; }
83
+
84
+ /* O padrão do Stack já é min-width: 0; estas duas só tornam a escolha explícita. */
85
+ .umds-stack--min-w-0 { min-width: 0; }
86
+ .umds-stack--min-w-auto { min-width: auto; }
87
+
88
+ /* ── Overflow: o eixo vem depois do geral, então vence por ordem de cascata ── */
89
+ .umds-stack--overflow-visible { overflow: visible; }
90
+ .umds-stack--overflow-hidden { overflow: hidden; }
91
+ .umds-stack--overflow-auto { overflow: auto; }
92
+ .umds-stack--overflow-scroll { overflow: scroll; }
93
+
94
+ .umds-stack--overflow-x-visible { overflow-x: visible; }
95
+ .umds-stack--overflow-x-hidden { overflow-x: hidden; }
96
+ .umds-stack--overflow-x-auto { overflow-x: auto; }
97
+ .umds-stack--overflow-x-scroll { overflow-x: scroll; }
98
+
99
+ .umds-stack--overflow-y-visible { overflow-y: visible; }
100
+ .umds-stack--overflow-y-hidden { overflow-y: hidden; }
101
+ .umds-stack--overflow-y-auto { overflow-y: auto; }
102
+ .umds-stack--overflow-y-scroll { overflow-y: scroll; }
103
+
104
+ /* ── Dimensão ── */
105
+ .umds-stack--full-height { height: 100%; }
106
+ .umds-stack--full-width { width: 100%; }
@@ -1,27 +1,60 @@
1
1
  import './Stack.css';
2
- /** Degraus da escala oficial de espaçamento do 1DS. */
3
- export type StackSpacing = "quarck" | "nano" | "micro" | "mini" | "xxxs" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | "xxxl";
2
+ /** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
3
+ export type StackSpacing = "none" | "quarck" | "nano" | "micro" | "mini" | "xxxs" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | "xxxl";
4
+ /** Elemento HTML que o Stack renderiza. */
5
+ /** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
6
+ /** Elemento HTML que o Stack renderiza. */
7
+ export type StackTag = "div" | "span" | "ul" | "ol" | "li" | "section" | "nav" | "header" | "footer" | "form";
8
+ /** Valores de `overflow` aceitos (por eixo ou nos dois). */
9
+ /** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
10
+ /** Elemento HTML que o Stack renderiza. */
11
+ /** Valores de `overflow` aceitos (por eixo ou nos dois). */
12
+ export type StackOverflow = "visible" | "hidden" | "auto" | "scroll";
4
13
  /**
5
14
  * Stack — empilha os filhos com espaçamento da escala do DS.
6
15
  *
7
16
  * Existe para eliminar o `style={{ display: "flex", gap: 16 }}` escrito à mão,
8
17
  * que é por onde o design system vaza: o 16 sai da cabeça de quem escreve, não
9
18
  * do token. Aqui o `gap` só aceita degraus da escala oficial.
19
+ *
20
+ * Também é o item de outro Stack: quem precisa crescer, encolher ou ocupar a
21
+ * altura toda dentro de um Stack pai aninha um Stack com `grow`, `shrink`,
22
+ * `basis`, `fullHeight`... (não existe `Stack.Item`: subcomponente por ponto
23
+ * não sobrevive aos dois geradores, e o Stack aninhado já é um item flex).
24
+ *
25
+ * Atributos HTML (`id`, `style`, `title`, `role`, `tabIndex`, `data-*`,
26
+ * `aria-*`) vão para o elemento raiz. Com `as="nav"`, `section` ou `form`,
27
+ * passe `aria-label` ou `aria-labelledby`: a região só é anunciada se tiver nome.
28
+ * @property {string} as - Elemento HTML: 'div' (padrão) | 'span' | 'ul' | 'ol' | 'li' | 'section' | 'nav' | 'header' | 'footer' | 'form'
10
29
  * @property {string} direction - Eixo do empilhamento: 'vertical' (padrão) | 'horizontal'
11
- * @property {string} gap - Espaço entre os filhos, na escala do DS
30
+ * @property {string} gap - Espaço entre os filhos, na escala do DS ('none' zera)
12
31
  * @property {string} align - Alinhamento no eixo transversal
13
32
  * @property {string} justify - Distribuição no eixo principal
14
33
  * @property {boolean} wrap - Permite quebrar em várias linhas
15
34
  * @property {boolean} inline - Usa display inline-flex em vez de flex
35
+ * @property {boolean} grow - Como item de outro Stack/flex: cresce para ocupar o espaço livre
36
+ * @property {string} shrink - Como item flex: '0' não encolhe, '1' encolhe
37
+ * @property {string} basis - Como item flex: tamanho base ('auto', '0', '25', '33', '50', '66', '75', '100'; os números são %)
38
+ * @property {string} minWidth - '0' (padrão do Stack) deixa o conteúdo longo encolher; 'auto' devolve o mínimo do conteúdo
39
+ * @property {string} overflow - Overflow nos dois eixos
40
+ * @property {string} overflowX - Overflow horizontal
41
+ * @property {string} overflowY - Overflow vertical
42
+ * @property {boolean} fullHeight - Ocupa 100% da altura do pai
43
+ * @property {boolean} fullWidth - Ocupa 100% da largura do pai
16
44
  * @property {string} className - Classes CSS adicionais
17
- * @quandoUsar Empilhar elementos com espaçamento consistente: campos de um formulário, botões de uma barra de ações, itens de uma lista. É o jeito certo de dar respiro sem escrever CSS.
18
- * @quandoNaoUsar Para layout em COLUNAS que se alinham entre si — use `Grid`. Para uma caixa com padding e fundo, use `Box`. Stack só distribui no eixo, não desenha nada.
45
+ * @property {function} onSubmit - Só com as="form": callback do envio
46
+ * @quandoUsar Empilhar elementos com espaçamento consistente: campos de um formulário, botões de uma barra de ações, itens de uma lista (`as="ul"` com filhos `as="li"`). É o jeito certo de dar respiro sem escrever CSS, e de fazer uma região crescer ou rolar dentro de outra.
47
+ * @quandoNaoUsar Para layout em COLUNAS que se alinham entre si — use `Grid`. Para uma caixa com padding e fundo, use `Box` (que também aceita direction e gap quando a superfície é a própria linha ou região). Stack só distribui no eixo, não desenha nada.
19
48
  */
20
- /** Degraus da escala oficial de espaçamento do 1DS. */
49
+ /** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
50
+ /** Elemento HTML que o Stack renderiza. */
51
+ /** Valores de `overflow` aceitos (por eixo ou nos dois). */
21
52
  export interface StackProps {
53
+ /** Elemento HTML renderizado. @default 'div' */
54
+ as?: StackTag;
22
55
  /** Eixo do empilhamento. @default 'vertical' */
23
56
  direction?: "vertical" | "horizontal";
24
- /** Espaço entre os filhos, na escala oficial (xxxs = 16px). @default 'xxxs' */
57
+ /** Espaço entre os filhos, na escala oficial (xxxs = 16px; `none` = 0). @default 'xxxs' */
25
58
  gap?: StackSpacing;
26
59
  /** Alinhamento no eixo transversal. */
27
60
  align?: "start" | "center" | "end" | "stretch" | "baseline";
@@ -31,8 +64,33 @@ export interface StackProps {
31
64
  wrap?: boolean;
32
65
  /** Usa `inline-flex` em vez de `flex`. */
33
66
  inline?: boolean;
67
+ /** Como item de outro Stack/flex: cresce para ocupar o espaço livre. */
68
+ grow?: boolean;
69
+ /** Como item flex: `"0"` não encolhe; `"1"` encolhe. */
70
+ shrink?: "0" | "1";
71
+ /** Como item flex: tamanho base. Os números são porcentagem do pai. */
72
+ basis?: "auto" | "0" | "25" | "33" | "50" | "66" | "75" | "100";
73
+ /** `"0"` (já é o padrão do Stack) deixa o conteúdo encolher; `"auto"` volta ao mínimo do conteúdo. */
74
+ minWidth?: "0" | "auto";
75
+ /** Overflow nos dois eixos. */
76
+ overflow?: StackOverflow;
77
+ /** Overflow horizontal (vence `overflow` no eixo X). */
78
+ overflowX?: StackOverflow;
79
+ /** Overflow vertical (vence `overflow` no eixo Y). */
80
+ overflowY?: StackOverflow;
81
+ /** Ocupa 100% da altura do pai. */
82
+ fullHeight?: boolean;
83
+ /** Ocupa 100% da largura do pai. */
84
+ fullWidth?: boolean;
34
85
  /** Classes CSS adicionais. */
35
86
  className?: string;
87
+ /** Só com `as="form"`: chamado no envio do formulário. */
88
+ onSubmit?: (event: any) => void;
89
+ /** ID HTML do elemento raiz. */
90
+ id?: string;
91
+ /** Atributos HTML repassados ao elemento raiz (style, data-*, aria-*…). */
92
+ style?: any;
93
+ [key: string]: any;
36
94
  /** Conteúdo empilhado. */
37
95
  children?: any;
38
96
  }