@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
@@ -5,7 +5,7 @@ import { useState } from "react";
5
5
  import { faWandMagicSparkles } from "@fortawesome/free-solid-svg-icons";
6
6
  import Icon from "../Icon/Icon";
7
7
  function AILabel(props) {
8
- const [internalOpen, setInternalOpen] = useState(() => false);
8
+ const [internalOpen, setInternalOpen] = useState(() => props.defaultOpen === true);
9
9
  const [uid, setUid] = useState(() => `umds-ailabel-${Math.random().toString(36).slice(2, 9)}`);
10
10
  function baseId() {
11
11
  return props.id || uid;
@@ -99,6 +99,19 @@
99
99
  opacity: 0.6; /* opacidade do protótipo sem token 1DS */
100
100
  }
101
101
 
102
+ /* ── Título neutro (titleVariant="neutral") ──
103
+ 14px na cor do texto, em peso médio, também no hover e no aberto: o título não
104
+ pega a cor de ação. O chevron aberto continua azul (é o sinal do estado). */
105
+ .umds-accordion--title-neutral .umds-accordion__title {
106
+ font-size: var(--umds-primitive-font-size-xxs); /* 14px */
107
+ font-weight: var(--umds-primitive-font-weight-medium);
108
+ color: var(--umds-semantic-color-neutral-dark-pure);
109
+ }
110
+
111
+ .umds-accordion--title-neutral .umds-accordion__trigger:disabled .umds-accordion__title {
112
+ color: inherit;
113
+ }
114
+
102
115
  /* ── Chevron ──
103
116
  Migrado de <svg> inline para o componente Icon (chevron-down).
104
117
  O wrapper .umds-accordion__chevron recebe cor (via currentColor →
@@ -2,16 +2,21 @@ import './Accordion.css';
2
2
  export interface AccordionItemData {
3
3
  id: string;
4
4
  title: string;
5
- /** Conteúdo do painel — aceita ReactNode no React (no Vue, prefira string) */
5
+ /**
6
+ * Conteúdo do painel. React: aceita qualquer nó. Vue: aqui vai só texto; para
7
+ * conteúdo livre (campos, botões) use o slot `#content-<id>` do item, que
8
+ * recebe `{ item }` e vale sobre este texto.
9
+ */
6
10
  content: any;
7
11
  disabled?: boolean;
8
12
  defaultOpen?: boolean;
9
13
  }
10
14
  /**
11
15
  * Accordion component — lista de painéis expansíveis (sanfona).
12
- * @property {AccordionItemData[]} items - Itens do accordion (id, title, content, disabled?, defaultOpen?)
16
+ * @property {AccordionItemData[]} items - Itens do accordion (id, title, content, disabled?, defaultOpen?). Conteúdo livre por item: no React, `content` aceita nó; no Vue, o slot `#content-<id>` (recebe `{ item }`).
13
17
  * @property {boolean} multiple - Permite manter vários painéis abertos ao mesmo tempo
14
18
  * @property {string} variant - Estilo visual: 'default' | 'bordered' | 'separated'
19
+ * @property {string} titleVariant - Título dos itens: 'default' | 'neutral'. O `neutral` é o título de texto, 14px na cor do texto, sem cor de ação (como um `Button text` neutro), para o accordion do CrisDoc.
15
20
  * @property {string} className - Classes CSS adicionais
16
21
  * @quandoUsar Conteúdo que fica RECOLHIDO até o usuário querer: FAQ, seções opcionais de formulário, detalhes secundários. Vários podem abrir juntos com `multiple`.
17
22
  * @quandoNaoUsar Para alternar entre visões equivalentes sempre disponíveis — use `Tabs`. Se o conteúdo é essencial, não esconda atrás de acordeão.
@@ -20,6 +25,8 @@ export interface AccordionProps {
20
25
  items: AccordionItemData[];
21
26
  multiple?: boolean;
22
27
  variant?: "default" | "bordered" | "separated";
28
+ /** Título dos itens. `neutral`: 14px na cor do texto, peso médio. @default 'default' */
29
+ titleVariant?: "default" | "neutral";
23
30
  className?: string;
24
31
  }
25
32
  declare function Accordion(props: AccordionProps): import("react/jsx-runtime").JSX.Element;
@@ -35,6 +35,7 @@ function Accordion(props) {
35
35
  return [
36
36
  "umds-accordion",
37
37
  `umds-accordion--${props.variant || "default"}`,
38
+ props.titleVariant === "neutral" ? "umds-accordion--title-neutral" : "",
38
39
  props.className,
39
40
  ]
40
41
  .filter(Boolean)
@@ -21,14 +21,23 @@
21
21
  }
