@1doc/1ds-react 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1540 -0
- package/dist/components/AILabel/AILabel.js +1 -1
- package/dist/components/Accordion/Accordion.css +13 -0
- package/dist/components/Accordion/Accordion.d.ts +9 -2
- package/dist/components/Accordion/Accordion.js +1 -0
- package/dist/components/AppSubheader/AppSubheader.css +10 -1
- package/dist/components/AttachmentCard/AttachmentCard.css +26 -8
- package/dist/components/AttachmentCard/AttachmentCard.d.ts +22 -2
- package/dist/components/AttachmentCard/AttachmentCard.js +47 -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 +67 -2
- package/dist/components/Badge/Badge.d.ts +23 -4
- package/dist/components/Badge/Badge.js +4 -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 +126 -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 +128 -0
- package/dist/components/Coachmark/Coachmark.d.ts +87 -0
- package/dist/components/Coachmark/Coachmark.js +362 -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 +140 -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 +254 -0
- package/dist/components/DataTable/DataTable.d.ts +81 -5
- package/dist/components/DataTable/DataTable.js +335 -19
- package/dist/components/DatePicker/DatePicker.css +8 -0
- package/dist/components/DatePicker/DatePicker.js +10 -1
- package/dist/components/DescriptionList/DescriptionList.css +127 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +62 -0
- package/dist/components/DescriptionList/DescriptionList.js +52 -0
- package/dist/components/EmptyState/EmptyState.d.ts +4 -2
- package/dist/components/EmptyState/EmptyState.js +2 -2
- 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 +59 -0
- package/dist/components/Input/Input.d.ts +17 -1
- package/dist/components/Input/Input.js +67 -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 +97 -0
- package/dist/components/List/ListItem.js +82 -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 +250 -0
- package/dist/components/RichTextEditor/RichTextEditor.d.ts +97 -0
- package/dist/components/RichTextEditor/RichTextEditor.js +951 -0
- package/dist/components/SegmentedControl/SegmentedControl.css +24 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +10 -2
- package/dist/components/Select/Select.css +164 -0
- package/dist/components/Select/Select.d.ts +34 -0
- package/dist/components/Select/Select.js +258 -28
- 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 +138 -0
- package/dist/components/StatCard/StatCard.d.ts +26 -0
- package/dist/components/StatCard/StatCard.js +13 -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/Toast/Toast.css +32 -0
- package/dist/components/Toast/Toast.d.ts +18 -0
- package/dist/components/Toast/Toast.js +14 -1
- package/dist/components/Toast/ToastStack.js +8 -1
- 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/AccordionTituloNeutro.test.d.ts +1 -0
- package/dist/teste/AccordionTituloNeutro.test.js +23 -0
- package/dist/teste/AppSubheaderRegiao.test.d.ts +1 -0
- package/dist/teste/AppSubheaderRegiao.test.js +13 -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/AttachmentCardLista.test.d.ts +1 -0
- package/dist/teste/AttachmentCardLista.test.js +49 -0
- package/dist/teste/AttachmentCardSm.test.d.ts +1 -0
- package/dist/teste/AttachmentCardSm.test.js +26 -0
- package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
- package/dist/teste/AvatarGroupOverlap.test.js +56 -0
- package/dist/teste/BadgeNeutroColado.test.d.ts +1 -0
- package/dist/teste/BadgeNeutroColado.test.js +11 -0
- package/dist/teste/BadgeTag.test.d.ts +1 -0
- package/dist/teste/BadgeTag.test.js +55 -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/CalendarCabecalho.test.d.ts +1 -0
- package/dist/teste/CalendarCabecalho.test.js +11 -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/CoachmarkSemVeu.test.d.ts +1 -0
- package/dist/teste/CoachmarkSemVeu.test.js +85 -0
- package/dist/teste/ColorPicker.test.d.ts +1 -0
- package/dist/teste/ColorPicker.test.js +132 -0
- package/dist/teste/ColorPickerXs.test.d.ts +1 -0
- package/dist/teste/ColorPickerXs.test.js +21 -0
- package/dist/teste/DataTableArvoreEVariantes.test.d.ts +1 -0
- package/dist/teste/DataTableArvoreEVariantes.test.js +190 -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/DescriptionListCompacta.test.d.ts +1 -0
- package/dist/teste/DescriptionListCompacta.test.js +22 -0
- package/dist/teste/EmptyStateTituloRico.test.d.ts +1 -0
- package/dist/teste/EmptyStateTituloRico.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/InputAgrupado.test.d.ts +1 -0
- package/dist/teste/InputAgrupado.test.js +24 -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/ListItemTooltipStandalone.test.d.ts +1 -0
- package/dist/teste/ListItemTooltipStandalone.test.js +39 -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/RichTextEditorAlinhaImagemTabela.test.d.ts +1 -0
- package/dist/teste/RichTextEditorAlinhaImagemTabela.test.js +212 -0
- package/dist/teste/RichTextEditorEstiloDeTexto.test.d.ts +1 -0
- package/dist/teste/RichTextEditorEstiloDeTexto.test.js +120 -0
- package/dist/teste/SegmentedControlContador.test.d.ts +1 -0
- package/dist/teste/SegmentedControlContador.test.js +39 -0
- package/dist/teste/SelectAbertoControladoEFlutuante.test.d.ts +1 -0
- package/dist/teste/SelectAbertoControladoEFlutuante.test.js +145 -0
- package/dist/teste/SelectFiltroCorETamanho.test.d.ts +1 -0
- package/dist/teste/SelectFiltroCorETamanho.test.js +77 -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/StatCardSecundariaETom.test.d.ts +1 -0
- package/dist/teste/StatCardSecundariaETom.test.js +45 -0
- package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
- package/dist/teste/TabsContadorFechavel.test.js +79 -0
- package/dist/teste/ToastAcaoEDetalhes.test.d.ts +1 -0
- package/dist/teste/ToastAcaoEDetalhes.test.js +94 -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 +45 -0
- package/dist/utils/html-seguro.js +208 -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/dist/utils/toast.d.ts +10 -1
- package/dist/utils/toast.js +2 -1
- 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/AccordionTituloNeutro.test.tsx +25 -0
- package/src/teste/AppSubheaderRegiao.test.tsx +17 -0
- package/src/teste/AtributosRepassados.test.tsx +73 -0
- package/src/teste/AttachmentCardIA.test.tsx +126 -0
- package/src/teste/AttachmentCardLista.test.tsx +53 -0
- package/src/teste/AttachmentCardSm.test.tsx +29 -0
- package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
- package/src/teste/BadgeNeutroColado.test.tsx +15 -0
- package/src/teste/BadgeTag.test.tsx +85 -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/CalendarCabecalho.test.tsx +11 -0
- package/src/teste/ChipsXs.test.tsx +41 -0
- package/src/teste/Coachmark.test.tsx +198 -0
- package/src/teste/CoachmarkSemVeu.test.tsx +101 -0
- package/src/teste/ColorPicker.test.tsx +153 -0
- package/src/teste/ColorPickerXs.test.tsx +22 -0
- package/src/teste/DataTableArvoreEVariantes.test.tsx +240 -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/DescriptionListCompacta.test.tsx +24 -0
- package/src/teste/EmptyStateTituloRico.test.tsx +34 -0
- package/src/teste/FileInputTrigger.test.tsx +89 -0
- package/src/teste/IconPicker.test.tsx +145 -0
- package/src/teste/InputAgrupado.test.tsx +26 -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/ListItemTooltipStandalone.test.tsx +64 -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/RichTextEditorAlinhaImagemTabela.test.tsx +238 -0
- package/src/teste/RichTextEditorEstiloDeTexto.test.tsx +137 -0
- package/src/teste/SegmentedControlContador.test.tsx +43 -0
- package/src/teste/SelectAbertoControladoEFlutuante.test.tsx +180 -0
- package/src/teste/SelectFiltroCorETamanho.test.tsx +90 -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/StatCardSecundariaETom.test.tsx +51 -0
- package/src/teste/TabsContadorFechavel.test.tsx +144 -0
- package/src/teste/ToastAcaoEDetalhes.test.tsx +109 -0
- package/src/teste/TooltipDark.test.tsx +51 -0
- package/src/utils/calendario.ts +78 -0
- package/src/utils/html-seguro.ts +197 -0
- package/src/utils/paleta-de-cores.ts +34 -0
- package/src/utils/texto.ts +5 -0
- package/src/utils/toast.ts +12 -2
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import './Select.css';
|
|
4
4
|
import { useState, useRef, useEffect } from "react";
|
|
5
5
|
import { faChevronUp, faChevronDown, faMagnifyingGlass, faXmark, faCheck, faTrash, } from "@fortawesome/free-solid-svg-icons";
|
|
6
|
+
import { computePosition, autoUpdate, offset, flip, size, } from "@floating-ui/dom";
|
|
6
7
|
import Text from "../Text/Text";
|
|
7
8
|
import Icon from "../Icon/Icon";
|
|
8
9
|
import Spinner from "../Spinner/Spinner";
|
|
@@ -15,6 +16,10 @@ function Select(props) {
|
|
|
15
16
|
const searchInputRef = useRef(null);
|
|
16
17
|
const outsideWatcherRef = useRef(null);
|
|
17
18
|
const searchTimeoutRef = useRef(null);
|
|
19
|
+
const dropdownRef = useRef(null);
|
|
20
|
+
const floatCleanupRef = useRef(null);
|
|
21
|
+
const latestOpenRef = useRef(false);
|
|
22
|
+
const latestOpenChangeRef = useRef(null);
|
|
18
23
|
function textoDeApoio() {
|
|
19
24
|
return props.helperText || props.description || "";
|
|
20
25
|
}
|
|
@@ -25,16 +30,43 @@ function Select(props) {
|
|
|
25
30
|
return props.readOnly ? "true" : undefined;
|
|
26
31
|
}
|
|
27
32
|
const [isOpen, setIsOpen] = useState(() => false);
|
|
33
|
+
const [prepared, setPrepared] = useState(() => false);
|
|
34
|
+
const [floatMode, setFloatMode] = useState(() => false);
|
|
35
|
+
const [floatReady, setFloatReady] = useState(() => false);
|
|
36
|
+
const [floatX, setFloatX] = useState(() => 0);
|
|
37
|
+
const [floatY, setFloatY] = useState(() => 0);
|
|
38
|
+
const [floatW, setFloatW] = useState(() => 0);
|
|
39
|
+
const [floatMaxH, setFloatMaxH] = useState(() => 0);
|
|
40
|
+
const [listMaxH, setListMaxH] = useState(() => 0);
|
|
28
41
|
const [searchTerm, setSearchTerm] = useState(() => "");
|
|
29
42
|
const [internalSelected, setInternalSelected] = useState(() => Array.isArray(props.defaultValue)
|
|
30
43
|
? props.defaultValue
|
|
31
44
|
: props.defaultValue !== undefined && props.defaultValue !== null
|
|
32
45
|
? [props.defaultValue]
|
|
33
46
|
: Array());
|
|
47
|
+
const [opensUp, setOpensUp] = useState(() => false);
|
|
34
48
|
const [shouldFocusSearch, setShouldFocusSearch] = useState(() => false);
|
|
35
49
|
const [shouldFocusTrigger, setShouldFocusTrigger] = useState(() => false);
|
|
36
50
|
const [activeIndex, setActiveIndex] = useState(() => -1);
|
|
37
51
|
const [uid, setUid] = useState(() => "");
|
|
52
|
+
function opened() {
|
|
53
|
+
if (props.open !== undefined)
|
|
54
|
+
return props.open === "" ? true : !!props.open;
|
|
55
|
+
return isOpen;
|
|
56
|
+
}
|
|
57
|
+
function isFilter() {
|
|
58
|
+
return (props.variant === "filter" ||
|
|
59
|
+
props.variant === "search" ||
|
|
60
|
+
props.variant === "combo");
|
|
61
|
+
}
|
|
62
|
+
function setOpen(next) {
|
|
63
|
+
if (next === opened())
|
|
64
|
+
return;
|
|
65
|
+
if (props.open === undefined)
|
|
66
|
+
setIsOpen(next);
|
|
67
|
+
if (props.onOpenChange)
|
|
68
|
+
props.onOpenChange(next);
|
|
69
|
+
}
|
|
38
70
|
function baseId() {
|
|
39
71
|
return props.id || uid;
|
|
40
72
|
}
|
|
@@ -47,6 +79,9 @@ function Select(props) {
|
|
|
47
79
|
function isInvalid() {
|
|
48
80
|
return !!props.invalid || !!props.errorMessage;
|
|
49
81
|
}
|
|
82
|
+
function ariaRequiredText() {
|
|
83
|
+
return props.required ? "true" : undefined;
|
|
84
|
+
}
|
|
50
85
|
function ariaInvalidText() {
|
|
51
86
|
return isInvalid() ? "true" : undefined;
|
|
52
87
|
}
|
|
@@ -92,6 +127,12 @@ function Select(props) {
|
|
|
92
127
|
: internalSelected || [];
|
|
93
128
|
if (currentVal.length === 0)
|
|
94
129
|
return props.placeholder || "Selecione...";
|
|
130
|
+
// Opção "sem filtro" escolhida: volta a mostrar o nome do filtro.
|
|
131
|
+
if (props.emptyOptionLabel &&
|
|
132
|
+
!props.multiple &&
|
|
133
|
+
currentVal.length === 1 &&
|
|
134
|
+
currentVal[0] === "")
|
|
135
|
+
return props.placeholder || "Selecione...";
|
|
95
136
|
if (props.multiple) {
|
|
96
137
|
if (props.selectionDisplay === "tags")
|
|
97
138
|
return "";
|
|
@@ -109,6 +150,14 @@ function Select(props) {
|
|
|
109
150
|
}
|
|
110
151
|
return String(currentVal[0]);
|
|
111
152
|
}
|
|
153
|
+
function triggerSwatchColor() {
|
|
154
|
+
if (props.triggerSwatch)
|
|
155
|
+
return props.triggerSwatch;
|
|
156
|
+
if (props.multiple || isPlaceholder())
|
|
157
|
+
return undefined;
|
|
158
|
+
const escolhida = selectedOptionsList()[0];
|
|
159
|
+
return escolhida ? escolhida.color : undefined;
|
|
160
|
+
}
|
|
112
161
|
function isPlaceholder() {
|
|
113
162
|
const currentVal = props.value !== undefined
|
|
114
163
|
? Array.isArray(props.value)
|
|
@@ -117,6 +166,11 @@ function Select(props) {
|
|
|
117
166
|
? []
|
|
118
167
|
: [props.value]
|
|
119
168
|
: internalSelected || [];
|
|
169
|
+
if (props.emptyOptionLabel &&
|
|
170
|
+
!props.multiple &&
|
|
171
|
+
currentVal.length === 1 &&
|
|
172
|
+
currentVal[0] === "")
|
|
173
|
+
return true;
|
|
120
174
|
return currentVal.length === 0;
|
|
121
175
|
}
|
|
122
176
|
function formValue() {
|
|
@@ -132,22 +186,40 @@ function Select(props) {
|
|
|
132
186
|
function filteredOptionsList() {
|
|
133
187
|
if (!props.options)
|
|
134
188
|
return [];
|
|
189
|
+
// Opção "sem filtro" no topo (seleção única), sempre visível sem busca.
|
|
190
|
+
const vazia = props.emptyOptionLabel && !props.multiple && !searchTerm
|
|
191
|
+
? [
|
|
192
|
+
{
|
|
193
|
+
label: props.emptyOptionLabel,
|
|
194
|
+
value: "",
|
|
195
|
+
},
|
|
196
|
+
]
|
|
197
|
+
: [];
|
|
135
198
|
// If it's remote search (onSearchChange provided), we don't filter locally
|
|
136
199
|
if (!props.searchable || !searchTerm || props.onSearchChange)
|
|
137
|
-
return props.options;
|
|
200
|
+
return vazia.concat(props.options);
|
|
138
201
|
const term = searchTerm.toLowerCase();
|
|
139
202
|
return props.options.filter((opt) => opt.label.toLowerCase().includes(term));
|
|
140
203
|
}
|
|
141
204
|
function wrapperClassesList() {
|
|
142
205
|
return [
|
|
143
206
|
"umds-select",
|
|
144
|
-
`umds-select--${props.size || "md"}`,
|
|
207
|
+
`umds-select--${props.size || (isFilter() ? "sm" : "md")}`,
|
|
208
|
+
isFilter() && !isPlaceholder() ? "umds-select--has-value" : "",
|
|
145
209
|
props.fullWidth ? "umds-select--full-width" : "",
|
|
146
210
|
props.disabled ? "umds-select--disabled" : "",
|
|
147
211
|
props.readOnly ? "umds-select--readonly" : "",
|
|
148
212
|
props.invalid ? "umds-select--invalid" : "",
|
|
149
|
-
|
|
213
|
+
opened() ? "umds-select--open" : "",
|
|
150
214
|
props.searchVariant === "inline" ? "umds-select--search-inline" : "",
|
|
215
|
+
isFilter() ? "umds-select--filter" : "",
|
|
216
|
+
props.variant === "search" ? "umds-select--filter-search" : "",
|
|
217
|
+
props.variant === "combo" ? "umds-select--filter-combo" : "",
|
|
218
|
+
opened() && floatMode ? "umds-select--floating" : "",
|
|
219
|
+
props.triggerIcon ? "umds-select--has-trigger-icon" : "",
|
|
220
|
+
opensUp && props.searchVariant !== "inline"
|
|
221
|
+
? "umds-select--placement-top"
|
|
222
|
+
: "",
|
|
151
223
|
props.multiple &&
|
|
152
224
|
props.selectionDisplay === "tags" &&
|
|
153
225
|
selectedOptionsList().length > 0
|
|
@@ -164,8 +236,16 @@ function Select(props) {
|
|
|
164
236
|
function labelIdText() {
|
|
165
237
|
return baseId() ? baseId() + "-label" : undefined;
|
|
166
238
|
}
|
|
239
|
+
function comboboxLabelledBy() {
|
|
240
|
+
return props.label && baseId() ? labelIdText() : undefined;
|
|
241
|
+
}
|
|
242
|
+
function comboboxAriaLabel() {
|
|
243
|
+
if (props.ariaLabel)
|
|
244
|
+
return props.ariaLabel;
|
|
245
|
+
return props.label && !baseId() ? props.label : undefined;
|
|
246
|
+
}
|
|
167
247
|
function activeDescendantText() {
|
|
168
|
-
if (!
|
|
248
|
+
if (!opened() || activeIndex < 0 || !baseId())
|
|
169
249
|
return undefined;
|
|
170
250
|
return baseId() + "-option-" + activeIndex;
|
|
171
251
|
}
|
|
@@ -175,23 +255,133 @@ function Select(props) {
|
|
|
175
255
|
function removeItemAriaLabelText(label) {
|
|
176
256
|
return (props.removeAriaLabel || "Remover") + " " + label;
|
|
177
257
|
}
|
|
258
|
+
function insideDialog() {
|
|
259
|
+
if (typeof document === "undefined" ||
|
|
260
|
+
!triggerRef.current ||
|
|
261
|
+
props.searchVariant === "inline")
|
|
262
|
+
return false;
|
|
263
|
+
if (typeof triggerRef.current.closest !== "function")
|
|
264
|
+
return false;
|
|
265
|
+
return !!triggerRef.current.closest('[role="dialog"], [aria-modal="true"]');
|
|
266
|
+
}
|
|
267
|
+
function shouldOpenUp(flutuante) {
|
|
268
|
+
const pedido = props.placement || "bottom";
|
|
269
|
+
setListMaxH(0);
|
|
270
|
+
if (pedido === "top")
|
|
271
|
+
return true;
|
|
272
|
+
if (pedido !== "auto")
|
|
273
|
+
return false;
|
|
274
|
+
if (typeof window === "undefined" || !triggerRef.current)
|
|
275
|
+
return false;
|
|
276
|
+
const caixa = triggerRef.current.getBoundingClientRect();
|
|
277
|
+
let topo = 0;
|
|
278
|
+
let base = window.innerHeight;
|
|
279
|
+
if (!flutuante) {
|
|
280
|
+
let pai = triggerRef.current.parentElement;
|
|
281
|
+
while (pai && pai !== document.body) {
|
|
282
|
+
const corte = window.getComputedStyle(pai).overflowY;
|
|
283
|
+
if (corte === "auto" ||
|
|
284
|
+
corte === "scroll" ||
|
|
285
|
+
corte === "hidden" ||
|
|
286
|
+
corte === "clip") {
|
|
287
|
+
const area = pai.getBoundingClientRect();
|
|
288
|
+
topo = Math.max(topo, area.top);
|
|
289
|
+
base = Math.min(base, area.bottom);
|
|
290
|
+
}
|
|
291
|
+
pai = pai.parentElement;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const abaixo = base - caixa.bottom;
|
|
295
|
+
const acima = caixa.top - topo;
|
|
296
|
+
const opcoes = filteredOptionsList().length;
|
|
297
|
+
const estimada = Math.min(300, opcoes * 36 + 8 + (props.searchable ? 44 : 0) + (props.footer ? 44 : 0));
|
|
298
|
+
const sobe = abaixo < estimada && acima > abaixo;
|
|
299
|
+
const espaco = (sobe ? acima : abaixo) - 8;
|
|
300
|
+
if (espaco < 300)
|
|
301
|
+
setListMaxH(Math.max(96, Math.floor(espaco)));
|
|
302
|
+
return sobe;
|
|
303
|
+
}
|
|
304
|
+
function prepareOpen() {
|
|
305
|
+
setPrepared(true);
|
|
306
|
+
// Local: no React gerado o setState é assíncrono e o estado leria STALE.
|
|
307
|
+
const flutuante = insideDialog();
|
|
308
|
+
setFloatMode(flutuante);
|
|
309
|
+
setFloatReady(false);
|
|
310
|
+
setOpensUp(shouldOpenUp(flutuante));
|
|
311
|
+
// Abre com a opção já selecionada ativa (padrão combobox).
|
|
312
|
+
setActiveIndex(filteredOptionsList().findIndex((opt) => isOptionSelected(opt.value)));
|
|
313
|
+
if (props.searchable &&
|
|
314
|
+
(props.autoFocusSearch || props.searchVariant === "inline" || isFilter())) {
|
|
315
|
+
setShouldFocusSearch(true);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function updateFloat() {
|
|
319
|
+
if (!triggerRef.current || !dropdownRef.current)
|
|
320
|
+
return;
|
|
321
|
+
computePosition(triggerRef.current, dropdownRef.current, {
|
|
322
|
+
strategy: "fixed",
|
|
323
|
+
placement: opensUp ? "top-start" : "bottom-start",
|
|
324
|
+
middleware: [
|
|
325
|
+
offset(4),
|
|
326
|
+
flip({
|
|
327
|
+
fallbackStrategy: "bestFit",
|
|
328
|
+
}),
|
|
329
|
+
size({
|
|
330
|
+
apply({ availableHeight, rects }) {
|
|
331
|
+
setFloatW(rects.reference.width);
|
|
332
|
+
setFloatMaxH(Math.max(96, Math.min(300, Math.floor(availableHeight - 8))));
|
|
333
|
+
},
|
|
334
|
+
}),
|
|
335
|
+
],
|
|
336
|
+
}).then((posicao) => {
|
|
337
|
+
setFloatX(Math.round(posicao.x));
|
|
338
|
+
setFloatY(Math.round(posicao.y));
|
|
339
|
+
setFloatReady(true);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
function dropdownStyle() {
|
|
343
|
+
if (props.searchVariant === "inline")
|
|
344
|
+
return {
|
|
345
|
+
top: "0",
|
|
346
|
+
};
|
|
347
|
+
if (opened() && floatMode) {
|
|
348
|
+
const estilo = {
|
|
349
|
+
position: "fixed",
|
|
350
|
+
top: "0",
|
|
351
|
+
left: "0",
|
|
352
|
+
bottom: "auto",
|
|
353
|
+
transform: "translate(" + floatX + "px, " + floatY + "px)",
|
|
354
|
+
visibility: floatReady ? "visible" : "hidden",
|
|
355
|
+
};
|
|
356
|
+
if (isFilter()) {
|
|
357
|
+
estilo.minWidth =
|
|
358
|
+
"max(" + floatW + "px, calc(var(--umds-primitive-spacing-xxl) * 3))";
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
estilo.width = floatW + "px";
|
|
362
|
+
}
|
|
363
|
+
if (floatMaxH)
|
|
364
|
+
estilo.maxHeight = floatMaxH + "px";
|
|
365
|
+
return estilo;
|
|
366
|
+
}
|
|
367
|
+
return listMaxH
|
|
368
|
+
? {
|
|
369
|
+
maxHeight: listMaxH + "px",
|
|
370
|
+
}
|
|
371
|
+
: {};
|
|
372
|
+
}
|
|
178
373
|
function toggle() {
|
|
179
374
|
if (props.disabled || props.readOnly)
|
|
180
375
|
return;
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
setIsOpen(next);
|
|
376
|
+
// Decide pela variável local: no React gerado o setState é assíncrono e
|
|
377
|
+
// ler o estado logo após atribuí-lo vem STALE.
|
|
378
|
+
const next = !opened();
|
|
379
|
+
setOpen(next);
|
|
186
380
|
if (next) {
|
|
187
|
-
|
|
188
|
-
setActiveIndex(filteredOptionsList().findIndex((opt) => isOptionSelected(opt.value)));
|
|
189
|
-
if (props.searchable &&
|
|
190
|
-
(props.autoFocusSearch || props.searchVariant === "inline")) {
|
|
191
|
-
setShouldFocusSearch(true);
|
|
192
|
-
}
|
|
381
|
+
prepareOpen();
|
|
193
382
|
}
|
|
194
383
|
else {
|
|
384
|
+
setPrepared(false);
|
|
195
385
|
setActiveIndex(-1);
|
|
196
386
|
}
|
|
197
387
|
}
|
|
@@ -224,7 +414,8 @@ function Select(props) {
|
|
|
224
414
|
}
|
|
225
415
|
}
|
|
226
416
|
function closeSearch() {
|
|
227
|
-
|
|
417
|
+
setOpen(false);
|
|
418
|
+
setPrepared(false);
|
|
228
419
|
setSearchTerm("");
|
|
229
420
|
setActiveIndex(-1);
|
|
230
421
|
if (props.onSearchChange) {
|
|
@@ -247,7 +438,7 @@ function Select(props) {
|
|
|
247
438
|
return;
|
|
248
439
|
const key = event.key;
|
|
249
440
|
if (key === "Escape") {
|
|
250
|
-
if (
|
|
441
|
+
if (opened()) {
|
|
251
442
|
event.preventDefault();
|
|
252
443
|
closeSearch();
|
|
253
444
|
}
|
|
@@ -260,7 +451,7 @@ function Select(props) {
|
|
|
260
451
|
return;
|
|
261
452
|
}
|
|
262
453
|
event.preventDefault();
|
|
263
|
-
if (!
|
|
454
|
+
if (!opened()) {
|
|
264
455
|
toggle();
|
|
265
456
|
return;
|
|
266
457
|
}
|
|
@@ -326,7 +517,8 @@ function Select(props) {
|
|
|
326
517
|
else {
|
|
327
518
|
newValue = option.value;
|
|
328
519
|
setInternalSelected([newValue]);
|
|
329
|
-
|
|
520
|
+
setOpen(false);
|
|
521
|
+
setPrepared(false);
|
|
330
522
|
setActiveIndex(-1);
|
|
331
523
|
}
|
|
332
524
|
if (props.onChange) {
|
|
@@ -368,17 +560,31 @@ function Select(props) {
|
|
|
368
560
|
? []
|
|
369
561
|
: [props.value]
|
|
370
562
|
: internalSelected || [];
|
|
563
|
+
// "Sem filtro" aparece marcada enquanto nada está escolhido.
|
|
564
|
+
if (props.emptyOptionLabel && !props.multiple && val === "") {
|
|
565
|
+
return currentVal.length === 0 || currentVal.includes("");
|
|
566
|
+
}
|
|
371
567
|
return currentVal.includes(val);
|
|
372
568
|
}
|
|
373
569
|
useEffect(() => {
|
|
374
570
|
if (!props.id)
|
|
375
571
|
setUid(gerarId("umds-select"));
|
|
572
|
+
// No Vue o onUpdate só roda depois de uma atualização: a lista que já nasce
|
|
573
|
+
// aberta (open controlado) é preparada aqui.
|
|
574
|
+
latestOpenRef.current = opened();
|
|
575
|
+
latestOpenChangeRef.current = props.onOpenChange;
|
|
576
|
+
if (opened() && !prepared)
|
|
577
|
+
prepareOpen();
|
|
376
578
|
if (typeof document === "undefined")
|
|
377
579
|
return;
|
|
378
580
|
const handleClickOutside = (event) => {
|
|
379
581
|
if (selectRef.current &&
|
|
380
582
|
!selectRef.current.contains(event.target)) {
|
|
583
|
+
// Só avisa quando a lista está aberta: o ouvinte vive no document inteiro.
|
|
584
|
+
if (latestOpenRef.current && latestOpenChangeRef.current)
|
|
585
|
+
latestOpenChangeRef.current(false);
|
|
381
586
|
setIsOpen(false);
|
|
587
|
+
setPrepared(false);
|
|
382
588
|
setActiveIndex(-1);
|
|
383
589
|
}
|
|
384
590
|
};
|
|
@@ -386,7 +592,27 @@ function Select(props) {
|
|
|
386
592
|
document.addEventListener("mousedown", handleClickOutside);
|
|
387
593
|
}, []);
|
|
388
594
|
useEffect(() => {
|
|
389
|
-
|
|
595
|
+
// Guarda o estado visto neste render para o ouvinte de clique fora.
|
|
596
|
+
latestOpenRef.current = opened();
|
|
597
|
+
latestOpenChangeRef.current = props.onOpenChange;
|
|
598
|
+
// Aberta de fora (open controlado): aplica os efeitos de abrir uma vez.
|
|
599
|
+
if (opened() && !prepared)
|
|
600
|
+
prepareOpen();
|
|
601
|
+
if (!opened() && prepared)
|
|
602
|
+
setPrepared(false);
|
|
603
|
+
// Lista flutuante: segue o gatilho (scroll, resize) enquanto aberta.
|
|
604
|
+
if (opened() &&
|
|
605
|
+
floatMode &&
|
|
606
|
+
triggerRef.current &&
|
|
607
|
+
dropdownRef.current &&
|
|
608
|
+
!floatCleanupRef.current) {
|
|
609
|
+
floatCleanupRef.current = autoUpdate(triggerRef.current, dropdownRef.current, () => updateFloat());
|
|
610
|
+
}
|
|
611
|
+
if ((!opened() || !floatMode) && floatCleanupRef.current) {
|
|
612
|
+
floatCleanupRef.current();
|
|
613
|
+
floatCleanupRef.current = null;
|
|
614
|
+
}
|
|
615
|
+
if (opened() && shouldFocusSearch) {
|
|
390
616
|
// Retry a few times if ref is not yet ready (though onUpdate usually implies rendered)
|
|
391
617
|
// We use a small timeout to ensure browser paints or simply check ref
|
|
392
618
|
if (searchInputRef.current) {
|
|
@@ -395,7 +621,7 @@ function Select(props) {
|
|
|
395
621
|
}
|
|
396
622
|
}
|
|
397
623
|
// Devolve o foco ao trigger após fechar por Esc/seleção via teclado.
|
|
398
|
-
if (!
|
|
624
|
+
if (!opened() && shouldFocusTrigger) {
|
|
399
625
|
if (triggerRef.current) {
|
|
400
626
|
triggerRef.current.focus();
|
|
401
627
|
setShouldFocusTrigger(false);
|
|
@@ -404,6 +630,10 @@ function Select(props) {
|
|
|
404
630
|
});
|
|
405
631
|
useEffect(() => {
|
|
406
632
|
return () => {
|
|
633
|
+
if (floatCleanupRef.current) {
|
|
634
|
+
floatCleanupRef.current();
|
|
635
|
+
floatCleanupRef.current = null;
|
|
636
|
+
}
|
|
407
637
|
// Cancela o debounce pendente da busca — evita callback após unmount.
|
|
408
638
|
if (searchTimeoutRef.current) {
|
|
409
639
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -417,13 +647,11 @@ function Select(props) {
|
|
|
417
647
|
}
|
|
418
648
|
};
|
|
419
649
|
}, []);
|
|
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: [!(
|
|
650
|
+
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: [!(opened() && 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": opened(), "aria-controls": listboxIdText(), "aria-activedescendant": activeDescendantText(), "aria-labelledby": comboboxLabelledBy(), "aria-label": comboboxAriaLabel(), "aria-invalid": ariaInvalidText(), "aria-required": ariaRequiredText(), "aria-describedby": describedByText(), "aria-disabled": props.disabled ? "true" : undefined, tabIndex: props.disabled ? -1 : 0, children: [_jsxs("div", { className: "umds-select__values", children: [props.triggerIcon ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__trigger-icon", children: _jsx(Icon, { variant: "inherit", customSize: "12px", icon: props.triggerIcon }) })) : null, triggerSwatchColor() ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__swatch", style: {
|
|
651
|
+
background: triggerSwatchColor(),
|
|
652
|
+
} })) : null, displayLabelText() ? (_jsx(Text, { as: "span", variant: "body2", className: isPlaceholder() ? "umds-select__placeholder" : "", children: displayLabelText() })) : null, props.multiple &&
|
|
421
653
|
props.selectionDisplay === "tags" &&
|
|
422
|
-
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:
|
|
423
|
-
? {
|
|
424
|
-
top: "0",
|
|
425
|
-
}
|
|
426
|
-
: {}, onKeyDown: (event) => handleDropdownKeyDown(event), children: [props.searchable ? (_jsxs("div", { className: "umds-select__search-container", children: [_jsx("div", { className: "umds-select__search-icon", children: _jsx(Icon, { size: "sm", icon: faMagnifyingGlass }) }), _jsx("input", { type: "text", className: "umds-select__search-input", ref: searchInputRef, placeholder: props.searchPlaceholder || "Buscar...", "aria-label": props.searchAriaLabel || "Buscar", value: searchTerm, onInput: (e) => handleSearch(e) }), props.searchVariant === "inline" ? (_jsx("button", { type: "button", className: "umds-select__search-close", "aria-label": props.closeSearchAriaLabel || "Fechar busca", onClick: (event) => closeSearch(), onKeyDown: (event) => handleSearchCloseKeyDown(event), children: _jsx(Icon, { size: "sm", icon: faXmark }) })) : null] })) : null, _jsxs("div", { role: "listbox", className: "umds-select__options", id: listboxIdText(), "aria-multiselectable": props.multiple ? "true" : undefined, onScroll: (e) => onScrollList(e), children: [filteredOptionsList().length === 0 && !props.loading ? (_jsx("div", { className: "umds-select__no-options", children: _jsx(Text, { variant: "body2", color: "secondary", children: props.emptyLabel || "Nenhum item encontrado" }) })) : null, filteredOptionsList()?.map((option, index) => (_jsxs("div", { role: "option", id: optionIdText(index), "aria-selected": isOptionSelected(option.value), onClick: (event) => selectOption(option), className: [
|
|
654
|
+
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: opened() ? faChevronUp : faChevronDown }) })] })] })) : null, opened() ? (_jsxs("div", { className: "umds-select__dropdown", ref: dropdownRef, style: dropdownStyle(), onKeyDown: (event) => handleDropdownKeyDown(event), children: [props.searchable ? (_jsxs("div", { className: "umds-select__search-container", children: [_jsx("div", { className: "umds-select__search-icon", children: _jsx(Icon, { size: "sm", icon: faMagnifyingGlass }) }), _jsx("input", { type: "text", className: "umds-select__search-input", ref: searchInputRef, placeholder: props.searchPlaceholder || "Buscar...", "aria-label": props.searchAriaLabel || "Buscar", value: searchTerm, onInput: (e) => handleSearch(e) }), props.searchVariant === "inline" ? (_jsx("button", { type: "button", className: "umds-select__search-close", "aria-label": props.closeSearchAriaLabel || "Fechar busca", onClick: (event) => closeSearch(), onKeyDown: (event) => handleSearchCloseKeyDown(event), children: _jsx(Icon, { size: "sm", icon: faXmark }) })) : null] })) : null, _jsxs("div", { role: "listbox", className: "umds-select__options", id: listboxIdText(), "aria-multiselectable": props.multiple ? "true" : undefined, onScroll: (e) => onScrollList(e), children: [filteredOptionsList().length === 0 && !props.loading ? (_jsx("div", { className: "umds-select__no-options", children: _jsx(Text, { variant: "body2", color: "secondary", children: props.emptyLabel || "Nenhum item encontrado" }) })) : null, filteredOptionsList()?.map((option, index) => (_jsxs("div", { role: "option", id: optionIdText(index), "aria-selected": isOptionSelected(option.value), onClick: (event) => selectOption(option), className: [
|
|
427
655
|
"umds-select__option",
|
|
428
656
|
isOptionSelected(option.value)
|
|
429
657
|
? "umds-select__option--selected"
|
|
@@ -431,7 +659,9 @@ function Select(props) {
|
|
|
431
659
|
index === activeIndex ? "umds-select__option--active" : "",
|
|
432
660
|
]
|
|
433
661
|
.filter(Boolean)
|
|
434
|
-
.join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null,
|
|
662
|
+
.join(" "), children: [props.multiple ? (_jsx("div", { className: "umds-select__option-checkbox", children: _jsx(Checkbox, { checked: isOptionSelected(option.value), decorative: true }) })) : null, option.color ? (_jsx("span", { "aria-hidden": "true", className: "umds-select__swatch", style: {
|
|
663
|
+
background: option.color,
|
|
664
|
+
} })) : 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
665
|
props.selectionDisplay === "list" &&
|
|
436
666
|
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
667
|
}
|
|
@@ -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
|
}
|