@1doc/1ds-react 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1106 -0
- package/dist/components/AILabel/AILabel.js +1 -1
- package/dist/components/Accordion/Accordion.d.ts +6 -2
- package/dist/components/AttachmentCard/AttachmentCard.css +16 -0
- package/dist/components/AttachmentCard/AttachmentCard.d.ts +19 -2
- package/dist/components/AttachmentCard/AttachmentCard.js +40 -3
- package/dist/components/Avatar/Avatar.css +7 -2
- package/dist/components/Avatar/AvatarGroup.d.ts +17 -0
- package/dist/components/Avatar/AvatarGroup.js +22 -8
- package/dist/components/Badge/Badge.css +54 -2
- package/dist/components/Badge/Badge.d.ts +14 -4
- package/dist/components/Badge/Badge.js +1 -0
- package/dist/components/Box/Box.css +83 -0
- package/dist/components/Box/Box.d.ts +82 -2
- package/dist/components/Box/Box.js +42 -2
- package/dist/components/Button/Button.css +29 -0
- package/dist/components/Button/Button.d.ts +4 -4
- package/dist/components/Button/Button.js +4 -1
- package/dist/components/Calendar/Calendar.css +245 -0
- package/dist/components/Calendar/Calendar.d.ts +125 -0
- package/dist/components/Calendar/Calendar.js +320 -0
- package/dist/components/Chips/Chips.css +38 -0
- package/dist/components/Chips/Chips.d.ts +5 -2
- package/dist/components/Chips/Chips.js +2 -1
- package/dist/components/Coachmark/Coachmark.css +118 -0
- package/dist/components/Coachmark/Coachmark.d.ts +75 -0
- package/dist/components/Coachmark/Coachmark.js +321 -0
- package/dist/components/CodeBlock/CodeBlock.css +96 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
- package/dist/components/CodeBlock/CodeBlock.js +103 -0
- package/dist/components/ColorPicker/ColorPicker.css +133 -0
- package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
- package/dist/components/ColorPicker/ColorPicker.js +219 -0
- package/dist/components/Combobox/Combobox.css +8 -0
- package/dist/components/DataTable/DataTable.css +80 -0
- package/dist/components/DataTable/DataTable.d.ts +19 -4
- package/dist/components/DataTable/DataTable.js +59 -15
- package/dist/components/DatePicker/DatePicker.css +8 -0
- package/dist/components/DatePicker/DatePicker.js +10 -1
- package/dist/components/DescriptionList/DescriptionList.css +113 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
- package/dist/components/DescriptionList/DescriptionList.js +51 -0
- package/dist/components/FileInput/FileInput.css +16 -0
- package/dist/components/FileInput/FileInput.d.ts +4 -2
- package/dist/components/FileInput/FileInput.js +8 -2
- package/dist/components/Grid/Grid.js +5 -5
- package/dist/components/IconPicker/IconPicker.css +107 -0
- package/dist/components/IconPicker/IconPicker.d.ts +74 -0
- package/dist/components/IconPicker/IconPicker.js +194 -0
- package/dist/components/Input/Input.css +38 -0
- package/dist/components/Input/Input.d.ts +10 -1
- package/dist/components/Input/Input.js +66 -5
- package/dist/components/Kanban/Kanban.css +4 -0
- package/dist/components/Kbd/Kbd.css +66 -0
- package/dist/components/Kbd/Kbd.d.ts +32 -0
- package/dist/components/Kbd/Kbd.js +40 -0
- package/dist/components/List/List.css +136 -0
- package/dist/components/List/List.d.ts +82 -0
- package/dist/components/List/List.js +53 -0
- package/dist/components/List/ListItem.d.ts +85 -0
- package/dist/components/List/ListItem.js +81 -0
- package/dist/components/Modal/Modal.css +80 -0
- package/dist/components/Modal/Modal.d.ts +33 -6
- package/dist/components/Modal/Modal.js +101 -6
- package/dist/components/MultiSelect/MultiSelect.css +8 -0
- package/dist/components/MultiSelect/MultiSelect.js +10 -1
- package/dist/components/OrgChart/OrgChart.css +149 -0
- package/dist/components/OrgChart/OrgChart.d.ts +83 -0
- package/dist/components/OrgChart/OrgChart.js +297 -0
- package/dist/components/OtpInput/OtpInput.css +93 -0
- package/dist/components/OtpInput/OtpInput.d.ts +60 -0
- package/dist/components/OtpInput/OtpInput.js +215 -0
- package/dist/components/PhoneInput/PhoneInput.css +8 -0
- package/dist/components/Popover/Popover.d.ts +7 -0
- package/dist/components/Popover/Popover.js +11 -1
- package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
- package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
- package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +7 -2
- package/dist/components/Select/Select.css +70 -0
- package/dist/components/Select/Select.d.ts +12 -0
- package/dist/components/Select/Select.js +59 -4
- package/dist/components/Stack/Stack.css +49 -0
- package/dist/components/Stack/Stack.d.ts +65 -7
- package/dist/components/Stack/Stack.js +30 -2
- package/dist/components/StatCard/StatCard.css +73 -0
- package/dist/components/StatCard/StatCard.d.ts +17 -0
- package/dist/components/StatCard/StatCard.js +4 -1
- package/dist/components/Tabs/Tab.d.ts +15 -0
- package/dist/components/Tabs/Tab.js +30 -1
- package/dist/components/Tabs/Tabs.css +132 -0
- package/dist/components/Tabs/Tabs.d.ts +7 -0
- package/dist/components/Tabs/Tabs.js +13 -2
- package/dist/components/Tag/Tag.css +85 -2
- package/dist/components/Tag/Tag.d.ts +13 -6
- package/dist/components/Tag/Tag.js +1 -0
- package/dist/components/Text/Text.js +2 -2
- package/dist/components/Textarea/Textarea.css +8 -0
- package/dist/components/TimePicker/TimePicker.css +8 -0
- package/dist/components/Tooltip/Tooltip.css +25 -0
- package/dist/components/Tooltip/Tooltip.d.ts +11 -0
- package/dist/components/Tooltip/Tooltip.js +18 -3
- package/dist/index.d.ts +25 -0
- package/dist/index.js +14 -0
- package/dist/teste/AILabel.test.d.ts +1 -0
- package/dist/teste/AILabel.test.js +33 -0
- package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
- package/dist/teste/AccordionConteudoLivre.test.js +29 -0
- package/dist/teste/AtributosRepassados.test.d.ts +1 -0
- package/dist/teste/AtributosRepassados.test.js +52 -0
- package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
- package/dist/teste/AttachmentCardIA.test.js +89 -0
- package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
- package/dist/teste/AvatarGroupOverlap.test.js +56 -0
- package/dist/teste/BadgeTag.test.d.ts +1 -0
- package/dist/teste/BadgeTag.test.js +42 -0
- package/dist/teste/BoxItemFlex.test.d.ts +1 -0
- package/dist/teste/BoxItemFlex.test.js +54 -0
- package/dist/teste/BoxLayout.test.d.ts +1 -0
- package/dist/teste/BoxLayout.test.js +35 -0
- package/dist/teste/Button.test.d.ts +1 -0
- package/dist/teste/Button.test.js +27 -0
- package/dist/teste/Calendar.test.d.ts +1 -0
- package/dist/teste/Calendar.test.js +221 -0
- package/dist/teste/ChipsXs.test.d.ts +1 -0
- package/dist/teste/ChipsXs.test.js +31 -0
- package/dist/teste/Coachmark.test.d.ts +1 -0
- package/dist/teste/Coachmark.test.js +149 -0
- package/dist/teste/ColorPicker.test.d.ts +1 -0
- package/dist/teste/ColorPicker.test.js +132 -0
- package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
- package/dist/teste/DataTableCelulaLivre.test.js +76 -0
- package/dist/teste/DataTableDocumento.test.d.ts +1 -0
- package/dist/teste/DataTableDocumento.test.js +92 -0
- package/dist/teste/DatePicker.test.js +23 -0
- package/dist/teste/FileInputTrigger.test.d.ts +1 -0
- package/dist/teste/FileInputTrigger.test.js +53 -0
- package/dist/teste/IconPicker.test.d.ts +1 -0
- package/dist/teste/IconPicker.test.js +130 -0
- package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
- package/dist/teste/InputMascaraEAfins.test.js +99 -0
- package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
- package/dist/teste/KbdCodeBlock.test.js +95 -0
- package/dist/teste/List.test.d.ts +1 -0
- package/dist/teste/List.test.js +153 -0
- package/dist/teste/ModalVariantes.test.d.ts +1 -0
- package/dist/teste/ModalVariantes.test.js +151 -0
- package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
- package/dist/teste/NomeAcessivelSsr.test.js +88 -0
- package/dist/teste/OrgChart.test.d.ts +1 -0
- package/dist/teste/OrgChart.test.js +162 -0
- package/dist/teste/OtpInput.test.d.ts +1 -0
- package/dist/teste/OtpInput.test.js +143 -0
- package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
- package/dist/teste/PopoverMaxHeight.test.js +38 -0
- package/dist/teste/RichTextEditor.test.d.ts +1 -0
- package/dist/teste/RichTextEditor.test.js +287 -0
- package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
- package/dist/teste/SelectPlacementFiltro.test.js +88 -0
- package/dist/teste/Stack.test.d.ts +1 -0
- package/dist/teste/Stack.test.js +57 -0
- package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
- package/dist/teste/StatCardRotuloTopo.test.js +34 -0
- package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
- package/dist/teste/TabsContadorFechavel.test.js +79 -0
- package/dist/teste/TooltipDark.test.d.ts +1 -0
- package/dist/teste/TooltipDark.test.js +31 -0
- package/dist/utils/calendario.d.ts +28 -0
- package/dist/utils/calendario.js +73 -0
- package/dist/utils/html-seguro.d.ts +27 -0
- package/dist/utils/html-seguro.js +97 -0
- package/dist/utils/paleta-de-cores.d.ts +26 -0
- package/dist/utils/paleta-de-cores.js +10 -0
- package/dist/utils/texto.d.ts +5 -0
- package/dist/utils/texto.js +5 -0
- package/package.json +3 -3
- package/src/index.ts +26 -0
- package/src/teste/AILabel.test.tsx +41 -0
- package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
- package/src/teste/AtributosRepassados.test.tsx +73 -0
- package/src/teste/AttachmentCardIA.test.tsx +126 -0
- package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
- package/src/teste/BadgeTag.test.tsx +64 -0
- package/src/teste/BoxItemFlex.test.tsx +81 -0
- package/src/teste/BoxLayout.test.tsx +50 -0
- package/src/teste/Button.test.tsx +39 -0
- package/src/teste/Calendar.test.tsx +282 -0
- package/src/teste/ChipsXs.test.tsx +41 -0
- package/src/teste/Coachmark.test.tsx +198 -0
- package/src/teste/ColorPicker.test.tsx +153 -0
- package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
- package/src/teste/DataTableDocumento.test.tsx +102 -0
- package/src/teste/DatePicker.test.tsx +38 -0
- package/src/teste/FileInputTrigger.test.tsx +89 -0
- package/src/teste/IconPicker.test.tsx +145 -0
- package/src/teste/InputMascaraEAfins.test.tsx +124 -0
- package/src/teste/KbdCodeBlock.test.tsx +106 -0
- package/src/teste/List.test.tsx +269 -0
- package/src/teste/ModalVariantes.test.tsx +173 -0
- package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
- package/src/teste/OrgChart.test.tsx +183 -0
- package/src/teste/OtpInput.test.tsx +163 -0
- package/src/teste/PopoverMaxHeight.test.tsx +47 -0
- package/src/teste/RichTextEditor.test.tsx +329 -0
- package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
- package/src/teste/Stack.test.tsx +80 -0
- package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
- package/src/teste/TabsContadorFechavel.test.tsx +144 -0
- package/src/teste/TooltipDark.test.tsx +51 -0
- package/src/utils/calendario.ts +78 -0
- package/src/utils/html-seguro.ts +94 -0
- package/src/utils/paleta-de-cores.ts +34 -0
- package/src/utils/texto.ts +5 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import './Kbd.css';
|
|
2
|
+
/**
|
|
3
|
+
* Kbd — uma tecla, ou uma combinação de teclas, num `<kbd>`.
|
|
4
|
+
*
|
|
5
|
+
* Uma tecla: `<Kbd>Esc</Kbd>`. Uma combinação: `keys` (`["Ctrl", "Shift", "P"]`),
|
|
6
|
+
* que desenha uma caixa por tecla com o `separator` entre elas (`+` por padrão).
|
|
7
|
+
* A fonte é a monoespaçada do DS (`--umds-semantic-font-family-mono`), a caixa é
|
|
8
|
+
* cinza com borda e uma sombra de base, como uma tecla de verdade.
|
|
9
|
+
*
|
|
10
|
+
* Semântica: `<kbd>` é o elemento HTML de "entrada de teclado", e um `<kbd>`
|
|
11
|
+
* dentro de outro é a forma de dizer "combinação de teclas". O leitor de tela lê
|
|
12
|
+
* "Ctrl + Shift + P" (o separador é texto, não desenho).
|
|
13
|
+
* @property {string[]} keys - Teclas de uma combinação, em ordem. Sem `keys`, vale o conteúdo (uma tecla)
|
|
14
|
+
* @property {string} separator - Texto entre as teclas de uma combinação (padrão "+")
|
|
15
|
+
* @property {string} size - 'sm' | 'md' (padrão)
|
|
16
|
+
* @property {string} className - Classes CSS adicionais
|
|
17
|
+
* @quandoUsar Mostrar um atalho de teclado ou a tecla que a pessoa deve apertar: painel de atalhos, dica de campo, instrução.
|
|
18
|
+
* @quandoNaoUsar Para botão, use `Button`. Para trecho de código, use `CodeBlock`.
|
|
19
|
+
*/
|
|
20
|
+
export interface KbdProps {
|
|
21
|
+
keys?: string[];
|
|
22
|
+
separator?: string;
|
|
23
|
+
size?: "sm" | "md";
|
|
24
|
+
className?: string;
|
|
25
|
+
id?: string;
|
|
26
|
+
style?: any;
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
/** Uma tecla (quando não há `keys`). */
|
|
29
|
+
children?: any;
|
|
30
|
+
}
|
|
31
|
+
declare function Kbd(props: KbdProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export default Kbd;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import './Kbd.css';
|
|
3
|
+
function Kbd(props) {
|
|
4
|
+
function isSingle() {
|
|
5
|
+
return !(props.keys && props.keys.length > 0);
|
|
6
|
+
}
|
|
7
|
+
function keyList() {
|
|
8
|
+
return props.keys || [];
|
|
9
|
+
}
|
|
10
|
+
function classes() {
|
|
11
|
+
const combinacao = !!props.keys && props.keys.length > 0;
|
|
12
|
+
return [
|
|
13
|
+
combinacao ? "umds-kbd-combo" : "umds-kbd",
|
|
14
|
+
`umds-kbd--${props.size || "md"}`,
|
|
15
|
+
props.className,
|
|
16
|
+
]
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.join(" ");
|
|
19
|
+
}
|
|
20
|
+
function separatorText() {
|
|
21
|
+
return props.separator || "+";
|
|
22
|
+
}
|
|
23
|
+
function isLast(index) {
|
|
24
|
+
return index === keyList().length - 1;
|
|
25
|
+
}
|
|
26
|
+
function htmlAttrs() {
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const chave in props) {
|
|
29
|
+
if (chave.indexOf("data-") === 0 ||
|
|
30
|
+
chave.indexOf("aria-") === 0 ||
|
|
31
|
+
chave === "style" ||
|
|
32
|
+
chave === "title") {
|
|
33
|
+
out[chave] = props[chave];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
return (_jsxs("kbd", { id: props.id, ...htmlAttrs(), className: classes(), children: [isSingle() ? _jsx(_Fragment, { children: props.children }) : null, keyList()?.map((tecla, posicao) => (_jsxs("span", { className: "umds-kbd-combo__item", children: [_jsx("kbd", { className: "umds-kbd umds-kbd--inner", children: tecla }), !isLast(posicao) ? (_jsx("span", { className: "umds-kbd-combo__separator", children: separatorText() })) : null] }, posicao)))] }));
|
|
39
|
+
}
|
|
40
|
+
export default Kbd;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────
|
|
2
|
+
LIST / LIST ITEM
|
|
3
|
+
Lista semântica (ul/ol > li) de linhas clicáveis com conteúdo livre.
|
|
4
|
+
Só tokens do DS. Sem equivalente (mantido como literal):
|
|
5
|
+
padding vertical de 10px do CrisDoc → usa spacing-nano (8px).
|
|
6
|
+
───────────────────────────────────────────── */
|
|
7
|
+
|
|
8
|
+
/* ── List ── */
|
|
9
|
+
.umds-list {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
min-width: 0;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
font-family: var(--umds-semantic-font-family-base);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
ul.umds-list,
|
|
18
|
+
ol.umds-list {
|
|
19
|
+
list-style: none;
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.umds-list--gap-none { gap: 0; }
|
|
25
|
+
.umds-list--gap-micro { gap: var(--umds-primitive-spacing-micro); }
|
|
26
|
+
.umds-list--gap-quarck { gap: var(--umds-primitive-spacing-quarck); }
|
|
27
|
+
.umds-list--gap-nano { gap: var(--umds-primitive-spacing-nano); }
|
|
28
|
+
.umds-list--gap-mini { gap: var(--umds-primitive-spacing-mini); }
|
|
29
|
+
.umds-list--gap-xxxs { gap: var(--umds-primitive-spacing-xxxs); }
|
|
30
|
+
|
|
31
|
+
/* Estado vazio: o miolo da lista troca de conteúdo; quem rodeia não muda. */
|
|
32
|
+
.umds-list--empty {
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ── <li> que envolve a linha ── */
|
|
38
|
+
.umds-list__item {
|
|
39
|
+
display: block;
|
|
40
|
+
list-style: none;
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
min-width: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* ── Linha ── */
|
|
47
|
+
.umds-list-item {
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: flex-start;
|
|
50
|
+
gap: var(--umds-primitive-spacing-nano); /* 8px */
|
|
51
|
+
width: 100%;
|
|
52
|
+
box-sizing: border-box;
|
|
53
|
+
min-width: 0;
|
|
54
|
+
margin: 0;
|
|
55
|
+
padding: var(--umds-primitive-spacing-nano) var(--umds-primitive-spacing-mini); /* 8px 12px */
|
|
56
|
+
border: 0;
|
|
57
|
+
border-radius: var(--umds-primitive-border-radius-sm); /* 8px */
|
|
58
|
+
background: transparent;
|
|
59
|
+
color: var(--umds-semantic-color-neutral-dark-pure);
|
|
60
|
+
font: inherit;
|
|
61
|
+
text-align: left;
|
|
62
|
+
text-decoration: none;
|
|
63
|
+
transition: background-color var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.umds-list-item--interactive {
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.umds-list-item--interactive:hover {
|
|
71
|
+
background: var(--umds-semantic-color-background-light);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.umds-list-item--interactive:focus-visible {
|
|
75
|
+
outline: 2px solid var(--umds-semantic-color-primary-pure);
|
|
76
|
+
outline-offset: -2px; /* dentro da linha: o anel não é cortado por overflow do pai */
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* ── Selecionado ── */
|
|
80
|
+
.umds-list-item--selected {
|
|
81
|
+
background: var(--umds-semantic-color-primary-light);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.umds-list-item--selected.umds-list-item--interactive:hover {
|
|
85
|
+
background: color-mix(
|
|
86
|
+
in srgb,
|
|
87
|
+
var(--umds-semantic-color-primary-light) 85%,
|
|
88
|
+
var(--umds-semantic-color-background-white)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ── Desabilitado ── */
|
|
93
|
+
.umds-list-item--disabled,
|
|
94
|
+
.umds-list-item--disabled .umds-list-item__subtitle,
|
|
95
|
+
.umds-list-item--disabled .umds-list-item__meta {
|
|
96
|
+
color: var(--umds-semantic-color-neutral-dark-up);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.umds-list-item--disabled,
|
|
100
|
+
.umds-list-item--disabled.umds-list-item--interactive:hover {
|
|
101
|
+
cursor: not-allowed;
|
|
102
|
+
background: transparent;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* ── Anatomia ── */
|
|
106
|
+
.umds-list-item__start,
|
|
107
|
+
.umds-list-item__end {
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
flex-shrink: 0;
|
|
110
|
+
align-items: center;
|
|
111
|
+
align-self: center;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.umds-list-item__end {
|
|
115
|
+
margin-left: auto;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.umds-list-item__body {
|
|
119
|
+
display: flex;
|
|
120
|
+
flex: 1 1 auto;
|
|
121
|
+
flex-direction: column;
|
|
122
|
+
gap: var(--umds-primitive-spacing-micro); /* 2px */
|
|
123
|
+
min-width: 0;
|
|
124
|
+
overflow-wrap: anywhere;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.umds-list-item__title {
|
|
128
|
+
display: block;
|
|
129
|
+
color: inherit;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.umds-list-item__subtitle,
|
|
133
|
+
.umds-list-item__meta {
|
|
134
|
+
display: block;
|
|
135
|
+
color: var(--umds-semantic-color-neutral-dark-down);
|
|
136
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import './List.css';
|
|
2
|
+
/** Espaço entre as linhas, na escala oficial do DS. `none` cola as linhas. */
|
|
3
|
+
export type ListGap = "none" | "micro" | "quarck" | "nano" | "mini" | "xxxs";
|
|
4
|
+
/** Elemento da lista: `ul` (padrão) ou `ol` quando a ordem importa. */
|
|
5
|
+
/** Espaço entre as linhas, na escala oficial do DS. `none` cola as linhas. */
|
|
6
|
+
/** Elemento da lista: `ul` (padrão) ou `ol` quando a ordem importa. */
|
|
7
|
+
export type ListTag = "ul" | "ol";
|
|
8
|
+
/**
|
|
9
|
+
* List — agrupa `ListItem` numa lista semântica (`ul`/`ol` com `li`) e traz o
|
|
10
|
+
* estado vazio dentro dela.
|
|
11
|
+
*
|
|
12
|
+
* Quando não há itens, passe `isEmpty`: a lista troca os itens por um
|
|
13
|
+
* `EmptyState` (`emptyTitle`, `emptyDescription`, `emptyIcon`, `emptyActionLabel`
|
|
14
|
+
* com `onEmptyAction`) ou, para um conteúdo próprio, pelo slot `empty`. Só o
|
|
15
|
+
* miolo troca: o título do cartão, a busca, os filtros e a paginação ao redor
|
|
16
|
+
* continuam montados, e o estado vazio é anunciado ao leitor de tela
|
|
17
|
+
* (`role="status"`). `isEmpty` é uma decisão sua, porque a lista não conta
|
|
18
|
+
* filhos: `:is-empty="!itens.length"`.
|
|
19
|
+
*
|
|
20
|
+
* A lista precisa de nome: passe `ariaLabel` (ou `ariaLabelledby`, apontando
|
|
21
|
+
* para o título visível). Sem isso o leitor de tela anuncia "lista, 5 itens"
|
|
22
|
+
* sem dizer de quê.
|
|
23
|
+
*
|
|
24
|
+
* `ul` e `ol` saem sem marcador, margem e recuo, com `role="list"` (o Safari
|
|
25
|
+
* tira a semântica de lista de `list-style: none`).
|
|
26
|
+
* @property {string} as - Elemento: 'ul' (padrão) | 'ol'
|
|
27
|
+
* @property {string} gap - Espaço entre as linhas, na escala do DS ('none' cola)
|
|
28
|
+
* @property {string} ariaLabel - Nome acessível da lista
|
|
29
|
+
* @property {string} ariaLabelledby - Id do título visível que nomeia a lista
|
|
30
|
+
* @property {boolean} isEmpty - Sem itens: mostra o estado vazio no lugar das linhas
|
|
31
|
+
* @property {string} emptyTitle - Título do estado vazio (padrão: "Nenhum item encontrado")
|
|
32
|
+
* @property {string} emptyDescription - Texto de apoio do estado vazio
|
|
33
|
+
* @property {IconProp} emptyIcon - Ícone do estado vazio (objeto do Font Awesome)
|
|
34
|
+
* @property {string} emptySize - Tamanho do estado vazio: 'sm' (padrão, compacto) | 'md' | 'lg'
|
|
35
|
+
* @property {string} emptyActionLabel - Rótulo do botão do estado vazio (junto de onEmptyAction)
|
|
36
|
+
* @property {function} onEmptyAction - Callback do botão do estado vazio
|
|
37
|
+
* @property {any} empty - Slot `empty`: conteúdo próprio no lugar do EmptyState
|
|
38
|
+
* @property {string} className - Classes CSS adicionais
|
|
39
|
+
* @slot empty - Conteúdo do estado vazio (substitui o EmptyState padrão).
|
|
40
|
+
* @quandoUsar Qualquer lista de linhas clicáveis (`ListItem`) ou de itens simples que pode ficar sem resultado: documentos não lidos, notificações, resultados de busca. Resolve a semântica de lista e o "nada por aqui" num lugar só.
|
|
41
|
+
* @quandoNaoUsar Para dados tabulares comparados coluna a coluna, use `DataTable` (que já tem o próprio estado vazio). Para só empilhar blocos com espaçamento, sem semântica de lista, use `Stack`. Para um estado vazio que ocupa a tela inteira (sem lista), use `EmptyState` direto.
|
|
42
|
+
*/
|
|
43
|
+
/** Espaço entre as linhas, na escala oficial do DS. `none` cola as linhas. */
|
|
44
|
+
/** Elemento da lista: `ul` (padrão) ou `ol` quando a ordem importa. */
|
|
45
|
+
export interface ListProps {
|
|
46
|
+
/** Elemento da lista. @default 'ul' */
|
|
47
|
+
as?: ListTag;
|
|
48
|
+
/** Espaço entre as linhas, na escala oficial (`none` cola). @default 'quarck' */
|
|
49
|
+
gap?: ListGap;
|
|
50
|
+
/** Nome acessível da lista. */
|
|
51
|
+
ariaLabel?: string;
|
|
52
|
+
/** Id do título visível que nomeia a lista. */
|
|
53
|
+
ariaLabelledby?: string;
|
|
54
|
+
/** Sem itens: mostra o estado vazio no lugar das linhas. @default false */
|
|
55
|
+
isEmpty?: boolean;
|
|
56
|
+
/** Título do estado vazio. @default 'Nenhum item encontrado' */
|
|
57
|
+
emptyTitle?: string;
|
|
58
|
+
/** Texto de apoio do estado vazio. */
|
|
59
|
+
emptyDescription?: string;
|
|
60
|
+
/** Ícone do estado vazio: o objeto importado do Font Awesome. */
|
|
61
|
+
emptyIcon?: IconProp;
|
|
62
|
+
/** Tamanho do estado vazio. @default 'sm' */
|
|
63
|
+
emptySize?: "sm" | "md" | "lg";
|
|
64
|
+
/** Rótulo do botão do estado vazio (exibido junto de `onEmptyAction`). */
|
|
65
|
+
emptyActionLabel?: string;
|
|
66
|
+
/** Chamado no botão do estado vazio. */
|
|
67
|
+
onEmptyAction?: () => void;
|
|
68
|
+
/** Conteúdo próprio do estado vazio. No Vue, slot `empty`. */
|
|
69
|
+
empty?: any;
|
|
70
|
+
/** Classes CSS adicionais. */
|
|
71
|
+
className?: string;
|
|
72
|
+
/** ID HTML do elemento raiz. */
|
|
73
|
+
id?: string;
|
|
74
|
+
/** Atributos HTML repassados ao elemento raiz (style, data-*…). */
|
|
75
|
+
style?: any;
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
/** As linhas: `ListItem` (ou `li`). */
|
|
78
|
+
children?: any;
|
|
79
|
+
}
|
|
80
|
+
import type { IconProp } from "../Icon/Icon";
|
|
81
|
+
declare function List(props: ListProps): import("react/jsx-runtime").JSX.Element;
|
|
82
|
+
export default List;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import './List.css';
|
|
3
|
+
import EmptyState from "../EmptyState/EmptyState";
|
|
4
|
+
function List(props) {
|
|
5
|
+
function elementTag() {
|
|
6
|
+
return props.as || "ul";
|
|
7
|
+
}
|
|
8
|
+
function showEmpty() {
|
|
9
|
+
return !!props.isEmpty;
|
|
10
|
+
}
|
|
11
|
+
function showItems() {
|
|
12
|
+
return !props.isEmpty;
|
|
13
|
+
}
|
|
14
|
+
function classes() {
|
|
15
|
+
return [
|
|
16
|
+
"umds-list",
|
|
17
|
+
`umds-list--gap-${props.gap || "quarck"}`,
|
|
18
|
+
props.className,
|
|
19
|
+
]
|
|
20
|
+
.filter(Boolean)
|
|
21
|
+
.join(" ");
|
|
22
|
+
}
|
|
23
|
+
function emptyClasses() {
|
|
24
|
+
return ["umds-list umds-list--empty", props.className]
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.join(" ");
|
|
27
|
+
}
|
|
28
|
+
function emptyTitleText() {
|
|
29
|
+
return props.emptyTitle || "Nenhum item encontrado";
|
|
30
|
+
}
|
|
31
|
+
function emptyActionProps() {
|
|
32
|
+
if (!props.onEmptyAction)
|
|
33
|
+
return {};
|
|
34
|
+
return {
|
|
35
|
+
actionLabel: props.emptyActionLabel,
|
|
36
|
+
onAction: props.onEmptyAction,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function emptySizeValue() {
|
|
40
|
+
return props.emptySize || "sm";
|
|
41
|
+
}
|
|
42
|
+
function htmlAttrs() {
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const chave in props) {
|
|
45
|
+
if (chave.indexOf("data-") === 0 || chave === "style") {
|
|
46
|
+
out[chave] = props[chave];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
return (_jsxs(_Fragment, { children: [showEmpty() ? (_jsx("div", { role: "status", id: props.id, ...htmlAttrs(), className: emptyClasses(), children: _jsx(_Fragment, { children: props.empty || (_jsx(EmptyState, { icon: props.emptyIcon, title: emptyTitleText(), description: props.emptyDescription, size: emptySizeValue(), ...emptyActionProps() })) }) })) : null, showItems() && elementTag() === "ul" ? (_jsx("ul", { role: "list", id: props.id, "aria-label": props.ariaLabel, "aria-labelledby": props.ariaLabelledby, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, showItems() && elementTag() === "ol" ? (_jsx("ol", { role: "list", id: props.id, "aria-label": props.ariaLabel, "aria-labelledby": props.ariaLabelledby, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null] }));
|
|
52
|
+
}
|
|
53
|
+
export default List;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Elemento interativo (ou não) que ocupa a linha inteira. */
|
|
2
|
+
export type ListItemTag = "button" | "a" | "div";
|
|
3
|
+
/**
|
|
4
|
+
* ListItem — linha de lista inteira clicável, com conteúdo livre.
|
|
5
|
+
*
|
|
6
|
+
* Renderiza um `<li>` que contém UM elemento (`button`, `a` ou `div`) do tamanho
|
|
7
|
+
* da linha: o alvo de clique e de foco é a linha toda, não só o título. Por isso
|
|
8
|
+
* o ListItem vive dentro de um `List` (ou de um `ul`/`ol`, como `Stack as="ul"`).
|
|
9
|
+
*
|
|
10
|
+
* O conteúdo se encaixa por slots, todos opcionais: `start` (avatar, ícone,
|
|
11
|
+
* checkbox decorativo), `title`, `subtitle`, `meta` (data, contexto), `end`
|
|
12
|
+
* (badge, seta, valor) e o conteúdo padrão, que entra abaixo de `meta`. `title`,
|
|
13
|
+
* `subtitle` e `meta` também aceitam texto direto por prop.
|
|
14
|
+
*
|
|
15
|
+
* Elemento: sem `as`, vira `a` quando há `href` e `button` nos outros casos.
|
|
16
|
+
* `as="div"` é a linha que não navega nem age (só mostra), e vira acionável
|
|
17
|
+
* (role="button", Enter e Espaço) se receber `onClick`. Controles dentro de uma
|
|
18
|
+
* linha clicável (botão, checkbox) quebram o HTML: se a linha precisa deles,
|
|
19
|
+
* use `as="div"` sem `onClick` e ponha a ação num deles.
|
|
20
|
+
*
|
|
21
|
+
* `selected` marca o item atual (fundo azul-claro e `aria-current`). `disabled`
|
|
22
|
+
* tira a linha da ordem de tabulação e bloqueia o clique.
|
|
23
|
+
*
|
|
24
|
+
* Atributos HTML (`id`, `style`, `role`, `tabIndex`, `data-*`, `aria-*`) vão
|
|
25
|
+
* para o elemento interativo, que é quem recebe `aria-label` quando a linha não
|
|
26
|
+
* tem texto visível. `title` NÃO é o atributo HTML: é o título da linha.
|
|
27
|
+
* @property {string} as - Elemento da linha: 'button' | 'a' | 'div'. Padrão: 'a' com href, senão 'button'
|
|
28
|
+
* @property {string} href - Destino do link (vira as="a")
|
|
29
|
+
* @property {string} target - Destino do link: '_blank' ganha rel="noopener noreferrer"
|
|
30
|
+
* @property {string} rel - Relação do link (sobrescreve o padrão do target)
|
|
31
|
+
* @property {boolean} selected - Item atual: fundo de seleção e aria-current
|
|
32
|
+
* @property {boolean} disabled - Bloqueia clique e foco
|
|
33
|
+
* @property {any} title - Título da linha: texto, ou slot `title` (nó)
|
|
34
|
+
* @property {any} subtitle - Segunda linha: texto, ou slot `subtitle` (nó)
|
|
35
|
+
* @property {any} meta - Terceira linha, menor (data, contexto): texto, ou slot `meta` (nó)
|
|
36
|
+
* @property {any} start - Slot `start`: conteúdo antes do texto (avatar, ícone)
|
|
37
|
+
* @property {any} end - Slot `end`: conteúdo no fim da linha (badge, seta, valor)
|
|
38
|
+
* @property {function} onClick - Callback do clique (ou de Enter/Espaço no as="div")
|
|
39
|
+
* @property {string} className - Classes CSS adicionais, no elemento interativo
|
|
40
|
+
* @slot start - Conteúdo antes do texto.
|
|
41
|
+
* @slot title - Título (substitui a prop `title`).
|
|
42
|
+
* @slot subtitle - Segunda linha (substitui a prop `subtitle`).
|
|
43
|
+
* @slot meta - Terceira linha (substitui a prop `meta`).
|
|
44
|
+
* @slot end - Conteúdo no fim da linha.
|
|
45
|
+
* @quandoUsar Itens de uma lista em que a linha toda é a ação: documentos não lidos, notificações, resultados de busca, opções de menu de filtro, itens de navegação secundária. Hover, foco visível e seleção já vêm resolvidos.
|
|
46
|
+
* @quandoNaoUsar Para dados comparados coluna a coluna, use `DataTable`. Para um cartão com título, ações e elevação própria, use `Card`. Para um botão solto fora de lista, use `Button`. Para a navegação principal do produto, use `SidePanelItem` ou `AppNavItem`.
|
|
47
|
+
*/
|
|
48
|
+
/** Elemento interativo (ou não) que ocupa a linha inteira. */
|
|
49
|
+
export interface ListItemProps {
|
|
50
|
+
/** Elemento da linha. Sem `as`: `a` quando há `href`, senão `button`. */
|
|
51
|
+
as?: ListItemTag;
|
|
52
|
+
/** Destino do link (liga `as="a"`). */
|
|
53
|
+
href?: string;
|
|
54
|
+
/** Destino do link. `_blank` ganha `rel="noopener noreferrer"`. */
|
|
55
|
+
target?: string;
|
|
56
|
+
/** Relação do link. Sobrescreve o padrão do `target`. */
|
|
57
|
+
rel?: string;
|
|
58
|
+
/** Item atual: fundo de seleção e `aria-current`. @default false */
|
|
59
|
+
selected?: boolean;
|
|
60
|
+
/** Bloqueia clique e foco. @default false */
|
|
61
|
+
disabled?: boolean;
|
|
62
|
+
/** Título da linha. Texto, ou slot `title` para um nó. */
|
|
63
|
+
title?: any;
|
|
64
|
+
/** Segunda linha. Texto, ou slot `subtitle` para um nó. */
|
|
65
|
+
subtitle?: any;
|
|
66
|
+
/** Terceira linha, menor (data, contexto). Texto, ou slot `meta` para um nó. */
|
|
67
|
+
meta?: any;
|
|
68
|
+
/** Conteúdo antes do texto (avatar, ícone). No Vue, slot `start`. */
|
|
69
|
+
start?: any;
|
|
70
|
+
/** Conteúdo no fim da linha (badge, seta, valor). No Vue, slot `end`. */
|
|
71
|
+
end?: any;
|
|
72
|
+
/** Chamado no clique da linha (ou em Enter/Espaço no `as="div"`). */
|
|
73
|
+
onClick?: (event: any) => void;
|
|
74
|
+
/** Classes CSS adicionais, no elemento interativo. */
|
|
75
|
+
className?: string;
|
|
76
|
+
/** ID HTML do elemento interativo. */
|
|
77
|
+
id?: string;
|
|
78
|
+
/** Atributos HTML repassados ao elemento interativo (style, data-*, aria-*…). */
|
|
79
|
+
style?: any;
|
|
80
|
+
[key: string]: any;
|
|
81
|
+
/** Conteúdo livre, abaixo de `meta`. */
|
|
82
|
+
children?: any;
|
|
83
|
+
}
|
|
84
|
+
declare function ListItem(props: ListItemProps): import("react/jsx-runtime").JSX.Element;
|
|
85
|
+
export default ListItem;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import Text from "../Text/Text";
|
|
4
|
+
function ListItem(props) {
|
|
5
|
+
function elementTag() {
|
|
6
|
+
if (props.as)
|
|
7
|
+
return props.as;
|
|
8
|
+
return props.href ? "a" : "button";
|
|
9
|
+
}
|
|
10
|
+
function isInteractive() {
|
|
11
|
+
return elementTag() !== "div" || !!props.onClick;
|
|
12
|
+
}
|
|
13
|
+
function classes() {
|
|
14
|
+
return [
|
|
15
|
+
"umds-list-item",
|
|
16
|
+
isInteractive() ? "umds-list-item--interactive" : "",
|
|
17
|
+
props.selected ? "umds-list-item--selected" : "",
|
|
18
|
+
props.disabled ? "umds-list-item--disabled" : "",
|
|
19
|
+
props.className,
|
|
20
|
+
]
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(" ");
|
|
23
|
+
}
|
|
24
|
+
function ariaCurrent() {
|
|
25
|
+
return props.selected ? "true" : undefined;
|
|
26
|
+
}
|
|
27
|
+
function ariaDisabled() {
|
|
28
|
+
return props.disabled ? "true" : undefined;
|
|
29
|
+
}
|
|
30
|
+
function hrefValue() {
|
|
31
|
+
return props.disabled ? undefined : props.href;
|
|
32
|
+
}
|
|
33
|
+
function relValue() {
|
|
34
|
+
if (props.rel)
|
|
35
|
+
return props.rel;
|
|
36
|
+
return props.target === "_blank" ? "noopener noreferrer" : undefined;
|
|
37
|
+
}
|
|
38
|
+
function divRole() {
|
|
39
|
+
return props.onClick ? "button" : undefined;
|
|
40
|
+
}
|
|
41
|
+
function divTabIndex() {
|
|
42
|
+
if (!props.onClick)
|
|
43
|
+
return undefined;
|
|
44
|
+
return props.disabled ? -1 : 0;
|
|
45
|
+
}
|
|
46
|
+
function handleClick(event) {
|
|
47
|
+
if (props.disabled) {
|
|
48
|
+
if (event && event.preventDefault)
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (props.onClick)
|
|
53
|
+
props.onClick(event);
|
|
54
|
+
}
|
|
55
|
+
function handleKeyDown(event) {
|
|
56
|
+
if (!props.onClick || props.disabled || !event)
|
|
57
|
+
return;
|
|
58
|
+
// Só a própria linha aciona: Enter/Espaço dentro de um controle interno não.
|
|
59
|
+
if (event.target !== event.currentTarget)
|
|
60
|
+
return;
|
|
61
|
+
if (event.key !== "Enter" && event.key !== " ")
|
|
62
|
+
return;
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
props.onClick(event);
|
|
65
|
+
}
|
|
66
|
+
function htmlAttrs() {
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const chave in props) {
|
|
69
|
+
if (chave.indexOf("data-") === 0 ||
|
|
70
|
+
chave.indexOf("aria-") === 0 ||
|
|
71
|
+
chave === "style" ||
|
|
72
|
+
chave === "role" ||
|
|
73
|
+
chave === "tabIndex") {
|
|
74
|
+
out[chave] = props[chave];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
return (_jsxs("li", { className: "umds-list__item", children: [elementTag() === "button" ? (_jsxs("button", { type: "button", id: props.id, disabled: props.disabled, "aria-current": ariaCurrent(), onClick: (event) => handleClick(event), ...htmlAttrs(), className: classes(), children: [props.start ? (_jsx("span", { className: "umds-list-item__start", children: _jsx(_Fragment, { children: props.start }) })) : null, _jsxs("span", { className: "umds-list-item__body", children: [props.title ? (_jsx("span", { className: "umds-list-item__title", children: _jsx(Text, { variant: "body2", as: "span", weight: "semibold", color: "inherit", children: _jsx(_Fragment, { children: props.title }) }) })) : null, props.subtitle ? (_jsx("span", { className: "umds-list-item__subtitle", children: _jsx(Text, { variant: "body2", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.subtitle }) }) })) : null, props.meta ? (_jsx("span", { className: "umds-list-item__meta", children: _jsx(Text, { variant: "caption", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.meta }) }) })) : null, _jsx(_Fragment, { children: props.children })] }), props.end ? (_jsx("span", { className: "umds-list-item__end", children: _jsx(_Fragment, { children: props.end }) })) : null] })) : null, elementTag() === "a" ? (_jsxs("a", { id: props.id, href: hrefValue(), target: props.target, rel: relValue(), "aria-current": ariaCurrent(), "aria-disabled": ariaDisabled(), onClick: (event) => handleClick(event), ...htmlAttrs(), className: classes(), children: [props.start ? (_jsx("span", { className: "umds-list-item__start", children: _jsx(_Fragment, { children: props.start }) })) : null, _jsxs("span", { className: "umds-list-item__body", children: [props.title ? (_jsx("span", { className: "umds-list-item__title", children: _jsx(Text, { variant: "body2", as: "span", weight: "semibold", color: "inherit", children: _jsx(_Fragment, { children: props.title }) }) })) : null, props.subtitle ? (_jsx("span", { className: "umds-list-item__subtitle", children: _jsx(Text, { variant: "body2", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.subtitle }) }) })) : null, props.meta ? (_jsx("span", { className: "umds-list-item__meta", children: _jsx(Text, { variant: "caption", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.meta }) }) })) : null, _jsx(_Fragment, { children: props.children })] }), props.end ? (_jsx("span", { className: "umds-list-item__end", children: _jsx(_Fragment, { children: props.end }) })) : null] })) : null, elementTag() === "div" ? (_jsxs("div", { id: props.id, role: divRole(), tabIndex: divTabIndex(), "aria-current": ariaCurrent(), "aria-disabled": ariaDisabled(), onClick: (event) => handleClick(event), onKeyDown: (event) => handleKeyDown(event), ...htmlAttrs(), className: classes(), children: [props.start ? (_jsx("span", { className: "umds-list-item__start", children: _jsx(_Fragment, { children: props.start }) })) : null, _jsxs("span", { className: "umds-list-item__body", children: [props.title ? (_jsx("span", { className: "umds-list-item__title", children: _jsx(Text, { variant: "body2", as: "span", weight: "semibold", color: "inherit", children: _jsx(_Fragment, { children: props.title }) }) })) : null, props.subtitle ? (_jsx("span", { className: "umds-list-item__subtitle", children: _jsx(Text, { variant: "body2", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.subtitle }) }) })) : null, props.meta ? (_jsx("span", { className: "umds-list-item__meta", children: _jsx(Text, { variant: "caption", as: "span", color: "inherit", children: _jsx(_Fragment, { children: props.meta }) }) })) : null, _jsx(_Fragment, { children: props.children })] }), props.end ? (_jsx("span", { className: "umds-list-item__end", children: _jsx(_Fragment, { children: props.end }) })) : null] })) : null] }));
|
|
80
|
+
}
|
|
81
|
+
export default ListItem;
|
|
@@ -375,6 +375,86 @@
|
|
|
375
375
|
border-radius: 0;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
/* ── variant="primary": cabeçalho cheio na cor primária ──
|
|
379
|
+
Título, subtítulo e controles em branco (neutral-light-pure, o mesmo par que
|
|
380
|
+
o Button primary usa sobre primary-pure). */
|
|
381
|
+
.umds-modal--primary .umds-modal__header {
|
|
382
|
+
background-color: var(--umds-semantic-color-primary-pure);
|
|
383
|
+
border-bottom-color: var(--umds-semantic-color-primary-pure);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.umds-modal--primary .umds-modal__title,
|
|
387
|
+
.umds-modal--primary .umds-modal__subtitle {
|
|
388
|
+
color: var(--umds-semantic-color-neutral-light-pure);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.umds-modal--primary .umds-modal__ctrl {
|
|
392
|
+
color: var(--umds-semantic-color-neutral-light-pure);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.umds-modal--primary .umds-modal__ctrl:hover,
|
|
396
|
+
.umds-modal--primary .umds-modal__ctrl--ativo,
|
|
397
|
+
.umds-modal--primary .umds-modal__ctrl--close:hover {
|
|
398
|
+
background: var(--umds-semantic-color-primary-dark);
|
|
399
|
+
color: var(--umds-semantic-color-neutral-light-pure);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.umds-modal--primary .umds-modal__ctrl:focus-visible {
|
|
403
|
+
outline-color: var(--umds-semantic-color-neutral-light-pure);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.umds-modal--primary .umds-modal__ctrl-divider {
|
|
407
|
+
background: var(--umds-semantic-color-primary-medium);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* ── responsive: abaixo do breakpoint vira painel que sobe pela borda de baixo ──
|
|
411
|
+
Mesma anatomia do BottomSheet (largura total, cantos de cima arredondados,
|
|
412
|
+
alça, entrada por baixo). Quem decide o breakpoint é o componente (media
|
|
413
|
+
query em JS, para a prop `responsiveBreakpoint` valer). */
|
|
414
|
+
.umds-modal-root--sheet {
|
|
415
|
+
align-items: flex-end;
|
|
416
|
+
padding: 0;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.umds-modal.umds-modal--sheet {
|
|
420
|
+
width: 100%;
|
|
421
|
+
max-width: none;
|
|
422
|
+
max-height: 90vh;
|
|
423
|
+
border-bottom-left-radius: 0;
|
|
424
|
+
border-bottom-right-radius: 0;
|
|
425
|
+
animation: umds-modal-sheet-in var(--umds-semantic-motion-duration-base)
|
|
426
|
+
var(--umds-semantic-motion-easing-standard);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
@keyframes umds-modal-sheet-in {
|
|
430
|
+
from {
|
|
431
|
+
transform: translateY(100%);
|
|
432
|
+
}
|
|
433
|
+
to {
|
|
434
|
+
transform: translateY(0);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.umds-modal__grabber {
|
|
439
|
+
display: flex;
|
|
440
|
+
align-items: center;
|
|
441
|
+
justify-content: center;
|
|
442
|
+
padding: var(--umds-primitive-spacing-nano) 0 0;
|
|
443
|
+
flex-shrink: 0;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.umds-modal--primary .umds-modal__grabber {
|
|
447
|
+
background-color: var(--umds-semantic-color-primary-pure);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.umds-modal__grabber-bar {
|
|
451
|
+
display: block;
|
|
452
|
+
width: var(--umds-primitive-spacing-sm); /* 40px */
|
|
453
|
+
height: var(--umds-primitive-spacing-quarck); /* 4px */
|
|
454
|
+
border-radius: var(--umds-primitive-border-radius-pill);
|
|
455
|
+
background-color: var(--umds-semantic-color-neutral-light-down);
|
|
456
|
+
}
|
|
457
|
+
|
|
378
458
|
/* ── Alto contraste ──
|
|
379
459
|
No 1doc-high-contrast o painel e a página são pretos e a sombra (preta)
|
|
380
460
|
não aparece: sem traço, o modal não tem borda visível. O traço é um
|
|
@@ -27,9 +27,30 @@ export interface ModalProps {
|
|
|
27
27
|
* - "positive": sucesso (verde, ícone circle-check).
|
|
28
28
|
* - "negative": erro/falha (vermelho, ícone circle-exclamation).
|
|
29
29
|
* - "info": atenção (laranja, ícone triangle-exclamation).
|
|
30
|
+
* - "primary": modal base com o cabeçalho cheio na cor primária (título e
|
|
31
|
+
* controles em branco). Não é diálogo de feedback: mantém as três faixas.
|
|
30
32
|
* @default 'default'
|
|
31
33
|
*/
|
|
32
|
-
variant?: "default" | "positive" | "negative" | "info";
|
|
34
|
+
variant?: "default" | "positive" | "negative" | "info" | "primary";
|
|
35
|
+
/**
|
|
36
|
+
* Largura do modal, qualquer valor CSS (`"600px"`, `"60vw"`). Sem
|
|
37
|
+
* `maxWidth`, o teto passa a ser a própria tela (o 498px do `md` não
|
|
38
|
+
* segura mais). Vence o `size`. Com `windowControls`, vale só no modo
|
|
39
|
+
* normal: expandido e tela cheia mandam no tamanho.
|
|
40
|
+
*/
|
|
41
|
+
width?: string;
|
|
42
|
+
/** Largura máxima, qualquer valor CSS. Vence o teto do `size`. */
|
|
43
|
+
maxWidth?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Abaixo do breakpoint (`responsiveBreakpoint`), o modal vira um painel que
|
|
46
|
+
* sobe pela borda de baixo, como o `BottomSheet`: largura total, cantos de
|
|
47
|
+
* cima arredondados, alça no topo. Acima dele, continua centralizado. É
|
|
48
|
+
* o mesmo componente reorganizado, então título, corpo e rodapé não mudam.
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
responsive?: boolean;
|
|
52
|
+
/** Largura da tela, em px, abaixo da qual o `responsive` vira painel. Lida na montagem. @default 640 */
|
|
53
|
+
responsiveBreakpoint?: number;
|
|
33
54
|
/**
|
|
34
55
|
* Título em destaque. Com título, o diálogo é nomeado por ele
|
|
35
56
|
* (`aria-labelledby`) e `ariaLabel` é ignorado.
|
|
@@ -79,12 +100,18 @@ export interface ModalProps {
|
|
|
79
100
|
/** Se verdadeiro, renderiza o modal inline (sem fixed/overlay), útil para documentação */
|
|
80
101
|
inline?: boolean;
|
|
81
102
|
/**
|
|
82
|
-
* Controles de janela no cabeçalho
|
|
83
|
-
*
|
|
84
|
-
*
|
|
103
|
+
* Controles de janela no cabeçalho, antes do ×. Duas formas:
|
|
104
|
+
* - `true`: o conjunto inteiro (restaurar, expandir, tela cheia e minimizar).
|
|
105
|
+
* O modal passa a mudar de tamanho sozinho (normal 780px, expandido, tela
|
|
106
|
+
* cheia).
|
|
107
|
+
* - uma lista com os que quiser, na ordem fixa do cabeçalho:
|
|
108
|
+
* `["expand", "fullscreen"]`, `["fullscreen"]`... Os nomes são `normal`,
|
|
109
|
+
* `expand`, `fullscreen` e `minimize`. Sem `normal` na lista, clicar de
|
|
110
|
+
* novo no modo ativo volta ao normal, e o modo normal usa o tamanho do
|
|
111
|
+
* próprio modal (`size`, `width`), não os 780px do conjunto inteiro.
|
|
85
112
|
*/
|
|
86
|
-
windowControls?: boolean
|
|
87
|
-
/** Acionado no botão minimizar. Só existe
|
|
113
|
+
windowControls?: boolean | Array<"normal" | "expand" | "fullscreen" | "minimize">;
|
|
114
|
+
/** Acionado no botão minimizar. Só existe quando `minimize` está entre os controles. */
|
|
88
115
|
onMinimize?: (event?: any) => void;
|
|
89
116
|
/**
|
|
90
117
|
* Região esquerda do rodapé — conteúdo de apoio que não é botão: a caixa
|