22
22
 
23
23
  /* O contexto cede espaço e rola sozinho: uma trilha longa não pode empurrar
24
- a busca e as ações para fora da tela. */
24
+ a busca e as ações para fora da tela.
25
+ Só rola na HORIZONTAL, e só quando a trilha estoura. `overflow-x: auto` sozinho
26
+ faz o `overflow-y` computar para `auto` também, e o `line-height` do item do
27
+ Breadcrumb (12px, numa linha de 12px) deixa o conteúdo 2px acima da caixa de 12px
28
+ (medido: scrollHeight 14, clientHeight 12): com a trilha só na página atual (sem
29
+ link para focar) o axe acusa `scrollable-region-focusable`. Por isso a região
30
+ ocupa a altura da barra (`align-self: stretch`, o conteúdo segue centralizado) e o
31
+ eixo vertical é cortado: não há o que rolar na vertical. */
25
32
  .umds-app-subheader__contexto {
26
33
  flex: 1;
34
+ align-self: stretch;
27
35
  min-width: 0;
28
36
  display: flex;
29
37
  align-items: center;
30
38
  gap: var(--umds-primitive-spacing-nano);
31
39
  overflow-x: auto;
40
+ overflow-y: hidden;
32
41
  scrollbar-width: none;
33
42
  }
34
43
 
@@ -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);
@@ -167,18 +183,10 @@
167
183
  }
168
184
 
169
185
  .umds-attachment-card__campo {
170
- display: flex;
171
- align-items: center;
172
- gap: var(--umds-primitive-spacing-nano);
173
186
  padding: var(--umds-primitive-spacing-nano) 0;
174
187
  border-top: 1px solid var(--umds-semantic-color-neutral-light-medium);
175
188
  }
176
189
 
177
- .umds-attachment-card__campo-texto {
178
- flex: 1;
179
- min-width: 0;
180
- }
181
-
182
190
  .umds-attachment-card__campo-rotulo {
183
191
  color: var(--umds-semantic-color-neutral-dark-down);
184
192
  font-size: var(--umds-primitive-font-size-xxxs);
@@ -186,7 +194,12 @@
186
194
  text-transform: uppercase;
187
195
  }
188
196
 
197
+ /* O valor e o botão de copiar na mesma linha: o botão mora dentro do <dd> (o <dl> só aceita
198
+ <dt> e <dd> dentro do <div>). */
189
199
  .umds-attachment-card__campo-valor {
200
+ display: flex;
201
+ align-items: center;
202
+ gap: var(--umds-primitive-spacing-nano);
190
203
  margin: var(--umds-primitive-spacing-micro) 0 0; /* 2px: respiro rótulo→valor */
191
204
  font-size: var(--umds-primitive-font-size-xxs);
192
205
  font-weight: var(--umds-primitive-font-weight-bold);
@@ -194,6 +207,11 @@
194
207
  overflow-wrap: anywhere;
195
208
  }
196
209
 
210
+ .umds-attachment-card__campo-valor-texto {
211
+ flex: 1;
212
+ min-width: 0;
213
+ }
214
+
197
215
  /* Alvo de toque WCAG 2.5.8: 32×32. */
