@1doc/1ds-react 2.9.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 (115) hide show
  1. package/CHANGELOG.md +434 -0
  2. package/dist/components/Accordion/Accordion.css +13 -0
  3. package/dist/components/Accordion/Accordion.d.ts +3 -0
  4. package/dist/components/Accordion/Accordion.js +1 -0
  5. package/dist/components/AppSubheader/AppSubheader.css +10 -1
  6. package/dist/components/AttachmentCard/AttachmentCard.css +10 -8
  7. package/dist/components/AttachmentCard/AttachmentCard.d.ts +3 -0
  8. package/dist/components/AttachmentCard/AttachmentCard.js +8 -1
  9. package/dist/components/Badge/Badge.css +14 -1
  10. package/dist/components/Badge/Badge.d.ts +11 -2
  11. package/dist/components/Badge/Badge.js +3 -0
  12. package/dist/components/Calendar/Calendar.d.ts +7 -6
  13. package/dist/components/Coachmark/Coachmark.css +10 -0
  14. package/dist/components/Coachmark/Coachmark.d.ts +12 -0
  15. package/dist/components/Coachmark/Coachmark.js +46 -5
  16. package/dist/components/ColorPicker/ColorPicker.css +8 -1
  17. package/dist/components/ColorPicker/ColorPicker.d.ts +2 -2
  18. package/dist/components/DataTable/DataTable.css +174 -0
  19. package/dist/components/DataTable/DataTable.d.ts +63 -2
  20. package/dist/components/DataTable/DataTable.js +278 -6
  21. package/dist/components/DescriptionList/DescriptionList.css +14 -0
  22. package/dist/components/DescriptionList/DescriptionList.d.ts +3 -0
  23. package/dist/components/DescriptionList/DescriptionList.js +1 -0
  24. package/dist/components/EmptyState/EmptyState.d.ts +4 -2
  25. package/dist/components/EmptyState/EmptyState.js +2 -2
  26. package/dist/components/Input/Input.css +21 -0
  27. package/dist/components/Input/Input.d.ts +7 -0
  28. package/dist/components/Input/Input.js +2 -1
  29. package/dist/components/List/ListItem.d.ts +14 -2
  30. package/dist/components/List/ListItem.js +3 -2
  31. package/dist/components/RichTextEditor/RichTextEditor.css +47 -0
  32. package/dist/components/RichTextEditor/RichTextEditor.d.ts +22 -8
  33. package/dist/components/RichTextEditor/RichTextEditor.js +460 -3
  34. package/dist/components/SegmentedControl/SegmentedControl.css +24 -0
  35. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  36. package/dist/components/SegmentedControl/SegmentedControl.js +4 -1
  37. package/dist/components/Select/Select.css +94 -0
  38. package/dist/components/Select/Select.d.ts +26 -4
  39. package/dist/components/Select/Select.js +210 -35
  40. package/dist/components/StatCard/StatCard.css +65 -0
  41. package/dist/components/StatCard/StatCard.d.ts +9 -0
  42. package/dist/components/StatCard/StatCard.js +10 -1
  43. package/dist/components/Toast/Toast.css +32 -0
  44. package/dist/components/Toast/Toast.d.ts +18 -0
  45. package/dist/components/Toast/Toast.js +14 -1
  46. package/dist/components/Toast/ToastStack.js +8 -1
  47. package/dist/teste/AccordionTituloNeutro.test.d.ts +1 -0
  48. package/dist/teste/AccordionTituloNeutro.test.js +23 -0
  49. package/dist/teste/AppSubheaderRegiao.test.d.ts +1 -0
  50. package/dist/teste/AppSubheaderRegiao.test.js +13 -0
  51. package/dist/teste/AttachmentCardLista.test.d.ts +1 -0
  52. package/dist/teste/AttachmentCardLista.test.js +49 -0
  53. package/dist/teste/AttachmentCardSm.test.d.ts +1 -0
  54. package/dist/teste/AttachmentCardSm.test.js +26 -0
  55. package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
  56. package/dist/teste/BadgeNeutroColado.test.js +11 -0
  57. package/dist/teste/BadgeTag.test.js +13 -0
  58. package/dist/teste/CalendarCabecalho.test.d.ts +1 -0
  59. package/dist/teste/CalendarCabecalho.test.js +11 -0
  60. package/dist/teste/CoachmarkSemVeu.test.d.ts +1 -0
  61. package/dist/teste/CoachmarkSemVeu.test.js +85 -0
  62. package/dist/teste/ColorPickerXs.test.d.ts +1 -0
  63. package/dist/teste/ColorPickerXs.test.js +21 -0
  64. package/dist/teste/DataTableArvoreEVariantes.test.d.ts +1 -0
  65. package/dist/teste/DataTableArvoreEVariantes.test.js +190 -0
  66. package/dist/teste/DescriptionListCompacta.test.d.ts +1 -0
  67. package/dist/teste/DescriptionListCompacta.test.js +22 -0
  68. package/dist/teste/EmptyStateTituloRico.test.d.ts +1 -0
  69. package/dist/teste/EmptyStateTituloRico.test.js +23 -0
  70. package/dist/teste/InputAgrupado.test.d.ts +1 -0
  71. package/dist/teste/InputAgrupado.test.js +24 -0
  72. package/dist/teste/ListItemTooltipStandalone.test.d.ts +1 -0
  73. package/dist/teste/ListItemTooltipStandalone.test.js +39 -0
  74. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.d.ts +1 -0
  75. package/dist/teste/RichTextEditorAlinhaImagemTabela.test.js +212 -0
  76. package/dist/teste/RichTextEditorEstiloDeTexto.test.d.ts +1 -0
  77. package/dist/teste/RichTextEditorEstiloDeTexto.test.js +120 -0
  78. package/dist/teste/SegmentedControlContador.test.d.ts +1 -0
  79. package/dist/teste/SegmentedControlContador.test.js +39 -0
  80. package/dist/teste/SelectAbertoControladoEFlutuante.test.d.ts +1 -0
  81. package/dist/teste/SelectAbertoControladoEFlutuante.test.js +145 -0
  82. package/dist/teste/SelectFiltroCorETamanho.test.d.ts +1 -0
  83. package/dist/teste/SelectFiltroCorETamanho.test.js +77 -0
  84. package/dist/teste/StatCardSecundariaETom.test.d.ts +1 -0
  85. package/dist/teste/StatCardSecundariaETom.test.js +45 -0
  86. package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
  87. package/dist/teste/ToastAcaoEDetalhes.test.js +94 -0
  88. package/dist/utils/html-seguro.d.ts +19 -1
  89. package/dist/utils/html-seguro.js +113 -2
  90. package/dist/utils/toast.d.ts +10 -1
  91. package/dist/utils/toast.js +2 -1
  92. package/package.json +2 -2
  93. package/src/teste/AccordionTituloNeutro.test.tsx +25 -0
  94. package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
  95. package/src/teste/AttachmentCardLista.test.tsx +53 -0
  96. package/src/teste/AttachmentCardSm.test.tsx +29 -0
  97. package/src/teste/BadgeNeutroColado.test.tsx +15 -0
  98. package/src/teste/BadgeTag.test.tsx +21 -0
  99. package/src/teste/CalendarCabecalho.test.tsx +11 -0
  100. package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
  101. package/src/teste/ColorPickerXs.test.tsx +22 -0
  102. package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -0
  103. package/src/teste/DescriptionListCompacta.test.tsx +24 -0
  104. package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
  105. package/src/teste/InputAgrupado.test.tsx +26 -0
  106. package/src/teste/ListItemTooltipStandalone.test.tsx +64 -0
  107. package/src/teste/RichTextEditorAlinhaImagemTabela.test.tsx +238 -0
  108. package/src/teste/RichTextEditorEstiloDeTexto.test.tsx +137 -0
  109. package/src/teste/SegmentedControlContador.test.tsx +43 -0
  110. package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
  111. package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -0
  112. package/src/teste/StatCardSecundariaETom.test.tsx +51 -0
  113. package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
  114. package/src/utils/html-seguro.ts +105 -2
  115. package/src/utils/toast.ts +12 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,439 @@
