@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
|
@@ -31,6 +31,7 @@ function Select(props) {
|
|
|
31
31
|
: props.defaultValue !== undefined && props.defaultValue !== null
|
|
32
32
|
? [props.defaultValue]
|
|
33
33
|
: Array());
|
|
34
|
+
const [opensUp, setOpensUp] = useState(() => false);
|
|
34
35
|
const [shouldFocusSearch, setShouldFocusSearch] = useState(() => false);
|
|
35
36
|
const [shouldFocusTrigger, setShouldFocusTrigger] = useState(() => false);
|
|
36
37
|
const [activeIndex, setActiveIndex] = useState(() => -1);
|
|
@@ -92,6 +93,12 @@ function Select(props) {
|
|
|
92
93
|
: internalSelected || [];
|
|
93
94
|
if (currentVal.length === 0)
|
|
94
95
|
return props.placeholder || "Selecione...";
|
|
96
|
+
// Opção "sem filtro" escolhida: volta a mostrar o nome do filtro.
|
|
97
|
+
if (props.emptyOptionLabel &&
|
|
98
|
+
!props.multiple &&
|
|
99
|
+
currentVal.length === 1 &&
|
|
100
|
+
currentVal[0] === "")
|
|
101
|
+
return props.placeholder || "Selecione...";
|
|
95
102
|
if (props.multiple) {
|
|
96
103
|
if (props.selectionDisplay === "tags")
|
|
97
104
|
return "";
|
|
@@ -117,6 +124,11 @@ function Select(props) {
|
|
|
117
124
|
? []
|
|
118
125
|
: [props.value]
|
|
119
126
|
: internalSelected || [];
|
|
127
|
+
if (props.emptyOptionLabel &&
|
|
128
|
+
!props.multiple &&
|
|
129
|
+
currentVal.length === 1 &&
|
|
130
|
+
currentVal[0] === "")
|
|
131
|
+
return true;
|
|
120
132
|
return currentVal.length === 0;
|
|
121
133
|
}
|
|
122
134
|
function formValue() {
|
|
@@ -132,9 +144,18 @@ function Select(props) {
|
|
|
132
144
|
function filteredOptionsList() {
|
|
133
145
|
if (!props.options)
|
|
134
146
|
return [];
|
|
147
|
+
// Opção "sem filtro" no topo (seleção única), sempre visível sem busca.
|
|
148
|
+
const vazia = props.emptyOptionLabel && !props.multiple && !searchTerm
|
|
149
|
+
? [
|
|
150
|
+
{
|
|
151
|
+
label: props.emptyOptionLabel,
|
|
152
|
+
value: "",
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: [];
|
|
135
156
|
// If it's remote search (onSearchChange provided), we don't filter locally
|
|
136
157
|
if (!props.searchable || !searchTerm || props.onSearchChange)
|
|
137
|
-
return props.options;
|
|
158
|
+
return vazia.concat(props.options);
|
|
138
159
|
const term = searchTerm.toLowerCase();
|
|
139
160
|
return props.options.filter((opt) => opt.label.toLowerCase().includes(term));
|
|
140
161
|
}
|
|
@@ -148,6 +169,10 @@ function Select(props) {
|
|
|
148
169
|
props.invalid ? "umds-select--invalid" : "",
|
|
149
170
|
isOpen ? "umds-select--open" : "",
|
|
150
171
|
props.searchVariant === "inline" ? "umds-select--search-inline" : "",
|
|
172
|
+
props.variant === "filter" ? "umds-select--filter" : "",
|
|
173
|
+
opensUp && props.searchVariant !== "inline"
|
|
174
|
+
? "umds-select--placement-top"
|
|
175
|
+
: "",
|
|
151
176
|
props.multiple &&
|
|
152
177
|
props.selectionDisplay === "tags" &&
|
|
153
178
|
selectedOptionsList().length > 0
|
|
@@ -164,6 +189,14 @@ function Select(props) {
|
|
|
164
189
|
function labelIdText() {
|
|
165
190
|
return baseId() ? baseId() + "-label" : undefined;
|
|
166
191
|
}
|
|
192
|
+
function comboboxLabelledBy() {
|
|
193
|
+
return props.label && baseId() ? labelIdText() : undefined;
|
|
194
|
+
}
|
|
195
|
+
function comboboxAriaLabel() {
|
|
196
|
+
if (props.ariaLabel)
|
|
197
|
+
return props.ariaLabel;
|
|
198
|
+
return props.label && !baseId() ? props.label : undefined;
|
|
199
|
+
}
|
|
167
200
|
function activeDescendantText() {
|
|
168
201
|
if (!isOpen || activeIndex < 0 || !baseId())
|
|
169
202
|
return undefined;
|
|
@@ -175,6 +208,21 @@ function Select(props) {
|
|
|
175
208
|
function removeItemAriaLabelText(label) {
|
|
176
209
|
return (props.removeAriaLabel || "Remover") + " " + label;
|
|
177
210
|
}
|
|
211
|
+
function shouldOpenUp() {
|
|
212
|
+
const pedido = props.placement || "bottom";
|
|
213
|
+
if (pedido === "top")
|
|
214
|
+
return true;
|
|
215
|
+
if (pedido !== "auto")
|
|
216
|
+
return false;
|
|
217
|
+
if (typeof window === "undefined" || !triggerRef.current)
|
|
218
|
+
return false;
|
|
219
|
+
const caixa = triggerRef.current.getBoundingClientRect();
|
|
220
|
+
const abaixo = window.innerHeight - caixa.bottom;
|
|
221
|
+
const acima = caixa.top;
|
|
222
|
+
const opcoes = filteredOptionsList().length;
|
|
223
|
+
const estimada = Math.min(300, opcoes * 36 + 8 + (props.searchable ? 44 : 0) + (props.footer ? 44 : 0));
|
|
224
|
+
return abaixo < estimada && acima > abaixo;
|
|
225
|
+
}
|
|
178
226
|
function toggle() {
|
|
179
227
|
if (props.disabled || props.readOnly)
|
|
180
228
|
return;
|
|
@@ -184,10 +232,13 @@ function Select(props) {
|
|
|
184
232
|
const next = !isOpen;
|
|
185
233
|
setIsOpen(next);
|
|
186
234
|
if (next) {
|
|
235
|
+
setOpensUp(shouldOpenUp());
|
|
187
236
|
// Abre com a opção já selecionada ativa (padrão combobox).
|
|
188
237
|
setActiveIndex(filteredOptionsList().findIndex((opt) => isOptionSelected(opt.value)));
|
|
189
238
|
if (props.searchable &&
|
|
190
|
-
(props.autoFocusSearch ||
|
|
239
|
+
(props.autoFocusSearch ||
|
|
240
|
+
props.searchVariant === "inline" ||
|
|
241
|
+
props.variant === "filter")) {
|
|
191
242
|
setShouldFocusSearch(true);
|
|
192
243
|
}
|
|
193
244
|
}
|
|
@@ -368,6 +419,10 @@ function Select(props) {
|
|
|
368
419
|
? []
|
|
369
420
|
: [props.value]
|
|
370
421
|
: internalSelected || [];
|
|
422
|
+
// "Sem filtro" aparece marcada enquanto nada está escolhido.
|
|
423
|
+
if (props.emptyOptionLabel && !props.multiple && val === "") {
|
|
424
|
+
return currentVal.length === 0 || currentVal.includes("");
|
|
425
|
+
}
|
|
371
426
|
return currentVal.includes(val);
|
|
372
427
|
}
|
|
373
428
|
useEffect(() => {
|
|
@@ -417,7 +472,7 @@ function Select(props) {
|
|
|
417
472
|
}
|
|
418
473
|
};
|
|
419
474
|
}, []);
|
|
420
|
-
return (_jsxs("div", { ref: selectRef, className: wrapperClassesList(), children: [props.label ? (_jsxs(Text, { as: "label", variant: "label", className: "umds-select__label", id: labelIdText(), children: [props.label, props.required ? (_jsx("span", { className: "umds-select__required", children: " *" })) : null] })) : null, _jsxs("div", { className: "umds-select__container", children: [!(isOpen && props.searchVariant === "inline") ? (_jsxs("div", { role: "combobox", "aria-haspopup": "listbox", className: "umds-select__trigger", ref: triggerRef, onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeyDown(event), "aria-readonly": ariaReadonly(), "aria-expanded": isOpen, "aria-controls": listboxIdText(), "aria-activedescendant": activeDescendantText(), "aria-labelledby":
|
|
475
|
+
return (_jsxs("div", { ref: selectRef, className: wrapperClassesList(), children: [props.label ? (_jsxs(Text, { as: "label", variant: "label", className: "umds-select__label", id: labelIdText(), children: [props.label, props.required ? (_jsx("span", { className: "umds-select__required", children: " *" })) : null] })) : null, _jsxs("div", { className: "umds-select__container", children: [!(isOpen && props.searchVariant === "inline") ? (_jsxs("div", { role: "combobox", "aria-haspopup": "listbox", className: "umds-select__trigger", ref: triggerRef, onClick: (event) => toggle(), onKeyDown: (event) => handleTriggerKeyDown(event), "aria-readonly": ariaReadonly(), "aria-expanded": isOpen, "aria-controls": listboxIdText(), "aria-activedescendant": activeDescendantText(), "aria-labelledby": comboboxLabelledBy(), "aria-label": comboboxAriaLabel(), "aria-invalid": ariaInvalidText(), "aria-describedby": describedByText(), "aria-disabled": props.disabled ? "true" : undefined, tabIndex: props.disabled ? -1 : 0, children: [_jsxs("div", { className: "umds-select__values", children: [displayLabelText() ? (_jsx(Text, { as: "span", variant: "body2", className: isPlaceholder() ? "umds-select__placeholder" : "", children: displayLabelText() })) : null, props.multiple &&
|
|
421
476
|
props.selectionDisplay === "tags" &&
|
|
422
477
|
selectedOptionsList().length > 0 ? (_jsx("div", { className: "umds-select__tags", children: selectedOptionsList()?.map((opt) => (_jsx(Tag, { size: "sm", label: opt.label, closable: true, disabled: props.disabled, onClose: (e) => removeValue(opt.value, e) }, opt.value))) })) : null] }), _jsxs("div", { className: "umds-select__actions", children: [props.loading ? _jsx(Spinner, { size: "sm", variant: "secondary" }) : null, _jsx("div", { className: "umds-select__arrow", children: _jsx(Icon, { size: "sm", icon: isOpen ? faChevronUp : faChevronDown }) })] })] })) : null, isOpen ? (_jsxs("div", { className: "umds-select__dropdown", style: props.searchVariant === "inline"
|
|
423
478
|
? {
|
|
@@ -431,7 +486,7 @@ function Select(props) {
|
|
|
431
486
|
index === activeIndex ? "umds-select__option--active" : "",
|
|
432
487
|
]
|
|
433
488
|
.filter(Boolean)
|
|
434
|
-
.join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null, _jsx("div", { className: "umds-select__option-content", children: _jsx(_Fragment, { children: props.item || (_jsx(Text, { variant: "body2", children: option.label })) }) }), !props.multiple && isOptionSelected(option.value) ? (_jsx("div", { className: "umds-select__option-check", children: _jsx(Icon, { size: "sm", icon: faCheck }) })) : null] }, option.value))), props.loading && props.pagination ? (_jsxs("div", { className: "umds-select__loading-more", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { variant: "caption", children: props.loadingLabel || "Carregando mais..." })] })) : null] })] })) : null] }), props.name ? (_jsx("input", { type: "hidden", name: props.name, value: formValue() || "" })) : null, props.errorMessage ? (_jsx(Text, { variant: "caption", color: "negative", className: "umds-select__error-message", id: errorIdText(), children: props.errorMessage })) : null, mostraApoio() ? (_jsx(Text, { variant: "caption", color: "secondary", className: "umds-select__description", id: helperIdText(), children: textoDeApoio() })) : null, props.multiple &&
|
|
489
|
+
.join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null, _jsx("div", { className: "umds-select__option-content", children: _jsx(_Fragment, { children: props.item || (_jsx(Text, { variant: "body2", children: option.label })) }) }), !props.multiple && isOptionSelected(option.value) ? (_jsx("div", { className: "umds-select__option-check", children: _jsx(Icon, { size: "sm", icon: faCheck }) })) : null] }, option.value))), props.loading && props.pagination ? (_jsxs("div", { className: "umds-select__loading-more", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { variant: "caption", children: props.loadingLabel || "Carregando mais..." })] })) : null] }), props.footer ? (_jsx("div", { className: "umds-select__footer", children: _jsx(_Fragment, { children: props.footer }) })) : null] })) : null] }), props.name ? (_jsx("input", { type: "hidden", name: props.name, value: formValue() || "" })) : null, props.errorMessage ? (_jsx(Text, { variant: "caption", color: "negative", className: "umds-select__error-message", id: errorIdText(), children: props.errorMessage })) : null, mostraApoio() ? (_jsx(Text, { variant: "caption", color: "secondary", className: "umds-select__description", id: helperIdText(), children: textoDeApoio() })) : null, props.multiple &&
|
|
435
490
|
props.selectionDisplay === "list" &&
|
|
436
491
|
selectedOptionsList().length > 0 ? (_jsx("div", { className: "umds-select__selected-list", children: selectedOptionsList()?.map((opt) => (_jsxs("div", { className: "umds-select__selected-list-item", children: [_jsx(Text, { variant: "body2", children: opt.label }), _jsx("button", { type: "button", className: "umds-select__list-remove", "aria-label": removeItemAriaLabelText(opt.label), onClick: (e) => removeValue(opt.value, e), children: _jsx(Icon, { size: "sm", icon: faTrash }) })] }, opt.value))) })) : null] }));
|
|
437
492
|
}
|
|
@@ -55,3 +55,52 @@
|
|
|
55
55
|
.umds-stack--justify-between { justify-content: space-between; }
|
|
56
56
|
.umds-stack--justify-around { justify-content: space-around; }
|
|
57
57
|
.umds-stack--justify-evenly { justify-content: space-evenly; }
|
|
58
|
+
|
|
59
|
+
/* ── Sem espaço ── */
|
|
60
|
+
.umds-stack--gap-none { gap: 0; }
|
|
61
|
+
|
|
62
|
+
/* ── Lista: ul/ol sem marcador, margem nem recuo do navegador ── */
|
|
63
|
+
ul.umds-stack,
|
|
64
|
+
ol.umds-stack {
|
|
65
|
+
list-style: none;
|
|
66
|
+
margin: 0;
|
|
67
|
+
padding: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ── Como item de outro Stack/flex ── */
|
|
71
|
+
.umds-stack--grow { flex-grow: 1; }
|
|
72
|
+
.umds-stack--shrink-0 { flex-shrink: 0; }
|
|
73
|
+
.umds-stack--shrink-1 { flex-shrink: 1; }
|
|
74
|
+
|
|
75
|
+
.umds-stack--basis-auto { flex-basis: auto; }
|
|
76
|
+
.umds-stack--basis-0 { flex-basis: 0; }
|
|
77
|
+
.umds-stack--basis-25 { flex-basis: 25%; }
|
|
78
|
+
.umds-stack--basis-33 { flex-basis: 33.3333%; }
|
|
79
|
+
.umds-stack--basis-50 { flex-basis: 50%; }
|
|
80
|
+
.umds-stack--basis-66 { flex-basis: 66.6667%; }
|
|
81
|
+
.umds-stack--basis-75 { flex-basis: 75%; }
|
|
82
|
+
.umds-stack--basis-100 { flex-basis: 100%; }
|
|
83
|
+
|
|
84
|
+
/* O padrão do Stack já é min-width: 0; estas duas só tornam a escolha explícita. */
|
|
85
|
+
.umds-stack--min-w-0 { min-width: 0; }
|
|
86
|
+
.umds-stack--min-w-auto { min-width: auto; }
|
|
87
|
+
|
|
88
|
+
/* ── Overflow: o eixo vem depois do geral, então vence por ordem de cascata ── */
|
|
89
|
+
.umds-stack--overflow-visible { overflow: visible; }
|
|
90
|
+
.umds-stack--overflow-hidden { overflow: hidden; }
|
|
91
|
+
.umds-stack--overflow-auto { overflow: auto; }
|
|
92
|
+
.umds-stack--overflow-scroll { overflow: scroll; }
|
|
93
|
+
|
|
94
|
+
.umds-stack--overflow-x-visible { overflow-x: visible; }
|
|
95
|
+
.umds-stack--overflow-x-hidden { overflow-x: hidden; }
|
|
96
|
+
.umds-stack--overflow-x-auto { overflow-x: auto; }
|
|
97
|
+
.umds-stack--overflow-x-scroll { overflow-x: scroll; }
|
|
98
|
+
|
|
99
|
+
.umds-stack--overflow-y-visible { overflow-y: visible; }
|
|
100
|
+
.umds-stack--overflow-y-hidden { overflow-y: hidden; }
|
|
101
|
+
.umds-stack--overflow-y-auto { overflow-y: auto; }
|
|
102
|
+
.umds-stack--overflow-y-scroll { overflow-y: scroll; }
|
|
103
|
+
|
|
104
|
+
/* ── Dimensão ── */
|
|
105
|
+
.umds-stack--full-height { height: 100%; }
|
|
106
|
+
.umds-stack--full-width { width: 100%; }
|
|
@@ -1,27 +1,60 @@
|
|
|
1
1
|
import './Stack.css';
|
|
2
|
-
/** Degraus da escala oficial de espaçamento do 1DS. */
|
|
3
|
-
export type StackSpacing = "quarck" | "nano" | "micro" | "mini" | "xxxs" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | "xxxl";
|
|
2
|
+
/** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
|
|
3
|
+
export type StackSpacing = "none" | "quarck" | "nano" | "micro" | "mini" | "xxxs" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl" | "xxl" | "xxxl";
|
|
4
|
+
/** Elemento HTML que o Stack renderiza. */
|
|
5
|
+
/** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
|
|
6
|
+
/** Elemento HTML que o Stack renderiza. */
|
|
7
|
+
export type StackTag = "div" | "span" | "ul" | "ol" | "li" | "section" | "nav" | "header" | "footer" | "form";
|
|
8
|
+
/** Valores de `overflow` aceitos (por eixo ou nos dois). */
|
|
9
|
+
/** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
|
|
10
|
+
/** Elemento HTML que o Stack renderiza. */
|
|
11
|
+
/** Valores de `overflow` aceitos (por eixo ou nos dois). */
|
|
12
|
+
export type StackOverflow = "visible" | "hidden" | "auto" | "scroll";
|
|
4
13
|
/**
|
|
5
14
|
* Stack — empilha os filhos com espaçamento da escala do DS.
|
|
6
15
|
*
|
|
7
16
|
* Existe para eliminar o `style={{ display: "flex", gap: 16 }}` escrito à mão,
|
|
8
17
|
* que é por onde o design system vaza: o 16 sai da cabeça de quem escreve, não
|
|
9
18
|
* do token. Aqui o `gap` só aceita degraus da escala oficial.
|
|
19
|
+
*
|
|
20
|
+
* Também é o item de outro Stack: quem precisa crescer, encolher ou ocupar a
|
|
21
|
+
* altura toda dentro de um Stack pai aninha um Stack com `grow`, `shrink`,
|
|
22
|
+
* `basis`, `fullHeight`... (não existe `Stack.Item`: subcomponente por ponto
|
|
23
|
+
* não sobrevive aos dois geradores, e o Stack aninhado já é um item flex).
|
|
24
|
+
*
|
|
25
|
+
* Atributos HTML (`id`, `style`, `title`, `role`, `tabIndex`, `data-*`,
|
|
26
|
+
* `aria-*`) vão para o elemento raiz. Com `as="nav"`, `section` ou `form`,
|
|
27
|
+
* passe `aria-label` ou `aria-labelledby`: a região só é anunciada se tiver nome.
|
|
28
|
+
* @property {string} as - Elemento HTML: 'div' (padrão) | 'span' | 'ul' | 'ol' | 'li' | 'section' | 'nav' | 'header' | 'footer' | 'form'
|
|
10
29
|
* @property {string} direction - Eixo do empilhamento: 'vertical' (padrão) | 'horizontal'
|
|
11
|
-
* @property {string} gap - Espaço entre os filhos, na escala do DS
|
|
30
|
+
* @property {string} gap - Espaço entre os filhos, na escala do DS ('none' zera)
|
|
12
31
|
* @property {string} align - Alinhamento no eixo transversal
|
|
13
32
|
* @property {string} justify - Distribuição no eixo principal
|
|
14
33
|
* @property {boolean} wrap - Permite quebrar em várias linhas
|
|
15
34
|
* @property {boolean} inline - Usa display inline-flex em vez de flex
|
|
35
|
+
* @property {boolean} grow - Como item de outro Stack/flex: cresce para ocupar o espaço livre
|
|
36
|
+
* @property {string} shrink - Como item flex: '0' não encolhe, '1' encolhe
|
|
37
|
+
* @property {string} basis - Como item flex: tamanho base ('auto', '0', '25', '33', '50', '66', '75', '100'; os números são %)
|
|
38
|
+
* @property {string} minWidth - '0' (padrão do Stack) deixa o conteúdo longo encolher; 'auto' devolve o mínimo do conteúdo
|
|
39
|
+
* @property {string} overflow - Overflow nos dois eixos
|
|
40
|
+
* @property {string} overflowX - Overflow horizontal
|
|
41
|
+
* @property {string} overflowY - Overflow vertical
|
|
42
|
+
* @property {boolean} fullHeight - Ocupa 100% da altura do pai
|
|
43
|
+
* @property {boolean} fullWidth - Ocupa 100% da largura do pai
|
|
16
44
|
* @property {string} className - Classes CSS adicionais
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
45
|
+
* @property {function} onSubmit - Só com as="form": callback do envio
|
|
46
|
+
* @quandoUsar Empilhar elementos com espaçamento consistente: campos de um formulário, botões de uma barra de ações, itens de uma lista (`as="ul"` com filhos `as="li"`). É o jeito certo de dar respiro sem escrever CSS, e de fazer uma região crescer ou rolar dentro de outra.
|
|
47
|
+
* @quandoNaoUsar Para layout em COLUNAS que se alinham entre si — use `Grid`. Para uma caixa com padding e fundo, use `Box` (que também aceita direction e gap quando a superfície é a própria linha ou região). Stack só distribui no eixo, não desenha nada.
|
|
19
48
|
*/
|
|
20
|
-
/** Degraus da escala oficial de espaçamento do 1DS. */
|
|
49
|
+
/** Degraus da escala oficial de espaçamento do 1DS. `none` zera o espaço. */
|
|
50
|
+
/** Elemento HTML que o Stack renderiza. */
|
|
51
|
+
/** Valores de `overflow` aceitos (por eixo ou nos dois). */
|
|
21
52
|
export interface StackProps {
|
|
53
|
+
/** Elemento HTML renderizado. @default 'div' */
|
|
54
|
+
as?: StackTag;
|
|
22
55
|
/** Eixo do empilhamento. @default 'vertical' */
|
|
23
56
|
direction?: "vertical" | "horizontal";
|
|
24
|
-
/** Espaço entre os filhos, na escala oficial (xxxs = 16px). @default 'xxxs' */
|
|
57
|
+
/** Espaço entre os filhos, na escala oficial (xxxs = 16px; `none` = 0). @default 'xxxs' */
|
|
25
58
|
gap?: StackSpacing;
|
|
26
59
|
/** Alinhamento no eixo transversal. */
|
|
27
60
|
align?: "start" | "center" | "end" | "stretch" | "baseline";
|
|
@@ -31,8 +64,33 @@ export interface StackProps {
|
|
|
31
64
|
wrap?: boolean;
|
|
32
65
|
/** Usa `inline-flex` em vez de `flex`. */
|
|
33
66
|
inline?: boolean;
|
|
67
|
+
/** Como item de outro Stack/flex: cresce para ocupar o espaço livre. */
|
|
68
|
+
grow?: boolean;
|
|
69
|
+
/** Como item flex: `"0"` não encolhe; `"1"` encolhe. */
|
|
70
|
+
shrink?: "0" | "1";
|
|
71
|
+
/** Como item flex: tamanho base. Os números são porcentagem do pai. */
|
|
72
|
+
basis?: "auto" | "0" | "25" | "33" | "50" | "66" | "75" | "100";
|
|
73
|
+
/** `"0"` (já é o padrão do Stack) deixa o conteúdo encolher; `"auto"` volta ao mínimo do conteúdo. */
|
|
74
|
+
minWidth?: "0" | "auto";
|
|
75
|
+
/** Overflow nos dois eixos. */
|
|
76
|
+
overflow?: StackOverflow;
|
|
77
|
+
/** Overflow horizontal (vence `overflow` no eixo X). */
|
|
78
|
+
overflowX?: StackOverflow;
|
|
79
|
+
/** Overflow vertical (vence `overflow` no eixo Y). */
|
|
80
|
+
overflowY?: StackOverflow;
|
|
81
|
+
/** Ocupa 100% da altura do pai. */
|
|
82
|
+
fullHeight?: boolean;
|
|
83
|
+
/** Ocupa 100% da largura do pai. */
|
|
84
|
+
fullWidth?: boolean;
|
|
34
85
|
/** Classes CSS adicionais. */
|
|
35
86
|
className?: string;
|
|
87
|
+
/** Só com `as="form"`: chamado no envio do formulário. */
|
|
88
|
+
onSubmit?: (event: any) => void;
|
|
89
|
+
/** ID HTML do elemento raiz. */
|
|
90
|
+
id?: string;
|
|
91
|
+
/** Atributos HTML repassados ao elemento raiz (style, data-*, aria-*…). */
|
|
92
|
+
style?: any;
|
|
93
|
+
[key: string]: any;
|
|
36
94
|
/** Conteúdo empilhado. */
|
|
37
95
|
children?: any;
|
|
38
96
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
import './Stack.css';
|
|
3
4
|
function Stack(props) {
|
|
5
|
+
function elementTag() {
|
|
6
|
+
return props.as || "div";
|
|
7
|
+
}
|
|
4
8
|
function classes() {
|
|
5
9
|
return [
|
|
6
10
|
"umds-stack",
|
|
@@ -10,11 +14,35 @@ function Stack(props) {
|
|
|
10
14
|
props.justify ? `umds-stack--justify-${props.justify}` : "",
|
|
11
15
|
props.wrap ? "umds-stack--wrap" : "",
|
|
12
16
|
props.inline ? "umds-stack--inline" : "",
|
|
17
|
+
props.grow ? "umds-stack--grow" : "",
|
|
18
|
+
props.shrink ? `umds-stack--shrink-${props.shrink}` : "",
|
|
19
|
+
props.basis ? `umds-stack--basis-${props.basis}` : "",
|
|
20
|
+
props.minWidth ? `umds-stack--min-w-${props.minWidth}` : "",
|
|
21
|
+
props.overflow ? `umds-stack--overflow-${props.overflow}` : "",
|
|
22
|
+
props.overflowX ? `umds-stack--overflow-x-${props.overflowX}` : "",
|
|
23
|
+
props.overflowY ? `umds-stack--overflow-y-${props.overflowY}` : "",
|
|
24
|
+
props.fullHeight ? "umds-stack--full-height" : "",
|
|
25
|
+
props.fullWidth ? "umds-stack--full-width" : "",
|
|
13
26
|
props.className,
|
|
14
27
|
]
|
|
15
28
|
.filter(Boolean)
|
|
16
29
|
.join(" ");
|
|
17
30
|
}
|
|
18
|
-
|
|
31
|
+
function htmlAttrs() {
|
|
32
|
+
const out = {};
|
|
33
|
+
for (const chave in props) {
|
|
34
|
+
if (chave.indexOf("data-") === 0 ||
|
|
35
|
+
chave.indexOf("aria-") === 0 ||
|
|
36
|
+
chave === "style" ||
|
|
37
|
+
chave === "class" ||
|
|
38
|
+
chave === "title" ||
|
|
39
|
+
chave === "role" ||
|
|
40
|
+
chave === "tabIndex") {
|
|
41
|
+
out[chave] = props[chave];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
return (_jsxs(_Fragment, { children: [elementTag() === "div" ? (_jsx("div", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "span" ? (_jsx("span", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "ul" ? (_jsx("ul", { role: "list", id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "ol" ? (_jsx("ol", { role: "list", id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "li" ? (_jsx("li", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "section" ? (_jsx("section", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "nav" ? (_jsx("nav", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "header" ? (_jsx("header", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "footer" ? (_jsx("footer", { id: props.id, ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null, elementTag() === "form" ? (_jsx("form", { id: props.id, onSubmit: (event) => props.onSubmit && props.onSubmit(event), ...htmlAttrs(), className: classes(), children: _jsx(_Fragment, { children: props.children }) })) : null] }));
|
|
19
47
|
}
|
|
20
48
|
export default Stack;
|
|
@@ -152,3 +152,76 @@
|
|
|
152
152
|
.umds-stat-card__variacao--neutral {
|
|
153
153
|
color: var(--umds-semantic-color-neutral-dark-down);
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
/* ── ⓘ de ajuda ao lado do rótulo (infoTooltip) ── */
|
|
157
|
+
.umds-stat-card__rotulo {
|
|
158
|
+
display: inline-flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
gap: var(--umds-primitive-spacing-nano);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.umds-stat-card__info {
|
|
164
|
+
display: inline-flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
justify-content: center;
|
|
167
|
+
padding: 0;
|
|
168
|
+
border: none;
|
|
169
|
+
background: transparent;
|
|
170
|
+
color: var(--umds-semantic-color-neutral-dark-medium);
|
|
171
|
+
cursor: help;
|
|
172
|
+
border-radius: var(--umds-primitive-border-radius-circular);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.umds-stat-card__info:hover {
|
|
176
|
+
color: var(--umds-semantic-color-neutral-dark-pure);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.umds-stat-card__info:focus-visible {
|
|
180
|
+
outline: 2px solid var(--umds-semantic-color-primary-pure);
|
|
181
|
+
outline-offset: 2px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* ── labelPosition="top": rótulo no topo, ícone e número embaixo ──
|
|
185
|
+
O HTML segue com o número antes do rótulo (a ordem do leitor de tela); só a
|
|
186
|
+
grade muda a ordem visual. O corpo vira `display: contents` para o rótulo,
|
|
187
|
+
o número e o resto virarem itens da própria grade do cartão. */
|
|
188
|
+
.umds-stat-card--rotulo-topo {
|
|
189
|
+
display: grid;
|
|
190
|
+
grid-template-columns: auto 1fr;
|
|
191
|
+
align-items: center;
|
|
192
|
+
column-gap: 0;
|
|
193
|
+
row-gap: var(--umds-primitive-spacing-nano);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__corpo {
|
|
197
|
+
display: contents;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__rotulo {
|
|
201
|
+
grid-column: 1 / -1;
|
|
202
|
+
grid-row: 1;
|
|
203
|
+
font-weight: var(--umds-primitive-font-weight-semibold);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__icone {
|
|
207
|
+
grid-column: 1;
|
|
208
|
+
grid-row: 2;
|
|
209
|
+
margin-right: var(--umds-primitive-spacing-mini);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__valor {
|
|
213
|
+
grid-column: 2;
|
|
214
|
+
grid-row: 2;
|
|
215
|
+
font-size: var(--umds-primitive-font-size-lg); /* 32px */
|
|
216
|
+
font-weight: var(--umds-primitive-font-weight-extrabold);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__descricao,
|
|
220
|
+
.umds-stat-card--rotulo-topo .umds-stat-card__variacao {
|
|
221
|
+
grid-column: 1 / -1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Sem ícone, o número ocupa a linha toda. */
|
|
225
|
+
.umds-stat-card--rotulo-topo:not(:has(.umds-stat-card__icone)) .umds-stat-card__valor {
|
|
226
|
+
grid-column: 1 / -1;
|
|
227
|
+
}
|
|
@@ -22,6 +22,9 @@ import './StatCard.css';
|
|
|
22
22
|
* @property {string} trendIntent - Se a variação é boa ou ruim (cor), independente da direção: 'positive' | 'negative' | 'neutral'
|
|
23
23
|
* @property {string} trendLabel - Texto da variação (ex.: '12% em relação ao mês anterior')
|
|
24
24
|
* @property {string} description - Texto auxiliar abaixo do rótulo
|
|
25
|
+
* @property {string} labelPosition - Onde o rótulo aparece: 'bottom' (padrão, embaixo do número) | 'top' (no topo do cartão, acima do ícone e do número, com o número em 32/800). No HTML o número continua vindo antes do rótulo, então o leitor de tela anuncia igual.
|
|
26
|
+
* @property {string} infoTooltip - Texto de ajuda: mostra um ⓘ ao lado do rótulo com um Tooltip escuro. É um botão dentro do cartão; com `onClick` no cartão, evite (botão dentro de botão).
|
|
27
|
+
* @property {string} infoLabel - Nome acessível do ⓘ. Troque para traduzir. Padrão: "Mais informações".
|
|
25
28
|
* @property {string} align - Alinhamento do conteúdo
|
|
26
29
|
* @property {string} className - Classes CSS adicionais
|
|
27
30
|
* @property {function} onClick - Torna o cartão acionável (vira botão)
|
|
@@ -56,6 +59,20 @@ export interface StatCardProps {
|
|
|
56
59
|
description?: string;
|
|
57
60
|
/** Alinhamento do conteúdo. @default 'start' */
|
|
58
61
|
align?: "start" | "center";
|
|
62
|
+
/**
|
|
63
|
+
* Onde o rótulo aparece. `top` põe o rótulo no topo do cartão, acima do
|
|
64
|
+
* ícone e do número (que passa a 32/800), como no painel da 1Doc. No HTML o
|
|
65
|
+
* número segue antes do rótulo: só a posição visual muda.
|
|
66
|
+
* @default 'bottom'
|
|
67
|
+
*/
|
|
68
|
+
labelPosition?: "bottom" | "top";
|
|
69
|
+
/**
|
|
70
|
+
* Texto de ajuda: mostra o ⓘ ao lado do rótulo, com um Tooltip escuro. É um
|
|
71
|
+
* botão focável dentro do cartão; com `onClick` no cartão, evite.
|
|
72
|
+
*/
|
|
73
|
+
infoTooltip?: string;
|
|
74
|
+
/** Nome acessível do ⓘ. @default 'Mais informações' */
|
|
75
|
+
infoLabel?: string;
|
|
59
76
|
/** Classes CSS adicionais. */
|
|
60
77
|
className?: string;
|
|
61
78
|
/** Torna o cartão acionável. */
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import './StatCard.css';
|
|
4
|
+
import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
|
|
4
5
|
import Icon from "../Icon/Icon";
|
|
6
|
+
import Tooltip from "../Tooltip/Tooltip";
|
|
5
7
|
function StatCard(props) {
|
|
6
8
|
function classes() {
|
|
7
9
|
return [
|
|
8
10
|
"umds-stat-card",
|
|
9
11
|
`umds-stat-card--${props.variant || "neutral"}`,
|
|
10
12
|
props.align === "center" ? "umds-stat-card--centro" : "",
|
|
13
|
+
props.labelPosition === "top" ? "umds-stat-card--rotulo-topo" : "",
|
|
11
14
|
props.onClick ? "umds-stat-card--acionavel" : "",
|
|
12
15
|
props.className,
|
|
13
16
|
]
|
|
@@ -45,6 +48,6 @@ function StatCard(props) {
|
|
|
45
48
|
if (props.onClick)
|
|
46
49
|
props.onClick();
|
|
47
50
|
}
|
|
48
|
-
return (_jsxs("div", { className: classes(), onClick: (event) => aoClicar(), role: ehAcionavel() ? "button" : undefined, tabIndex: ehAcionavel() ? 0 : undefined, children: [props.icon ? (_jsx("span", { className: "umds-stat-card__icone", "aria-hidden": "true", children: _jsx(Icon, { size: "md", variant: "inherit", icon: props.icon }) })) : null, _jsxs("div", { className: "umds-stat-card__corpo", children: [_jsx("span", { className: "umds-stat-card__valor", children: props.value }),
|
|
51
|
+
return (_jsxs("div", { className: classes(), onClick: (event) => aoClicar(), role: ehAcionavel() ? "button" : undefined, tabIndex: ehAcionavel() ? 0 : undefined, children: [props.icon ? (_jsx("span", { className: "umds-stat-card__icone", "aria-hidden": "true", children: _jsx(Icon, { size: "md", variant: "inherit", icon: props.icon }) })) : null, _jsxs("div", { className: "umds-stat-card__corpo", children: [_jsx("span", { className: "umds-stat-card__valor", children: props.value }), _jsxs("span", { className: "umds-stat-card__rotulo", children: [props.label, props.infoTooltip ? (_jsx(Tooltip, { variant: "dark", side: "top", content: props.infoTooltip, children: _jsx("button", { type: "button", className: "umds-stat-card__info", "aria-label": props.infoLabel || "Mais informações", children: _jsx(Icon, { variant: "inherit", customSize: "14px", icon: faCircleInfo }) }) })) : null] }), props.description ? (_jsx("span", { className: "umds-stat-card__descricao", children: props.description })) : null, props.trendLabel ? (_jsxs("span", { className: classesDaVariacao(), children: [_jsx("span", { "aria-hidden": "true", children: simboloDaVariacao() }), props.trendLabel] })) : null] })] }));
|
|
49
52
|
}
|
|
50
53
|
export default StatCard;
|
|
@@ -16,6 +16,21 @@ export interface TabProps {
|
|
|
16
16
|
icon?: IconProp;
|
|
17
17
|
/** Se a tab está desabilitada */
|
|
18
18
|
disabled?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Contador em pílula ao lado do texto: azul na aba ativa, cinza nas outras.
|
|
21
|
+
* Aceita número ou texto; o `0` aparece. Sem a prop, não há pílula.
|
|
22
|
+
*/
|
|
23
|
+
count?: number | string;
|
|
24
|
+
/**
|
|
25
|
+
* Mostra o × para fechar a aba (abas de navegador, documentos abertos). O
|
|
26
|
+
* × é um botão próprio, irmão da aba (não dentro dela), e a tecla Delete
|
|
27
|
+
* na aba focada faz o mesmo. Quem remove a aba é o app, em `onClose`.
|
|
28
|
+
*/
|
|
29
|
+
closable?: boolean;
|
|
30
|
+
/** Chamado ao fechar a aba, com o `index` dela e o evento. */
|
|
31
|
+
onClose?: (index: string, event?: any) => void;
|
|
32
|
+
/** Prefixo do nome acessível do ×; o texto da aba vem depois ("Fechar Documento 1"). Troque para traduzir. @default 'Fechar' */
|
|
33
|
+
closeLabel?: string;
|
|
19
34
|
/** Classes CSS adicionais */
|
|
20
35
|
className?: string;
|
|
21
36
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useContext } from "react";
|
|
4
|
+
import { faXmark } from "@fortawesome/free-solid-svg-icons";
|
|
4
5
|
import TabsContext from "./tabs.context";
|
|
5
6
|
import Icon from "../Icon/Icon";
|
|
6
7
|
function Tab(props) {
|
|
@@ -17,11 +18,26 @@ function Tab(props) {
|
|
|
17
18
|
? tabsContext.tabsId + "-panel-" + props.index
|
|
18
19
|
: undefined;
|
|
19
20
|
}
|
|
21
|
+
function temContador() {
|
|
22
|
+
return (props.count !== undefined && props.count !== null && props.count !== "");
|
|
23
|
+
}
|
|
24
|
+
function itemClasses() {
|
|
25
|
+
return [
|
|
26
|
+
"umds-tabs__item",
|
|
27
|
+
props.closable ? "umds-tabs__item--closable" : "",
|
|
28
|
+
]
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
.join(" ");
|
|
31
|
+
}
|
|
32
|
+
function closeAriaText() {
|
|
33
|
+
return (props.closeLabel || "Fechar") + " " + props.label;
|
|
34
|
+
}
|
|
20
35
|
function classes() {
|
|
21
36
|
return [
|
|
22
37
|
"umds-tabs__tab",
|
|
23
38
|
isSelected() ? "umds-tabs__tab--selected" : "",
|
|
24
39
|
props.disabled ? "umds-tabs__tab--disabled" : "",
|
|
40
|
+
props.closable ? "umds-tabs__tab--closable" : "",
|
|
25
41
|
props.className,
|
|
26
42
|
]
|
|
27
43
|
.filter(Boolean)
|
|
@@ -42,9 +58,22 @@ function Tab(props) {
|
|
|
42
58
|
tabsContext.onChange(props.index);
|
|
43
59
|
}
|
|
44
60
|
}
|
|
61
|
+
function handleClose(event) {
|
|
62
|
+
event.stopPropagation();
|
|
63
|
+
if (props.disabled)
|
|
64
|
+
return;
|
|
65
|
+
if (typeof props.onClose === "function") {
|
|
66
|
+
props.onClose(props.index, event);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
45
69
|
function handleKeyDown(event) {
|
|
46
70
|
if (props.disabled)
|
|
47
71
|
return;
|
|
72
|
+
if (props.closable && event.key === "Delete") {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
handleClose(event);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
48
77
|
if (event.key === "Enter" || event.key === " ") {
|
|
49
78
|
event.preventDefault();
|
|
50
79
|
handleClick();
|
|
@@ -81,6 +110,6 @@ function Tab(props) {
|
|
|
81
110
|
}
|
|
82
111
|
}
|
|
83
112
|
const tabsContext = useContext(TabsContext);
|
|
84
|
-
return (_jsxs("button", { role: "tab", id: tabId(), "aria-controls": panelId(), "data-tab-index": props.index, "aria-selected": isSelected(), "aria-disabled": props.disabled, tabIndex: isSelected() ? 0 : -1, disabled: props.disabled, onClick: (event) => handleClick(), onKeyDown: (event) => handleKeyDown(event), className: classes(), children: [props.icon ? (_jsx(Icon, { size: "md", variant: "inherit", icon: props.icon })) : null, _jsx("span", { className: labelClasses(), children: props.label })] }));
|
|
113
|
+
return (_jsxs("span", { role: "presentation", className: itemClasses(), children: [_jsxs("button", { role: "tab", id: tabId(), "aria-controls": panelId(), "data-tab-index": props.index, "aria-selected": isSelected(), "aria-disabled": props.disabled, tabIndex: isSelected() ? 0 : -1, disabled: props.disabled, onClick: (event) => handleClick(), onKeyDown: (event) => handleKeyDown(event), className: classes(), children: [props.icon ? (_jsx(Icon, { size: "md", variant: "inherit", icon: props.icon })) : null, _jsx("span", { className: labelClasses(), children: props.label }), temContador() ? (_jsx("span", { className: "umds-tabs__count", children: props.count })) : null] }), props.closable ? (_jsx("button", { type: "button", className: "umds-tabs__close", "aria-label": closeAriaText(), disabled: props.disabled, tabIndex: -1, onClick: (event) => handleClose(event), children: _jsx(Icon, { variant: "inherit", customSize: "10px", icon: faXmark }) })) : null] }));
|
|
85
114
|
}
|
|
86
115
|
export default Tab;
|