198
216
  .umds-attachment-card__copiar {
199
217
  display: inline-flex;
@@ -6,12 +6,16 @@ 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.
18
+ * @property {string} size - Tamanho do cartão: 'md' (padrão) | 'sm'. O `sm` é o compacto do CrisDoc: ícone do preview de 40px (no `md`, 48px) e ícone do rodapé de 12px (no `md`, 16px). A largura e os selos não mudam.
15
19
  * @property {Function} onOpen - Abre o anexo. Com ele o cartão inteiro vira alvo de clique, com um único ponto de foco.
16
20
  * @property {string} openAriaLabel - Nome acessível da ação de abrir. Padrão: "Abrir <tipo>: <arquivo>".
17
21
  * @property {string} className - Classes CSS adicionais
@@ -37,12 +41,28 @@ export interface AttachmentCardProps {
37
41
  fileName: string;
38
42
  documentType?: string;
39
43
  required?: boolean;
40
- status?: "positive" | "negative";
44
+ status?: "positive" | "negative" | "ai";
41
45
  statusLabel?: string;
42
46
  statusIcon?: IconProp;
43
47
  statusDetails?: AttachmentCardStatusDetails;
48
+ /**
49
+ * Conteúdo livre do painel do selo, no lugar do resultado da conferência
50
+ * (`statusDetails`): ações, campos, texto. React: o elemento; Vue: o slot
51
+ * `panel`. Com ele o selo vira botão mesmo sem `statusDetails`.
52
+ */
53
+ panel?: any;
54
+ /** Largura do painel, em px. @default 300 */
55
+ panelWidth?: number;
56
+ /**
57
+ * Fecha o painel e devolve o foco ao selo quando alguém aciona um botão ou
58
+ * link de dentro dele. O botão de copiar um campo não conta. Sem a prop, o
59
+ * painel fica aberto até Esc, clique fora ou o foco sair.
60
+ */
61
+ closePanelOnAction?: boolean;
44
62
  onCopyField?: (field: AttachmentCardField) => void;
45
63
  icon?: IconProp;
64
+ /** Tamanho do cartão. `sm`: ícone do preview de 40px e ícone do rodapé de 12px. @default 'md' */
65
+ size?: "md" | "sm";
46
66
  onOpen?: (event?: any) => void;
47
67
  openAriaLabel?: string;
48
68
  /** 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 */
@@ -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"])';
@@ -29,6 +29,7 @@ function AttachmentCard(props) {
29
29
  return [
30
30
  "umds-attachment-card",
31
31
  props.onOpen ? "umds-attachment-card--interativo" : "",
32
+ props.size === "sm" ? "umds-attachment-card--sm" : "",
32
33
  props.className,
33
34
  ]
34
35
  .filter(Boolean)
@@ -47,7 +48,30 @@ function AttachmentCard(props) {
47
48
  return Boolean(props.status && props.statusLabel);
48
49
  }
49
50
  function temDetalhe() {
50
- return Boolean(temSelo() && props.statusDetails);
51
+ return Boolean(temSelo() && (props.statusDetails || props.panel));
52
+ }
53
+ function painelTemConteudoLivre() {
54
+ return Boolean(props.panel);
55
+ }
56
+ function seloIcone() {
57
+ if (props.statusIcon)
58
+ return props.statusIcon;
59
+ return props.status === "ai" ? faWandMagicSparkles : undefined;
60
+ }
61
+ function detalheEstilo() {
62
+ return props.panelWidth
63
+ ? {
64
+ width: props.panelWidth + "px",
65
+ }
66
+ : undefined;
67
+ }
68
+ function painelNomeadoPor() {
69
+ return props.panel ? undefined : tituloId();
70
+ }
71
+ function painelRotulo() {
72
+ if (!props.panel)
73
+ return undefined;
74
+ return (props.statusLabel || "") + seloComplemento();
51
75
  }
52
76
  function painelId() {
53
77
  return `${props.id || uid}-conferencia`;
@@ -85,6 +109,8 @@ function AttachmentCard(props) {
85
109
  return (props.statusDetails && props.statusDetails.fields) || [];
86
110
  }
87
111
  function detalheIcone() {
112
+ if (props.status === "ai")
113
+ return faWandMagicSparkles;
88
114
  return props.status === "negative" ? faCircleXmark : faCircleCheck;
89
115
  }
90
116
  function detalheIconeClasses() {
@@ -120,6 +146,12 @@ function AttachmentCard(props) {
120
146
  return faFileExcel;
121
147
  return faFile;
122
148
  }
149
+ function tamanhoIconeCentral() {
150
+ return props.size === "sm" ? "40px" : "48px";
151
+ }
152
+ function tamanhoIconeRodape() {
153
+ return props.size === "sm" ? "12px" : undefined;
154
+ }
123
155
  function iconeCentral() {
124
156
  return props.icon || faFileLines;
125
157
  }
@@ -283,6 +315,18 @@ function AttachmentCard(props) {
283
315
  fechar(true);
284
316
  }
285
317
  }
318
+ function cliqueNoPainel(event) {
319
+ if (!props.closePanelOnAction)
320
+ return;
321
+ const alvo = event.target && event.target.closest
322
+ ? event.target.closest("button, a[href]")
323
+ : null;
324
+ if (!alvo)
325
+ return;
326
+ if (alvo.classList.contains("umds-attachment-card__copiar"))
327
+ return;
328
+ fechar(true);
329
+ }
286
330
  function teclaNoPainel(event) {
287
331
  if (event.key === "Escape") {
288
332
  event.preventDefault();
@@ -349,6 +393,6 @@ function AttachmentCard(props) {
349
393
  desligarObservadores();
350
394
  };
351
395
  }, []);
352
- 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: 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 }))] })] }));
396
+ 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: [_jsx("dt", { className: "umds-attachment-card__campo-rotulo", children: campo.label }), _jsxs("dd", { className: "umds-attachment-card__campo-valor", children: [_jsx("span", { className: "umds-attachment-card__campo-valor-texto", 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, { variant: "inherit", icon: iconeCentral(), customSize: tamanhoIconeCentral() }) }), _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(), customSize: tamanhoIconeRodape() }) }), 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 }))] })] }));
353
397
  }