1
1
  # @1doc/1ds-react
2
2
 
3
+ ## 2.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 12c65e9: feat(accordion): `titleVariant="neutral"`, o título de texto
8
+
9
+ `titleVariant` aceita `default` (o título como era) e `neutral`: 14px na cor do texto
10
+ (`neutral-dark-pure`), peso médio, também no hover e no aberto, sem cor de ação. O chevron
11
+ aberto continua azul (é o sinal do estado). Combina com qualquer `variant`.
12
+
13
+ ```vue
14
+ <Accordion :items="itens" variant="separated" titleVariant="neutral" />
15
+ ```
16
+
17
+ - 6df8835: feat(attachmentcard): `size="sm"`, o cartão compacto do CrisDoc
18
+
19
+ `size="sm"` leva o ícone do preview a 40px (no `md`, 48px) e o ícone do rodapé a
20
+ 12px (no `md`, o `sm` do `Icon`). A largura do cartão, os selos e o painel não
21
+ mudam. Sem `size`, ou com `md`, o cartão é o mesmo.
22
+
23
+ ```vue
24
+ <AttachmentCard
25
+ fileName="Protocolo 104-2026.pdf"
26
+ documentType="Parecer"
27
+ size="sm"
28
+ :onOpen="abrir"
29
+ />
30
+ ```
31
+
32
+ - 4ab330c: feat(badge): `attachedSide="left" | "right"` no `Badge attached`
33
+
34
+ O rótulo colado no topo do card pode ir para o canto direito. Sem a prop, ou com
35
+ `left`, continua no esquerdo. Só vale com `attached`.
36
+
37
+ ```vue
38
+ <Badge
39
+ :attached="true"
40
+ attachedSide="right"
41
+ size="sm"
42
+ appearance="solid"
43
+ variant="primary"
44
+ >Prazo hoje</Badge>
45
+ ```
46
+
47
+ - 1f805cd: feat(coachmark): `modal={false}`, o cartão sem véu nem foco preso, para dica pontual
48
+
49
+ Com `modal={false}` não há véu, recorte nem foco preso: o cartão é um popover
50
+ ancorado no alvo (`role="dialog"` com `aria-modal="false"`). A página segue
51
+ clicável, o foco entra no cartão ao abrir mas o Tab pode sair dele, e o Esc fecha de
52
+ qualquer lugar da página (uma vez só, com o motivo `escape`). Ao fechar, o foco só
53
+ volta ao elemento de antes se a pessoa não foi a outro lugar. Sem a prop, o tour é
54
+ modal como sempre (no Vue, `modal` é `any` para a ausência não virar `false`).
55
+
56
+ Corrige também o elemento de antes guardado duas vezes no React (o segundo
57
+ `sincronizar`, antes de o `active` valer, guardava o próprio cartão e o foco não voltava).
58
+
59
+ ```vue
60
+ <Coachmark
61
+ :open="aberto"
62
+ :modal="false"
63
+ :hideSkip="true"
64
+ finishLabel="Entendi"
65
+ :steps="[{ target: '#salvar', title: 'Novo: salvar com Ctrl+S' }]"
66
+ :onClose="() => (aberto = false)"
67
+ />
68
+ ```
69
+
70
+ - 46b3b42: feat(colorpicker): `size="xs"`, a amostra de 20px do CrisDoc
71
+
72
+ `size` ganha `xs` (20px), além de `sm` (24px) e `md` (32px). O anel de seleção (o anel duplo)
73
+ e o roving tabindex são os mesmos nos três tamanhos. O `sm` segue em 24px: o `xs` é o 20px do
74
+ CrisDoc.
75
+
76
+ ```vue
77
+ <ColorPicker
78
+ ariaLabel="Marcador"
79
+ size="xs"
80
+ :families="['blue', 'red']"
81
+ defaultValue="--umds-primitive-red-pure"
82
+ />
83
+ ```
84
+
85
+ - 82e85c5: feat(datatable): cabeçalho escuro, zebra, destaque de linha, vazio com ícone, `hideHeader` e linhas hierárquicas (`treeData`)
86
+
87
+ Tudo opt-in; sem as props novas a tabela é a mesma.
88
+
89
+ - `headerVariant="dark"`: cabeçalho navy com texto claro (`background-dark` e
90
+ `neutral-light-pure`, então o tema acompanha). `headerUppercase`: caixa alta
91
+ nos rótulos, vale para qualquer cabeçalho.
92
+ - `striped`: zebra nas linhas ímpares.
93
+ - `selectedRowKeys` (com `rowKey`) e `isRowSelected(row, index)`: destacam a linha
94
+ sem checkbox (fundo, barra de 4px à esquerda e `aria-selected`). Serve à linha
95
+ "aberta" de uma lista mestre-detalhe. `selectedKeys` segue sendo o checkbox.
96
+ - `emptyIcon` (objeto Font Awesome, padrão `faInbox`) e `emptyDescription`.
97
+ - `hideHeader`: o cabeçalho some da tela e as colunas continuam nomeadas para o
98
+ leitor de tela (a linha fica visualmente oculta, não removida).
99
+ - `density="compact"` + `variant="document"`: fonte de 12px e célula de 4px × 8px.
100
+ A escala do DS não tem 13px, então o compacto da tabela de interface segue em 14.
101
+ - `treeData` + `childrenKey`: linhas hierárquicas. A tabela vira `role="treegrid"`,
102
+ as linhas ganham `aria-level`, `aria-posinset`, `aria-setsize` e `aria-expanded`,
103
+ e a primeira coluna leva recuo por nível, fios (tee, cotovelo e linha contínua) e o
104
+ botão de expandir/recolher. Teclado: ↓ ↑ andam, → expande (ou desce à primeira
105
+ filha), ← recolhe (ou sobe ao pai), Home e End. Uma linha por vez na ordem de Tab.
106
+ Estado: `expandedKeys` (controlado), `defaultExpandedKeys`, `defaultExpandAll` e
107
+ `onExpand(chaves, linha, expandida)`. A chave é o `rowKey`; sem ele, o caminho de
108
+ índices. `expandLabel` e `collapseLabel` traduzem o botão. Com `treeData`, os índices
109
+ dos callbacks contam as linhas visíveis.
110
+
111
+ O slot `#cell-<key>` do Vue segue valendo na coluna da árvore (o `postbuild` agora
112
+ liga as duas ocorrências da célula).
113
+
114
+ ```vue
115
+ <DataTable
116
+ :columns="colunas"
117
+ :data="setores"
118
+ rowKey="id"
119
+ :treeData="true"
120
+ headerVariant="dark"
121
+ :headerUppercase="true"
122
+ :striped="true"
123
+ :defaultExpandedKeys="['gab']"
124
+ :onExpand="aoExpandir"
125
+ >
126
+ <template #cell-nome="{ row }"><strong>{{ row.sigla }}</strong> {{ row.nome }}</template>
127
+ </DataTable>
128
+ ```
129
+
130
+ - 1c9f7cb: feat(descriptionlist): `density="compact"`, a fonte de 12px do CrisDoc
131
+
132
+ `density="compact"` leva a fonte da lista de 14 para 12px (nos dois desenhos), aperta o
133
+ espaço entre os pares do `stacked` (de 16 para 12px) e o padding do valor com `bordered`.
134
+ Sem a prop, ou com `default`, a lista é a mesma.
135
+
136
+ ```vue
137
+ <DescriptionList
138
+ :items="dados"
139
+ layout="stacked"
140
+ :bordered="true"
141
+ density="compact"
142
+ />
143
+ ```
144
+
145
+ - d062029: feat(emptystate): título com conteúdo rico (elemento no React, slot `title` no Vue)
146
+
147
+ O `title` do `EmptyState` aceita conteúdo (negrito, link, ícone). No React é um
148
+ elemento na própria prop; no Vue é o slot `title`, com a prop como texto de reserva.
149
+ O título passa a ser um `div` (antes um `p`), com a mesma classe e o mesmo visual,
150
+ para o conteúdo de bloco não virar HTML inválido. `title` deixou de ser obrigatório
151
+ na tipagem: no Vue o slot basta.
152
+
153
+ ```vue
154
+ <EmptyState :icon="faMagnifyingGlass" description="Ajuste o filtro de setor.">
155
+ <template #title>Nenhum processo para <strong>SOBR</strong></template>
156
+ </EmptyState>
157
+ ```
158
+
159
+ - 29955dd: feat(input): `grouped`, o campo dentro de um contêiner que já tem moldura e foco (campo de chips)
160
+
161
+ Opt-in. `grouped` implica `borderless` e tira a altura de campo, o padding e o anel
162
+ de foco próprio do `Input`: a altura vem do conteúdo (a linha cresce com as tags), o
163
+ campo ocupa o espaço que sobra (`flex: 1 1 80px`, sem `fullWidth`) e quem mostra o foco é
164
+ o contêiner, com `:focus-within`. O `borderless` sozinho continua como era: com altura de
165
+ campo e o contorno de foco para dentro. Sem o foco no contêiner, quem usa teclado perde o
166
+ indicador (WCAG 2.4.7): a doc da prop avisa.
167
+
168
+ ```vue
169
+ <div class="chips-campo"> <!-- a moldura e o :focus-within são seus -->
170
+ <Tag label="SADM" size="sm" />
171
+ <Input ariaLabel="Adicionar setor" :grouped="true" size="sm" />
172
+ </div>
173
+ ```
174
+
175
+ - 76c0087: feat(listitem): `tooltip`, `standalone` e atributos HTML só no elemento interativo
176
+
177
+ - `tooltip`: vira o atributo HTML `title` do `button`, `a` ou `div` (a dica nativa do
178
+ navegador). `title` continua sendo o título da linha, não o atributo.
179
+ - `standalone`: renderiza sem o `li`, só o elemento interativo, para usar fora de um
180
+ `List` (botão de número de página, item de carrossel). `class` (Vue) ou `className`
181
+ vai ao elemento.
182
+ - Correção no Vue: `aria-*`, `role`, `data-*` e `style` iam ao `li` além do elemento
183
+ interativo (o `aria-label` aparecia duas vezes e o `li` ganhava um `role` que não era
184
+ dele). Agora o `inheritAttrs` está desligado e esses atributos vão só ao elemento
185
+ interativo, como no React. O `class` do Vue continua no `li`, como sempre. Por baixo,
186
+ o ListItem passa a ter duas raízes (com `li` e `standalone`), então o HTML do servidor
187
+ abre com marcador de fragmento.
188
+
189
+ ```vue
190
+ <ListItem
191
+ :standalone="true"
192
+ title="12"
193
+ tooltip="Página 12"
194
+ :selected="pagina === 12"
195
+ :onClick="irPara"
196
+ />
197
+ ```
198
+
199
+ - 3500910: feat(richtexteditor): alinhamento, imagem e tabela simples na `toolbar`
200
+
201
+ Opt-in: a barra padrão não muda. Entram na `toolbar` por nome:
202
+
203
+ - `alignLeft`, `alignCenter`, `alignRight`, `alignJustify`: botões de liga/desliga
204
+ que seguem o cursor (`aria-pressed`). O valor guarda `text-align` nos blocos.
205
+ - `image`: abre um painel (como o do link) com o endereço da imagem, o arquivo
206
+ (PNG, JPEG, GIF ou WebP até 2 MB, que entra como `data:` URL) e o texto
207
+ alternativo. Endereço e arquivo inválidos mostram o erro e o painel continua aberto.
208
+ - `table`: abre um painel com linhas e colunas (1 a 20 e 1 a 10, padrão 3 × 3) e
209
+ insere a tabela. Com o cursor numa célula aparece a barra de adicionar e remover
210
+ linha e coluna e remover a tabela (mexe no DOM, então fica fora do desfazer).
211
+
212
+ A higienização do valor passou a aceitar `text-align` nos blocos (também pelo
213
+ atributo `align`), `img` e a tabela (`table`, `thead`, `tbody`, `tr`, `th`, `td`
214
+ com `colspan` e `rowspan`). Imagem só vale com `http(s)`, caminho (`/x`, `./x`,
215
+ `../x`) ou `data:image` em base64 de PNG, JPEG, GIF e WebP; SVG, `javascript:`,
216
+ `//host` e o resto saem inteiros. Colar continua entrando como texto puro.
217
+
218
+ Todos os textos novos vêm por `labels` (`imageUrl`, `imageAlt`, `imageFile`,
219
+ `imageApply`, `imageCancel`, `imageInvalid`, `imageType`, `imageTooLarge`,
220
+ `tableRows`, `tableCols`, `tableApply`, `tableCancel`, `tableInvalid`,
221
+ `tableActions`, `tableAddRow`, `tableRemoveRow`, `tableAddCol`, `tableRemoveCol`,
222
+ `tableRemove` e o nome de cada ferramenta nova).
223
+
224
+ ```vue
225
+ <RichTextEditor
226
+ label="Parecer"
227
+ :defaultValue="html"
228
+ :toolbar="[
229
+ 'bold',
230
+ 'italic',
231
+ '|',
232
+ 'alignLeft',
233
+ 'alignCenter',
234
+ 'alignRight',
235
+ 'alignJustify',
236
+ '|',
237
+ 'link',
238
+ 'image',
239
+ 'table',
240
+ ]"
241
+ />
242
+ ```
243
+
244
+ - af0d976: feat(richtexteditor): família, tamanho de fonte e cor do texto, por token do DS
245
+
246
+ Opt-in na `toolbar`: `fontFamily`, `fontSize` e `textColor`. Cada um abre um painel abaixo da
247
+ barra e aplica ao texto selecionado, embrulhando-o num `<span style="...">`:
248
+
249
+ - `fontFamily`: padrão ou monoespaçada (`var(--umds-semantic-font-family-base|mono)`), num `Select`.
250
+ - `fontSize`: 12, 14, 16, 20 e 24px, os degraus da escala do DS (`var(--umds-primitive-font-size-*)`).
251
+ - `textColor`: a paleta do DS, num `ColorPicker` `xs`; o valor guarda o `var()` do token escolhido.
252
+
253
+ Sem texto selecionado o painel pede a seleção e não aplica nada. Esc fecha só a lista do `Select`
254
+ aberta; o seguinte fecha o painel. Para voltar ao padrão, use `clear`.
255
+
256
+ A higienização aceita `color`, `font-size` e `font-family` só em `<span>` e só com token do DS: cor
257
+ em hex, `rgb()` ou nome, tamanho em px e fonte por nome saem, e o resto do `style` também.
258
+
259
+ Textos novos por `labels`: `fontFamily`, `fontSize`, `textColor`, `fontFamilyBase`,
260
+ `fontFamilyMono`, `styleClose` e `styleNeedsSelection`.
261
+
262
+ ```vue
263
+ <RichTextEditor
264
+ label="Parecer"
265
+ :toolbar="['bold', 'italic', '|', 'fontFamily', 'fontSize', 'textColor']"
266
+ />
267
+ ```
268
+
269
+ - 992f59a: feat(segmentedcontrol): `count` por item, a pílula do contador como a do `Tab`
270
+
271
+ Cada opção aceita `count` (número ou texto): uma pílula de 18px depois do rótulo,
272
+ cinza no segmento solto e branca sobre o azul do escolhido (o mesmo desenho do
273
+ contador do `Tab`). `0` aparece; vazio e ausente não. O contador entra no nome
274
+ acessível do segmento ("Todas 31"). Sem `count`, o segmento é o mesmo.
275
+
276
+ ```vue
277
+ <SegmentedControl
278
+ label="Fila"
279
+ :value="fila"
280
+ :onChange="(v) => (fila = v)"
281
+ :options="[
282
+ { label: 'Todas', value: 'todas', count: 31 },
283
+ { label: 'Minhas', value: 'minhas', count: 12 },
284
+ ]"
285
+ />
286
+ ```
287
+
288
+ - 22a79d8: feat(select): `open`/`onOpenChange`, gatilho com ícone e amostra de cor, variantes `search` e `combo`, lista por cima de diálogo e `placement="auto"` que mede o ancestral
289
+
290
+ Tudo opt-in; o Select sem as props novas se comporta como antes, fora de diálogo.
291
+
292
+ - `open` e `onOpenChange(open)`: a lista controlada de fora. O clique, o teclado,
293
+ o clique fora, o Esc e a escolha de uma opção avisam o pai, que decide o novo
294
+ `open`. Sem `open`, o Select abre e fecha sozinho e também avisa. É o que deixa o
295
+ filtro com ação no rodapé fechar a lista antes de abrir um modal.
296
+ - `triggerIcon` (objeto Font Awesome) e `triggerSwatch` (um token de cor): ícone e
297
+ amostra de cor à esquerda do texto do gatilho, decorativos.
298
+ - `variant="search"` (o filtro numa barra de busca: altura de campo e contorno neutro)
299
+ e `variant="combo"` (colado a outro controle, sem borda nem raio próprios). Os dois
300
+ são filtro: busca focada ao abrir, `emptyOptionLabel` e o rodapé valem.
301
+ - Dentro de um diálogo (`role="dialog"` ou `aria-modal`), a lista abre por cima dele:
302
+ `position: fixed` ancorada no gatilho pelo `@floating-ui/dom`, com a largura do
303
+ gatilho e a altura limitada ao espaço da janela. O `overflow` do corpo do modal
304
+ não corta mais a lista.
305
+ - `placement="auto"` agora mede também cada ancestral que rola ou corta (um corpo de
306
+ modal, um painel com `overflow`), não só a janela, e limita a altura da lista ao
307
+ espaço que sobra (mínimo de 96px).
308
+ - `required` repassa `aria-required` ao combobox.
309
+
310
+ ```vue
311
+ <Select
312
+ variant="filter"
313
+ ariaLabel="Marcadores"
314
+ placeholder="Marcadores"
315
+ :triggerIcon="faTag"
316
+ :open="aberto"
317
+ :onOpenChange="(v) => (aberto = v)"
318
+ :options="marcadores"
319
+ :value="valor"
320
+ :onChange="(v) => (valor = v)"
321
+ >
322
+ <template #footer>
323
+ <Button variant="text" size="sm" @click="abrirGerenciador">Gerenciar marcadores</Button>
324
+ </template>
325
+ </Select>
326
+ ```
327
+
328
+ - f7fa5dd: feat(select): o filtro no tamanho do CrisDoc, com cor por opção (`option.color`)
329
+
330
+ Para substituir o `FiltroSelect` do app:
331
+
332
+ - As variantes de filtro (`filter`, `search`, `combo`) nascem no tamanho `sm` (32px, fonte de
333
+ 12px) quando `size` não é passado; `size="md"` continua valendo. O `Select` padrão não muda.
334
+ - O gatilho do `filter` tem fundo branco com contorno azul. O azul-claro só vem depois de
335
+ escolhido um valor (a classe `umds-select--has-value`), que é quando o filtro está
336
+ recortando a lista. `search` e `combo` mantêm o fundo deles.
337
+ - `option.color` (um token, `var(--umds-semantic-color-...)`): uma amostra de 12px antes do
338
+ texto de cada opção na lista e, com a opção escolhida (seleção única), no gatilho.
339
+ `triggerSwatch` explícito manda sobre ela. A cor é decorativa: o nome da opção continua
340
+ sendo o texto.
341
+ - O `useStore` do `Select` passou a checar o gatilho antes do `autoUpdate` (o `tsc` do React
342
+ acusava o `null`).
343
+
344
+ ```vue
345
+ <Select
346
+ variant="filter"
347
+ ariaLabel="Marcadores"
348
+ placeholder="Marcadores"
349
+ :triggerIcon="faFilter"
350
+ :options="[
351
+ {
352
+ label: 'Urgente',
353
+ value: 'urgente',
354
+ color: 'var(--umds-semantic-color-feedback-negative-pure)',
355
+ },
356
+ ]"
357
+ />
358
+ ```
359
+
360
+ - b9f0813: feat(statcard): segunda medida (`secondaryValue`/`secondaryLabel`) e `valueTone`
361
+
362
+ - `secondaryValue` e `secondaryLabel`: a segunda medida do cartão, menor (20px), à direita da
363
+ principal, separada por um filete ("22,31% Meu Setor | 14,11% Geral"). No HTML vem depois do
364
+ resto, então o leitor de tela lê a medida principal inteira antes. `0` aparece; vazio e
365
+ ausente não. Com `labelPosition="top"` a grade ganha uma terceira coluna.
366
+ - `valueTone`: cor do número principal, `default` | `primary` | `positive` | `negative` |
367
+ `info`, pelas variantes escuras (contraste AA no branco). Não mexe na `variant`, que segue
368
+ pintando o ícone e a variação.
369
+
370
+ ```vue
371
+ <StatCard
372
+ labelPosition="top"
373
+ label="Eficiência"
374
+ value="22,31%"
375
+ description="Meu Setor"
376
+ secondaryValue="14,11%"
377
+ secondaryLabel="Geral"
378
+ valueTone="primary"
379
+ />
380
+ ```
381
+
382
+ - a4b6bb7: feat(toast): ação (`actionLabel`/`onAction`) e lista de detalhes (`details`)
383
+
384
+ - `actionLabel` + `onAction`: um botão depois do texto ("Desfazer", "Ver processo").
385
+ Acionar chama `onAction` e depois fecha o toast (`onClose`). O botão só aparece com os
386
+ dois. O botão de fechar continua ao lado.
387
+ - `details`: lista de linhas curtas abaixo da descrição ("Anexo 1 acima de 10 MB").
388
+ - No `toast()` imperativo e no `ToastStack`, as três opções passam adiante. Toast com ação
389
+ tem `duration: 0` por padrão (não some antes de dar tempo de agir, WCAG 2.2.1); sem ação
390
+ continua em 5000, e um `duration` explícito vale sempre.
391
+
392
+ ```ts
393
+ toast({
394
+ message: "Despacho enviado",
395
+ variant: "positive",
396
+ actionLabel: "Desfazer",
397
+ onAction: desfazer,
398
+ });
399
+ ```
400
+
401
+ ### Patch Changes
402
+
403
+ - 6c12a37: fix(appsubheader): a região do contexto ocupa a altura da barra e só rola na horizontal
404
+
405
+ Com a trilha só na página atual (um `Breadcrumb` sem link), o axe acusava
406
+ `scrollable-region-focusable`. Medido no navegador: a região do contexto tinha 12px de
407
+ altura (a do item do Breadcrumb, `line-height: 1` em 12px) e `scrollHeight` de 14, e como
408
+ `overflow-x: auto` faz o `overflow-y` computar para `auto`, ela virava uma região rolável
409
+ sem nenhum elemento focável dentro. Agora a região ocupa a altura da barra
410
+ (`align-self: stretch`, 41px, com o conteúdo centralizado) e corta o eixo vertical
411
+ (`overflow-y: hidden`): não há o que rolar na vertical. A rolagem horizontal da trilha longa
412
+ continua igual. Story nova "Só a página atual" confere `scrollHeight` e `scrollWidth`.
413
+
414
+ - e8f1894: fix(attachmentcard): o `dl` do painel de conferência passa no axe (`definition-list`)
415
+
416
+ Cada campo do painel era `div > (div > dt + dd) + button`: o `dl` só aceita `div` com `dt` e
417
+ `dd` direto dentro, então o axe acusava `definition-list`. Agora é `div > dt + dd`, e o
418
+ botão de copiar mora dentro do `dd`, ao lado do valor (o valor passou a ter o próprio
419
+ `span`, `umds-attachment-card__campo-valor-texto`). O visual muda só no detalhe: o botão
420
+ de copiar fica alinhado à linha do valor, não ao centro das duas linhas do campo.
421
+
422
+ - 04d5a43: fix(badge): o neutro colado é o cinza claro com texto escuro
423
+
424
+ `<Badge attached variant="neutral" appearance="solid">` ficava no cinza escuro do `solid`
425
+ neutro, pesado demais para o rótulo de um card. Agora o neutro colado e sólido é o cinza claro
426
+ com texto escuro (o "Tarefa manual" do CrisDoc). O `solid` neutro fora do `attached` não muda.
427
+
428
+ - e5896d9: docs(calendar): os slots do cabeçalho no Vue são `#header-start` e `#header-end`
429
+
430
+ O `index.d.ts` e a documentação diziam `headerStart` e `headerEnd` para os dois
431
+ frameworks, mas no Vue só os nomes com hífen chegam ao cabeçalho (o Vue lê o nome do
432
+ slot como está: `#headerStart` é descartado em silêncio). A doc do componente, o
433
+ comentário das props e os `argTypes` dos Storybooks agora dizem: no React, as props
434
+ `headerStart` e `headerEnd` (um nó); no Vue, os slots `#header-start` e `#header-end`.
435
+ Sem mudança de comportamento.
436
+
3
437
  ## 2.9.0
