@1doc/1ds-react 2.7.2 → 2.9.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 (302) hide show
  1. package/CHANGELOG.md +1280 -0
  2. package/dist/components/AIContent/AIContent.d.ts +10 -0
  3. package/dist/components/AIContent/AIContent.js +1 -1
  4. package/dist/components/AILabel/AILabel.d.ts +4 -0
  5. package/dist/components/AILabel/AILabel.js +2 -2
  6. package/dist/components/Accordion/Accordion.d.ts +6 -2
  7. package/dist/components/Alert/Alert.css +2 -0
  8. package/dist/components/Alert/Alert.d.ts +3 -1
  9. package/dist/components/Alert/Alert.js +7 -1
  10. package/dist/components/AppHeader/AppHeader.css +82 -8
  11. package/dist/components/AppHeader/AppHeader.d.ts +12 -1
  12. package/dist/components/AppHeader/AppHeader.js +186 -1
  13. package/dist/components/AppNavItem/AppNavItem.css +11 -3
  14. package/dist/components/AppShell/AppShell.css +9 -0
  15. package/dist/components/AppShell/AppShell.d.ts +8 -0
  16. package/dist/components/AppShell/AppShell.js +4 -1
  17. package/dist/components/AppSidebar/AppSidebar.css +1 -1
  18. package/dist/components/AppSidebar/AppSidebar.d.ts +4 -0
  19. package/dist/components/AppSidebar/AppSidebar.js +3 -1
  20. package/dist/components/AttachmentCard/AttachmentCard.css +17 -1
  21. package/dist/components/AttachmentCard/AttachmentCard.d.ts +29 -2
  22. package/dist/components/AttachmentCard/AttachmentCard.js +88 -20
  23. package/dist/components/Avatar/Avatar.css +7 -2
  24. package/dist/components/Avatar/AvatarGroup.d.ts +27 -0
  25. package/dist/components/Avatar/AvatarGroup.js +28 -4
  26. package/dist/components/Badge/Badge.css +61 -3
  27. package/dist/components/Badge/Badge.d.ts +14 -4
  28. package/dist/components/Badge/Badge.js +1 -0
  29. package/dist/components/BottomSheet/BottomSheet.css +1 -0
  30. package/dist/components/BottomSheet/BottomSheet.d.ts +8 -0
  31. package/dist/components/BottomSheet/BottomSheet.js +14 -2
  32. package/dist/components/Box/Box.css +83 -0
  33. package/dist/components/Box/Box.d.ts +82 -2
  34. package/dist/components/Box/Box.js +42 -2
  35. package/dist/components/Button/Button.css +29 -0
  36. package/dist/components/Button/Button.d.ts +4 -4
  37. package/dist/components/Button/Button.js +4 -1
  38. package/dist/components/Calendar/Calendar.css +245 -0
  39. package/dist/components/Calendar/Calendar.d.ts +125 -0
  40. package/dist/components/Calendar/Calendar.js +320 -0
  41. package/dist/components/Chart/BarChart.d.ts +6 -0
  42. package/dist/components/Chart/BarChart.js +3 -1
  43. package/dist/components/Chart/LineChart.d.ts +6 -0
  44. package/dist/components/Chart/LineChart.js +3 -1
  45. package/dist/components/Checkbox/Checkbox.css +4 -1
  46. package/dist/components/Chips/Chips.css +39 -0
  47. package/dist/components/Chips/Chips.d.ts +7 -2
  48. package/dist/components/Chips/Chips.js +6 -2
  49. package/dist/components/Coachmark/Coachmark.css +118 -0
  50. package/dist/components/Coachmark/Coachmark.d.ts +75 -0
  51. package/dist/components/Coachmark/Coachmark.js +321 -0
  52. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  53. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  54. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  55. package/dist/components/ColorPicker/ColorPicker.css +133 -0
  56. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  57. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  58. package/dist/components/Combobox/Combobox.css +11 -3
  59. package/dist/components/ConfirmAIAction/ConfirmAIAction.d.ts +11 -1
  60. package/dist/components/ConfirmAIAction/ConfirmAIAction.js +6 -1
  61. package/dist/components/ConfirmDialog/ConfirmDialog.css +3 -0
  62. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +14 -0
  63. package/dist/components/ConfirmDialog/ConfirmDialog.js +2 -2
  64. package/dist/components/DataTable/DataTable.css +80 -0
  65. package/dist/components/DataTable/DataTable.d.ts +23 -4
  66. package/dist/components/DataTable/DataTable.js +61 -15
  67. package/dist/components/DatePicker/DatePicker.css +8 -0
  68. package/dist/components/DatePicker/DatePicker.d.ts +4 -0
  69. package/dist/components/DatePicker/DatePicker.js +14 -1
  70. package/dist/components/DescriptionList/DescriptionList.css +113 -0
  71. package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
  72. package/dist/components/DescriptionList/DescriptionList.js +51 -0
  73. package/dist/components/Drawer/Drawer.css +1 -0
  74. package/dist/components/Dropdown/Dropdown.js +47 -29
  75. package/dist/components/FileInput/FileInput.css +24 -4
  76. package/dist/components/FileInput/FileInput.d.ts +22 -2
  77. package/dist/components/FileInput/FileInput.js +23 -2
  78. package/dist/components/Grid/Grid.js +5 -5
  79. package/dist/components/IconPicker/IconPicker.css +107 -0
  80. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  81. package/dist/components/IconPicker/IconPicker.js +194 -0
  82. package/dist/components/Input/Input.css +41 -3
  83. package/dist/components/Input/Input.d.ts +14 -1
  84. package/dist/components/Input/Input.js +72 -6
  85. package/dist/components/Kanban/Kanban.css +5 -0
  86. package/dist/components/Kanban/Kanban.d.ts +41 -0
  87. package/dist/components/Kanban/Kanban.js +59 -27
  88. package/dist/components/Kanban/KanbanCard.d.ts +2 -0
  89. package/dist/components/Kanban/KanbanCard.js +1 -1
  90. package/dist/components/Kanban/KanbanColumn.d.ts +2 -0
  91. package/dist/components/Kanban/KanbanColumn.js +3 -0
  92. package/dist/components/Kbd/Kbd.css +66 -0
  93. package/dist/components/Kbd/Kbd.d.ts +32 -0
  94. package/dist/components/Kbd/Kbd.js +40 -0
  95. package/dist/components/Link/Link.css +1 -1
  96. package/dist/components/List/List.css +136 -0
  97. package/dist/components/List/List.d.ts +82 -0
  98. package/dist/components/List/List.js +53 -0
  99. package/dist/components/List/ListItem.d.ts +85 -0
  100. package/dist/components/List/ListItem.js +81 -0
  101. package/dist/components/Modal/Modal.css +93 -8
  102. package/dist/components/Modal/Modal.d.ts +45 -7
  103. package/dist/components/Modal/Modal.js +106 -6
  104. package/dist/components/MultiSelect/MultiSelect.css +9 -1
  105. package/dist/components/MultiSelect/MultiSelect.js +45 -8
  106. package/dist/components/OrgChart/OrgChart.css +149 -0
  107. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  108. package/dist/components/OrgChart/OrgChart.js +297 -0
  109. package/dist/components/OtpInput/OtpInput.css +93 -0
  110. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  111. package/dist/components/OtpInput/OtpInput.js +215 -0
  112. package/dist/components/Pagination/Pagination.d.ts +6 -0
  113. package/dist/components/Pagination/Pagination.js +9 -1
  114. package/dist/components/PhoneInput/PhoneInput.css +9 -1
  115. package/dist/components/PhoneInput/PhoneInput.d.ts +10 -0
  116. package/dist/components/PhoneInput/PhoneInput.js +20 -3
  117. package/dist/components/Popover/Popover.d.ts +7 -0
  118. package/dist/components/Popover/Popover.js +11 -1
  119. package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
  120. package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
  121. package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
  122. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  123. package/dist/components/SegmentedControl/SegmentedControl.js +21 -8
  124. package/dist/components/Select/Select.css +71 -1
  125. package/dist/components/Select/Select.d.ts +12 -0
  126. package/dist/components/Select/Select.js +93 -10
  127. package/dist/components/SidePanel/SidePanel.css +4 -4
  128. package/dist/components/SidePanelItem/SidePanelItem.css +7 -5
  129. package/dist/components/SidePanelSearch/SidePanelSearch.css +2 -2
  130. package/dist/components/SidePanelSection/SidePanelSection.css +7 -5
  131. package/dist/components/Stack/Stack.css +49 -0
  132. package/dist/components/Stack/Stack.d.ts +65 -7
  133. package/dist/components/Stack/Stack.js +30 -2
  134. package/dist/components/StatCard/StatCard.css +73 -0
  135. package/dist/components/StatCard/StatCard.d.ts +17 -0
  136. package/dist/components/StatCard/StatCard.js +4 -1
  137. package/dist/components/Stepper/Stepper.css +4 -1
  138. package/dist/components/Stepper/Stepper.d.ts +8 -0
  139. package/dist/components/Stepper/Stepper.js +4 -4
  140. package/dist/components/Switch/Switch.css +1 -0
  141. package/dist/components/Tabs/Tab.d.ts +15 -0
  142. package/dist/components/Tabs/Tab.js +30 -1
  143. package/dist/components/Tabs/Tabs.css +132 -0
  144. package/dist/components/Tabs/Tabs.d.ts +7 -0
  145. package/dist/components/Tabs/Tabs.js +13 -2
  146. package/dist/components/Tag/Tag.css +85 -2
  147. package/dist/components/Tag/Tag.d.ts +13 -6
  148. package/dist/components/Tag/Tag.js +1 -0
  149. package/dist/components/Text/Text.d.ts +9 -1
  150. package/dist/components/Text/Text.js +2 -2
  151. package/dist/components/Textarea/Textarea.css +11 -3
  152. package/dist/components/TimePicker/TimePicker.css +8 -0
  153. package/dist/components/TimePicker/TimePicker.d.ts +6 -0
  154. package/dist/components/TimePicker/TimePicker.js +1 -1
  155. package/dist/components/Tooltip/Tooltip.css +40 -0
  156. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  157. package/dist/components/Tooltip/Tooltip.js +114 -11
  158. package/dist/index.d.ts +25 -0
  159. package/dist/index.js +14 -0
  160. package/dist/teste/AILabel.test.d.ts +1 -0
  161. package/dist/teste/AILabel.test.js +33 -0
  162. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  163. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  164. package/dist/teste/Alert.test.d.ts +1 -0
  165. package/dist/teste/Alert.test.js +27 -0
  166. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  167. package/dist/teste/AtributosRepassados.test.js +52 -0
  168. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  169. package/dist/teste/AttachmentCardIA.test.js +89 -0
  170. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  171. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  172. package/dist/teste/BadgeTag.test.d.ts +1 -0
  173. package/dist/teste/BadgeTag.test.js +42 -0
  174. package/dist/teste/BottomSheet.test.d.ts +1 -0
  175. package/dist/teste/BottomSheet.test.js +23 -0
  176. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  177. package/dist/teste/BoxItemFlex.test.js +54 -0
  178. package/dist/teste/BoxLayout.test.d.ts +1 -0
  179. package/dist/teste/BoxLayout.test.js +35 -0
  180. package/dist/teste/Button.test.d.ts +1 -0
  181. package/dist/teste/Button.test.js +27 -0
  182. package/dist/teste/Calendar.test.d.ts +1 -0
  183. package/dist/teste/Calendar.test.js +221 -0
  184. package/dist/teste/ChipsXs.test.d.ts +1 -0
  185. package/dist/teste/ChipsXs.test.js +31 -0
  186. package/dist/teste/Coachmark.test.d.ts +1 -0
  187. package/dist/teste/Coachmark.test.js +149 -0
  188. package/dist/teste/ColorPicker.test.d.ts +1 -0
  189. package/dist/teste/ColorPicker.test.js +132 -0
  190. package/dist/teste/ConfirmAIAction.test.d.ts +1 -0
  191. package/dist/teste/ConfirmAIAction.test.js +33 -0
  192. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  193. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  194. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  195. package/dist/teste/DataTableDocumento.test.js +92 -0
  196. package/dist/teste/DatePicker.test.js +23 -0
  197. package/dist/teste/Dropdown.test.js +111 -0
  198. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  199. package/dist/teste/FileInputTrigger.test.js +53 -0
  200. package/dist/teste/IconPicker.test.d.ts +1 -0
  201. package/dist/teste/IconPicker.test.js +130 -0
  202. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  203. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  204. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  205. package/dist/teste/KbdCodeBlock.test.js +95 -0
  206. package/dist/teste/List.test.d.ts +1 -0
  207. package/dist/teste/List.test.js +153 -0
  208. package/dist/teste/Modal.test.d.ts +1 -0
  209. package/dist/teste/Modal.test.js +26 -0
  210. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  211. package/dist/teste/ModalVariantes.test.js +151 -0
  212. package/dist/teste/MultiSelectErro.test.d.ts +1 -0
  213. package/dist/teste/MultiSelectErro.test.js +62 -0
  214. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  215. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  216. package/dist/teste/OrgChart.test.d.ts +1 -0
  217. package/dist/teste/OrgChart.test.js +162 -0
  218. package/dist/teste/OtpInput.test.d.ts +1 -0
  219. package/dist/teste/OtpInput.test.js +143 -0
  220. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  221. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  222. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  223. package/dist/teste/RichTextEditor.test.js +287 -0
  224. package/dist/teste/RotulosTraduziveis.test.d.ts +1 -0
  225. package/dist/teste/RotulosTraduziveis.test.js +405 -0
  226. package/dist/teste/SegmentedControl.test.js +33 -0
  227. package/dist/teste/Select.test.d.ts +1 -0
  228. package/dist/teste/Select.test.js +62 -0
  229. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  230. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  231. package/dist/teste/Stack.test.d.ts +1 -0
  232. package/dist/teste/Stack.test.js +57 -0
  233. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  234. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  235. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  236. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  237. package/dist/teste/Tooltip.test.d.ts +1 -0
  238. package/dist/teste/Tooltip.test.js +109 -0
  239. package/dist/teste/TooltipDark.test.d.ts +1 -0
  240. package/dist/teste/TooltipDark.test.js +31 -0
  241. package/dist/utils/calendario.d.ts +28 -0
  242. package/dist/utils/calendario.js +73 -0
  243. package/dist/utils/chart.d.ts +4 -0
  244. package/dist/utils/chart.js +3 -2
  245. package/dist/utils/html-seguro.d.ts +27 -0
  246. package/dist/utils/html-seguro.js +97 -0
  247. package/dist/utils/id.d.ts +2 -0
  248. package/dist/utils/id.js +23 -0
  249. package/dist/utils/paleta-de-cores.d.ts +26 -0
  250. package/dist/utils/paleta-de-cores.js +10 -0
  251. package/dist/utils/texto.d.ts +5 -0
  252. package/dist/utils/texto.js +5 -0
  253. package/package.json +3 -3
  254. package/src/index.ts +26 -0
  255. package/src/teste/AILabel.test.tsx +41 -0
  256. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  257. package/src/teste/Alert.test.tsx +32 -0
  258. package/src/teste/AtributosRepassados.test.tsx +73 -0
  259. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  260. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  261. package/src/teste/BadgeTag.test.tsx +64 -0
  262. package/src/teste/BottomSheet.test.tsx +25 -0
  263. package/src/teste/BoxItemFlex.test.tsx +81 -0
  264. package/src/teste/BoxLayout.test.tsx +50 -0
  265. package/src/teste/Button.test.tsx +39 -0
  266. package/src/teste/Calendar.test.tsx +282 -0
  267. package/src/teste/ChipsXs.test.tsx +41 -0
  268. package/src/teste/Coachmark.test.tsx +198 -0
  269. package/src/teste/ColorPicker.test.tsx +153 -0
  270. package/src/teste/ConfirmAIAction.test.tsx +41 -0
  271. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  272. package/src/teste/DataTableDocumento.test.tsx +102 -0
  273. package/src/teste/DatePicker.test.tsx +38 -0
  274. package/src/teste/Dropdown.test.tsx +146 -0
  275. package/src/teste/FileInputTrigger.test.tsx +89 -0
  276. package/src/teste/IconPicker.test.tsx +145 -0
  277. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  278. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  279. package/src/teste/List.test.tsx +269 -0
  280. package/src/teste/Modal.test.tsx +28 -0
  281. package/src/teste/ModalVariantes.test.tsx +173 -0
  282. package/src/teste/MultiSelectErro.test.tsx +97 -0
  283. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  284. package/src/teste/OrgChart.test.tsx +183 -0
  285. package/src/teste/OtpInput.test.tsx +163 -0
  286. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  287. package/src/teste/RichTextEditor.test.tsx +329 -0
  288. package/src/teste/RotulosTraduziveis.test.tsx +545 -0
  289. package/src/teste/SegmentedControl.test.tsx +57 -0
  290. package/src/teste/Select.test.tsx +97 -0
  291. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  292. package/src/teste/Stack.test.tsx +80 -0
  293. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  294. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  295. package/src/teste/Tooltip.test.tsx +219 -0
  296. package/src/teste/TooltipDark.test.tsx +51 -0
  297. package/src/utils/calendario.ts +78 -0
  298. package/src/utils/chart.ts +7 -2
  299. package/src/utils/html-seguro.ts +94 -0
  300. package/src/utils/id.ts +24 -0
  301. package/src/utils/paleta-de-cores.ts +34 -0
  302. package/src/utils/texto.ts +5 -0
