@1doc/1ds-react 2.14.0 → 2.15.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 +51 -67
- package/dist/components/AILabel/AILabel.css +1 -1
- package/dist/components/Alert/Alert.css +1 -1
- package/dist/components/AppShell/AppShell.css +4 -0
- package/dist/components/AttachmentCard/AttachmentCard.css +2 -2
- package/dist/components/Avatar/Avatar.d.ts +8 -3
- package/dist/components/Avatar/Avatar.js +28 -4
- package/dist/components/BottomNavigation/BottomNavigation.css +2 -2
- package/dist/components/BottomSheet/BottomSheet.css +2 -2
- package/dist/components/Box/Box.css +3 -3
- package/dist/components/Card/Card.css +5 -5
- package/dist/components/Chart/Chart.css +1 -1
- package/dist/components/Coachmark/Coachmark.css +1 -1
- package/dist/components/Combobox/Combobox.css +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.css +1 -1
- package/dist/components/DatePicker/DatePicker.css +1 -1
- package/dist/components/Drawer/Drawer.css +2 -2
- package/dist/components/Dropdown/Dropdown.css +1 -1
- package/dist/components/Dropdown/Dropdown.d.ts +8 -0
- package/dist/components/Dropdown/Dropdown.js +2 -0
- package/dist/components/EmptyState/EmptyState.css +12 -0
- package/dist/components/EmptyState/EmptyState.d.ts +3 -0
- package/dist/components/EmptyState/EmptyState.js +1 -0
- package/dist/components/Kanban/Kanban.css +2 -2
- package/dist/components/Kanban/KanbanCard.css +2 -2
- package/dist/components/List/List.css +37 -1
- package/dist/components/List/List.d.ts +3 -0
- package/dist/components/List/List.js +6 -2
- package/dist/components/List/ListItem.d.ts +9 -0
- package/dist/components/List/ListItem.js +5 -1
- package/dist/components/Modal/Modal.css +3 -4
- package/dist/components/MultiSelect/MultiSelect.css +1 -1
- package/dist/components/OrgChart/OrgChart.css +2 -2
- package/dist/components/PhoneInput/PhoneInput.css +2 -2
- package/dist/components/Popover/Popover.css +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.css +1 -1
- package/dist/components/Select/Select.css +1 -1
- package/dist/components/StatCard/StatCard.css +42 -3
- package/dist/components/Switch/Switch.css +2 -2
- package/dist/components/Text/Text.d.ts +6 -0
- package/dist/components/TimePicker/TimePicker.css +1 -1
- package/dist/components/Toast/Toast.css +2 -2
- package/dist/components/Tooltip/Tooltip.css +20 -3
- package/dist/teste/PedidosMatheus2.test.d.ts +1 -0
- package/dist/teste/PedidosMatheus2.test.js +82 -0
- package/dist/teste/SegmentedControlSuperficie.test.js +1 -1
- package/package.json +3 -3
- package/src/teste/PedidosMatheus2.test.tsx +102 -0
- package/src/teste/SegmentedControlSuperficie.test.tsx +1 -1
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
align-items: flex-start;
|
|
12
12
|
gap: var(--umds-primitive-spacing-mini);
|
|
13
13
|
padding: var(--umds-primitive-spacing-xxxs);
|
|
14
|
-
|
|
14
|
+
/* Mesma borda e superfície do Card: lado a lado, os cartões têm o mesmo
|
|
15
|
+
contorno (#EBEBEB no claro), e no escuro o fundo é o elevado. */
|
|
16
|
+
border: 1px solid var(--umds-semantic-color-neutral-light-medium);
|
|
15
17
|
border-radius: var(--umds-primitive-border-radius-sm);
|
|
16
|
-
background-color: var(--umds-semantic-color-background-
|
|
18
|
+
background-color: var(--umds-semantic-color-background-elevated);
|
|
17
19
|
color: var(--umds-semantic-color-neutral-dark-pure);
|
|
18
20
|
font-family: var(--umds-semantic-font-family-base);
|
|
19
21
|
text-align: left;
|
|
@@ -38,7 +40,7 @@
|
|
|
38
40
|
|
|
39
41
|
.umds-stat-card--acionavel:hover {
|
|
40
42
|
border-color: var(--umds-semantic-color-primary-pure);
|
|
41
|
-
box-shadow: var(--umds-semantic-shadow-sm);
|
|
43
|
+
box-shadow: var(--umds-semantic-shadow-bottom-sm);
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
/* Foco canônico de não-campo. */
|
|
@@ -353,3 +355,40 @@
|
|
|
353
355
|
display: inline-flex;
|
|
354
356
|
align-items: center;
|
|
355
357
|
}
|
|
358
|
+
|
|
359
|
+
/* ── Segunda medida em largura pequena (container query) ──
|
|
360
|
+
Num cartão estreito (cabeçalho mobile, ~115px) as duas medidas lado a lado
|
|
361
|
+
se sobrepunham. O cartão com segunda medida vira container de largura e,
|
|
362
|
+
abaixo de 240px, a segunda medida desce para a linha de baixo, separada por
|
|
363
|
+
um filete em cima em vez do da esquerda.
|
|
364
|
+
`width: 100%`: um container de inline-size não mede o conteúdo, então num
|
|
365
|
+
pai flex com tamanho pelo conteúdo ele encolheria até sumir. Com 100%, numa
|
|
366
|
+
linha flex os cartões dividem o espaço; em grade e em bloco nada muda. */
|
|
367
|
+
.umds-stat-card--com-secundaria {
|
|
368
|
+
container-type: inline-size;
|
|
369
|
+
width: 100%;
|
|
370
|
+
flex-wrap: wrap;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/* 240px: duas medidas de 24px com o filete e o respiro não cabem abaixo disso.
|
|
374
|
+
Container query não aceita var(), por isso o literal. */
|
|
375
|
+
@container (max-width: 240px) {
|
|
376
|
+
.umds-stat-card:not(.umds-stat-card--centro) .umds-stat-card__secundaria {
|
|
377
|
+
flex-basis: 100%;
|
|
378
|
+
margin-left: 0;
|
|
379
|
+
padding-left: 0;
|
|
380
|
+
padding-top: var(--umds-primitive-spacing-nano);
|
|
381
|
+
border-left: none;
|
|
382
|
+
border-top: var(--umds-primitive-border-width-hairline) solid var(--umds-semantic-color-neutral-light-medium);
|
|
383
|
+
align-items: flex-start;
|
|
384
|
+
text-align: left;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__secundaria,
|
|
388
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__secundaria:has(.umds-stat-card__rotulo-secundario) {
|
|
389
|
+
grid-column: 1 / -1;
|
|
390
|
+
grid-row: auto;
|
|
391
|
+
display: flex;
|
|
392
|
+
margin-left: 0;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
.umds-switch__thumb {
|
|
52
52
|
background-color: var(--umds-semantic-color-neutral-light-pure);
|
|
53
53
|
border-radius: var(--umds-primitive-border-radius-circular);
|
|
54
|
-
box-shadow: var(--umds-semantic-shadow-sm); /* era 0 1px 2px 0.1, 0 1px 1px 0.06 — mapeado para shadow-sm 14/07 (sombra do thumb fica mais sutil) */
|
|
54
|
+
box-shadow: var(--umds-semantic-shadow-bottom-sm); /* era 0 1px 2px 0.1, 0 1px 1px 0.06 — mapeado para shadow-sm 14/07 (sombra do thumb fica mais sutil) */
|
|
55
55
|
display: flex;
|
|
56
56
|
align-items: center;
|
|
57
57
|
justify-content: center;
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
background-color: var(--umds-semantic-color-neutral-light-pure);
|
|
145
145
|
padding: var(--umds-primitive-spacing-xxxs);
|
|
146
146
|
border-radius: var(--umds-primitive-border-radius-sm);
|
|
147
|
-
box-shadow: var(--umds-semantic-shadow-sm); /* era 0 4px 8px 0.06 — mapeado para shadow-sm 14/07 (card de fundo sutil) */
|
|
147
|
+
box-shadow: var(--umds-semantic-shadow-bottom-sm); /* era 0 4px 8px 0.06 — mapeado para shadow-sm 14/07 (card de fundo sutil) */
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
.umds-switch-text {
|
|
@@ -62,6 +62,12 @@ export interface TextProps {
|
|
|
62
62
|
/**
|
|
63
63
|
* Cor do texto usando tokens semânticos.
|
|
64
64
|
*
|
|
65
|
+
* SEM `color`, o texto HERDA a cor do pai (é o que deixa um Text dentro de um
|
|
66
|
+
* botão, alerta ou cartão colorido acompanhar a cor dele). Dentro do
|
|
67
|
+
* `AppShell` o pai já tem a cor de texto do tema. Fora dele, num título solto
|
|
68
|
+
* na página, passe `color="primary"` (`neutral-dark-pure`, o texto principal,
|
|
69
|
+
* não o azul) para o tema escuro funcionar.
|
|
70
|
+
*
|
|
65
71
|
* `disabled` (`neutral-dark-up`, #A3A3A3, 2,5:1 sobre branco) é SÓ para
|
|
66
72
|
* texto de controle desabilitado (rótulo, valor ou ajuda de um campo ou
|
|
67
73
|
* botão inativo), que o WCAG 1.4.3 isenta de contraste. Em qualquer outro
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
background: var(--umds-semantic-color-background-elevated); /* superfície elevada: igual ao white no light; mais clara no dark (decisão 25/07) */
|
|
124
124
|
border: 1px solid var(--umds-semantic-color-neutral-light-medium); /* #EBEBEB */
|
|
125
125
|
border-radius: var(--umds-primitive-border-radius-sm); /* 8px — protótipo --radius-lg 12px, aproximado para sm (coerente com input e dígitos) */
|
|
126
|
-
box-shadow: var(--umds-semantic-shadow-md);
|
|
126
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md);
|
|
127
127
|
padding: var(--umds-primitive-spacing-xxxs); /* 16px — protótipo --space-4 */
|
|
128
128
|
box-sizing: border-box;
|
|
129
129
|
animation: umds-timepicker-in var(--umds-semantic-motion-duration-fast) var(--umds-semantic-motion-easing-standard) both;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Variantes semânticas (prop `variant`): positive, negative, info, neutral
|
|
5
5
|
(warning do protótipo mesclado no info — ambos laranja feedback-info).
|
|
6
6
|
Tokens do protótipo mapeados para os tokens 1DS.
|
|
7
|
-
Snap 16/07 (decisões novas): sombra → --umds-semantic-shadow-md (token novo,
|
|
7
|
+
Snap 16/07 (decisões novas): sombra → --umds-semantic-shadow-bottom-md (token novo,
|
|
8
8
|
valor idêntico ao literal do protótipo); radius 12px → md 16px (overlay
|
|
9
9
|
flutuante → md, como Dropdown/Modal); radius 6px → sm 8px; font-size
|
|
10
10
|
11px → xxxs 12px; spacing 12px → xxxs 16px (mesmas decisões do Alert —
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
padding: var(--umds-primitive-spacing-xxxs, 16px); /* era 12px 16px (protótipo --space-3/--space-4) — snap 16/07 */
|
|
25
25
|
border-radius: var(--umds-primitive-border-radius-sm); /* 8px universal (rodada ago/2026) — a exceção "overlay flutuante → md" caiu */
|
|
26
26
|
border: 1px solid transparent;
|
|
27
|
-
box-shadow: var(--umds-semantic-shadow-md); /* protótipo --shadow-md — token novo com valor idêntico */
|
|
27
|
+
box-shadow: var(--umds-semantic-shadow-bottom-md); /* protótipo --shadow-md — token novo com valor idêntico */
|
|
28
28
|
font-family: var(--umds-semantic-font-family-base);
|
|
29
29
|
box-sizing: border-box;
|
|
30
30
|
/* O Portal usa display: contents e não posiciona nada — o próprio toast
|
|
@@ -47,9 +47,12 @@
|
|
|
47
47
|
flex-direction: column;
|
|
48
48
|
position: relative;
|
|
49
49
|
padding: var(--umds-primitive-spacing-mini); /* protótipo --space-3: sem equivalente 1DS exato */
|
|
50
|
-
|
|
50
|
+
/* Superfície elevada, como o Card: igual ao branco nos temas claros e no
|
|
51
|
+
alto contraste; nos escuros é mais clara que a página (o neutral-light-pure
|
|
52
|
+
de antes era quase da cor do fundo, e o balão sumia). */
|
|
53
|
+
background-color: var(--umds-semantic-color-background-elevated);
|
|
51
54
|
border-radius: var(--umds-primitive-border-radius-sm); /* 8px */
|
|
52
|
-
box-shadow: var(--umds-
|
|
55
|
+
box-shadow: var(--umds-semantic-shadow-bottom-lg);
|
|
53
56
|
font-family: var(--umds-semantic-font-family-base);
|
|
54
57
|
font-size: var(--umds-primitive-font-size-xxxs); /* 12px */
|
|
55
58
|
line-height: 1.25;
|
|
@@ -93,7 +96,7 @@
|
|
|
93
96
|
position: absolute;
|
|
94
97
|
width: 8px;
|
|
95
98
|
height: 8px;
|
|
96
|
-
background-color: var(--umds-semantic-color-
|
|
99
|
+
background-color: var(--umds-semantic-color-background-elevated);
|
|
97
100
|
transform: rotate(45deg);
|
|
98
101
|
}
|
|
99
102
|
|
|
@@ -181,6 +184,20 @@
|
|
|
181
184
|
border-color: var(--umds-semantic-color-background-dark);
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
/* ── Temas escuros (1doc-dark e os *-dark da paleta) ──
|
|
188
|
+
A sombra preta não aparece sobre fundo escuro: o balão ganha o traço do Card
|
|
189
|
+
(neutral-light-medium), por dentro para não mudar o tamanho. A seta troca o
|
|
190
|
+
traço das duas faces expostas pelo mesmo tom e continua o contorno. O
|
|
191
|
+
variant="dark" (balão claro invertido) não precisa: ele contrasta sozinho. */
|
|
192
|
+
[data-theme$="-dark"] .umds-tooltip__bubble:not(.umds-tooltip__bubble--dark) {
|
|
193
|
+
outline: var(--umds-primitive-border-width-hairline) solid var(--umds-semantic-color-neutral-light-medium);
|
|
194
|
+
outline-offset: calc(-1 * var(--umds-primitive-border-width-hairline));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
[data-theme$="-dark"] .umds-tooltip__bubble:not(.umds-tooltip__bubble--dark) .umds-tooltip__arrow {
|
|
198
|
+
border-color: var(--umds-semantic-color-neutral-light-medium);
|
|
199
|
+
}
|
|
200
|
+
|
|
184
201
|
/* ── Alto contraste ──
|
|
185
202
|
O balão usa neutral-light-pure, que neste tema é preto como a página, e a
|
|
186
203
|
sombra não aparece: sem traço o balão some. Outline para dentro (não
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import Avatar from "../components/Avatar/Avatar";
|
|
5
|
+
import Dropdown from "../components/Dropdown/Dropdown";
|
|
6
|
+
import EmptyState from "../components/EmptyState/EmptyState";
|
|
7
|
+
import List from "../components/List/List";
|
|
8
|
+
import ListItem from "../components/List/ListItem";
|
|
9
|
+
import { lerArquivo } from "./lerArquivo";
|
|
10
|
+
describe("Avatar · fallback e name", () => {
|
|
11
|
+
it("a foto que falha volta para as iniciais do name", () => {
|
|
12
|
+
const onError = vi.fn();
|
|
13
|
+
const { container } = render(_jsx(Avatar, { src: "/quebrada.png", name: "Cris Lima", onError: onError }));
|
|
14
|
+
fireEvent.error(container.querySelector("img"));
|
|
15
|
+
expect(container.querySelector("img")).toBeNull();
|
|
16
|
+
expect(container.textContent).toBe("CL");
|
|
17
|
+
expect(container.firstElementChild).toHaveClass("umds-avatar--letter");
|
|
18
|
+
expect(onError).toHaveBeenCalledTimes(1);
|
|
19
|
+
});
|
|
20
|
+
it("sem name, a falha mostra o children", () => {
|
|
21
|
+
const { container } = render(_jsx(Avatar, { src: "/quebrada.png", children: "ML" }));
|
|
22
|
+
fireEvent.error(container.querySelector("img"));
|
|
23
|
+
expect(container.textContent).toBe("ML");
|
|
24
|
+
});
|
|
25
|
+
it("um src novo tenta a foto de novo", () => {
|
|
26
|
+
const { container, rerender } = render(_jsx(Avatar, { src: "/quebrada.png", name: "Cris Lima" }));
|
|
27
|
+
fireEvent.error(container.querySelector("img"));
|
|
28
|
+
rerender(_jsx(Avatar, { src: "/boa.png", name: "Cris Lima" }));
|
|
29
|
+
expect(container.querySelector("img")).toHaveAttribute("src", "/boa.png");
|
|
30
|
+
});
|
|
31
|
+
it("name gera as iniciais (primeiro e último nome) e o nome acessível", () => {
|
|
32
|
+
const { container } = render(_jsx(Avatar, { name: "Matheus de Souza" }));
|
|
33
|
+
expect(container.textContent).toBe("MS");
|
|
34
|
+
expect(container.firstElementChild).toHaveAttribute("aria-label", "Matheus de Souza");
|
|
35
|
+
expect(container.firstElementChild).toHaveAttribute("role", "img");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe("Dropdown · onSelect no item", () => {
|
|
39
|
+
it("chama a ação do item com os campos próprios, e depois o onSelect do Dropdown", async () => {
|
|
40
|
+
const ordem = [];
|
|
41
|
+
const doItem = vi.fn((item) => ordem.push("item:" + item.command));
|
|
42
|
+
const doMenu = vi.fn(() => ordem.push("menu"));
|
|
43
|
+
render(_jsx(Dropdown, { ariaLabel: "A\u00E7\u00F5es", onSelect: doMenu, items: [{ key: "a", label: "Assinar", command: "assinar", onSelect: doItem }], children: _jsx("button", { type: "button", children: "Abrir" }) }));
|
|
44
|
+
fireEvent.click(screen.getByRole("button", { name: "Abrir" }));
|
|
45
|
+
fireEvent.click(await screen.findByRole("menuitem", { name: "Assinar" }));
|
|
46
|
+
expect(ordem).toEqual(["item:assinar", "menu"]);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("ListItem · variant e li", () => {
|
|
50
|
+
it("variant primary marca a classe sem aria-current", () => {
|
|
51
|
+
render(_jsx("ul", { children: _jsx(ListItem, { variant: "primary", href: "#c", title: "Circular" }) }));
|
|
52
|
+
const link = screen.getByRole("link", { name: "Circular" });
|
|
53
|
+
expect(link).toHaveClass("umds-list-item--primary");
|
|
54
|
+
expect(link).not.toHaveAttribute("aria-current");
|
|
55
|
+
});
|
|
56
|
+
it("liClassName e liStyle vão para o li", () => {
|
|
57
|
+
const { container } = render(_jsx("ul", { children: _jsx(ListItem, { title: "Memorando", liClassName: "entra", liStyle: { "--ordem": 2 }, onClick: () => { } }) }));
|
|
58
|
+
const li = container.querySelector("li");
|
|
59
|
+
expect(li).toHaveClass("umds-list__item");
|
|
60
|
+
expect(li).toHaveClass("entra");
|
|
61
|
+
expect(li.style.getPropertyValue("--ordem")).toBe("2");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe("EmptyState · fill e List · emptyFill", () => {
|
|
65
|
+
it("fill escreve a classe; List repassa emptyFill", () => {
|
|
66
|
+
const { container } = render(_jsxs(_Fragment, { children: [_jsx(EmptyState, { title: "Vazio", fill: true }), _jsx(List, { ariaLabel: "Docs", isEmpty: true, emptyFill: true })] }));
|
|
67
|
+
expect(container.querySelector(".umds-empty-state--fill")).not.toBeNull();
|
|
68
|
+
expect(container.querySelector(".umds-list--empty-fill .umds-empty-state--fill")).not.toBeNull();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("AppShell e StatCard · CSS", () => {
|
|
72
|
+
it("o AppShell dá a cor de texto do tema a quem herda", async () => {
|
|
73
|
+
const css = (await lerArquivo("../core/src/components/AppShell/AppShell.css")).replace(/\r\n/g, "\n");
|
|
74
|
+
const bloco = css.slice(css.indexOf(".umds-app-shell {"), css.indexOf("}", css.indexOf(".umds-app-shell {")));
|
|
75
|
+
expect(bloco).toContain("color: var(--umds-semantic-color-neutral-dark-pure)");
|
|
76
|
+
});
|
|
77
|
+
it("a StatCard com segunda medida empilha em largura pequena", async () => {
|
|
78
|
+
const css = (await lerArquivo("../core/src/components/StatCard/StatCard.css")).replace(/\r\n/g, "\n");
|
|
79
|
+
expect(css).toContain("container-type: inline-size");
|
|
80
|
+
expect(css).toMatch(/@container \(max-width: 240px\)/);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -27,7 +27,7 @@ describe("SegmentedControl · variant surface", () => {
|
|
|
27
27
|
const escolhido = bloco(t, ".umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item,\n.umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item:hover");
|
|
28
28
|
expect(escolhido).toMatch(/background-color:\s*var\(--umds-semantic-color-background-white\)/);
|
|
29
29
|
expect(escolhido).toMatch(/font-weight:\s*var\(--umds-primitive-font-weight-bold\)/);
|
|
30
|
-
expect(escolhido).toMatch(/box-shadow:\s*var\(--umds-semantic-shadow-md\)/);
|
|
30
|
+
expect(escolhido).toMatch(/box-shadow:\s*var\(--umds-semantic-shadow-bottom-md\)/);
|
|
31
31
|
expect(bloco(t, ".umds-segmented--surface .umds-segmented__track")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
32
32
|
expect(t).toMatch(/\.umds-segmented__input:checked \+ \.umds-segmented__item,\n\.umds-segmented__input:checked \+ \.umds-segmented__item:hover \{\n\s*background-color:\s*var\(--umds-semantic-color-primary-pure\)/);
|
|
33
33
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1doc/1ds-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"react-dom": "^18.0.0",
|
|
46
46
|
"typescript": "^5.0.0",
|
|
47
47
|
"vitest": "^3.2.7",
|
|
48
|
-
"@1doc/1ds-core": "2.
|
|
49
|
-
"@1doc/1ds-tokens": "0.
|
|
48
|
+
"@1doc/1ds-core": "2.15.0",
|
|
49
|
+
"@1doc/1ds-tokens": "0.8.0"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import Avatar from "../components/Avatar/Avatar";
|
|
4
|
+
import Dropdown from "../components/Dropdown/Dropdown";
|
|
5
|
+
import EmptyState from "../components/EmptyState/EmptyState";
|
|
6
|
+
import List from "../components/List/List";
|
|
7
|
+
import ListItem from "../components/List/ListItem";
|
|
8
|
+
import { lerArquivo } from "./lerArquivo";
|
|
9
|
+
|
|
10
|
+
describe("Avatar · fallback e name", () => {
|
|
11
|
+
it("a foto que falha volta para as iniciais do name", () => {
|
|
12
|
+
const onError = vi.fn();
|
|
13
|
+
const { container } = render(<Avatar src="/quebrada.png" name="Cris Lima" onError={onError} />);
|
|
14
|
+
fireEvent.error(container.querySelector("img")!);
|
|
15
|
+
expect(container.querySelector("img")).toBeNull();
|
|
16
|
+
expect(container.textContent).toBe("CL");
|
|
17
|
+
expect(container.firstElementChild).toHaveClass("umds-avatar--letter");
|
|
18
|
+
expect(onError).toHaveBeenCalledTimes(1);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("sem name, a falha mostra o children", () => {
|
|
22
|
+
const { container } = render(<Avatar src="/quebrada.png">ML</Avatar>);
|
|
23
|
+
fireEvent.error(container.querySelector("img")!);
|
|
24
|
+
expect(container.textContent).toBe("ML");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("um src novo tenta a foto de novo", () => {
|
|
28
|
+
const { container, rerender } = render(<Avatar src="/quebrada.png" name="Cris Lima" />);
|
|
29
|
+
fireEvent.error(container.querySelector("img")!);
|
|
30
|
+
rerender(<Avatar src="/boa.png" name="Cris Lima" />);
|
|
31
|
+
expect(container.querySelector("img")).toHaveAttribute("src", "/boa.png");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("name gera as iniciais (primeiro e último nome) e o nome acessível", () => {
|
|
35
|
+
const { container } = render(<Avatar name="Matheus de Souza" />);
|
|
36
|
+
expect(container.textContent).toBe("MS");
|
|
37
|
+
expect(container.firstElementChild).toHaveAttribute("aria-label", "Matheus de Souza");
|
|
38
|
+
expect(container.firstElementChild).toHaveAttribute("role", "img");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("Dropdown · onSelect no item", () => {
|
|
43
|
+
it("chama a ação do item com os campos próprios, e depois o onSelect do Dropdown", async () => {
|
|
44
|
+
const ordem: string[] = [];
|
|
45
|
+
const doItem = vi.fn((item) => ordem.push("item:" + item.command));
|
|
46
|
+
const doMenu = vi.fn(() => ordem.push("menu"));
|
|
47
|
+
render(
|
|
48
|
+
<Dropdown ariaLabel="Ações" onSelect={doMenu} items={[{ key: "a", label: "Assinar", command: "assinar", onSelect: doItem }]}>
|
|
49
|
+
<button type="button">Abrir</button>
|
|
50
|
+
</Dropdown>,
|
|
51
|
+
);
|
|
52
|
+
fireEvent.click(screen.getByRole("button", { name: "Abrir" }));
|
|
53
|
+
fireEvent.click(await screen.findByRole("menuitem", { name: "Assinar" }));
|
|
54
|
+
expect(ordem).toEqual(["item:assinar", "menu"]);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("ListItem · variant e li", () => {
|
|
59
|
+
it("variant primary marca a classe sem aria-current", () => {
|
|
60
|
+
render(<ul><ListItem variant="primary" href="#c" title="Circular" /></ul>);
|
|
61
|
+
const link = screen.getByRole("link", { name: "Circular" });
|
|
62
|
+
expect(link).toHaveClass("umds-list-item--primary");
|
|
63
|
+
expect(link).not.toHaveAttribute("aria-current");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("liClassName e liStyle vão para o li", () => {
|
|
67
|
+
const { container } = render(
|
|
68
|
+
<ul><ListItem title="Memorando" liClassName="entra" liStyle={{ "--ordem": 2 } as any} onClick={() => {}} /></ul>,
|
|
69
|
+
);
|
|
70
|
+
const li = container.querySelector("li")!;
|
|
71
|
+
expect(li).toHaveClass("umds-list__item");
|
|
72
|
+
expect(li).toHaveClass("entra");
|
|
73
|
+
expect(li.style.getPropertyValue("--ordem")).toBe("2");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("EmptyState · fill e List · emptyFill", () => {
|
|
78
|
+
it("fill escreve a classe; List repassa emptyFill", () => {
|
|
79
|
+
const { container } = render(
|
|
80
|
+
<>
|
|
81
|
+
<EmptyState title="Vazio" fill />
|
|
82
|
+
<List ariaLabel="Docs" isEmpty emptyFill />
|
|
83
|
+
</>,
|
|
84
|
+
);
|
|
85
|
+
expect(container.querySelector(".umds-empty-state--fill")).not.toBeNull();
|
|
86
|
+
expect(container.querySelector(".umds-list--empty-fill .umds-empty-state--fill")).not.toBeNull();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("AppShell e StatCard · CSS", () => {
|
|
91
|
+
it("o AppShell dá a cor de texto do tema a quem herda", async () => {
|
|
92
|
+
const css = (await lerArquivo("../core/src/components/AppShell/AppShell.css")).replace(/\r\n/g, "\n");
|
|
93
|
+
const bloco = css.slice(css.indexOf(".umds-app-shell {"), css.indexOf("}", css.indexOf(".umds-app-shell {")));
|
|
94
|
+
expect(bloco).toContain("color: var(--umds-semantic-color-neutral-dark-pure)");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("a StatCard com segunda medida empilha em largura pequena", async () => {
|
|
98
|
+
const css = (await lerArquivo("../core/src/components/StatCard/StatCard.css")).replace(/\r\n/g, "\n");
|
|
99
|
+
expect(css).toContain("container-type: inline-size");
|
|
100
|
+
expect(css).toMatch(/@container \(max-width: 240px\)/);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -37,7 +37,7 @@ describe("SegmentedControl · variant surface", () => {
|
|
|
37
37
|
const escolhido = bloco(t, ".umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item,\n.umds-segmented--surface .umds-segmented__input:checked + .umds-segmented__item:hover");
|
|
38
38
|
expect(escolhido).toMatch(/background-color:\s*var\(--umds-semantic-color-background-white\)/);
|
|
39
39
|
expect(escolhido).toMatch(/font-weight:\s*var\(--umds-primitive-font-weight-bold\)/);
|
|
40
|
-
expect(escolhido).toMatch(/box-shadow:\s*var\(--umds-semantic-shadow-md\)/);
|
|
40
|
+
expect(escolhido).toMatch(/box-shadow:\s*var\(--umds-semantic-shadow-bottom-md\)/);
|
|
41
41
|
expect(bloco(t, ".umds-segmented--surface .umds-segmented__track")).toMatch(/background-color:\s*var\(--umds-semantic-color-neutral-light-medium\)/);
|
|
42
42
|
expect(t).toMatch(/\.umds-segmented__input:checked \+ \.umds-segmented__item,\n\.umds-segmented__input:checked \+ \.umds-segmented__item:hover \{\n\s*background-color:\s*var\(--umds-semantic-color-primary-pure\)/);
|
|
43
43
|
});
|