4
438
 
5
439
  ### Minor Changes
@@ -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 →
@@ -16,6 +16,7 @@ export interface AccordionItemData {
16
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 }`).
17
17
  * @property {boolean} multiple - Permite manter vários painéis abertos ao mesmo tempo
18
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.
19
20
  * @property {string} className - Classes CSS adicionais
20
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`.
21
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.
@@ -24,6 +25,8 @@ export interface AccordionProps {
24
25
  items: AccordionItemData[];
25
26
  multiple?: boolean;
26
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";
27
30
  className?: string;
28
31
  }
29
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
 
@@ -183,18 +183,10 @@
183
183
  }
184
184
 
185
185
  .umds-attachment-card__campo {
186
- display: flex;
187
- align-items: center;
188
- gap: var(--umds-primitive-spacing-nano);
189
186
  padding: var(--umds-primitive-spacing-nano) 0;
190
187
  border-top: 1px solid var(--umds-semantic-color-neutral-light-medium);
191
188
  }
192
189
 
193
- .umds-attachment-card__campo-texto {
194
- flex: 1;
195
- min-width: 0;
196
- }
197
-
198
190
  .umds-attachment-card__campo-rotulo {
199
191
  color: var(--umds-semantic-color-neutral-dark-down);
200
192
  font-size: var(--umds-primitive-font-size-xxxs);
@@ -202,7 +194,12 @@
202
194
  text-transform: uppercase;
203
195
  }