@@ -80,6 +80,13 @@
80
80
  color: var(--umds-semantic-color-feedback-negative-dark);
81
81
  }
82
82
 
83
+ /* Selo de recurso de IA: o roxo da IA (mesmos tokens do AILabel). */
84
+ .umds-attachment-card__status--ai {
85
+ border-color: color-mix(in srgb, var(--umds-semantic-color-ai-pure) 25%, transparent);
86
+ background-color: var(--umds-semantic-color-ai-light);
87
+ color: var(--umds-semantic-color-ai-dark);
88
+ }
89
+
83
90
  /* Selo com painel de conferência: vira botão, e fica acima do `::after` do
84
91
  "abrir" — senão o clique no selo abriria o arquivo. */
85
92
  .umds-attachment-card__status--interativo {
@@ -101,6 +108,11 @@
101
108
  border-color: var(--umds-semantic-color-feedback-negative-pure);
102
109
  }
103
110
 
111
+ .umds-attachment-card__status--interativo.umds-attachment-card__status--ai:hover,
112
+ .umds-attachment-card__status--interativo.umds-attachment-card__status--ai[aria-expanded="true"] {
113
+ border-color: var(--umds-semantic-color-ai-pure);
114
+ }
115
+
104
116
  .umds-attachment-card__status--interativo:focus-visible {
105
117
  outline: 2px solid var(--umds-semantic-color-primary-pure);
106
118
  outline-offset: 2px; /* anel de foco canônico: micro-espaçamento, candidato a token */
@@ -146,6 +158,10 @@
146
158
  color: var(--umds-semantic-color-feedback-negative-pure);
147
159
  }
