@navikt/ds-react 5.7.6 → 5.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/_docs.json +1824 -1758
- package/cjs/accordion/AccordionHeader.js +2 -2
- package/cjs/date/context/useDateInputContext.js +1 -5
- package/cjs/date/datepicker/DatePicker.js +26 -25
- package/cjs/date/hooks/useDatepicker.js +9 -17
- package/cjs/date/hooks/useMonthPicker.js +9 -17
- package/cjs/date/hooks/useRangeDatepicker.js +9 -20
- package/cjs/date/monthpicker/MonthPicker.js +11 -6
- package/cjs/date/{DateInput.js → parts/DateInput.js} +14 -10
- package/cjs/date/parts/DateWrapper.js +55 -0
- package/cjs/date/utils/labels.js +77 -1
- package/cjs/form/combobox/Combobox.js +2 -2
- package/cjs/form/combobox/ComboboxProvider.js +1 -2
- package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
- package/cjs/form/combobox/FilteredOptions/filtered-options-util.js +24 -0
- package/cjs/form/combobox/FilteredOptions/filteredOptionsContext.js +24 -108
- package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js +55 -0
- package/cjs/form/combobox/Input/Input.js +33 -16
- package/cjs/form/combobox/customOptionsContext.js +2 -3
- package/cjs/layout/sidemal-test/Sidebar.js +1 -1
- package/cjs/loader/Loader.js +1 -1
- package/cjs/modal/Modal.js +39 -15
- package/cjs/popover/Popover.js +5 -7
- package/cjs/tooltip/Tooltip.js +14 -3
- package/cjs/util/useMedia.js +30 -0
- package/esm/accordion/AccordionHeader.js +2 -2
- package/esm/accordion/AccordionHeader.js.map +1 -1
- package/esm/date/context/useDateInputContext.d.ts +6 -2
- package/esm/date/context/useDateInputContext.js +1 -5
- package/esm/date/context/useDateInputContext.js.map +1 -1
- package/esm/date/datepicker/DatePicker.d.ts +1 -1
- package/esm/date/datepicker/DatePicker.js +28 -27
- package/esm/date/datepicker/DatePicker.js.map +1 -1
- package/esm/date/datepicker/types.d.ts +0 -5
- package/esm/date/hooks/useDatepicker.d.ts +8 -5
- package/esm/date/hooks/useDatepicker.js +10 -18
- package/esm/date/hooks/useDatepicker.js.map +1 -1
- package/esm/date/hooks/useMonthPicker.d.ts +7 -4
- package/esm/date/hooks/useMonthPicker.js +10 -18
- package/esm/date/hooks/useMonthPicker.js.map +1 -1
- package/esm/date/hooks/useRangeDatepicker.d.ts +9 -3
- package/esm/date/hooks/useRangeDatepicker.js +10 -21
- package/esm/date/hooks/useRangeDatepicker.js.map +1 -1
- package/esm/date/index.d.ts +1 -1
- package/esm/date/index.js.map +1 -1
- package/esm/date/monthpicker/MonthPicker.d.ts +1 -1
- package/esm/date/monthpicker/MonthPicker.js +13 -8
- package/esm/date/monthpicker/MonthPicker.js.map +1 -1
- package/esm/date/monthpicker/types.d.ts +0 -5
- package/esm/date/{DateInput.d.ts → parts/DateInput.d.ts} +5 -1
- package/esm/date/{DateInput.js → parts/DateInput.js} +15 -11
- package/esm/date/parts/DateInput.js.map +1 -0
- package/esm/date/parts/DateWrapper.d.ts +15 -0
- package/esm/date/parts/DateWrapper.js +26 -0
- package/esm/date/parts/DateWrapper.js.map +1 -0
- package/esm/date/utils/labels.d.ts +2 -0
- package/esm/date/utils/labels.js +74 -0
- package/esm/date/utils/labels.js.map +1 -1
- package/esm/form/combobox/Combobox.js +2 -2
- package/esm/form/combobox/Combobox.js.map +1 -1
- package/esm/form/combobox/ComboboxProvider.js +1 -2
- package/esm/form/combobox/ComboboxProvider.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js +15 -14
- package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/filtered-options-util.d.ts +12 -0
- package/esm/form/combobox/FilteredOptions/filtered-options-util.js +23 -0
- package/esm/form/combobox/FilteredOptions/filtered-options-util.js.map +1 -0
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.d.ts +10 -13
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js +25 -109
- package/esm/form/combobox/FilteredOptions/filteredOptionsContext.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.d.ts +15 -0
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js +54 -0
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -0
- package/esm/form/combobox/Input/Input.js +33 -16
- package/esm/form/combobox/Input/Input.js.map +1 -1
- package/esm/form/combobox/customOptionsContext.d.ts +4 -1
- package/esm/form/combobox/customOptionsContext.js +2 -3
- package/esm/form/combobox/customOptionsContext.js.map +1 -1
- package/esm/layout/bleed/Bleed.d.ts +1 -1
- package/esm/layout/bleed/Bleed.js +1 -1
- package/esm/layout/bleed/Bleed.js.map +1 -1
- package/esm/layout/box/Box.d.ts +1 -2
- package/esm/layout/box/Box.js +1 -1
- package/esm/layout/box/Box.js.map +1 -1
- package/esm/layout/grid/HGrid.d.ts +1 -1
- package/esm/layout/grid/HGrid.js +1 -1
- package/esm/layout/grid/HGrid.js.map +1 -1
- package/esm/layout/responsive/Responsive.d.ts +1 -1
- package/esm/layout/sidemal-test/Sidebar.js +1 -1
- package/esm/layout/sidemal-test/Sidebar.js.map +1 -1
- package/esm/layout/stack/Stack.d.ts +1 -1
- package/esm/layout/stack/Stack.js +1 -1
- package/esm/layout/stack/Stack.js.map +1 -1
- package/esm/layout/utilities/css.d.ts +1 -8
- package/esm/layout/utilities/css.js.map +1 -1
- package/esm/layout/utilities/types.d.ts +9 -0
- package/esm/loader/Loader.d.ts +1 -1
- package/esm/loader/Loader.js +1 -1
- package/esm/modal/Modal.js +39 -15
- package/esm/modal/Modal.js.map +1 -1
- package/esm/modal/ModalContext.d.ts +1 -0
- package/esm/modal/ModalContext.js.map +1 -1
- package/esm/modal/types.d.ts +7 -0
- package/esm/popover/Popover.d.ts +0 -5
- package/esm/popover/Popover.js +5 -7
- package/esm/popover/Popover.js.map +1 -1
- package/esm/tooltip/Tooltip.js +16 -5
- package/esm/tooltip/Tooltip.js.map +1 -1
- package/esm/util/useMedia.d.ts +8 -0
- package/esm/util/useMedia.js +27 -0
- package/esm/util/useMedia.js.map +1 -0
- package/package.json +3 -3
- package/src/accordion/AccordionHeader.tsx +3 -3
- package/src/date/context/useDateInputContext.tsx +5 -5
- package/src/date/datepicker/DatePicker.tsx +58 -65
- package/src/date/datepicker/datepicker.stories.tsx +37 -46
- package/src/date/datepicker/types.ts +0 -5
- package/src/date/hooks/useDatepicker.tsx +20 -25
- package/src/date/hooks/useMonthPicker.tsx +18 -24
- package/src/date/hooks/useRangeDatepicker.tsx +27 -30
- package/src/date/index.ts +1 -1
- package/src/date/monthpicker/MonthPicker.tsx +39 -43
- package/src/date/monthpicker/types.ts +0 -5
- package/src/date/{DateInput.tsx → parts/DateInput.tsx} +23 -12
- package/src/date/parts/DateWrapper.tsx +80 -0
- package/src/date/utils/labels.ts +83 -0
- package/src/form/combobox/Combobox.tsx +2 -2
- package/src/form/combobox/ComboboxProvider.tsx +1 -2
- package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +28 -16
- package/src/form/combobox/FilteredOptions/filtered-options-util.ts +38 -0
- package/src/form/combobox/FilteredOptions/filteredOptionsContext.tsx +71 -142
- package/src/form/combobox/FilteredOptions/useVirtualFocus.ts +87 -0
- package/src/form/combobox/Input/Input.tsx +40 -21
- package/src/form/combobox/combobox.stories.tsx +44 -0
- package/src/form/combobox/customOptionsContext.tsx +10 -5
- package/src/guide-panel/guidepanel.stories.tsx +2 -2
- package/src/layout/bleed/Bleed.tsx +2 -5
- package/src/layout/box/Box.tsx +1 -3
- package/src/layout/grid/HGrid.tsx +2 -6
- package/src/layout/responsive/Responsive.tsx +1 -1
- package/src/layout/sidemal-test/Sidebar.tsx +1 -1
- package/src/layout/stack/Stack.tsx +2 -6
- package/src/layout/utilities/css.ts +1 -36
- package/src/layout/utilities/types.ts +16 -0
- package/src/loader/Loader.tsx +1 -1
- package/src/modal/Modal.tsx +54 -21
- package/src/modal/ModalContext.ts +1 -0
- package/src/modal/modal.stories.tsx +30 -2
- package/src/modal/types.ts +7 -0
- package/src/popover/Popover.tsx +4 -12
- package/src/tooltip/Tooltip.tsx +18 -6
- package/src/util/__tests__/useMedia.test.tsx +19 -0
- package/src/util/useMedia.ts +38 -0
- package/cjs/date/hooks/useEscape.js +0 -23
- package/cjs/date/hooks/useOutsideClickHandler.js +0 -26
- package/esm/date/DateInput.js.map +0 -1
- package/esm/date/hooks/useEscape.d.ts +0 -2
- package/esm/date/hooks/useEscape.js +0 -20
- package/esm/date/hooks/useEscape.js.map +0 -1
- package/esm/date/hooks/useOutsideClickHandler.d.ts +0 -1
- package/esm/date/hooks/useOutsideClickHandler.js +0 -23
- package/esm/date/hooks/useOutsideClickHandler.js.map +0 -1
- package/src/date/hooks/useEscape.tsx +0 -30
- package/src/date/hooks/useOutsideClickHandler.tsx +0 -34
|
@@ -78,7 +78,7 @@ const ComboboxProvider = (0, react_1.forwardRef)((props, ref) => {
|
|
|
78
78
|
shouldAutocomplete,
|
|
79
79
|
size,
|
|
80
80
|
} },
|
|
81
|
-
react_1.default.createElement(customOptionsContext_1.CustomOptionsProvider,
|
|
81
|
+
react_1.default.createElement(customOptionsContext_1.CustomOptionsProvider, { value: { isMultiSelect } },
|
|
82
82
|
react_1.default.createElement(selectedOptionsContext_1.SelectedOptionsProvider, { value: {
|
|
83
83
|
allowNewValues,
|
|
84
84
|
isMultiSelect,
|
|
@@ -91,7 +91,6 @@ const ComboboxProvider = (0, react_1.forwardRef)((props, ref) => {
|
|
|
91
91
|
filteredOptions,
|
|
92
92
|
isListOpen,
|
|
93
93
|
isLoading,
|
|
94
|
-
isMultiSelect,
|
|
95
94
|
options,
|
|
96
95
|
} },
|
|
97
96
|
react_1.default.createElement(Combobox_1.default, Object.assign({ ref: ref }, rest), children))))));
|
|
@@ -11,27 +11,28 @@ const selectedOptionsContext_1 = require("../SelectedOptions/selectedOptionsCont
|
|
|
11
11
|
const inputContext_1 = require("../Input/inputContext");
|
|
12
12
|
const loader_1 = require("../../../loader");
|
|
13
13
|
const typography_1 = require("../../../typography");
|
|
14
|
+
const filtered_options_util_1 = __importDefault(require("./filtered-options-util"));
|
|
14
15
|
const FilteredOptions = () => {
|
|
15
16
|
const { inputProps: { id }, size, value, } = (0, inputContext_1.useInputContext)();
|
|
16
|
-
const { allowNewValues, isLoading, isListOpen, filteredOptions,
|
|
17
|
+
const { allowNewValues, isLoading, isListOpen, filteredOptions, setFilteredOptionsRef, isMouseLastUsedInputDevice, setIsMouseLastUsedInputDevice, isValueNew, toggleIsListOpen, activeDecendantId, virtualFocus, } = (0, filteredOptionsContext_1.useFilteredOptionsContext)();
|
|
17
18
|
const { isMultiSelect, selectedOptions, toggleOption } = (0, selectedOptionsContext_1.useSelectedOptionsContext)();
|
|
18
|
-
return (react_1.default.createElement("ul", { ref:
|
|
19
|
+
return (react_1.default.createElement("ul", { ref: setFilteredOptionsRef, className: (0, clsx_1.default)("navds-combobox__list", {
|
|
19
20
|
"navds-combobox__list--closed": !isListOpen,
|
|
20
21
|
"navds-combobox__list--with-hover": isMouseLastUsedInputDevice,
|
|
21
|
-
}), id:
|
|
22
|
-
isLoading && (react_1.default.createElement("li", { className: "navds-combobox__list-item--loading", role: "option", "aria-selected": false, id:
|
|
22
|
+
}), id: filtered_options_util_1.default.getFilteredOptionsId(id), role: "listbox", tabIndex: -1 },
|
|
23
|
+
isLoading && (react_1.default.createElement("li", { className: "navds-combobox__list-item--loading", role: "option", "aria-selected": false, id: filtered_options_util_1.default.getIsLoadingId(id), "data-no-focus": "true" },
|
|
23
24
|
react_1.default.createElement(loader_1.Loader, { "aria-label": "S\u00F8ker..." }))),
|
|
24
25
|
isValueNew && allowNewValues && (react_1.default.createElement("li", { tabIndex: -1, onMouseMove: () => {
|
|
25
|
-
if (
|
|
26
|
-
|
|
26
|
+
if (activeDecendantId !== filtered_options_util_1.default.getAddNewOptionId(id)) {
|
|
27
|
+
virtualFocus.moveFocusToElement(filtered_options_util_1.default.getAddNewOptionId(id));
|
|
27
28
|
setIsMouseLastUsedInputDevice(true);
|
|
28
29
|
}
|
|
29
30
|
}, onPointerUp: (event) => {
|
|
30
31
|
toggleOption(value, event);
|
|
31
32
|
if (!isMultiSelect && !selectedOptions.includes(value))
|
|
32
33
|
toggleIsListOpen(false);
|
|
33
|
-
}, id:
|
|
34
|
-
"navds-combobox__list-item__new-option--focus":
|
|
34
|
+
}, id: filtered_options_util_1.default.getAddNewOptionId(id), className: (0, clsx_1.default)("navds-combobox__list-item__new-option", {
|
|
35
|
+
"navds-combobox__list-item__new-option--focus": activeDecendantId === filtered_options_util_1.default.getAddNewOptionId(id),
|
|
35
36
|
}), role: "option", "aria-selected": false },
|
|
36
37
|
react_1.default.createElement(aksel_icons_1.PlusIcon, { "aria-hidden": true }),
|
|
37
38
|
react_1.default.createElement(typography_1.BodyShort, { size: size },
|
|
@@ -41,13 +42,13 @@ const FilteredOptions = () => {
|
|
|
41
42
|
"\u201C",
|
|
42
43
|
value,
|
|
43
44
|
"\u201D")))),
|
|
44
|
-
!isLoading && filteredOptions.length === 0 && (react_1.default.createElement("li", { className: "navds-combobox__list-item__no-options", role: "option", "aria-selected": false, id:
|
|
45
|
-
filteredOptions.map((option
|
|
46
|
-
"navds-combobox__list-item--focus":
|
|
45
|
+
!isLoading && filteredOptions.length === 0 && (react_1.default.createElement("li", { className: "navds-combobox__list-item__no-options", role: "option", "aria-selected": false, id: filtered_options_util_1.default.getNoHitsId(id), "data-no-focus": "true" }, "Ingen s\u00F8ketreff")),
|
|
46
|
+
filteredOptions.map((option) => (react_1.default.createElement("li", { className: (0, clsx_1.default)("navds-combobox__list-item", {
|
|
47
|
+
"navds-combobox__list-item--focus": activeDecendantId === filtered_options_util_1.default.getOptionId(id, option),
|
|
47
48
|
"navds-combobox__list-item--selected": selectedOptions.includes(option),
|
|
48
|
-
}), id:
|
|
49
|
-
if (
|
|
50
|
-
|
|
49
|
+
}), id: filtered_options_util_1.default.getOptionId(id, option), key: option, tabIndex: -1, onMouseMove: () => {
|
|
50
|
+
if (activeDecendantId !== filtered_options_util_1.default.getOptionId(id, option)) {
|
|
51
|
+
virtualFocus.moveFocusToElement(filtered_options_util_1.default.getOptionId(id, option));
|
|
51
52
|
setIsMouseLastUsedInputDevice(true);
|
|
52
53
|
}
|
|
53
54
|
}, onPointerUp: (event) => {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const normalizeText = (text) => typeof text === "string" ? text.toLocaleLowerCase().trim() : "";
|
|
4
|
+
const isPartOfText = (value, text) => normalizeText(text).startsWith(normalizeText(value !== null && value !== void 0 ? value : ""));
|
|
5
|
+
const isValueInList = (value, list) => list === null || list === void 0 ? void 0 : list.find((listItem) => normalizeText(value) === normalizeText(listItem));
|
|
6
|
+
const getMatchingValuesFromList = (value, list) => list === null || list === void 0 ? void 0 : list.filter((listItem) => isPartOfText(value, listItem));
|
|
7
|
+
const getFilteredOptionsId = (comboboxId) => `${comboboxId}-filtered-options`;
|
|
8
|
+
const getOptionId = (comboboxId, option) => `${comboboxId.toLocaleLowerCase()}-option-${option
|
|
9
|
+
.replace(" ", "-")
|
|
10
|
+
.toLocaleLowerCase()}`;
|
|
11
|
+
const getAddNewOptionId = (comboboxId) => `${comboboxId}-combobox-new-option`;
|
|
12
|
+
const getIsLoadingId = (comboboxId) => `${comboboxId}-is-loading`;
|
|
13
|
+
const getNoHitsId = (comboboxId) => `${comboboxId}-no-hits`;
|
|
14
|
+
exports.default = {
|
|
15
|
+
normalizeText,
|
|
16
|
+
isPartOfText,
|
|
17
|
+
isValueInList,
|
|
18
|
+
getMatchingValuesFromList,
|
|
19
|
+
getFilteredOptionsId,
|
|
20
|
+
getAddNewOptionId,
|
|
21
|
+
getOptionId,
|
|
22
|
+
getIsLoadingId,
|
|
23
|
+
getNoHitsId,
|
|
24
|
+
};
|
|
@@ -33,16 +33,14 @@ const customOptionsContext_1 = require("../customOptionsContext");
|
|
|
33
33
|
const inputContext_1 = require("../Input/inputContext");
|
|
34
34
|
const usePrevious_1 = __importDefault(require("../../../util/usePrevious"));
|
|
35
35
|
const util_1 = require("../../../util");
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const isValueInList = (value, list) => list === null || list === void 0 ? void 0 : list.find((listItem) => normalizeText(value) === normalizeText(listItem));
|
|
39
|
-
const getMatchingValuesFromList = (value, list) => list === null || list === void 0 ? void 0 : list.filter((listItem) => isPartOfText(value, listItem));
|
|
36
|
+
const filtered_options_util_1 = __importDefault(require("./filtered-options-util"));
|
|
37
|
+
const useVirtualFocus_1 = __importDefault(require("./useVirtualFocus"));
|
|
40
38
|
const FilteredOptionsContext = (0, react_1.createContext)({});
|
|
41
|
-
const FilteredOptionsProvider = ({ children, value: props }) => {
|
|
39
|
+
const FilteredOptionsProvider = ({ children, value: props, }) => {
|
|
42
40
|
const { allowNewValues, filteredOptions: externalFilteredOptions, isListOpen: isExternalListOpen, isLoading, options, } = props;
|
|
43
|
-
const filteredOptionsRef = (0, react_1.
|
|
41
|
+
const [filteredOptionsRef, setFilteredOptionsRef] = (0, react_1.useState)(null);
|
|
42
|
+
const virtualFocus = (0, useVirtualFocus_1.default)(filteredOptionsRef);
|
|
44
43
|
const { inputProps: { "aria-describedby": partialAriaDescribedBy, id }, value, searchTerm, setValue, setSearchTerm, shouldAutocomplete, } = (0, inputContext_1.useInputContext)();
|
|
45
|
-
const [filteredOptionsIndex, setFilteredOptionsIndex] = (0, react_1.useState)(null);
|
|
46
44
|
const [isInternalListOpen, setInternalListOpen] = (0, react_1.useState)(false);
|
|
47
45
|
const { customOptions } = (0, customOptionsContext_1.useCustomOptionsContext)();
|
|
48
46
|
const filteredOptions = (0, react_1.useMemo)(() => {
|
|
@@ -50,17 +48,20 @@ const FilteredOptionsProvider = ({ children, value: props }) => {
|
|
|
50
48
|
return externalFilteredOptions;
|
|
51
49
|
}
|
|
52
50
|
const opts = [...customOptions, ...options];
|
|
53
|
-
|
|
54
|
-
return getMatchingValuesFromList(searchTerm, opts);
|
|
51
|
+
return filtered_options_util_1.default.getMatchingValuesFromList(searchTerm, opts);
|
|
55
52
|
}, [customOptions, externalFilteredOptions, options, searchTerm]);
|
|
56
53
|
const previousSearchTerm = (0, usePrevious_1.default)(searchTerm);
|
|
57
54
|
const [isMouseLastUsedInputDevice, setIsMouseLastUsedInputDevice] = (0, react_1.useState)(false);
|
|
55
|
+
const filteredOptionsMap = (0, react_1.useMemo)(() => options.reduce((map, _option) => (Object.assign(Object.assign({}, map), { [filtered_options_util_1.default.getOptionId(id, _option)]: _option })), {
|
|
56
|
+
[filtered_options_util_1.default.getAddNewOptionId(id)]: allowNewValues
|
|
57
|
+
? value
|
|
58
|
+
: undefined,
|
|
59
|
+
}), [allowNewValues, id, options, value]);
|
|
58
60
|
(0, util_1.useClientLayoutEffect)(() => {
|
|
59
61
|
if (shouldAutocomplete &&
|
|
60
|
-
normalizeText(searchTerm) !== "" &&
|
|
62
|
+
filtered_options_util_1.default.normalizeText(searchTerm) !== "" &&
|
|
61
63
|
((previousSearchTerm === null || previousSearchTerm === void 0 ? void 0 : previousSearchTerm.length) || 0) < searchTerm.length &&
|
|
62
|
-
filteredOptions.length > 0
|
|
63
|
-
!isValueInList(searchTerm, filteredOptions)) {
|
|
64
|
+
filteredOptions.length > 0) {
|
|
64
65
|
setValue(`${searchTerm}${filteredOptions[0].substring(searchTerm.length)}`);
|
|
65
66
|
setSearchTerm(searchTerm);
|
|
66
67
|
}
|
|
@@ -76,24 +77,22 @@ const FilteredOptionsProvider = ({ children, value: props }) => {
|
|
|
76
77
|
return isExternalListOpen !== null && isExternalListOpen !== void 0 ? isExternalListOpen : isInternalListOpen;
|
|
77
78
|
}, [isExternalListOpen, isInternalListOpen]);
|
|
78
79
|
const toggleIsListOpen = (0, react_1.useCallback)((newState) => {
|
|
79
|
-
|
|
80
|
+
virtualFocus.moveFocusToTop();
|
|
80
81
|
setInternalListOpen((oldState) => newState !== null && newState !== void 0 ? newState : !oldState);
|
|
81
|
-
}, []);
|
|
82
|
-
const isValueNew = (0, react_1.useMemo)(() => Boolean(value) &&
|
|
83
|
-
|
|
84
|
-
return isValueNew && allowNewValues ? -1 : 0;
|
|
85
|
-
}, [allowNewValues, isValueNew]);
|
|
82
|
+
}, [virtualFocus]);
|
|
83
|
+
const isValueNew = (0, react_1.useMemo)(() => Boolean(value) &&
|
|
84
|
+
!filteredOptionsMap[filtered_options_util_1.default.getOptionId(id, value)], [filteredOptionsMap, id, value]);
|
|
86
85
|
const ariaDescribedBy = (0, react_1.useMemo)(() => {
|
|
87
86
|
let activeOption;
|
|
88
87
|
if (!isLoading && filteredOptions.length === 0) {
|
|
89
|
-
activeOption =
|
|
88
|
+
activeOption = filtered_options_util_1.default.getNoHitsId(id);
|
|
90
89
|
}
|
|
91
90
|
else if ((value && value !== "") || isLoading) {
|
|
92
91
|
if (shouldAutocomplete && filteredOptions[0]) {
|
|
93
|
-
activeOption =
|
|
92
|
+
activeOption = filtered_options_util_1.default.getOptionId(id, filteredOptions[0]);
|
|
94
93
|
}
|
|
95
94
|
else if (isListOpen && isLoading) {
|
|
96
|
-
activeOption =
|
|
95
|
+
activeOption = filtered_options_util_1.default.getIsLoadingId(id);
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
98
|
return (0, clsx_1.default)(activeOption, partialAriaDescribedBy) || undefined;
|
|
@@ -106,91 +105,12 @@ const FilteredOptionsProvider = ({ children, value: props }) => {
|
|
|
106
105
|
filteredOptions,
|
|
107
106
|
id,
|
|
108
107
|
]);
|
|
109
|
-
const currentOption = (0, react_1.useMemo)(() => {
|
|
110
|
-
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
if (filteredOptionsIndex === -1) {
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
return filteredOptions[filteredOptionsIndex];
|
|
117
|
-
}, [filteredOptionsIndex, filteredOptions, value]);
|
|
118
|
-
const resetFilteredOptionsIndex = () => {
|
|
119
|
-
setFilteredOptionsIndex(getMinimumIndex());
|
|
120
|
-
};
|
|
121
|
-
const scrollToOption = (0, react_1.useCallback)((newIndex) => {
|
|
122
|
-
if (filteredOptionsRef.current &&
|
|
123
|
-
filteredOptionsRef.current.children[newIndex]) {
|
|
124
|
-
const child = filteredOptionsRef.current.children[newIndex];
|
|
125
|
-
const { top, bottom } = child.getBoundingClientRect();
|
|
126
|
-
const parentRect = filteredOptionsRef.current.getBoundingClientRect();
|
|
127
|
-
if (top < parentRect.top || bottom > parentRect.bottom) {
|
|
128
|
-
child.scrollIntoView({ block: "nearest" });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}, []);
|
|
132
|
-
(0, react_1.useEffect)(() => {
|
|
133
|
-
if (filteredOptionsIndex !== null && isListOpen) {
|
|
134
|
-
scrollToOption(filteredOptionsIndex);
|
|
135
|
-
}
|
|
136
|
-
}, [filteredOptionsIndex, isListOpen, scrollToOption]);
|
|
137
|
-
const moveFocusToInput = (0, react_1.useCallback)(() => {
|
|
138
|
-
setFilteredOptionsIndex(null);
|
|
139
|
-
toggleIsListOpen(false);
|
|
140
|
-
}, [toggleIsListOpen]);
|
|
141
|
-
const moveFocusToEnd = (0, react_1.useCallback)(() => {
|
|
142
|
-
const lastIndex = filteredOptions.length - 1;
|
|
143
|
-
toggleIsListOpen(true);
|
|
144
|
-
setFilteredOptionsIndex(lastIndex);
|
|
145
|
-
}, [filteredOptions.length, toggleIsListOpen]);
|
|
146
|
-
const moveFocusUp = (0, react_1.useCallback)(() => {
|
|
147
|
-
if (filteredOptionsIndex === null) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
if (filteredOptionsIndex === getMinimumIndex()) {
|
|
151
|
-
toggleIsListOpen(false);
|
|
152
|
-
setFilteredOptionsIndex(null);
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
const newIndex = Math.max(getMinimumIndex(), filteredOptionsIndex - 1);
|
|
156
|
-
setFilteredOptionsIndex(newIndex);
|
|
157
|
-
}
|
|
158
|
-
}, [filteredOptionsIndex, getMinimumIndex, toggleIsListOpen]);
|
|
159
|
-
const moveFocusDown = (0, react_1.useCallback)(() => {
|
|
160
|
-
if (filteredOptionsIndex === null || !isListOpen) {
|
|
161
|
-
toggleIsListOpen(true);
|
|
162
|
-
if (allowNewValues || filteredOptions.length >= 1) {
|
|
163
|
-
setFilteredOptionsIndex(getMinimumIndex());
|
|
164
|
-
}
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const newIndex = Math.min(filteredOptionsIndex + 1, Math.max(getMinimumIndex(), filteredOptions.length - 1));
|
|
168
|
-
setFilteredOptionsIndex(newIndex);
|
|
169
|
-
}, [
|
|
170
|
-
allowNewValues,
|
|
171
|
-
filteredOptions.length,
|
|
172
|
-
filteredOptionsIndex,
|
|
173
|
-
getMinimumIndex,
|
|
174
|
-
isListOpen,
|
|
175
|
-
toggleIsListOpen,
|
|
176
|
-
]);
|
|
177
|
-
const activeDecendantId = (0, react_1.useMemo)(() => {
|
|
178
|
-
if (filteredOptionsIndex === null) {
|
|
179
|
-
return undefined;
|
|
180
|
-
}
|
|
181
|
-
else if (filteredOptionsIndex === -1) {
|
|
182
|
-
return `${id}-combobox-new-option`;
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
return `${id}-option-${currentOption === null || currentOption === void 0 ? void 0 : currentOption.replace(" ", "-")}`;
|
|
186
|
-
}
|
|
187
|
-
}, [filteredOptionsIndex, currentOption, id]);
|
|
108
|
+
const currentOption = (0, react_1.useMemo)(() => { var _a; return filteredOptionsMap[((_a = virtualFocus.activeElement) === null || _a === void 0 ? void 0 : _a.getAttribute("id")) || -1]; }, [filteredOptionsMap, virtualFocus]);
|
|
109
|
+
const activeDecendantId = (0, react_1.useMemo)(() => { var _a; return ((_a = virtualFocus.activeElement) === null || _a === void 0 ? void 0 : _a.getAttribute("id")) || undefined; }, [virtualFocus.activeElement]);
|
|
188
110
|
const filteredOptionsState = {
|
|
189
111
|
activeDecendantId,
|
|
190
112
|
allowNewValues,
|
|
191
|
-
|
|
192
|
-
filteredOptionsIndex,
|
|
193
|
-
setFilteredOptionsIndex,
|
|
113
|
+
setFilteredOptionsRef,
|
|
194
114
|
shouldAutocomplete,
|
|
195
115
|
isListOpen,
|
|
196
116
|
isLoading,
|
|
@@ -200,11 +120,7 @@ const FilteredOptionsProvider = ({ children, value: props }) => {
|
|
|
200
120
|
isValueNew,
|
|
201
121
|
toggleIsListOpen,
|
|
202
122
|
currentOption,
|
|
203
|
-
|
|
204
|
-
moveFocusUp,
|
|
205
|
-
moveFocusDown,
|
|
206
|
-
moveFocusToInput,
|
|
207
|
-
moveFocusToEnd,
|
|
123
|
+
virtualFocus,
|
|
208
124
|
ariaDescribedBy,
|
|
209
125
|
};
|
|
210
126
|
return (react_1.default.createElement(FilteredOptionsContext.Provider, { value: filteredOptionsState }, children));
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
const useVirtualFocus = (containerRef) => {
|
|
5
|
+
const [index, setIndex] = (0, react_1.useState)(-1);
|
|
6
|
+
const listOfAllChildren = (containerRef === null || containerRef === void 0 ? void 0 : containerRef.children)
|
|
7
|
+
? Array.prototype.slice.call(containerRef === null || containerRef === void 0 ? void 0 : containerRef.children)
|
|
8
|
+
: [];
|
|
9
|
+
const elementsAbleToReceiveFocus = listOfAllChildren.filter((child) => child.getAttribute("data-no-focus") !== "true");
|
|
10
|
+
const activeElement = elementsAbleToReceiveFocus[index];
|
|
11
|
+
const getElementById = (id) => listOfAllChildren.find((element) => element.id === id);
|
|
12
|
+
const isFocusOnTheTop = index === 0;
|
|
13
|
+
const isFocusOnTheBottom = index === elementsAbleToReceiveFocus.length - 1;
|
|
14
|
+
const scrollToOption = (newIndex) => {
|
|
15
|
+
const indexOfElementToScrollTo = Math.min(Math.max(newIndex, 0), (containerRef === null || containerRef === void 0 ? void 0 : containerRef.children.length) || 0);
|
|
16
|
+
if (containerRef === null || containerRef === void 0 ? void 0 : containerRef.children[indexOfElementToScrollTo]) {
|
|
17
|
+
const child = containerRef.children[indexOfElementToScrollTo];
|
|
18
|
+
const { top, bottom } = child.getBoundingClientRect();
|
|
19
|
+
const parentRect = containerRef.getBoundingClientRect();
|
|
20
|
+
if (top < parentRect.top || bottom > parentRect.bottom) {
|
|
21
|
+
child.scrollIntoView({ block: "nearest" });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const _moveFocusAndScrollTo = (_index) => {
|
|
26
|
+
setIndex(_index);
|
|
27
|
+
scrollToOption(_index);
|
|
28
|
+
};
|
|
29
|
+
const moveFocusUp = () => _moveFocusAndScrollTo(Math.max(index - 1, -1));
|
|
30
|
+
const moveFocusDown = () => _moveFocusAndScrollTo(Math.min(index + 1, elementsAbleToReceiveFocus.length - 1));
|
|
31
|
+
const moveFocusToTop = () => _moveFocusAndScrollTo(-1);
|
|
32
|
+
const moveFocusToBottom = () => _moveFocusAndScrollTo(elementsAbleToReceiveFocus.length - 1);
|
|
33
|
+
const moveFocusToElement = (id) => {
|
|
34
|
+
const thisElement = elementsAbleToReceiveFocus.find((_element) => _element.getAttribute("id") === id);
|
|
35
|
+
const indexOfElement = thisElement
|
|
36
|
+
? elementsAbleToReceiveFocus.indexOf(thisElement)
|
|
37
|
+
: -1;
|
|
38
|
+
if (indexOfElement >= 0) {
|
|
39
|
+
setIndex(indexOfElement);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
activeElement,
|
|
44
|
+
getElementById,
|
|
45
|
+
isFocusOnTheTop,
|
|
46
|
+
isFocusOnTheBottom,
|
|
47
|
+
setIndex,
|
|
48
|
+
moveFocusUp,
|
|
49
|
+
moveFocusDown,
|
|
50
|
+
moveFocusToElement,
|
|
51
|
+
moveFocusToTop,
|
|
52
|
+
moveFocusToBottom,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
exports.default = useVirtualFocus;
|
|
@@ -43,20 +43,25 @@ const clsx_1 = __importDefault(require("clsx"));
|
|
|
43
43
|
const selectedOptionsContext_1 = require("../SelectedOptions/selectedOptionsContext");
|
|
44
44
|
const filteredOptionsContext_1 = require("../FilteredOptions/filteredOptionsContext");
|
|
45
45
|
const inputContext_1 = require("./inputContext");
|
|
46
|
+
const filtered_options_util_1 = __importDefault(require("../FilteredOptions/filtered-options-util"));
|
|
46
47
|
const Input = (0, react_1.forwardRef)((_a, ref) => {
|
|
47
48
|
var { inputClassName } = _a, rest = __rest(_a, ["inputClassName"]);
|
|
48
49
|
const { clearInput, inputProps, onChange, size, value } = (0, inputContext_1.useInputContext)();
|
|
49
50
|
const { selectedOptions, removeSelectedOption, toggleOption, isMultiSelect, } = (0, selectedOptionsContext_1.useSelectedOptionsContext)();
|
|
50
|
-
const { activeDecendantId, allowNewValues, currentOption, filteredOptions, toggleIsListOpen, isListOpen,
|
|
51
|
+
const { activeDecendantId, allowNewValues, currentOption, filteredOptions, isValueNew, toggleIsListOpen, isListOpen, ariaDescribedBy, setIsMouseLastUsedInputDevice, shouldAutocomplete, virtualFocus, } = (0, filteredOptionsContext_1.useFilteredOptionsContext)();
|
|
51
52
|
const onEnter = (0, react_1.useCallback)((event) => {
|
|
53
|
+
const isTextInSelectedOptions = (text) => {
|
|
54
|
+
return selectedOptions.find((item) => item.toLocaleLowerCase() === text.toLocaleLowerCase());
|
|
55
|
+
};
|
|
52
56
|
if (currentOption) {
|
|
53
57
|
event.preventDefault();
|
|
54
58
|
// Selecting a value from the dropdown / FilteredOptions
|
|
55
59
|
toggleOption(currentOption, event);
|
|
56
|
-
if (!isMultiSelect && !
|
|
60
|
+
if (!isMultiSelect && !isTextInSelectedOptions(currentOption)) {
|
|
57
61
|
toggleIsListOpen(false);
|
|
62
|
+
}
|
|
58
63
|
}
|
|
59
|
-
else if (shouldAutocomplete &&
|
|
64
|
+
else if (shouldAutocomplete && isTextInSelectedOptions(value)) {
|
|
60
65
|
event.preventDefault();
|
|
61
66
|
// Trying to set the same value that is already set, so just clearing the input
|
|
62
67
|
clearInput(event);
|
|
@@ -64,15 +69,20 @@ const Input = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
64
69
|
else if ((allowNewValues || shouldAutocomplete) && value !== "") {
|
|
65
70
|
event.preventDefault();
|
|
66
71
|
// Autocompleting or adding a new value
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
const selectedValue = allowNewValues && isValueNew ? value : filteredOptions[0];
|
|
73
|
+
toggleOption(selectedValue, event);
|
|
74
|
+
if (!isMultiSelect &&
|
|
75
|
+
!isTextInSelectedOptions(filteredOptions[0] || selectedValue)) {
|
|
69
76
|
toggleIsListOpen(false);
|
|
77
|
+
}
|
|
70
78
|
}
|
|
71
79
|
}, [
|
|
72
80
|
allowNewValues,
|
|
73
81
|
clearInput,
|
|
74
82
|
currentOption,
|
|
83
|
+
filteredOptions,
|
|
75
84
|
isMultiSelect,
|
|
85
|
+
isValueNew,
|
|
76
86
|
selectedOptions,
|
|
77
87
|
shouldAutocomplete,
|
|
78
88
|
toggleIsListOpen,
|
|
@@ -91,10 +101,10 @@ const Input = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
91
101
|
onEnter(e);
|
|
92
102
|
break;
|
|
93
103
|
case "Home":
|
|
94
|
-
|
|
104
|
+
virtualFocus.moveFocusToTop();
|
|
95
105
|
break;
|
|
96
106
|
case "End":
|
|
97
|
-
|
|
107
|
+
virtualFocus.moveFocusToBottom();
|
|
98
108
|
break;
|
|
99
109
|
default:
|
|
100
110
|
break;
|
|
@@ -113,26 +123,32 @@ const Input = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
113
123
|
// so we don't interfere with text editing
|
|
114
124
|
if (e.target.selectionStart === (value === null || value === void 0 ? void 0 : value.length)) {
|
|
115
125
|
e.preventDefault();
|
|
116
|
-
|
|
126
|
+
if (virtualFocus.activeElement === null || !isListOpen) {
|
|
127
|
+
toggleIsListOpen(true);
|
|
128
|
+
}
|
|
129
|
+
virtualFocus.moveFocusDown();
|
|
117
130
|
}
|
|
118
131
|
}
|
|
119
132
|
else if (e.key === "ArrowUp") {
|
|
120
133
|
// Check that the FilteredOptions list is open and has virtual focus.
|
|
121
134
|
// Otherwise ignore keystrokes, so it doesn't interfere with text editing
|
|
122
|
-
if (isListOpen &&
|
|
135
|
+
if (isListOpen && activeDecendantId) {
|
|
123
136
|
e.preventDefault();
|
|
124
|
-
|
|
137
|
+
if (virtualFocus.isFocusOnTheTop) {
|
|
138
|
+
toggleIsListOpen(false);
|
|
139
|
+
}
|
|
140
|
+
virtualFocus.moveFocusUp();
|
|
125
141
|
}
|
|
126
142
|
}
|
|
127
143
|
}, [
|
|
128
144
|
value,
|
|
129
145
|
selectedOptions,
|
|
130
146
|
removeSelectedOption,
|
|
131
|
-
moveFocusDown,
|
|
132
147
|
isListOpen,
|
|
133
|
-
|
|
134
|
-
moveFocusUp,
|
|
148
|
+
activeDecendantId,
|
|
135
149
|
setIsMouseLastUsedInputDevice,
|
|
150
|
+
toggleIsListOpen,
|
|
151
|
+
virtualFocus,
|
|
136
152
|
]);
|
|
137
153
|
const onChangeHandler = (0, react_1.useCallback)((event) => {
|
|
138
154
|
const newValue = event.target.value;
|
|
@@ -142,11 +158,12 @@ const Input = (0, react_1.forwardRef)((_a, ref) => {
|
|
|
142
158
|
else if (filteredOptions.length === 0) {
|
|
143
159
|
toggleIsListOpen(false);
|
|
144
160
|
}
|
|
161
|
+
virtualFocus.moveFocusToTop();
|
|
145
162
|
onChange(event);
|
|
146
|
-
}, [filteredOptions.length, onChange, toggleIsListOpen]);
|
|
163
|
+
}, [filteredOptions.length, virtualFocus, onChange, toggleIsListOpen]);
|
|
147
164
|
const onBlur = () => {
|
|
148
|
-
|
|
165
|
+
virtualFocus.moveFocusToTop();
|
|
149
166
|
};
|
|
150
|
-
return (react_1.default.createElement("input", Object.assign({}, rest, (0, util_1.omit)(inputProps, ["aria-invalid"]), { ref: ref, value: value, onChange: onChangeHandler, type: "text", role: "combobox", onBlur: onBlur, onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, "aria-controls":
|
|
167
|
+
return (react_1.default.createElement("input", Object.assign({}, rest, (0, util_1.omit)(inputProps, ["aria-invalid"]), { ref: ref, value: value, onChange: onChangeHandler, type: "text", role: "combobox", onBlur: onBlur, onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, "aria-controls": filtered_options_util_1.default.getFilteredOptionsId(inputProps.id), "aria-expanded": !!isListOpen, autoComplete: "off", "aria-autocomplete": shouldAutocomplete ? "both" : "list", "aria-activedescendant": activeDecendantId, "aria-describedby": ariaDescribedBy, "aria-invalid": inputProps["aria-invalid"], className: (0, clsx_1.default)(inputClassName, "navds-combobox__input", "navds-body-short", `navds-body-short--${size}`) })));
|
|
151
168
|
});
|
|
152
169
|
exports.default = Input;
|
|
@@ -26,12 +26,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.useCustomOptionsContext = exports.CustomOptionsProvider = void 0;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
28
|
const inputContext_1 = require("./Input/inputContext");
|
|
29
|
-
const selectedOptionsContext_1 = require("./SelectedOptions/selectedOptionsContext");
|
|
30
29
|
const CustomOptionsContext = (0, react_1.createContext)({});
|
|
31
|
-
const CustomOptionsProvider = ({ children }) => {
|
|
30
|
+
const CustomOptionsProvider = ({ children, value, }) => {
|
|
32
31
|
const [customOptions, setCustomOptions] = (0, react_1.useState)([]);
|
|
33
32
|
const { focusInput } = (0, inputContext_1.useInputContext)();
|
|
34
|
-
const { isMultiSelect } =
|
|
33
|
+
const { isMultiSelect } = value;
|
|
35
34
|
const removeCustomOption = (0, react_1.useCallback)((option) => {
|
|
36
35
|
setCustomOptions((prevCustomOptions) => prevCustomOptions.filter((o) => o !== option));
|
|
37
36
|
focusInput();
|
|
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.NewsPanel = exports.ContentPanel = exports.Sidebar = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const link_1 = require("../../link");
|
|
8
9
|
const typography_1 = require("../../typography");
|
|
9
10
|
const box_1 = require("../box");
|
|
10
11
|
const stack_1 = require("../stack");
|
|
11
|
-
const link_1 = require("../../link");
|
|
12
12
|
const LinkElement = ({ children }) => {
|
|
13
13
|
return (react_1.default.createElement(typography_1.Label, { as: "li", className: "sidebarlink" }, children));
|
|
14
14
|
};
|
package/cjs/loader/Loader.js
CHANGED
package/cjs/modal/Modal.js
CHANGED
|
@@ -42,6 +42,7 @@ const react_1 = require("@floating-ui/react");
|
|
|
42
42
|
const clsx_1 = __importDefault(require("clsx"));
|
|
43
43
|
const react_2 = __importStar(require("react"));
|
|
44
44
|
const react_dom_1 = require("react-dom");
|
|
45
|
+
const context_1 = require("../date/context");
|
|
45
46
|
const provider_1 = require("../provider");
|
|
46
47
|
const typography_1 = require("../typography");
|
|
47
48
|
const util_1 = require("../util");
|
|
@@ -99,13 +100,15 @@ const dialog_polyfill_1 = __importStar(require("./dialog-polyfill"));
|
|
|
99
100
|
*/
|
|
100
101
|
exports.Modal = (0, react_2.forwardRef)((_a, ref) => {
|
|
101
102
|
var _b, _c;
|
|
102
|
-
var { header, children, open, onBeforeClose, onCancel, width, portal, className, "aria-labelledby": ariaLabelledby, style } = _a, rest = __rest(_a, ["header", "children", "open", "onBeforeClose", "onCancel", "width", "portal", "className", "aria-labelledby", "style"]);
|
|
103
|
+
var { header, children, open, onBeforeClose, onCancel, closeOnBackdropClick, width, portal, className, "aria-labelledby": ariaLabelledby, style, onClick } = _a, rest = __rest(_a, ["header", "children", "open", "onBeforeClose", "onCancel", "closeOnBackdropClick", "width", "portal", "className", "aria-labelledby", "style", "onClick"]);
|
|
103
104
|
const modalRef = (0, react_2.useRef)(null);
|
|
104
105
|
const mergedRef = (0, react_2.useMemo)(() => (0, util_1.mergeRefs)([modalRef, ref]), [ref]);
|
|
105
106
|
const ariaLabelId = (0, util_1.useId)();
|
|
106
107
|
const rootElement = (_b = (0, provider_1.useProvider)()) === null || _b === void 0 ? void 0 : _b.rootElement;
|
|
107
108
|
const portalNode = (0, react_1.useFloatingPortalNode)({ root: rootElement });
|
|
108
|
-
|
|
109
|
+
const dateContext = (0, react_2.useContext)(context_1.DateContext);
|
|
110
|
+
const modalContext = (0, react_2.useContext)(ModalContext_1.ModalContext);
|
|
111
|
+
if (modalContext && !dateContext) {
|
|
109
112
|
console.error("Modals should not be nested");
|
|
110
113
|
}
|
|
111
114
|
(0, react_2.useEffect)(() => {
|
|
@@ -115,6 +118,12 @@ exports.Modal = (0, react_2.forwardRef)((_a, ref) => {
|
|
|
115
118
|
if (dialog_polyfill_1.needPolyfill && modalRef.current && portalNode) {
|
|
116
119
|
dialog_polyfill_1.default.registerDialog(modalRef.current);
|
|
117
120
|
}
|
|
121
|
+
// We set autofocus on the dialog element to prevent the default behavior where first focusable element gets focus when modal is opened.
|
|
122
|
+
// This is mainly to fix an edge case where having a Tooltip as the first focusable element would make it activate when you open the modal.
|
|
123
|
+
// We have to use JS because it doesn't work to set it with a prop (React bug?)
|
|
124
|
+
// Currently doesn't seem to work in Chrome. See also Tooltip.tsx
|
|
125
|
+
if (modalRef.current && portalNode)
|
|
126
|
+
modalRef.current.autofocus = true;
|
|
118
127
|
}, [modalRef, portalNode]);
|
|
119
128
|
(0, react_2.useEffect)(() => {
|
|
120
129
|
// We need to have this in a useEffect so that the content renders before the modal is displayed,
|
|
@@ -131,22 +140,37 @@ exports.Modal = (0, react_2.forwardRef)((_a, ref) => {
|
|
|
131
140
|
}, [modalRef, portalNode, open]);
|
|
132
141
|
(0, ModalUtils_1.useBodyScrollLock)(modalRef, portalNode);
|
|
133
142
|
const isWidthPreset = typeof width === "string" && ["small", "medium"].includes(width);
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
const mergedClassName = (0, clsx_1.default)("navds-modal", className, {
|
|
144
|
+
"navds-modal--polyfilled": dialog_polyfill_1.needPolyfill,
|
|
145
|
+
"navds-modal--autowidth": !width,
|
|
146
|
+
[`navds-modal--${width}`]: isWidthPreset,
|
|
147
|
+
});
|
|
148
|
+
const mergedStyle = Object.assign(Object.assign({}, style), (!isWidthPreset ? { width } : {}));
|
|
149
|
+
const mergedOnCancel = (event) => {
|
|
150
|
+
if (onBeforeClose && onBeforeClose() === false) {
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
}
|
|
153
|
+
else if (onCancel)
|
|
154
|
+
onCancel(event);
|
|
155
|
+
};
|
|
156
|
+
const mergedOnClick = closeOnBackdropClick && !dialog_polyfill_1.needPolyfill // closeOnBackdropClick has issues on polyfill when nesting modals (DatePicker)
|
|
157
|
+
? (event) => {
|
|
158
|
+
onClick && onClick(event);
|
|
159
|
+
if (event.target === modalRef.current &&
|
|
160
|
+
(!onBeforeClose || onBeforeClose() !== false)) {
|
|
161
|
+
modalRef.current.close();
|
|
142
162
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
163
|
+
}
|
|
164
|
+
: onClick;
|
|
165
|
+
const mergedAriaLabelledBy = !ariaLabelledby && !rest["aria-label"] && header
|
|
166
|
+
? ariaLabelId
|
|
167
|
+
: ariaLabelledby;
|
|
168
|
+
const component = (
|
|
169
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions
|
|
170
|
+
react_2.default.createElement("dialog", Object.assign({}, rest, { ref: mergedRef, className: mergedClassName, style: mergedStyle, onCancel: mergedOnCancel, onClick: mergedOnClick, "aria-labelledby": mergedAriaLabelledBy }),
|
|
148
171
|
react_2.default.createElement(ModalContext_1.ModalContext.Provider, { value: {
|
|
149
172
|
closeHandler: (0, ModalUtils_1.getCloseHandler)(modalRef, header, onBeforeClose),
|
|
173
|
+
ref: modalRef,
|
|
150
174
|
} },
|
|
151
175
|
header && (react_2.default.createElement(ModalHeader_1.default, null,
|
|
152
176
|
header.label && (react_2.default.createElement(typography_1.Detail, { className: "navds-modal__label" }, header.label)),
|
package/cjs/popover/Popover.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.Popover = void 0;
|
|
|
41
41
|
const react_1 = require("@floating-ui/react");
|
|
42
42
|
const clsx_1 = __importDefault(require("clsx"));
|
|
43
43
|
const react_2 = __importStar(require("react"));
|
|
44
|
+
const context_1 = require("../date/context");
|
|
44
45
|
const ModalContext_1 = require("../modal/ModalContext");
|
|
45
46
|
const util_1 = require("../util");
|
|
46
47
|
const PopoverContent_1 = __importDefault(require("./PopoverContent"));
|
|
@@ -65,11 +66,12 @@ const PopoverContent_1 = __importDefault(require("./PopoverContent"));
|
|
|
65
66
|
* ```
|
|
66
67
|
*/
|
|
67
68
|
exports.Popover = (0, react_2.forwardRef)((_a, ref) => {
|
|
68
|
-
var { className, children, anchorEl, arrow = true, open, onClose, placement = "top", offset, strategy: userStrategy,
|
|
69
|
+
var { className, children, anchorEl, arrow = true, open, onClose, placement = "top", offset, strategy: userStrategy, flip: _flip = true } = _a, rest = __rest(_a, ["className", "children", "anchorEl", "arrow", "open", "onClose", "placement", "offset", "strategy", "flip"]);
|
|
69
70
|
const arrowRef = (0, react_2.useRef)(null);
|
|
70
71
|
const isInModal = (0, react_2.useContext)(ModalContext_1.ModalContext) !== null;
|
|
72
|
+
const isInDatepicker = (0, react_2.useContext)(context_1.DateContext) !== null;
|
|
71
73
|
const chosenStrategy = userStrategy !== null && userStrategy !== void 0 ? userStrategy : (isInModal ? "fixed" : "absolute");
|
|
72
|
-
const chosenFlip =
|
|
74
|
+
const chosenFlip = isInDatepicker ? false : _flip;
|
|
73
75
|
const { x, y, strategy, context, update, refs, placement: flPlacement, middlewareData: { arrow: { x: arrowX, y: arrowY } = {} }, } = (0, react_1.useFloating)({
|
|
74
76
|
strategy: chosenStrategy,
|
|
75
77
|
placement,
|
|
@@ -85,11 +87,7 @@ exports.Popover = (0, react_2.forwardRef)((_a, ref) => {
|
|
|
85
87
|
});
|
|
86
88
|
const { getFloatingProps } = (0, react_1.useInteractions)([
|
|
87
89
|
(0, react_1.useClick)(context),
|
|
88
|
-
(0, react_1.useDismiss)(context,
|
|
89
|
-
bubbles: {
|
|
90
|
-
escapeKey: bubbleEscape,
|
|
91
|
-
},
|
|
92
|
-
}),
|
|
90
|
+
(0, react_1.useDismiss)(context),
|
|
93
91
|
]);
|
|
94
92
|
(0, util_1.useClientLayoutEffect)(() => {
|
|
95
93
|
refs.setReference(anchorEl);
|