204
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>). */
205
199
  .umds-attachment-card__campo-valor {
200
+ display: flex;
201
+ align-items: center;
202
+ gap: var(--umds-primitive-spacing-nano);
206
203
  margin: var(--umds-primitive-spacing-micro) 0 0; /* 2px: respiro rótulo→valor */
207
204
  font-size: var(--umds-primitive-font-size-xxs);
208
205
  font-weight: var(--umds-primitive-font-weight-bold);
@@ -210,6 +207,11 @@
210
207
  overflow-wrap: anywhere;
211
208
  }
212
209
 
210
+ .umds-attachment-card__campo-valor-texto {
211
+ flex: 1;
212
+ min-width: 0;
213
+ }
214
+
213
215
  /* Alvo de toque WCAG 2.5.8: 32×32. */
214
216
  .umds-attachment-card__copiar {
215
217
  display: inline-flex;
@@ -15,6 +15,7 @@ import './AttachmentCard.css';
15
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.
16
16
  * @property {Function} onCopyField - Avisa quando um campo do painel é copiado (recebe o campo)
17
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.
18
19
  * @property {Function} onOpen - Abre o anexo. Com ele o cartão inteiro vira alvo de clique, com um único ponto de foco.
19
20
  * @property {string} openAriaLabel - Nome acessível da ação de abrir. Padrão: "Abrir <tipo>: <arquivo>".
20
21
  * @property {string} className - Classes CSS adicionais
@@ -60,6 +61,8 @@ export interface AttachmentCardProps {
60
61
  closePanelOnAction?: boolean;
61
62
  onCopyField?: (field: AttachmentCardField) => void;
62
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";
63
66
  onOpen?: (event?: any) => void;
64
67
  openAriaLabel?: string;
65
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 */
@@ -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)
@@ -145,6 +146,12 @@ function AttachmentCard(props) {
145
146
  return faFileExcel;
146
147
  return faFile;
147
148
  }
149
+ function tamanhoIconeCentral() {
150
+ return props.size === "sm" ? "40px" : "48px";
151
+ }
152
+ function tamanhoIconeRodape() {
153
+ return props.size === "sm" ? "12px" : undefined;
154
+ }
148
155
  function iconeCentral() {
149
156
  return props.icon || faFileLines;
150
157
  }
@@ -386,6 +393,6 @@ function AttachmentCard(props) {
386
393
  desligarObservadores();
387
394
  };
388
395
  }, []);
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 }))] })] }));
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 }))] })] }));
390
397
  }
391
398
  export default AttachmentCard;
@@ -3,7 +3,7 @@
3
3
  Variantes: neutral, positive, negative, info, primary, new
4
4
  Aparências (appearance): solid, soft, outlined
5
5
  Tamanhos: 2xs, xs, sm, md, lg, pill
6
- Modificador: attached (rótulo colado no topo de um card)
6
+ Modificador: attached (rótulo colado no topo de um card), attachedSide left | right
7
7
  ============================================ */
8
8
 
9
9
  .umds-badge {
@@ -254,3 +254,16 @@
254
254
  left: 0;
255
255
  border-radius: 0 0 var(--umds-primitive-border-radius-sm) var(--umds-primitive-border-radius-sm);
256
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
+ }