148
160
 
161
+ .umds-attachment-card__detalhe-icone--ai {
162
+ color: var(--umds-semantic-color-ai-pure);
163
+ }
164
+
149
165
  .umds-attachment-card__detalhe-titulo {
150
166
  min-width: 0;
151
167
  font-size: var(--umds-primitive-font-size-xxs);
@@ -187,7 +203,7 @@
187
203
  }
188
204
 
189
205
  .umds-attachment-card__campo-valor {
190
- margin: 2px 0 0; /* candidato a novo token: respiro rótulo→valor */
206
+ margin: var(--umds-primitive-spacing-micro) 0 0; /* 2px: respiro rótulo→valor */
191
207
  font-size: var(--umds-primitive-font-size-xxs);
192
208
  font-weight: var(--umds-primitive-font-weight-bold);
193
209
  line-height: 1.4;
@@ -6,10 +6,13 @@ import './AttachmentCard.css';
6
6
  * @property {string} fileName - Nome do arquivo, com extensão. A extensão escolhe o ícone do rodapé.
7
7
  * @property {string} documentType - Tipo de documento que o arquivo cumpre ("CNH", "RG", "Título de Eleitor")
8
8
  * @property {boolean} required - O tipo de documento é obrigatório (asterisco no selo)
9
- * @property {string} status - Situação da conferência: 'positive' | 'negative'. Sem ela o selo não aparece.
9
+ * @property {string} status - Situação da conferência: 'positive' | 'negative' | 'ai'. O `ai` é o selo de recurso de IA (roxo da IA, com a varinha por padrão), para quando a IA propõe e a pessoa decide. Sem `status` o selo não aparece.
10
10
  * @property {string} statusLabel - Texto do selo de situação ("Pré-aprovado", "Rejeitado")
11
11
  * @property {IconProp} statusIcon - Ícone à esquerda do texto do selo
12
12
  * @property {object} statusDetails - Resultado da conferência: `{ title?, description?, fields?: [{ label, value, copyable? }] }`. Com ele o selo vira botão e abre um painel no hover (sem tirar o foco de onde está) e no clique/teclado (levando o foco para dentro).
13
+ * @property {any} panel - Conteúdo livre do painel do selo, no lugar do resultado da conferência (ações, campos, texto). Passe o elemento (React) ou o slot `panel` (Vue). Com ele o selo vira botão mesmo sem `statusDetails`.
14
+ * @property {number} panelWidth - Largura do painel, em px. Padrão: 300.
15
+ * @property {boolean} closePanelOnAction - Fecha o painel e devolve o foco ao selo quando alguém aciona um botão ou link de dentro dele (o botão "Aplicar sugestão" do painel de IA). O botão de copiar um campo não conta.
13
16
  * @property {Function} onCopyField - Avisa quando um campo do painel é copiado (recebe o campo)
14
17
  * @property {IconProp} icon - Ícone central. Padrão: documento.
15
18
  * @property {Function} onOpen - Abre o anexo. Com ele o cartão inteiro vira alvo de clique, com um único ponto de foco.
@@ -37,14 +40,38 @@ export interface AttachmentCardProps {
37
40
  fileName: string;
38
41
  documentType?: string;
39
42
  required?: boolean;
40
- status?: "positive" | "negative";
43
+ status?: "positive" | "negative" | "ai";
41
44
  statusLabel?: string;
42
45
  statusIcon?: IconProp;
43
46
  statusDetails?: AttachmentCardStatusDetails;
47
+ /**
48
+ * Conteúdo livre do painel do selo, no lugar do resultado da conferência
49
+ * (`statusDetails`): ações, campos, texto. React: o elemento; Vue: o slot
50
+ * `panel`. Com ele o selo vira botão mesmo sem `statusDetails`.
51
+ */
52
+ panel?: any;
53
+ /** Largura do painel, em px. @default 300 */
54
+ panelWidth?: number;
55
+ /**
56
+ * Fecha o painel e devolve o foco ao selo quando alguém aciona um botão ou
57
+ * link de dentro dele. O botão de copiar um campo não conta. Sem a prop, o
58
+ * painel fica aberto até Esc, clique fora ou o foco sair.
59
+ */
60
+ closePanelOnAction?: boolean;
44
61
  onCopyField?: (field: AttachmentCardField) => void;
45
62
  icon?: IconProp;
46
63
  onOpen?: (event?: any) => void;
47
64
  openAriaLabel?: string;
65
+ /** Complemento lido depois do selo, para dizer de qual documento ele é. Recebe o tipo de documento (ou o nome do arquivo). Troque para traduzir. @default (subject) => 'conferência de ' + subject */
66
+ statusContextLabel?: (subject: string) => string;
67
+ /** Texto lido depois do asterisco de obrigatório. Troque para traduzir. @default '(obrigatório)' */
68
+ requiredLabel?: string;
69
+ /** Nome acessível do botão de copiar um campo do painel. Recebe o rótulo do campo. Troque para traduzir. @default (field) => 'Copiar ' + field */
70
+ copyLabel?: (field: string) => string;
71
+ /** Nome acessível do botão e anúncio depois da cópia. Recebe o rótulo do campo. Troque para traduzir. @default (field) => field + ' copiado' */
72
+ copiedLabel?: (field: string) => string;
73
+ /** Anúncio quando a cópia falha. Recebe o rótulo do campo. Troque para traduzir. @default (field) => 'Não foi possível copiar ' + field */
74
+ copyErrorLabel?: (field: string) => string;
48
75
  className?: string;
49
76
  id?: string;
50
77
  }
@@ -4,7 +4,7 @@ import './AttachmentCard.css';
4
4
  import { useState, useRef, useEffect } from "react";
5
5
  import { computePosition, autoUpdate, offset, flip, shift, } from "@floating-ui/dom";
6
6
  import { faCopy, faFile, faFileLines, faFilePdf, faFileImage, faFileWord, faFileExcel, } from "@fortawesome/free-regular-svg-icons";
7
- import { faCheck, faCircleCheck, faCircleXmark, } from "@fortawesome/free-solid-svg-icons";
7
+ import { faCheck, faCircleCheck, faCircleXmark, faWandMagicSparkles, } from "@fortawesome/free-solid-svg-icons";
8
8
  import Icon from "../Icon/Icon";
9
9
  import Portal from "../Portal/Portal";
10
10
  const FOCAVEIS = 'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
@@ -47,7 +47,30 @@ function AttachmentCard(props) {
47
47
  return Boolean(props.status && props.statusLabel);
48
48
  }
49
49
  function temDetalhe() {
50
- return Boolean(temSelo() && props.statusDetails);
50
+ return Boolean(temSelo() && (props.statusDetails || props.panel));
51
+ }
52
+ function painelTemConteudoLivre() {
53
+ return Boolean(props.panel);
54
+ }
55
+ function seloIcone() {
56
+ if (props.statusIcon)
57
+ return props.statusIcon;
58
+ return props.status === "ai" ? faWandMagicSparkles : undefined;
59
+ }
60
+ function detalheEstilo() {
61
+ return props.panelWidth
62
+ ? {
63
+ width: props.panelWidth + "px",
64
+ }
65
+ : undefined;
66
+ }
67
+ function painelNomeadoPor() {
68
+ return props.panel ? undefined : tituloId();
69
+ }
70
+ function painelRotulo() {
71
+ if (!props.panel)
72
+ return undefined;
73
+ return (props.statusLabel || "") + seloComplemento();
51
74
  }
52
75
  function painelId() {
53
76
  return `${props.id || uid}-conferencia`;
@@ -62,7 +85,18 @@ function AttachmentCard(props) {
62
85
  return aberto ? painelId() : undefined;
63
86
  }
64
87
  function seloComplemento() {
65
- return `: conferência de ${props.documentType || props.fileName}`;
88
+ const assunto = props.documentType || props.fileName;
89
+ if (props.statusContextLabel)
90
+ return ": " + props.statusContextLabel(assunto);
91
+ return `: conferência de ${assunto}`;
92
+ }
93
+ function textoCopiado(rotulo) {
94
+ return props.copiedLabel ? props.copiedLabel(rotulo) : `${rotulo} copiado`;
95
+ }
96
+ function textoFalhaCopia(rotulo) {
97
+ return props.copyErrorLabel
98
+ ? props.copyErrorLabel(rotulo)
99
+ : `Não foi possível copiar ${rotulo}`;
66
100
  }
67
101
  function detalheTitulo() {
68
102
  return (props.statusDetails && props.statusDetails.title) || props.fileName;
@@ -74,6 +108,8 @@ function AttachmentCard(props) {
74
108
  return (props.statusDetails && props.statusDetails.fields) || [];
75
109
  }
76
110
  function detalheIcone() {
111
+ if (props.status === "ai")
112
+ return faWandMagicSparkles;
77
113
  return props.status === "negative" ? faCircleXmark : faCircleCheck;
78
114
  }
79
115
  function detalheIconeClasses() {
@@ -137,8 +173,36 @@ function AttachmentCard(props) {
137
173
  setPosX(Math.round(pos.x * dpr) / dpr);
138
174
  setPosY(Math.round(pos.y * dpr) / dpr);
139
175
  setPosicionado(true);
176
+ // No Vue o `onUpdate` NAO roda aqui: `posicionado` so e lido pelo
177
+ // estilo do flutuante, que mora no slot do Portal. Quem re-renderiza
178
+ // e o Portal (filho), e o `updated` do cartao nunca dispara, entao o
179
+ // foco nao entrava no painel. Um quadro depois o estilo ja foi
180
+ // aplicado nos dois frameworks; no React o `onUpdate` costuma chegar
181
+ // antes, e aqui vira no-op (`focarPainel` ja voltou a false).
182
+ if (focarPainel) {
183
+ if (typeof requestAnimationFrame !== "undefined") {
184
+ requestAnimationFrame(() => focarPainelSePreciso());
185
+ }
186
+ else {
187
+ setTimeout(() => focarPainelSePreciso(), 0);
188
+ }
189
+ }
140
190
  });
141
191
  }
192
+ function focarPainelSePreciso() {
193
+ if (!focarPainel || !aberto || !posicionado)
194
+ return;
195
+ if (!painelRef.current)
196
+ return;
197
+ const primeiro = painelRef.current.querySelector(FOCAVEIS);
198
+ if (primeiro) {
199
+ primeiro.focus();
200
+ }
201
+ else {
202
+ painelRef.current.focus();
203
+ }
204
+ setFocarPainel(false);
205
+ }
142
206
  function ligarObservadores() {
143
207
  if (!autoUpdateRef.current && seloRef.current && flutuanteRef.current) {
144
208
  autoUpdateRef.current = autoUpdate(seloRef.current, flutuanteRef.current, () => posicionar());
@@ -244,6 +308,18 @@ function AttachmentCard(props) {
244
308
  fechar(true);
245
309
  }
246
310
  }
311
+ function cliqueNoPainel(event) {
312
+ if (!props.closePanelOnAction)
313
+ return;
314
+ const alvo = event.target && event.target.closest
315
+ ? event.target.closest("button, a[href]")
316
+ : null;
317
+ if (!alvo)
318
+ return;
319
+ if (alvo.classList.contains("umds-attachment-card__copiar"))
320
+ return;
321
+ fechar(true);
322
+ }
247
323
  function teclaNoPainel(event) {
248
324
  if (event.key === "Escape") {
249
325
  event.preventDefault();
@@ -266,12 +342,12 @@ function AttachmentCard(props) {
266
342
  }
267
343
  function copiarCampo(campo) {
268
344
  if (typeof navigator === "undefined" || !navigator.clipboard) {
269
- setAnuncio(`Não foi possível copiar ${campo.label}`);
345
+ setAnuncio(textoFalhaCopia(campo.label));
270
346
  return;
271
347
  }
272
348
  navigator.clipboard.writeText(campo.value).then(() => {
273
349
  setCopiado(campo.label);
274
- setAnuncio(`${campo.label} copiado`);
350
+ setAnuncio(textoCopiado(campo.label));
275
351
  setTimeout(() => {
276
352
  if (copiado === campo.label)
277
353
  setCopiado("");
@@ -280,12 +356,14 @@ function AttachmentCard(props) {
280
356
  props.onCopyField(campo);
281
357
  }
282
358
  }, () => {
283
- setAnuncio(`Não foi possível copiar ${campo.label}`);
359
+ setAnuncio(textoFalhaCopia(campo.label));
284
360
  });
285
361
  }
286
362
  function rotuloCopiar(campo) {
287
- return copiado === campo.label
288
- ? `${campo.label} copiado`
363
+ if (copiado === campo.label)
364
+ return textoCopiado(campo.label);
365
+ return props.copyLabel
366
+ ? props.copyLabel(campo.label)
289
367
  : `Copiar ${campo.label}`;
290
368
  }
291
369
  function iconeCopiar(campo) {
@@ -300,17 +378,7 @@ function AttachmentCard(props) {
300
378
  if (aberto) {
301
379
  ligarObservadores();
302
380
  }
303
- // Espera `posicionado`: focar elemento com visibility:hidden é no-op.
304
- if (focarPainel && aberto && posicionado && painelRef.current) {
305
- const primeiro = painelRef.current.querySelector(FOCAVEIS);
306
- if (primeiro) {
307
- primeiro.focus();
308
- }
309
- else {
310
- painelRef.current.focus();
311
- }
312
- setFocarPainel(false);
313
- }
381
+ focarPainelSePreciso();
314
382
  });
315
383
  useEffect(() => {
316
384
  return () => {
@@ -318,6 +386,6 @@ function AttachmentCard(props) {
318
386
  desligarObservadores();
319
387
  };
320
388
  }, []);
321
- return (_jsxs("div", { className: classes(), id: props.id, children: [_jsxs("div", { className: "umds-attachment-card__topo", children: [temSelo() && !temDetalhe() ? (_jsxs("span", { className: statusClasses(), children: [props.statusIcon ? (_jsx(Icon, { size: "sm", variant: "inherit", icon: props.statusIcon })) : null, _jsx("span", { className: "umds-attachment-card__status-texto", children: props.statusLabel })] })) : null, temDetalhe() ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", "aria-haspopup": "dialog", ref: seloRef, className: statusBotaoClasses(), "aria-expanded": ariaExpandidoTexto(), "aria-controls": ariaControlsTexto(), onMouseEnter: (event) => abrir(false), onMouseLeave: (event) => agendarFechar(), onClick: (event) => alternar(), onKeyDown: (event) => teclaNoSelo(event), onBlur: (event) => focoSaiu(event), children: [props.statusIcon ? (_jsx(Icon, { size: "sm", variant: "inherit", icon: props.statusIcon })) : null, _jsx("span", { className: "umds-attachment-card__status-texto", children: props.statusLabel }), _jsx("span", { className: "umds-attachment-card__sr", children: seloComplemento() })] }), _jsx(Portal, { children: aberto ? (_jsx("span", { className: "umds-attachment-card__flutuante", ref: flutuanteRef, style: flutuanteEstilo(), children: _jsxs("div", { className: "umds-attachment-card__detalhe", role: "dialog", "aria-modal": "false", ref: painelRef, id: painelId(), "aria-labelledby": tituloId(), tabIndex: -1, onMouseEnter: (event) => cancelarFechar(), onMouseLeave: (event) => agendarFechar(), onKeyDown: (event) => teclaNoPainel(event), children: [_jsx("span", { className: "umds-attachment-card__sr", role: "status", "aria-live": "polite", children: anuncio }), _jsxs("div", { className: "umds-attachment-card__detalhe-topo", children: [_jsx("span", { "aria-hidden": "true", className: detalheIconeClasses(), children: _jsx(Icon, { size: "md", variant: "inherit", icon: detalheIcone() }) }), _jsx("span", { className: "umds-attachment-card__detalhe-titulo", id: tituloId(), children: detalheTitulo() })] }), detalheDescricao() ? (_jsx("p", { className: "umds-attachment-card__detalhe-descricao", children: detalheDescricao() })) : null, detalheCampos().length > 0 ? (_jsx("dl", { className: "umds-attachment-card__campos", children: detalheCampos()?.map((campo) => (_jsxs("div", { className: "umds-attachment-card__campo", children: [_jsxs("div", { className: "umds-attachment-card__campo-texto", children: [_jsx("dt", { className: "umds-attachment-card__campo-rotulo", children: campo.label }), _jsx("dd", { className: "umds-attachment-card__campo-valor", children: campo.value })] }), campo.copyable ? (_jsx("button", { type: "button", className: "umds-attachment-card__copiar", "aria-label": rotuloCopiar(campo), onClick: (event) => copiarCampo(campo), children: _jsx(Icon, { size: "sm", variant: "inherit", icon: iconeCopiar(campo) }) })) : null] }, campo.label))) })) : null] }) })) : null })] })) : null] }), _jsx("div", { className: "umds-attachment-card__preview", "aria-hidden": "true", children: _jsx(Icon, { customSize: "48px", variant: "inherit", icon: iconeCentral() }) }), _jsx("div", { className: "umds-attachment-card__tipo-area", children: props.documentType ? (_jsxs("span", { className: "umds-attachment-card__tipo", children: [_jsx("span", { className: "umds-attachment-card__tipo-texto", children: props.documentType }), props.required ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "umds-attachment-card__obrigatorio", "aria-hidden": "true", children: "*" }), _jsx("span", { className: "umds-attachment-card__sr", children: "(obrigat\u00F3rio)" })] })) : null] })) : null }), _jsxs("div", { className: "umds-attachment-card__rodape", title: props.fileName, children: [_jsx("span", { className: "umds-attachment-card__rodape-icone", "aria-hidden": "true", children: _jsx(Icon, { size: "sm", variant: "inherit", icon: iconeArquivo() }) }), props.onOpen ? (_jsx("button", { type: "button", className: "umds-attachment-card__nome umds-attachment-card__abrir", "aria-label": rotuloAbrir(), onClick: (event) => handleOpen(event), children: props.fileName })) : (_jsx("span", { className: "umds-attachment-card__nome", children: props.fileName }))] })] }));
389
+ return (_jsxs("div", { className: classes(), id: props.id, children: [_jsxs("div", { className: "umds-attachment-card__topo", children: [temSelo() && !temDetalhe() ? (_jsxs("span", { className: statusClasses(), children: [seloIcone() ? (_jsx(Icon, { size: "sm", variant: "inherit", icon: seloIcone() })) : null, _jsx("span", { className: "umds-attachment-card__status-texto", children: props.statusLabel })] })) : null, temDetalhe() ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", "aria-haspopup": "dialog", ref: seloRef, className: statusBotaoClasses(), "aria-expanded": ariaExpandidoTexto(), "aria-controls": ariaControlsTexto(), onMouseEnter: (event) => abrir(false), onMouseLeave: (event) => agendarFechar(), onClick: (event) => alternar(), onKeyDown: (event) => teclaNoSelo(event), onBlur: (event) => focoSaiu(event), children: [seloIcone() ? (_jsx(Icon, { size: "sm", variant: "inherit", icon: seloIcone() })) : null, _jsx("span", { className: "umds-attachment-card__status-texto", children: props.statusLabel }), _jsx("span", { className: "umds-attachment-card__sr", children: seloComplemento() })] }), _jsx(Portal, { children: aberto ? (_jsx("span", { className: "umds-attachment-card__flutuante", ref: flutuanteRef, style: flutuanteEstilo(), children: _jsxs("div", { className: "umds-attachment-card__detalhe", role: "dialog", "aria-modal": "false", ref: painelRef, id: painelId(), "aria-labelledby": painelNomeadoPor(), "aria-label": painelRotulo(), tabIndex: -1, style: detalheEstilo(), onClick: (event) => cliqueNoPainel(event), onMouseEnter: (event) => cancelarFechar(), onMouseLeave: (event) => agendarFechar(), onKeyDown: (event) => teclaNoPainel(event), children: [_jsx("span", { className: "umds-attachment-card__sr", role: "status", "aria-live": "polite", children: anuncio }), props.panel ? (_jsx(_Fragment, { children: props.panel })) : (_jsx(_Fragment, { children: _jsxs(_Fragment, { children: [_jsxs("div", { className: "umds-attachment-card__detalhe-topo", children: [_jsx("span", { "aria-hidden": "true", className: detalheIconeClasses(), children: _jsx(Icon, { size: "md", variant: "inherit", icon: detalheIcone() }) }), _jsx("span", { className: "umds-attachment-card__detalhe-titulo", id: tituloId(), children: detalheTitulo() })] }), detalheDescricao() ? (_jsx("p", { className: "umds-attachment-card__detalhe-descricao", children: detalheDescricao() })) : null, detalheCampos().length > 0 ? (_jsx("dl", { className: "umds-attachment-card__campos", children: detalheCampos()?.map((campo) => (_jsxs("div", { className: "umds-attachment-card__campo", children: [_jsxs("div", { className: "umds-attachment-card__campo-texto", children: [_jsx("dt", { className: "umds-attachment-card__campo-rotulo", children: campo.label }), _jsx("dd", { className: "umds-attachment-card__campo-valor", children: campo.value })] }), campo.copyable ? (_jsx("button", { type: "button", className: "umds-attachment-card__copiar", "aria-label": rotuloCopiar(campo), onClick: (event) => copiarCampo(campo), children: _jsx(Icon, { size: "sm", variant: "inherit", icon: iconeCopiar(campo) }) })) : null] }, campo.label))) })) : null] }) }))] }) })) : null })] })) : null] }), _jsx("div", { className: "umds-attachment-card__preview", "aria-hidden": "true", children: _jsx(Icon, { customSize: "48px", variant: "inherit", icon: iconeCentral() }) }), _jsx("div", { className: "umds-attachment-card__tipo-area", children: props.documentType ? (_jsxs("span", { className: "umds-attachment-card__tipo", children: [_jsx("span", { className: "umds-attachment-card__tipo-texto", children: props.documentType }), props.required ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "umds-attachment-card__obrigatorio", "aria-hidden": "true", children: "*" }), _jsx("span", { className: "umds-attachment-card__sr", children: props.requiredLabel || "(obrigatório)" })] })) : null] })) : null }), _jsxs("div", { className: "umds-attachment-card__rodape", title: props.fileName, children: [_jsx("span", { className: "umds-attachment-card__rodape-icone", "aria-hidden": "true", children: _jsx(Icon, { size: "sm", variant: "inherit", icon: iconeArquivo() }) }), props.onOpen ? (_jsx("button", { type: "button", className: "umds-attachment-card__nome umds-attachment-card__abrir", "aria-label": rotuloAbrir(), onClick: (event) => handleOpen(event), children: props.fileName })) : (_jsx("span", { className: "umds-attachment-card__nome", children: props.fileName }))] })] }));
322
390
  }
323
391
  export default AttachmentCard;
@@ -72,17 +72,22 @@
72
72
 
73
73
  /* Avatar Group Styles */
74
74
  .umds-avatar-group {
75
+ /* Sobreposição e anel do grupo: os padrões de sempre; as props `overlap` e
76
+ `ring` do AvatarGroup trocam estes dois valores por style inline. */
77
+ --umds-avatar-group-overlap: var(--umds-primitive-spacing-nano); /* 8px */
78
+ --umds-avatar-group-ring: 1.5px; /* a borda do Avatar base */
75
79
  display: inline-flex;
76
80
  flex-direction: row;
77
81
  align-items: center;
78
82
  /* compensa a sobreposição negativa do último item */
79
- padding-right: var(--umds-primitive-spacing-nano);
83
+ padding-right: var(--umds-avatar-group-overlap);
80
84
  }
81
85
 
82
86
  /* Sobreposição: cada avatar do grupo avança sobre o anterior (protótipo: -8px) */
83
87
  .umds-avatar-group .umds-avatar {
84
88
  /* Borda branca já definida no componente base Avatar */
85
- margin-right: calc(-1 * var(--umds-primitive-spacing-nano));
89
+ margin-right: calc(-1 * var(--umds-avatar-group-overlap));
90
+ border-width: var(--umds-avatar-group-ring);
86
91
  position: relative;
87
92
  z-index: 1;
88
93
  transition: z-index var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard);
@@ -45,6 +45,23 @@ export interface AvatarGroupProps {
45
45
  * @default 'md'
46
46
  */
47
47
  size?: "sm" | "md" | "lg";
48
+ /**
49
+ * Quantas pessoas a mais existem além das que estão em `avatars`: entra na
50
+ * conta do "+N" sem precisar de itens-fantasma. Com 16 responsáveis, passe
51
+ * os 4 primeiros em `avatars` e `overflowCount={12}` para ver "+12". Soma com
52
+ * o que passar de `max` dentro de `avatars`.
53
+ * @default 0
54
+ */
55
+ overflowCount?: number;
56
+ /**
57
+ * Quanto cada avatar avança sobre o anterior, em px. O padrão é 8
58
+ * (`spacing-nano`); 6 deixa as iniciais menos cortadas.
59
+ */
60
+ overlap?: number;
61
+ /**
62
+ * Largura do anel (a borda da cor do fundo) de cada avatar, em px. O padrão é 1,5.
63
+ */
64
+ ring?: number;
48
65
  /**
49
66
  * Classes adicionais.
50
67
  */
@@ -54,6 +71,16 @@ export interface AvatarGroupProps {
54
71
  * Recebe o item correspondente.
55
72
  */
56
73
  onError?: (item: AvatarGroupItem) => void;
74
+ /**
75
+ * Nome acessível do avatar de excedente. Recebe a quantidade escondida.
76
+ * Troque para traduzir. @default (count) => 'Mais ' + count + ' avatares'
77
+ */
78
+ overflowAriaLabel?: (count: number) => string;
79
+ /**
80
+ * Dica (title) do avatar de excedente. Recebe a quantidade escondida.
81
+ * Troque para traduzir. @default (count) => count + ' outros'
82
+ */
83
+ overflowTitle?: (count: number) => string;
57
84
  }
58
85
  declare function AvatarGroup(props: AvatarGroupProps): import("react/jsx-runtime").JSX.Element;
59
86
  export default AvatarGroup;
@@ -10,12 +10,36 @@ function AvatarGroup(props) {
10
10
  function visibleAvatars() {
11
11
  return avatarList().slice(0, maxCount());
12
12
  }
13
- function overflowCount() {
13
+ function hiddenCount() {
14
14
  const total = avatarList().length;
15
- return total > maxCount() ? total - maxCount() : 0;
15
+ const alem = total > maxCount() ? total - maxCount() : 0;
16
+ return alem + (props.overflowCount || 0);
16
17
  }
17
18
  function hasOverflow() {
18
- return overflowCount() > 0;
19
+ return hiddenCount() > 0;
20
+ }
21
+ function overflowAriaLabelText() {
22
+ return props.overflowAriaLabel
23
+ ? props.overflowAriaLabel(hiddenCount())
24
+ : "Mais " + hiddenCount() + " avatares";
25
+ }
26
+ function overflowTitleText() {
27
+ return props.overflowTitle
28
+ ? props.overflowTitle(hiddenCount())
29
+ : hiddenCount() + " outros";
30
+ }
31
+ function groupStyle() {
32
+ if (props.overlap === undefined && props.ring === undefined) {
33
+ return undefined;
34
+ }
35
+ const estilo = {};
36
+ if (props.overlap !== undefined) {
37
+ estilo["--umds-avatar-group-overlap"] = props.overlap + "px";
38
+ }
39
+ if (props.ring !== undefined) {
40
+ estilo["--umds-avatar-group-ring"] = props.ring + "px";
41
+ }
42
+ return estilo;
19
43
  }
20
44
  function size() {
21
45
  return props.size || "md";
@@ -38,6 +62,6 @@ function AvatarGroup(props) {
38
62
  const second = parts[1] ? parts[1][0] : "";
39
63
  return (first + second).toUpperCase();
40
64
  }
41
- return (_jsxs("div", { role: "group", "aria-label": props.ariaLabel || "Grupo de avatares", className: classes(), children: [visibleAvatars()?.map((avatar, index) => (_jsx(Avatar, { className: "umds-avatar-group__item", size: size(), type: avatar.src ? "photo" : "letter", src: avatar.src, alt: avatar.name, title: avatar.name, ariaLabel: avatar.name, onError: (event) => props.onError && props.onError(avatar), children: !avatar.src ? _jsx(_Fragment, { children: getInitials(avatar) }) : null }, avatar.name + "-" + index))), hasOverflow() ? (_jsxs(Avatar, { className: "umds-avatar-group__item umds-avatar-group__overflow", type: "number", size: size(), title: overflowCount() + " outros", ariaLabel: "Mais " + overflowCount() + " avatares", children: ["+", overflowCount()] })) : null] }));
65
+ return (_jsxs("div", { role: "group", style: groupStyle(), "aria-label": props.ariaLabel || "Grupo de avatares", className: classes(), children: [visibleAvatars()?.map((avatar, index) => (_jsx(Avatar, { className: "umds-avatar-group__item", size: size(), type: avatar.src ? "photo" : "letter", src: avatar.src, alt: avatar.name, title: avatar.name, ariaLabel: avatar.name, onError: (event) => props.onError && props.onError(avatar), children: !avatar.src ? _jsx(_Fragment, { children: getInitials(avatar) }) : null }, avatar.name + "-" + index))), hasOverflow() ? (_jsxs(Avatar, { className: "umds-avatar-group__item umds-avatar-group__overflow", type: "number", size: size(), title: overflowTitleText(), ariaLabel: overflowAriaLabelText(), children: ["+", hiddenCount()] })) : null] }));
42
66
  }
43
67
  export default AvatarGroup;
@@ -1,8 +1,9 @@
1
1
  /* ============================================
2
2
  Badge Component
3
- Variantes: neutral, positive, negative, info, primary
3
+ Variantes: neutral, positive, negative, info, primary, new
4
4
  Aparências (appearance): solid, soft, outlined
5
- Tamanhos: xs, sm, md, lg, pill
5
+ Tamanhos: 2xs, xs, sm, md, lg, pill
6
+ Modificador: attached (rótulo colado no topo de um card)
6
7
  ============================================ */
7
8
 
8
9
  .umds-badge {
@@ -41,7 +42,13 @@
41
42
  display: block;
42
43
  }
43
44
 
44
- .umds-badge__icon svg {
45
+ /* Escopado em `.umds-badge` de propósito: `.umds-badge__icon svg` tinha a MESMA
46
+ especificidade de `.umds-icon svg` (0,1,1), e quem vencia era a ordem de
47
+ carga do CSS. No build do Storybook React o CSS do Icon chega depois do do
48
+ Badge, e o SVG voltava a 1em com `vertical-align: -0.125em` (ícone de 12px
49
+ deslocado). Com o bloco na frente (0,2,1) a regra vence em qualquer ordem
50
+ de carga, sem `!important`. */
51
+ .umds-badge .umds-badge__icon svg {
45
52
  width: 100%;
46
53
  height: 100%;
47
54
  display: block;
@@ -53,6 +60,16 @@
53
60
 
54
61
  /* ── Tamanhos — padding + gap por tamanho (sem height fixa) ── */
55
62
 
63
+ /* 2xs: 16px de altura (10 de fonte + 2 + 2 de padding + 2 de borda). A fonte de
64
+ 10px não está na escala do DS (menor degrau: 12px); é o selo compacto do
65
+ CrisDoc, sem token equivalente. */
66
+ .umds-badge--2xs {
67
+ font-size: 0.625rem; /* 10px: fora da escala, selo compacto */
68
+ padding: var(--umds-primitive-spacing-micro) var(--umds-primitive-spacing-quarck);
69
+ gap: var(--umds-primitive-spacing-micro);
70
+ border-radius: var(--umds-primitive-border-radius-xs); /* 4px */
71
+ }
72
+
56
73
  .umds-badge--lg {
57
74
  font-size: var(--umds-primitive-font-size-xxs); /* 14px */
58
75
  padding: var(--umds-primitive-spacing-quarck) var(--umds-primitive-spacing-mini); /* 10px: candidato a novo token */
@@ -110,6 +127,11 @@
110
127
  height: 11px;
111
128
  }
112
129
 
130
+ .umds-badge--2xs .umds-badge__icon {
131
+ width: 8px;
132
+ height: 8px;
133
+ }
134
+
113
135
  /* ─────────────── SOLID ─────────────── */
114
136
 
115
137
  .umds-badge--solid.umds-badge--neutral {
@@ -196,3 +218,39 @@
196
218
  border-color: var(--umds-semantic-color-primary-pure);
197
219
  color: var(--umds-semantic-color-primary-pure);
198
220
  }
221
+
222
+ /* ─────────────── NEW (selo de novidade) ───────────────
223
+ O DS não tem token semântico de amarelo. Usa os primitivos de amarelo e o
224
+ cinza escuro, todos fixos nos temas, então o contraste (8:1 do texto sobre o
225
+ fundo) não depende do tema. Candidato a token semântico de destaque. */
226
+
227
+ .umds-badge--new {
228
+ font-weight: var(--umds-primitive-font-weight-extrabold);
229
+ text-transform: uppercase;
230
+ letter-spacing: var(--umds-primitive-font-letter-spacing-wider);
231
+ border-radius: var(--umds-primitive-border-radius-pill);
232
+ }
233
+
234
+ .umds-badge--solid.umds-badge--new,
235
+ .umds-badge--soft.umds-badge--new {
236
+ /* stylelint-disable-next-line 1ds/cor-por-token -- o DS não tem token semântico de amarelo (candidato a novo token) */
237
+ background-color: var(--umds-primitive-yellow-medium);
238
+ /* stylelint-disable-next-line 1ds/cor-por-token -- par fixo do amarelo: o semântico inverte no tema escuro e perderia o contraste */
239
+ color: var(--umds-primitive-gray-darkest);
240
+ }
241
+
242
+ .umds-badge--outlined.umds-badge--new {
243
+ /* stylelint-disable-next-line 1ds/cor-por-token -- o DS não tem token semântico de amarelo (candidato a novo token) */
244
+ border-color: var(--umds-primitive-yellow-pure);
245
+ /* stylelint-disable-next-line 1ds/cor-por-token -- o DS não tem token semântico de amarelo (candidato a novo token) */
246
+ color: var(--umds-primitive-yellow-dark);
247
+ }
248
+
249
+ /* ─────────────── ATTACHED (rótulo colado no topo do card) ─────────────── */
250
+
251
+ .umds-badge--attached {
252
+ position: absolute;
253
+ top: 0;
254
+ left: 0;
255
+ border-radius: 0 0 var(--umds-primitive-border-radius-sm) var(--umds-primitive-border-radius-sm);
256
+ }
@@ -7,15 +7,25 @@ import './Badge.css';
7
7
  */
8
8
  export interface BadgeProps {
9
9
  /**
10
- * Variação de cor semântica.
10
+ * Variação de cor semântica. `new` é o selo de novidade: amarelo, em caixa
11
+ * alta e pílula, para destacar uma funcionalidade recém-chegada.
11
12
  * @default 'neutral'
12
13
  */
13
- variant?: "neutral" | "positive" | "negative" | "info" | "primary";
14
+ variant?: "neutral" | "positive" | "negative" | "info" | "primary" | "new";
14
15
  /**
15
- * Tamanho do badge.
16
+ * Tamanho do badge. `2xs` é o compacto (16px, fonte de 10px) para selo de
17
+ * setor e de contagem dentro de linha de lista e card.
16
18
  * @default 'md'
17
19
  */
18
- size?: "sm" | "md" | "lg" | "xs" | "pill";
20
+ size?: "2xs" | "xs" | "sm" | "md" | "lg" | "pill";
21
+ /**
22
+ * Cola o badge no canto superior esquerdo do card (rótulo de card, como
23
+ * "Tarefa pendente"): cantos de baixo arredondados, os de cima retos.
24
+ * Posiciona em `absolute`, então o pai precisa de `position: relative`
25
+ * (o `Card` e o `Box` com `position` já servem).
26
+ * @default false
27
+ */
28
+ attached?: boolean;
19
29
  /**
20
30
  * Estilo visual do badge.
21
31
  * @default 'soft'
@@ -7,6 +7,7 @@ function Badge(props) {
7
7
  `umds-badge--${props.variant || "neutral"}`,
8
8
  `umds-badge--${props.size || "md"}`,
9
9
  `umds-badge--${props.appearance || "soft"}`,
10
+ props.attached ? "umds-badge--attached" : "",
10
11
  props.className,
11
12
  ]
12
13
  .filter(Boolean)
@@ -22,6 +22,7 @@
22
22
  .umds-bottomsheet__backdrop {
23
23
  position: absolute;
24
24
  inset: 0;
25
+ /* stylelint-disable-next-line 1ds/cor-por-token -- o DS não tem token de scrim/overlay (candidato a novo token) */
25
26
  background-color: rgba(0, 0, 0, 0.4); /* overlay escuro — sem token 1DS: candidato a novo token (igual ao Modal) */
26
27
  backdrop-filter: blur(4px);
27
28
  z-index: 1;
@@ -34,8 +34,16 @@ export interface BottomSheetProps {
34
34
  closable?: any;
35
35
  closeOnEsc?: any;
36
36
  closeOnBackdrop?: any;
37
+ /**
38
+ * Nome acessível do painel quando não há `title` (vira `aria-label`). Sem
39
+ * título, sem esta prop e sem `ariaLabelledby`, o componente usa "Painel"
40
+ * como último recurso, para o `role="dialog"` nunca sair anônimo.
41
+ */
37
42
  ariaLabel?: string;
43
+ /** Id de um elemento externo que nomeia o painel. Vence o `title`. */
38
44
  ariaLabelledby?: string;
45
+ /** Nome acessível da alça de arrastar (slider), que só existe com mais de um encaixe. Troque para traduzir. @default 'Altura do painel' */
46
+ grabberLabel?: string;
39
47
  className?: string;
40
48
  id?: string;
41
49
  children?: any;
@@ -20,6 +20,18 @@ function BottomSheet(props) {
20
20
  function labelId() {
21
21
  return uid + "-titulo";
22
22
  }
23
+ function labelledByText() {
24
+ if (props.ariaLabelledby)
25
+ return props.ariaLabelledby;
26
+ return props.title ? labelId() : undefined;
27
+ }
28
+ function nomeAcessivel() {
29
+ if (props.ariaLabel)
30
+ return props.ariaLabel;
31
+ if (props.ariaLabelledby || props.title)
32
+ return undefined;
33
+ return "Painel";
34
+ }
23
35
  function alturaDoPainel() {
24
36
  const pontos = props.snapPoints || [];
25
37
  if (!pontos.length)
@@ -31,7 +43,7 @@ function BottomSheet(props) {
31
43
  return !!props.snapPoints && props.snapPoints.length > 1;
32
44
  }
33
45
  function grabberAriaLabel() {
34
- return "Altura do painel";
46
+ return props.grabberLabel || "Altura do painel";
35
47
  }
36
48
  function handleClose(event) {
37
49
  if (props.onClose)
@@ -158,7 +170,7 @@ function BottomSheet(props) {
158
170
  removeOverlay(uid);
159
171
  };
160
172
  }, []);
161
- return (_jsx(_Fragment, { children: props.open ? (_jsx(_Fragment, { children: _jsxs("div", { id: props.id, className: rootClasses(), children: [_jsx("div", { className: "umds-bottomsheet__backdrop", onClick: (event) => handleBackdropClick(event) }), _jsxs("div", { role: "dialog", "aria-modal": "true", className: "umds-bottomsheet", ref: sheetRef, "aria-label": props.ariaLabel, "aria-labelledby": props.ariaLabelledby || (props.title ? labelId() : undefined), tabIndex: -1, style: {
173
+ return (_jsx(_Fragment, { children: props.open ? (_jsx(_Fragment, { children: _jsxs("div", { id: props.id, className: rootClasses(), children: [_jsx("div", { className: "umds-bottomsheet__backdrop", onClick: (event) => handleBackdropClick(event) }), _jsxs("div", { role: "dialog", "aria-modal": "true", className: "umds-bottomsheet", ref: sheetRef, "aria-label": nomeAcessivel(), "aria-labelledby": labelledByText(), tabIndex: -1, style: {
162
174
  height: alturaDoPainel(),
163
175
  }, onKeyDown: (event) => handleTrapKeydown(event), children: [_jsxs("div", { className: "umds-bottomsheet__top", children: [props.grabber !== false ? (_jsx("div", { className: "umds-bottomsheet__grabber", role: temMaisDeUmEncaixe() ? "slider" : undefined, tabIndex: temMaisDeUmEncaixe() ? 0 : undefined, "aria-label": temMaisDeUmEncaixe() ? grabberAriaLabel() : undefined, "aria-valuenow": temMaisDeUmEncaixe() ? snapAtual : undefined, "aria-valuemin": temMaisDeUmEncaixe() ? 0 : undefined, "aria-valuemax": temMaisDeUmEncaixe()
164
176
  ? (props.snapPoints || []).length - 1