354
398
  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
  */
@@ -10,22 +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;
19
20
  }
20
21
  function overflowAriaLabelText() {
21
22
  return props.overflowAriaLabel
22
- ? props.overflowAriaLabel(overflowCount())
23
- : "Mais " + overflowCount() + " avatares";
23
+ ? props.overflowAriaLabel(hiddenCount())
24
+ : "Mais " + hiddenCount() + " avatares";
24
25
  }
25
26
  function overflowTitleText() {
26
27
  return props.overflowTitle
27
- ? props.overflowTitle(overflowCount())
28
- : overflowCount() + " outros";
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;
29
43
  }
30
44
  function size() {
31
45
  return props.size || "md";
@@ -48,6 +62,6 @@ function AvatarGroup(props) {
48
62
  const second = parts[1] ? parts[1][0] : "";
49
63
  return (first + second).toUpperCase();
50
64
  }
51
- 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: overflowTitleText(), ariaLabel: overflowAriaLabelText(), 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] }));
52
66
  }
53
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), attachedSide left | right
6
7
  ============================================ */
7
8
 
8
9
  .umds-badge {
@@ -59,6 +60,16 @@
59
60
 
60
61
  /* ── Tamanhos — padding + gap por tamanho (sem height fixa) ── */
61
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
+
62
73
  .umds-badge--lg {
63
74
  font-size: var(--umds-primitive-font-size-xxs); /* 14px */
64
75
  padding: var(--umds-primitive-spacing-quarck) var(--umds-primitive-spacing-mini); /* 10px: candidato a novo token */
@@ -116,6 +127,11 @@
116
127
  height: 11px;
117
128
  }
118
129
 
130
+ .umds-badge--2xs .umds-badge__icon {
131
+ width: 8px;
132
+ height: 8px;
133
+ }
134
+
119
135
  /* ─────────────── SOLID ─────────────── */
120
136
 
121
137
  .umds-badge--solid.umds-badge--neutral {
@@ -202,3 +218,52 @@
202
218
  border-color: var(--umds-semantic-color-primary-pure);
203
219
  color: var(--umds-semantic-color-primary-pure);
204
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
+ }
257
+
258
+ /* Canto direito (attachedSide="right"): o rótulo cola no canto superior direito. */
259
+ .umds-badge--attached.umds-badge--attached-right {
260
+ left: auto;
261
+ right: 0;
262
+ }
263
+
264
+ /* Neutro colado: cinza claro com texto escuro (o "Tarefa manual" do CrisDoc).
265
+ O `solid` neutro é cinza escuro com texto branco, pesado demais para um rótulo de card. */
266
+ .umds-badge--attached.umds-badge--neutral.umds-badge--solid {
267
+ background-color: var(--umds-semantic-color-neutral-light-medium);
268
+ color: var(--umds-semantic-color-neutral-dark-pure);
269
+ }
@@ -7,15 +7,34 @@ 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 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). O canto é o esquerdo, ou o
26
+ * direito com `attachedSide="right"`. Com `variant="neutral"` e `appearance="solid"` o
27
+ * rótulo colado é o cinza claro com texto escuro (o "Tarefa manual" do CrisDoc), e não o
28
+ * cinza escuro do `solid`, pesado demais para um rótulo de card.
29
+ * @default false
30
+ */
31
+ attached?: boolean;
32
+ /**
33
+ * Em que canto do card o `attached` cola: `left` (padrão) ou `right`.
34
+ * Só vale com `attached`.
35
+ * @default 'left'
36
+ */
37
+ attachedSide?: "left" | "right";
19
38
  /**
20
39
  * Estilo visual do badge.
21
40
  * @default 'soft'
@@ -7,6 +7,10 @@ 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" : "",
11
+ props.attached && props.attachedSide === "right"
12
+ ? "umds-badge--attached-right"
13
+ : "",
10
14
  props.className,
11
15
  ]
12
16
  .filter(Boolean)