@elliemae/ds-form-combobox 3.49.0-rc.4 → 3.50.0-next.2
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/dist/cjs/ComboBoxCTX.js +4 -0
- package/dist/cjs/ComboBoxCTX.js.map +2 -2
- package/dist/cjs/config/useComboBox.js +36 -19
- package/dist/cjs/config/useComboBox.js.map +2 -2
- package/dist/cjs/config/useCorrectOptions.js +6 -3
- package/dist/cjs/config/useCorrectOptions.js.map +2 -2
- package/dist/cjs/parts/controls-input/ControlsInput.js +5 -10
- package/dist/cjs/parts/controls-input/ControlsInput.js.map +2 -2
- package/dist/cjs/parts/controls-input/useKeyboardNavigation.js +16 -14
- package/dist/cjs/parts/controls-input/useKeyboardNavigation.js.map +2 -2
- package/dist/cjs/parts/controls-input/useMaskedOnChange.js +5 -4
- package/dist/cjs/parts/controls-input/useMaskedOnChange.js.map +2 -2
- package/dist/cjs/parts/header-list/HeaderList.js +104 -0
- package/dist/cjs/parts/header-list/HeaderList.js.map +7 -0
- package/dist/cjs/parts/header-list/index.js +36 -0
- package/dist/cjs/parts/header-list/index.js.map +7 -0
- package/dist/cjs/parts/header-list/styled.js +85 -0
- package/dist/cjs/parts/header-list/styled.js.map +7 -0
- package/dist/cjs/parts/header-list/useHeaderListHandlers.js +140 -0
- package/dist/cjs/parts/header-list/useHeaderListHandlers.js.map +7 -0
- package/dist/cjs/parts/menu-list/MenuList.js +35 -20
- package/dist/cjs/parts/menu-list/MenuList.js.map +2 -2
- package/dist/cjs/parts/menu-list/styled.js.map +2 -2
- package/dist/cjs/parts/menu-list/useItemRenderer.js +1 -2
- package/dist/cjs/parts/menu-list/useItemRenderer.js.map +2 -2
- package/dist/cjs/parts/multi-selected-values-container/RemovableSelectedValuePill.js +1 -9
- package/dist/cjs/parts/multi-selected-values-container/RemovableSelectedValuePill.js.map +2 -2
- package/dist/cjs/react-desc-prop-types.js +1 -2
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/sharedTypes.js.map +2 -2
- package/dist/cjs/utils/listHelper.js +23 -7
- package/dist/cjs/utils/listHelper.js.map +2 -2
- package/dist/esm/ComboBoxCTX.js +4 -0
- package/dist/esm/ComboBoxCTX.js.map +2 -2
- package/dist/esm/config/useComboBox.js +37 -20
- package/dist/esm/config/useComboBox.js.map +2 -2
- package/dist/esm/config/useCorrectOptions.js +7 -4
- package/dist/esm/config/useCorrectOptions.js.map +2 -2
- package/dist/esm/parts/controls-input/ControlsInput.js +5 -10
- package/dist/esm/parts/controls-input/ControlsInput.js.map +2 -2
- package/dist/esm/parts/controls-input/useKeyboardNavigation.js +16 -14
- package/dist/esm/parts/controls-input/useKeyboardNavigation.js.map +2 -2
- package/dist/esm/parts/controls-input/useMaskedOnChange.js +5 -4
- package/dist/esm/parts/controls-input/useMaskedOnChange.js.map +2 -2
- package/dist/esm/parts/header-list/HeaderList.js +80 -0
- package/dist/esm/parts/header-list/HeaderList.js.map +7 -0
- package/dist/esm/parts/header-list/index.js +6 -0
- package/dist/esm/parts/header-list/index.js.map +7 -0
- package/dist/esm/parts/header-list/styled.js +55 -0
- package/dist/esm/parts/header-list/styled.js.map +7 -0
- package/dist/esm/parts/header-list/useHeaderListHandlers.js +110 -0
- package/dist/esm/parts/header-list/useHeaderListHandlers.js.map +7 -0
- package/dist/esm/parts/menu-list/MenuList.js +36 -21
- package/dist/esm/parts/menu-list/MenuList.js.map +2 -2
- package/dist/esm/parts/menu-list/styled.js.map +2 -2
- package/dist/esm/parts/menu-list/useItemRenderer.js +1 -2
- package/dist/esm/parts/menu-list/useItemRenderer.js.map +2 -2
- package/dist/esm/parts/multi-selected-values-container/RemovableSelectedValuePill.js +1 -9
- package/dist/esm/parts/multi-selected-values-container/RemovableSelectedValuePill.js.map +2 -2
- package/dist/esm/react-desc-prop-types.js +1 -2
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/esm/sharedTypes.js.map +2 -2
- package/dist/esm/utils/listHelper.js +23 -7
- package/dist/esm/utils/listHelper.js.map +2 -2
- package/dist/types/config/useCorrectOptions.d.ts +1 -1
- package/dist/types/parts/header-list/HeaderList.d.ts +1 -0
- package/dist/types/parts/header-list/index.d.ts +1 -0
- package/dist/types/parts/header-list/styled.d.ts +6 -0
- package/dist/types/parts/header-list/useHeaderListHandlers.d.ts +11 -0
- package/dist/types/parts/menu-list/styled.d.ts +1 -0
- package/dist/types/react-desc-prop-types.d.ts +1 -2
- package/dist/types/sharedTypes.d.ts +4 -0
- package/dist/types/utils/listHelper.d.ts +1 -0
- package/package.json +16 -16
- package/dist/types/tests/read-only.test.d.ts +0 -1
package/dist/cjs/ComboBoxCTX.js
CHANGED
|
@@ -61,17 +61,21 @@ const defaultContext = {
|
|
|
61
61
|
referenceElement: null,
|
|
62
62
|
inputValue: "",
|
|
63
63
|
focusOptionIdx: "",
|
|
64
|
+
showSelectedOptions: false,
|
|
64
65
|
pillGroupRef: (0, import_react.createRef)(),
|
|
65
66
|
listRef: (0, import_react.createRef)(),
|
|
66
67
|
wrapperListRef: (0, import_react.createRef)(),
|
|
67
68
|
controlsWrapperRef: (0, import_react.createRef)(),
|
|
68
69
|
selectedOptionsRef: (0, import_react.createRef)(),
|
|
70
|
+
selectAllCheckboxRef: (0, import_react.createRef)(),
|
|
71
|
+
toggleSelectionButtonRef: (0, import_react.createRef)(),
|
|
69
72
|
setShowPopover: noop,
|
|
70
73
|
scrollOptionIntoView: noop,
|
|
71
74
|
setHasFocus: noop,
|
|
72
75
|
setInputValue: noop,
|
|
73
76
|
setReferenceElement: noop,
|
|
74
77
|
setFocusOptionIdx: noop,
|
|
78
|
+
setShowSelectedOptions: noop,
|
|
75
79
|
setMenuState: noop,
|
|
76
80
|
internalRef: (0, import_react.createRef)(),
|
|
77
81
|
correctOptions: [],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/ComboBoxCTX.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { createContext, createRef } from 'react';\nimport type { DSComboboxT } from './react-desc-prop-types.js';\nimport type { DSComboboxInternalsT } from './sharedTypes.js';\n// eslint-disable-next-line @typescript-eslint/no-empty-function\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\nexport function noop<T extends unknown[]>(..._args: T): void {}\n\nexport const defaultProps: DSComboboxT.DefaultProps = {\n hasError: false,\n inline: false,\n withoutPortal: false,\n disabled: false,\n useMask: noop,\n innerRef: createRef(),\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n noOptionsMessage: 'No Matches Found',\n isNonClearable: false,\n onlySelectable: false,\n isSkeleton: false,\n // override in useCombobox to avoid ref duplications when more than one cb is used\n applyAriaDisabled: false,\n};\n\nconst defaultContext: DSComboboxInternalsT.ComboBoxContextT = {\n props: defaultProps as DSComboboxT.InternalProps,\n menuState: false,\n hasFocus: false,\n referenceElement: null,\n inputValue: '',\n focusOptionIdx: '',\n pillGroupRef: createRef<HTMLDivElement>(),\n listRef: createRef<HTMLDivElement>(),\n wrapperListRef: createRef<HTMLDivElement>(),\n controlsWrapperRef: createRef<HTMLInputElement>(),\n selectedOptionsRef: createRef<HTMLInputElement>(),\n setShowPopover: noop,\n scrollOptionIntoView: noop,\n setHasFocus: noop,\n setInputValue: noop,\n setReferenceElement: noop,\n setFocusOptionIdx: noop,\n setMenuState: noop,\n internalRef: createRef<HTMLInputElement>(),\n correctOptions: [],\n instanceUid: '',\n};\n/** Context for cross component communication */\nexport const ComboBoxContext = createContext(defaultContext);\n\nexport default ComboBoxContext;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAyC;AAMlC,SAAS,QAA6B,OAAgB;AAAC;AAEvD,MAAM,eAAyC;AAAA,EACpD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAU,wBAAU;AAAA,EACpB,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,gBAAgB,WAAW;AAAA,EACtD,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,YAAY;AAAA;AAAA,EAEZ,mBAAmB;AACrB;AAEA,MAAM,iBAAwD;AAAA,EAC5D,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,kBAAc,wBAA0B;AAAA,EACxC,aAAS,wBAA0B;AAAA,EACnC,oBAAgB,wBAA0B;AAAA,EAC1C,wBAAoB,wBAA4B;AAAA,EAChD,wBAAoB,wBAA4B;AAAA,EAChD,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,iBAAa,wBAA4B;AAAA,EACzC,gBAAgB,CAAC;AAAA,EACjB,aAAa;AACf;AAEO,MAAM,sBAAkB,4BAAc,cAAc;AAE3D,IAAO,sBAAQ;",
|
|
4
|
+
"sourcesContent": ["import { createContext, createRef } from 'react';\nimport type { DSComboboxT } from './react-desc-prop-types.js';\nimport type { DSComboboxInternalsT } from './sharedTypes.js';\n// eslint-disable-next-line @typescript-eslint/no-empty-function\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars\nexport function noop<T extends unknown[]>(..._args: T): void {}\n\nexport const defaultProps: DSComboboxT.DefaultProps = {\n hasError: false,\n inline: false,\n withoutPortal: false,\n disabled: false,\n useMask: noop,\n innerRef: createRef(),\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n noOptionsMessage: 'No Matches Found',\n isNonClearable: false,\n onlySelectable: false,\n isSkeleton: false,\n // override in useCombobox to avoid ref duplications when more than one cb is used\n applyAriaDisabled: false,\n};\n\nconst defaultContext: DSComboboxInternalsT.ComboBoxContextT = {\n props: defaultProps as DSComboboxT.InternalProps,\n menuState: false,\n hasFocus: false,\n referenceElement: null,\n inputValue: '',\n focusOptionIdx: '',\n showSelectedOptions: false,\n pillGroupRef: createRef<HTMLDivElement>(),\n listRef: createRef<HTMLDivElement>(),\n wrapperListRef: createRef<HTMLDivElement>(),\n controlsWrapperRef: createRef<HTMLInputElement>(),\n selectedOptionsRef: createRef<HTMLInputElement>(),\n selectAllCheckboxRef: createRef<HTMLInputElement>(),\n toggleSelectionButtonRef: createRef<HTMLButtonElement>(),\n setShowPopover: noop,\n scrollOptionIntoView: noop,\n setHasFocus: noop,\n setInputValue: noop,\n setReferenceElement: noop,\n setFocusOptionIdx: noop,\n setShowSelectedOptions: noop,\n setMenuState: noop,\n internalRef: createRef<HTMLInputElement>(),\n correctOptions: [],\n instanceUid: '',\n};\n/** Context for cross component communication */\nexport const ComboBoxContext = createContext(defaultContext);\n\nexport default ComboBoxContext;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAyC;AAMlC,SAAS,QAA6B,OAAgB;AAAC;AAEvD,MAAM,eAAyC;AAAA,EACpD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAU,wBAAU;AAAA,EACpB,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,gBAAgB,WAAW;AAAA,EACtD,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,YAAY;AAAA;AAAA,EAEZ,mBAAmB;AACrB;AAEA,MAAM,iBAAwD;AAAA,EAC5D,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,kBAAc,wBAA0B;AAAA,EACxC,aAAS,wBAA0B;AAAA,EACnC,oBAAgB,wBAA0B;AAAA,EAC1C,wBAAoB,wBAA4B;AAAA,EAChD,wBAAoB,wBAA4B;AAAA,EAChD,0BAAsB,wBAA4B;AAAA,EAClD,8BAA0B,wBAA6B;AAAA,EACvD,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,cAAc;AAAA,EACd,iBAAa,wBAA4B;AAAA,EACzC,gBAAgB,CAAC;AAAA,EACjB,aAAa;AACf;AAEO,MAAM,sBAAkB,4BAAc,cAAc;AAE3D,IAAO,sBAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -41,11 +41,13 @@ var import_react_desc_prop_types = require("../react-desc-prop-types.js");
|
|
|
41
41
|
var import_useCorrectOptions = require("./useCorrectOptions.js");
|
|
42
42
|
var import_listHelper = require("../utils/listHelper.js");
|
|
43
43
|
var import_theming = require("../theming.js");
|
|
44
|
+
var import_useMakeMutable = require("./useMakeMutable.js");
|
|
44
45
|
const useComboBox = (props) => {
|
|
45
46
|
const propsWithDefaults = (0, import_ds_props_helpers.useMemoMergePropsWithDefault)(props, import_ComboBoxCTX.defaultProps);
|
|
46
47
|
(0, import_ds_props_helpers.useValidateTypescriptPropTypes)(propsWithDefaults, import_react_desc_prop_types.ComboboxPropTypes, import_theming.DSComboBoxName);
|
|
47
48
|
const [showPopover, setShowPopover] = (0, import_react.useState)(false);
|
|
48
49
|
const [referenceElement, setReferenceElement] = (0, import_react.useState)(null);
|
|
50
|
+
const [showSelectedOptions, setShowSelectedOptions] = (0, import_react.useState)(false);
|
|
49
51
|
const [inputValue, setInputValue] = (0, import_react.useState)("");
|
|
50
52
|
const [hasFocus, setHasFocus] = (0, import_react.useState)(false);
|
|
51
53
|
const internalRef = (0, import_react.useRef)(null);
|
|
@@ -53,6 +55,8 @@ const useComboBox = (props) => {
|
|
|
53
55
|
const wrapperListRef = (0, import_react.useRef)(null);
|
|
54
56
|
const selectedOptionsRef = (0, import_react.useRef)(null);
|
|
55
57
|
const controlsWrapperRef = (0, import_react.useRef)(null);
|
|
58
|
+
const selectAllCheckboxRef = (0, import_react.useRef)(null);
|
|
59
|
+
const toggleSelectionButtonRef = (0, import_react.useRef)(null);
|
|
56
60
|
const pillGroupRef = (0, import_react.useRef)(null);
|
|
57
61
|
const { id, selectedValues, isMenuOpen, onMenuChange, applyAriaDisabled } = propsWithDefaults;
|
|
58
62
|
const instanceUid = (0, import_react.useMemo)(() => id || (0, import_uid.uid)(5), [id]);
|
|
@@ -60,7 +64,15 @@ const useComboBox = (props) => {
|
|
|
60
64
|
if (isMenuOpen !== void 0) return isMenuOpen;
|
|
61
65
|
return showPopover;
|
|
62
66
|
}, [showPopover, isMenuOpen]);
|
|
63
|
-
const
|
|
67
|
+
const setMenuState = (0, import_react.useCallback)(
|
|
68
|
+
(newState, reason, e) => {
|
|
69
|
+
if (applyAriaDisabled) return;
|
|
70
|
+
if (onMenuChange !== void 0) onMenuChange(newState, reason, e);
|
|
71
|
+
setShowPopover(newState);
|
|
72
|
+
},
|
|
73
|
+
[onMenuChange, applyAriaDisabled]
|
|
74
|
+
);
|
|
75
|
+
const correctOptions = (0, import_useCorrectOptions.useCorrectOptions)(propsWithDefaults, inputValue, showSelectedOptions);
|
|
64
76
|
const virtualListHelpers = (0, import_react_virtual.useVirtual)({
|
|
65
77
|
size: correctOptions.length,
|
|
66
78
|
parentRef: listRef,
|
|
@@ -77,26 +89,24 @@ const useComboBox = (props) => {
|
|
|
77
89
|
[correctOptions, virtualListHelpers]
|
|
78
90
|
);
|
|
79
91
|
const [focusOptionIdx, setFocusOptionIdx] = (0, import_react.useState)("");
|
|
80
|
-
const setMenuState = (0, import_react.useCallback)(
|
|
81
|
-
(newState, reason, e) => {
|
|
82
|
-
if (applyAriaDisabled) return;
|
|
83
|
-
if (onMenuChange !== void 0) onMenuChange(newState, reason, e);
|
|
84
|
-
setShowPopover(newState);
|
|
85
|
-
if (!inputValue && newState && !focusOptionIdx && !(0, import_listHelper.isSelectedValueEmpty)(selectedValues)) {
|
|
86
|
-
const focusedValue = (0, import_listHelper.getFirstOption)(correctOptions, selectedValues);
|
|
87
|
-
setFocusOptionIdx(focusedValue);
|
|
88
|
-
scrollOptionIntoView(focusedValue, { align: "center" });
|
|
89
|
-
} else {
|
|
90
|
-
setFocusOptionIdx("");
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
[applyAriaDisabled, onMenuChange, inputValue, focusOptionIdx, selectedValues, correctOptions, scrollOptionIntoView]
|
|
94
|
-
);
|
|
95
92
|
(0, import_react.useEffect)(() => {
|
|
96
|
-
if (
|
|
97
|
-
|
|
93
|
+
if (!hasFocus) setFocusOptionIdx("");
|
|
94
|
+
if (hasFocus && (!focusOptionIdx || showSelectedOptions)) {
|
|
95
|
+
const focusedValue = (0, import_listHelper.getFirstOption)(correctOptions, selectedValues);
|
|
96
|
+
setFocusOptionIdx(focusedValue);
|
|
97
|
+
scrollOptionIntoView(focusedValue, { align: "center" });
|
|
98
|
+
}
|
|
99
|
+
}, [showPopover, hasFocus, correctOptions, selectedValues]);
|
|
100
|
+
const correctOptionsRef = (0, import_useMakeMutable.useMakeMutable)(correctOptions);
|
|
101
|
+
(0, import_react.useEffect)(() => {
|
|
102
|
+
setFocusOptionIdx(correctOptionsRef.current?.[0]?.dsId ?? "");
|
|
103
|
+
}, [correctOptionsRef, inputValue]);
|
|
104
|
+
(0, import_react.useEffect)(() => {
|
|
105
|
+
if (!showPopover) {
|
|
106
|
+
setFocusOptionIdx("");
|
|
107
|
+
setShowSelectedOptions(false);
|
|
98
108
|
}
|
|
99
|
-
}, []);
|
|
109
|
+
}, [showPopover]);
|
|
100
110
|
const ctx = (0, import_react.useMemo)(
|
|
101
111
|
() => ({
|
|
102
112
|
props: { ...propsWithDefaults },
|
|
@@ -107,12 +117,16 @@ const useComboBox = (props) => {
|
|
|
107
117
|
focusOptionIdx,
|
|
108
118
|
selectedOptionsRef,
|
|
109
119
|
controlsWrapperRef,
|
|
120
|
+
selectAllCheckboxRef,
|
|
110
121
|
inputValue,
|
|
111
122
|
setInputValue,
|
|
112
123
|
setMenuState,
|
|
113
124
|
hasFocus,
|
|
125
|
+
toggleSelectionButtonRef,
|
|
114
126
|
pillGroupRef,
|
|
127
|
+
showSelectedOptions,
|
|
115
128
|
wrapperListRef,
|
|
129
|
+
setShowSelectedOptions,
|
|
116
130
|
setHasFocus,
|
|
117
131
|
setFocusOptionIdx,
|
|
118
132
|
scrollOptionIntoView,
|
|
@@ -132,11 +146,14 @@ const useComboBox = (props) => {
|
|
|
132
146
|
inputValue,
|
|
133
147
|
focusOptionIdx,
|
|
134
148
|
wrapperListRef,
|
|
149
|
+
showSelectedOptions,
|
|
135
150
|
menuState,
|
|
136
151
|
pillGroupRef,
|
|
137
152
|
referenceElement,
|
|
138
153
|
selectedOptionsRef,
|
|
139
154
|
controlsWrapperRef,
|
|
155
|
+
selectAllCheckboxRef,
|
|
156
|
+
toggleSelectionButtonRef,
|
|
140
157
|
listRef,
|
|
141
158
|
internalRef,
|
|
142
159
|
instanceUid
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/config/useComboBox.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable import/prefer-default-export */\n/* eslint-disable complexity */\n/* eslint-disable max-statements */\nimport { useMemo, useState, useRef, useCallback, useEffect } from 'react';\nimport { useVirtual, type ScrollToIndexOptions } from 'react-virtual';\nimport { uid } from 'uid';\nimport { useMemoMergePropsWithDefault, useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';\nimport { defaultProps } from '../ComboBoxCTX.js';\nimport type { DSComboboxT } from '../react-desc-prop-types.js';\nimport { ComboboxPropTypes } from '../react-desc-prop-types.js';\nimport type { DSComboboxInternalsT } from '../sharedTypes.js';\nimport { useCorrectOptions } from './useCorrectOptions.js';\nimport { getFirstOption
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADIvB,mBAAkE;AAClE,2BAAsD;AACtD,iBAAoB;AACpB,8BAA6E;AAC7E,yBAA6B;AAE7B,mCAAkC;AAElC,+BAAkC;AAClC,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable import/prefer-default-export */\n/* eslint-disable complexity */\n/* eslint-disable max-statements */\nimport { useMemo, useState, useRef, useCallback, useEffect } from 'react';\nimport { useVirtual, type ScrollToIndexOptions } from 'react-virtual';\nimport { uid } from 'uid';\nimport { useMemoMergePropsWithDefault, useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';\nimport { defaultProps } from '../ComboBoxCTX.js';\nimport type { DSComboboxT } from '../react-desc-prop-types.js';\nimport { ComboboxPropTypes } from '../react-desc-prop-types.js';\nimport type { DSComboboxInternalsT } from '../sharedTypes.js';\nimport { useCorrectOptions } from './useCorrectOptions.js';\nimport { getFirstOption } from '../utils/listHelper.js';\nimport { DSComboBoxName } from '../theming.js';\nimport { useMakeMutable } from './useMakeMutable.js';\n\nexport const useComboBox = (props: DSComboboxT.Props): DSComboboxInternalsT.ComboBoxContextT => {\n const propsWithDefaults = useMemoMergePropsWithDefault<DSComboboxT.InternalProps>(props, defaultProps);\n useValidateTypescriptPropTypes(propsWithDefaults, ComboboxPropTypes, DSComboBoxName);\n const [showPopover, setShowPopover] = useState<boolean>(false);\n const [referenceElement, setReferenceElement] = useState<HTMLElement | null>(null);\n const [showSelectedOptions, setShowSelectedOptions] = useState<boolean>(false);\n\n const [inputValue, setInputValue] = useState<string>('');\n const [hasFocus, setHasFocus] = useState<boolean>(false);\n\n const internalRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const wrapperListRef = useRef<HTMLDivElement>(null);\n\n const selectedOptionsRef = useRef<HTMLDivElement>(null);\n const controlsWrapperRef = useRef<HTMLDivElement>(null);\n const selectAllCheckboxRef = useRef<HTMLInputElement>(null);\n const toggleSelectionButtonRef = useRef<HTMLButtonElement>(null);\n const pillGroupRef = useRef<HTMLDivElement>(null);\n\n const { id, selectedValues, isMenuOpen, onMenuChange, applyAriaDisabled } = propsWithDefaults;\n\n const instanceUid = useMemo(() => id || uid(5), [id]);\n\n const menuState = useMemo(() => {\n if (isMenuOpen !== undefined) return isMenuOpen;\n return showPopover;\n }, [showPopover, isMenuOpen]);\n\n const setMenuState = useCallback(\n (\n newState: boolean,\n reason: string,\n e?: React.KeyboardEvent | React.MouseEvent | React.ChangeEvent<HTMLInputElement>,\n ) => {\n if (applyAriaDisabled) return;\n if (onMenuChange !== undefined) onMenuChange(newState, reason, e);\n setShowPopover(newState);\n },\n [onMenuChange, applyAriaDisabled],\n );\n // ---------------------------------------------------------------------------\n // Options with creatable option + filtered by selected\n // ---------------------------------------------------------------------------\n\n const correctOptions = useCorrectOptions(propsWithDefaults, inputValue, showSelectedOptions);\n\n // ===========================================================================\n // Virtualization setup\n // ===========================================================================\n\n const virtualListHelpers: ReturnType<typeof useVirtual> = useVirtual({\n size: correctOptions.length,\n parentRef: listRef,\n overscan: 15,\n paddingStart: 0,\n });\n\n // ===========================================================================\n // Scroll into view function\n // ===========================================================================\n const scrollOptionIntoView = useCallback(\n (dsId: string, opts: ScrollToIndexOptions = { align: 'center' }) => {\n virtualListHelpers.scrollToIndex(\n correctOptions.findIndex((opt) => opt.dsId === dsId),\n opts,\n );\n },\n [correctOptions, virtualListHelpers],\n );\n\n // ===========================================================================\n // Init focused option when opening the menu list\n // ===========================================================================\n\n const [focusOptionIdx, setFocusOptionIdx] = useState<string>('');\n\n useEffect(() => {\n // this code calculate the option to be focused when opening the menu\n // when losing focus we remove the focused one\n // when focus adquired again getFirstOption calculate the correct one\n if (!hasFocus) setFocusOptionIdx('');\n if (hasFocus && (!focusOptionIdx || showSelectedOptions)) {\n const focusedValue = getFirstOption(correctOptions, selectedValues);\n setFocusOptionIdx(focusedValue);\n scrollOptionIntoView(focusedValue, { align: 'center' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showPopover, hasFocus, correctOptions, selectedValues]);\n\n const correctOptionsRef = useMakeMutable(correctOptions);\n\n // focus first option when typing\n useEffect(() => {\n setFocusOptionIdx(correctOptionsRef.current?.[0]?.dsId ?? '');\n }, [correctOptionsRef, inputValue]);\n\n useEffect(() => {\n if (!showPopover) {\n setFocusOptionIdx('');\n setShowSelectedOptions(false);\n }\n }, [showPopover]);\n\n const ctx = useMemo(\n () => ({\n props: { ...propsWithDefaults },\n virtualListHelpers,\n menuState,\n referenceElement,\n listRef,\n focusOptionIdx,\n selectedOptionsRef,\n controlsWrapperRef,\n selectAllCheckboxRef,\n inputValue,\n setInputValue,\n setMenuState,\n hasFocus,\n toggleSelectionButtonRef,\n pillGroupRef,\n showSelectedOptions,\n wrapperListRef,\n setShowSelectedOptions,\n setHasFocus,\n setFocusOptionIdx,\n scrollOptionIntoView,\n setReferenceElement,\n setShowPopover,\n internalRef,\n correctOptions,\n instanceUid,\n }),\n [\n scrollOptionIntoView,\n setMenuState,\n correctOptions,\n hasFocus,\n propsWithDefaults,\n virtualListHelpers,\n inputValue,\n focusOptionIdx,\n wrapperListRef,\n showSelectedOptions,\n menuState,\n pillGroupRef,\n referenceElement,\n selectedOptionsRef,\n controlsWrapperRef,\n selectAllCheckboxRef,\n toggleSelectionButtonRef,\n listRef,\n internalRef,\n instanceUid,\n ],\n );\n\n return ctx;\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -36,8 +36,8 @@ var import_react = require("react");
|
|
|
36
36
|
var import_uid = require("uid");
|
|
37
37
|
var import_constants = require("../constants.js");
|
|
38
38
|
var import_listHelper = require("../utils/listHelper.js");
|
|
39
|
-
const useCorrectOptions = (propsWithDefaults, inputValue) => {
|
|
40
|
-
const { filteredOptions, allOptions, onCreate } = propsWithDefaults;
|
|
39
|
+
const useCorrectOptions = (propsWithDefaults, inputValue, showSelectedOptions) => {
|
|
40
|
+
const { filteredOptions, allOptions, selectedValues, onCreate } = propsWithDefaults;
|
|
41
41
|
return (0, import_react.useMemo)(() => {
|
|
42
42
|
let correctAllOptions = allOptions;
|
|
43
43
|
if (allOptions?.every((option) => typeof option === "string")) {
|
|
@@ -49,6 +49,9 @@ const useCorrectOptions = (propsWithDefaults, inputValue) => {
|
|
|
49
49
|
}));
|
|
50
50
|
}
|
|
51
51
|
const correctFilterOptions = filteredOptions ?? (0, import_listHelper.filterOptions)(inputValue, correctAllOptions);
|
|
52
|
+
if (showSelectedOptions && Array.isArray(selectedValues) && selectedValues.length > 0) {
|
|
53
|
+
return (0, import_listHelper.selectedValuesWithSections)(correctFilterOptions, selectedValues);
|
|
54
|
+
}
|
|
52
55
|
if (onCreate && inputValue && correctFilterOptions.findIndex(
|
|
53
56
|
(option) => option.type === import_constants.MENU_OPTION_TYPES.OPTION && option.label === inputValue
|
|
54
57
|
) === -1) {
|
|
@@ -62,6 +65,6 @@ const useCorrectOptions = (propsWithDefaults, inputValue) => {
|
|
|
62
65
|
return [creatableItem, ...correctFilterOptions];
|
|
63
66
|
}
|
|
64
67
|
return correctFilterOptions;
|
|
65
|
-
}, [filteredOptions, allOptions, onCreate, inputValue]);
|
|
68
|
+
}, [filteredOptions, allOptions, showSelectedOptions, selectedValues, onCreate, inputValue]);
|
|
66
69
|
};
|
|
67
70
|
//# sourceMappingURL=useCorrectOptions.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/config/useCorrectOptions.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable complexity */\nimport { useMemo } from 'react';\nimport { uid } from 'uid';\nimport type { DSComboboxT } from '../react-desc-prop-types.js';\nimport { MENU_OPTION_TYPES } from '../constants.js';\nimport { filterOptions } from '../utils/listHelper.js';\nconst useCorrectOptions = (propsWithDefaults: DSComboboxT.Props, inputValue: string) => {\n const { filteredOptions, allOptions, onCreate } = propsWithDefaults;\n\n return useMemo(() => {\n let correctAllOptions = allOptions;\n if (allOptions?.every((option) => typeof option === 'string')) {\n correctAllOptions = allOptions.map((option, index) => ({\n dsId: index.toString(),\n label: option as unknown as string,\n type: MENU_OPTION_TYPES.OPTION,\n value: option as unknown as string,\n }));\n }\n const correctFilterOptions = filteredOptions ?? filterOptions(inputValue, correctAllOptions);\n\n // whether oncreate is passed we add as first option the creatable action based on input value string\n if (\n onCreate &&\n inputValue &&\n correctFilterOptions.findIndex(\n (option) => option.type === MENU_OPTION_TYPES.OPTION && option.label === inputValue,\n ) === -1\n ) {\n const creatableUuid = uid();\n const creatableItem: DSComboboxT.ItemCreatableOption = {\n dsId: `creatable-${creatableUuid}`,\n label: inputValue,\n type: 'creatable',\n 'aria-describedby': `aria-creatable`,\n };\n\n return [creatableItem, ...correctFilterOptions];\n }\n\n return correctFilterOptions;\n }, [filteredOptions, allOptions, onCreate, inputValue]);\n};\n\nexport { useCorrectOptions };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADCvB,mBAAwB;AACxB,iBAAoB;AAEpB,uBAAkC;AAClC,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable complexity */\nimport { useMemo } from 'react';\nimport { uid } from 'uid';\nimport type { DSComboboxT } from '../react-desc-prop-types.js';\nimport { MENU_OPTION_TYPES } from '../constants.js';\nimport { selectedValuesWithSections, filterOptions } from '../utils/listHelper.js';\nconst useCorrectOptions = (propsWithDefaults: DSComboboxT.Props, inputValue: string, showSelectedOptions: boolean) => {\n const { filteredOptions, allOptions, selectedValues, onCreate } = propsWithDefaults;\n\n return useMemo(() => {\n let correctAllOptions = allOptions;\n if (allOptions?.every((option) => typeof option === 'string')) {\n correctAllOptions = allOptions.map((option, index) => ({\n dsId: index.toString(),\n label: option as unknown as string,\n type: MENU_OPTION_TYPES.OPTION,\n value: option as unknown as string,\n }));\n }\n const correctFilterOptions = filteredOptions ?? filterOptions(inputValue, correctAllOptions);\n // when show selected toggle is on we return the selected value only as filteredOptions prop\n if (showSelectedOptions && Array.isArray(selectedValues) && selectedValues.length > 0) {\n return selectedValuesWithSections(correctFilterOptions, selectedValues);\n }\n\n // whether oncreate is passed we add as first option the creatable action based on input value string\n if (\n onCreate &&\n inputValue &&\n correctFilterOptions.findIndex(\n (option) => option.type === MENU_OPTION_TYPES.OPTION && option.label === inputValue,\n ) === -1\n ) {\n const creatableUuid = uid();\n const creatableItem: DSComboboxT.ItemCreatableOption = {\n dsId: `creatable-${creatableUuid}`,\n label: inputValue,\n type: 'creatable',\n 'aria-describedby': `aria-creatable`,\n };\n\n return [creatableItem, ...correctFilterOptions];\n }\n\n return correctFilterOptions;\n }, [filteredOptions, allOptions, showSelectedOptions, selectedValues, onCreate, inputValue]);\n};\n\nexport { useCorrectOptions };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADCvB,mBAAwB;AACxB,iBAAoB;AAEpB,uBAAkC;AAClC,wBAA0D;AAC1D,MAAM,oBAAoB,CAAC,mBAAsC,YAAoB,wBAAiC;AACpH,QAAM,EAAE,iBAAiB,YAAY,gBAAgB,SAAS,IAAI;AAElE,aAAO,sBAAQ,MAAM;AACnB,QAAI,oBAAoB;AACxB,QAAI,YAAY,MAAM,CAAC,WAAW,OAAO,WAAW,QAAQ,GAAG;AAC7D,0BAAoB,WAAW,IAAI,CAAC,QAAQ,WAAW;AAAA,QACrD,MAAM,MAAM,SAAS;AAAA,QACrB,OAAO;AAAA,QACP,MAAM,mCAAkB;AAAA,QACxB,OAAO;AAAA,MACT,EAAE;AAAA,IACJ;AACA,UAAM,uBAAuB,uBAAmB,iCAAc,YAAY,iBAAiB;AAE3F,QAAI,uBAAuB,MAAM,QAAQ,cAAc,KAAK,eAAe,SAAS,GAAG;AACrF,iBAAO,8CAA2B,sBAAsB,cAAc;AAAA,IACxE;AAGA,QACE,YACA,cACA,qBAAqB;AAAA,MACnB,CAAC,WAAW,OAAO,SAAS,mCAAkB,UAAU,OAAO,UAAU;AAAA,IAC3E,MAAM,IACN;AACA,YAAM,oBAAgB,gBAAI;AAC1B,YAAM,gBAAiD;AAAA,QACrD,MAAM,aAAa,aAAa;AAAA,QAChC,OAAO;AAAA,QACP,MAAM;AAAA,QACN,oBAAoB;AAAA,MACtB;AAEA,aAAO,CAAC,eAAe,GAAG,oBAAoB;AAAA,IAChD;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,YAAY,qBAAqB,gBAAgB,UAAU,UAAU,CAAC;AAC7F;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -55,7 +55,6 @@ const ControlsInput = () => {
|
|
|
55
55
|
isLoading,
|
|
56
56
|
onlySelectable,
|
|
57
57
|
applyAriaDisabled,
|
|
58
|
-
readOnly,
|
|
59
58
|
...restProps
|
|
60
59
|
},
|
|
61
60
|
focusOptionIdx,
|
|
@@ -85,16 +84,13 @@ const ControlsInput = () => {
|
|
|
85
84
|
}, [ariaDescribedBy, id]);
|
|
86
85
|
const currentPlaceholder = (0, import_react.useMemo)(() => {
|
|
87
86
|
if ((0, import_listHelper.isArrayOfItems)(selectedValues)) {
|
|
88
|
-
return `options ${selectedValues.map((item) => item.label).join(", ")} selected
|
|
87
|
+
return `options ${selectedValues.map((item) => item.label).join(", ")} selected`;
|
|
89
88
|
}
|
|
90
89
|
if (typeof selectedValues?.label === "string") {
|
|
91
|
-
return `option ${selectedValues.label} selected
|
|
92
|
-
}
|
|
93
|
-
if (readOnly) {
|
|
94
|
-
return `${placeholder}. Read only`;
|
|
90
|
+
return `option ${selectedValues.label} selected`;
|
|
95
91
|
}
|
|
96
92
|
return placeholder;
|
|
97
|
-
}, [placeholder, selectedValues
|
|
93
|
+
}, [placeholder, selectedValues]);
|
|
98
94
|
const activeDescendant = (0, import_react.useMemo)(() => {
|
|
99
95
|
if (!isLoading && hasFocus && menuState) {
|
|
100
96
|
return focusOptionIdx;
|
|
@@ -116,7 +112,7 @@ const ControlsInput = () => {
|
|
|
116
112
|
{
|
|
117
113
|
onBlur: handleOnBlur,
|
|
118
114
|
onFocus: handleOnFocus,
|
|
119
|
-
readOnly:
|
|
115
|
+
readOnly: onlySelectable,
|
|
120
116
|
...globalAttrs,
|
|
121
117
|
id,
|
|
122
118
|
"data-testid": import_ComboboxDataTestids.ComboboxDataTestid.INPUT,
|
|
@@ -138,8 +134,7 @@ const ControlsInput = () => {
|
|
|
138
134
|
onChange: handleOnChange,
|
|
139
135
|
tabIndex,
|
|
140
136
|
withoutCaret: onlySelectable,
|
|
141
|
-
autoComplete: "off"
|
|
142
|
-
"aria-readonly": readOnly
|
|
137
|
+
autoComplete: "off"
|
|
143
138
|
}
|
|
144
139
|
),
|
|
145
140
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyleHiddenInput, { type: "text", name: "hidden", tabIndex: -1, onPaste: handleOnPaste, "aria-hidden": "true" })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parts/controls-input/ControlsInput.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import React, { useContext, useMemo } from 'react';\nimport { SimpleTruncatedTooltipText } from '@elliemae/ds-truncated-tooltip-text';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport { ComboboxDataTestid } from '../../ComboboxDataTestids.js';\nimport {\n StyledInput,\n StyledInputWrapper,\n StyledInputPlaceHolder,\n StyledInputWidthReference,\n StyledHiddenDiv,\n StyleHiddenInput,\n} from './styled.js';\nimport { useKeyboardNavigation } from './useKeyboardNavigation.js';\nimport { useControlsInput } from './useControlsInput.js';\nimport { ComboBoxContext } from '../../ComboBoxCTX.js';\nimport { isArrayOfItems } from '../../utils/listHelper.js';\n\nexport const ControlsInput = (): JSX.Element => {\n const {\n props: {\n autoFocus,\n inline,\n selectedValues,\n placeholder,\n disabled,\n innerRef,\n isLoading,\n onlySelectable,\n applyAriaDisabled,\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
4
|
+
"sourcesContent": ["import React, { useContext, useMemo } from 'react';\nimport { SimpleTruncatedTooltipText } from '@elliemae/ds-truncated-tooltip-text';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport { ComboboxDataTestid } from '../../ComboboxDataTestids.js';\nimport {\n StyledInput,\n StyledInputWrapper,\n StyledInputPlaceHolder,\n StyledInputWidthReference,\n StyledHiddenDiv,\n StyleHiddenInput,\n} from './styled.js';\nimport { useKeyboardNavigation } from './useKeyboardNavigation.js';\nimport { useControlsInput } from './useControlsInput.js';\nimport { ComboBoxContext } from '../../ComboBoxCTX.js';\nimport { isArrayOfItems } from '../../utils/listHelper.js';\n\nexport const ControlsInput = (): JSX.Element => {\n const {\n props: {\n autoFocus,\n inline,\n selectedValues,\n placeholder,\n disabled,\n innerRef,\n isLoading,\n onlySelectable,\n applyAriaDisabled,\n ...restProps\n },\n focusOptionIdx,\n hasFocus,\n internalRef,\n inputValue,\n setInputValue,\n menuState,\n instanceUid,\n } = useContext(ComboBoxContext);\n const { onInputKeyDown } = useKeyboardNavigation();\n const { spanReference, width, spanReferenceText, showPlaceholder, handleOnBlur, handleOnChange, handleOnFocus } =\n useControlsInput();\n\n const {\n tabIndex,\n id,\n 'aria-describedby': ariaDescribedBy,\n ...globalAttrs\n } = useGetGlobalAttributes(restProps, {\n onFocus: handleOnFocus,\n onBlur: handleOnBlur,\n });\n\n const actualAriaDescribedBy = useMemo(() => {\n if (id) {\n return `${ariaDescribedBy ?? ''} ${id}_current_placeholder ${id}_feedback_message ${id}_error_message`;\n }\n return ariaDescribedBy;\n }, [ariaDescribedBy, id]);\n\n const currentPlaceholder = useMemo(() => {\n if (isArrayOfItems(selectedValues)) {\n return `options ${selectedValues.map((item) => item.label).join(', ')} selected`;\n }\n if (typeof selectedValues?.label === 'string') {\n return `option ${selectedValues.label} selected`;\n }\n return placeholder;\n }, [placeholder, selectedValues]);\n\n const activeDescendant = useMemo(() => {\n if (!isLoading && hasFocus && menuState) {\n return focusOptionIdx;\n }\n return undefined;\n }, [focusOptionIdx, hasFocus, isLoading, menuState]);\n\n const handleOnPaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n setInputValue(e.clipboardData.getData('text/plain'));\n internalRef.current?.focus();\n };\n return (\n <StyledInputWrapper>\n <StyledInputWidthReference innerRef={spanReference}>{spanReferenceText}</StyledInputWidthReference>\n {showPlaceholder && (\n <StyledInputPlaceHolder aria-hidden=\"true\">\n <SimpleTruncatedTooltipText value={showPlaceholder}></SimpleTruncatedTooltipText>\n </StyledInputPlaceHolder>\n )}\n\n {/* The purpose of this div is to always have the 'combo-listbox-{uid}' present in the DOM */}\n {/* Fix for PUI-11597 */}\n {menuState === false && !inline ? <StyledHiddenDiv id={`combo-listbox-${instanceUid}`}></StyledHiddenDiv> : null}\n\n {/* The announcement of currentPlaceholder is being overridden by the value of actualAriaDescribedBy */}\n {/* and since this variable is necessary for the annoucement of FormLayoutBlockItem error and feedback */}\n {/* messages, we concatenate the value of actualPlaceholder with that aria description */}\n {/* Fix for PUI-9609 */}\n <StyledHiddenDiv id={`${id}_current_placeholder`}>{currentPlaceholder}</StyledHiddenDiv>\n\n <StyledInput\n onBlur={handleOnBlur}\n onFocus={handleOnFocus}\n readOnly={onlySelectable}\n {...globalAttrs}\n id={id}\n data-testid={ComboboxDataTestid.INPUT}\n autoFocus={autoFocus}\n placeholder={currentPlaceholder}\n aria-activedescendant={activeDescendant}\n aria-expanded={menuState}\n aria-controls={`combo-listbox-${instanceUid}`}\n aria-describedby={actualAriaDescribedBy}\n aria-autocomplete=\"list\"\n role=\"combobox\"\n disabled={disabled}\n applyAriaDisabled={applyAriaDisabled}\n style={{ width }}\n innerRef={mergeRefs(innerRef, internalRef)}\n value={inputValue}\n type=\"text\"\n onKeyDown={onInputKeyDown}\n onChange={handleOnChange}\n tabIndex={tabIndex}\n withoutCaret={onlySelectable}\n autoComplete=\"off\"\n />\n {/* This input is used to handle the paste event */}\n <StyleHiddenInput type=\"text\" name=\"hidden\" tabIndex={-1} onPaste={handleOnPaste} aria-hidden=\"true\" />\n </StyledInputWrapper>\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADoFnB;AApFJ,mBAA2C;AAC3C,uCAA2C;AAC3C,uBAA0B;AAC1B,8BAAuC;AACvC,iCAAmC;AACnC,oBAOO;AACP,mCAAsC;AACtC,8BAAiC;AACjC,yBAAgC;AAChC,wBAA+B;AAExB,MAAM,gBAAgB,MAAmB;AAC9C,QAAM;AAAA,IACJ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,yBAAW,kCAAe;AAC9B,QAAM,EAAE,eAAe,QAAI,oDAAsB;AACjD,QAAM,EAAE,eAAe,OAAO,mBAAmB,iBAAiB,cAAc,gBAAgB,cAAc,QAC5G,0CAAiB;AAEnB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB,GAAG;AAAA,EACL,QAAI,gDAAuB,WAAW;AAAA,IACpC,SAAS;AAAA,IACT,QAAQ;AAAA,EACV,CAAC;AAED,QAAM,4BAAwB,sBAAQ,MAAM;AAC1C,QAAI,IAAI;AACN,aAAO,GAAG,mBAAmB,EAAE,IAAI,EAAE,wBAAwB,EAAE,qBAAqB,EAAE;AAAA,IACxF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,EAAE,CAAC;AAExB,QAAM,yBAAqB,sBAAQ,MAAM;AACvC,YAAI,kCAAe,cAAc,GAAG;AAClC,aAAO,WAAW,eAAe,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,IACvE;AACA,QAAI,OAAO,gBAAgB,UAAU,UAAU;AAC7C,aAAO,UAAU,eAAe,KAAK;AAAA,IACvC;AACA,WAAO;AAAA,EACT,GAAG,CAAC,aAAa,cAAc,CAAC;AAEhC,QAAM,uBAAmB,sBAAQ,MAAM;AACrC,QAAI,CAAC,aAAa,YAAY,WAAW;AACvC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,GAAG,CAAC,gBAAgB,UAAU,WAAW,SAAS,CAAC;AAEnD,QAAM,gBAAgB,CAAC,MAA8C;AACnE,MAAE,eAAe;AACjB,kBAAc,EAAE,cAAc,QAAQ,YAAY,CAAC;AACnD,gBAAY,SAAS,MAAM;AAAA,EAC7B;AACA,SACE,6CAAC,oCACC;AAAA,gDAAC,2CAA0B,UAAU,eAAgB,6BAAkB;AAAA,IACtE,mBACC,4CAAC,wCAAuB,eAAY,QAClC,sDAAC,+DAA2B,OAAO,iBAAiB,GACtD;AAAA,IAKD,cAAc,SAAS,CAAC,SAAS,4CAAC,iCAAgB,IAAI,iBAAiB,WAAW,IAAI,IAAqB;AAAA,IAM5G,4CAAC,iCAAgB,IAAI,GAAG,EAAE,wBAAyB,8BAAmB;AAAA,IAEtE;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,UAAU;AAAA,QACT,GAAG;AAAA,QACJ;AAAA,QACA,eAAa,8CAAmB;AAAA,QAChC;AAAA,QACA,aAAa;AAAA,QACb,yBAAuB;AAAA,QACvB,iBAAe;AAAA,QACf,iBAAe,iBAAiB,WAAW;AAAA,QAC3C,oBAAkB;AAAA,QAClB,qBAAkB;AAAA,QAClB,MAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA,OAAO,EAAE,MAAM;AAAA,QACf,cAAU,4BAAU,UAAU,WAAW;AAAA,QACzC,OAAO;AAAA,QACP,MAAK;AAAA,QACL,WAAW;AAAA,QACX,UAAU;AAAA,QACV;AAAA,QACA,cAAc;AAAA,QACd,cAAa;AAAA;AAAA,IACf;AAAA,IAEA,4CAAC,kCAAiB,MAAK,QAAO,MAAK,UAAS,UAAU,IAAI,SAAS,eAAe,eAAY,QAAO;AAAA,KACvG;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -53,14 +53,15 @@ const useKeyboardNavigation = () => {
|
|
|
53
53
|
selectedValues,
|
|
54
54
|
withoutPortal,
|
|
55
55
|
onlySelectable,
|
|
56
|
-
applyAriaDisabled
|
|
57
|
-
readOnly
|
|
56
|
+
applyAriaDisabled
|
|
58
57
|
},
|
|
59
58
|
inputValue,
|
|
60
59
|
correctOptions: filteredOptions,
|
|
61
60
|
menuState,
|
|
62
61
|
focusOptionIdx,
|
|
63
62
|
listRef,
|
|
63
|
+
selectAllCheckboxRef,
|
|
64
|
+
toggleSelectionButtonRef,
|
|
64
65
|
setMenuState,
|
|
65
66
|
setInputValue,
|
|
66
67
|
scrollOptionIntoView,
|
|
@@ -93,7 +94,7 @@ const useKeyboardNavigation = () => {
|
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
96
|
if (e.key === "Enter" || e.keyCode === 32 && e.altKey || e.key === "Tab" && !multiple && !inline) {
|
|
96
|
-
if (
|
|
97
|
+
if (currentItem?.applyAriaDisabled) return;
|
|
97
98
|
if (e.key !== "Tab") e.preventDefault();
|
|
98
99
|
e.stopPropagation();
|
|
99
100
|
if (focusOptionIdx !== "" && (menuState || inline) && currentItem?.type === import_constants.MENU_OPTION_TYPES.OPTION && !currentItem.disabled) {
|
|
@@ -117,7 +118,7 @@ const useKeyboardNavigation = () => {
|
|
|
117
118
|
if (e.key === "ArrowDown") {
|
|
118
119
|
e.preventDefault();
|
|
119
120
|
e.stopPropagation();
|
|
120
|
-
if ((menuState || inline) &&
|
|
121
|
+
if ((menuState || inline) && selectableOptions.length) {
|
|
121
122
|
const nextItemIndexIndex = (0, import_listHelper.findInCircularList)(filteredOptions, currentItemIndex, isOptionFocuseable);
|
|
122
123
|
if (nextItemIndexIndex > -1) {
|
|
123
124
|
setFocusOptionIdx(filteredOptions[nextItemIndexIndex].dsId);
|
|
@@ -128,13 +129,8 @@ const useKeyboardNavigation = () => {
|
|
|
128
129
|
if (e.key === "ArrowUp") {
|
|
129
130
|
e.preventDefault();
|
|
130
131
|
e.stopPropagation();
|
|
131
|
-
if (!selectableOptions.length
|
|
132
|
-
const prevItemIndex = (0, import_listHelper.findInCircularList)(
|
|
133
|
-
filteredOptions,
|
|
134
|
-
currentItemIndex === -1 ? 0 : currentItemIndex,
|
|
135
|
-
isOptionFocuseable,
|
|
136
|
-
-1
|
|
137
|
-
);
|
|
132
|
+
if (!selectableOptions.length) return;
|
|
133
|
+
const prevItemIndex = (0, import_listHelper.findInCircularList)(filteredOptions, currentItemIndex, isOptionFocuseable, -1);
|
|
138
134
|
if (prevItemIndex > -1) {
|
|
139
135
|
if (menuState || inline) {
|
|
140
136
|
setFocusOptionIdx(filteredOptions[prevItemIndex].dsId);
|
|
@@ -150,14 +146,19 @@ const useKeyboardNavigation = () => {
|
|
|
150
146
|
}
|
|
151
147
|
}
|
|
152
148
|
if (e.key === "Backspace" && e.currentTarget.value.length <= 0 && !inline) {
|
|
153
|
-
if (readOnly) return;
|
|
154
149
|
const lastValue = (0, import_listHelper.getLastValueSelected)(selectedValues);
|
|
155
150
|
if (!e.currentTarget.value && lastValue && !isNonClearable && !lastValue.applyAriaDisabled) {
|
|
156
151
|
onChange((0, import_listHelper.getSuggestedValueOnChange)(lastValue, selectedValues), lastValue, e);
|
|
157
152
|
}
|
|
158
153
|
}
|
|
159
154
|
if (e.key === "Tab" && !inline && menuState) {
|
|
160
|
-
|
|
155
|
+
const element = selectAllCheckboxRef.current ?? toggleSelectionButtonRef.current;
|
|
156
|
+
if (element) {
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
element.focus();
|
|
159
|
+
} else {
|
|
160
|
+
setMenuState(false, import_constants.MENU_CONTROL_REASONS.BLUR, e);
|
|
161
|
+
}
|
|
161
162
|
}
|
|
162
163
|
if (onlySelectable && /^[a-zA-Z\d]$/.test(e.key)) {
|
|
163
164
|
if (!menuState) {
|
|
@@ -166,7 +167,6 @@ const useKeyboardNavigation = () => {
|
|
|
166
167
|
const isOptionFocusableByLetter = (opt) => isOptionFocuseable(opt) && optionHasFirstLetter(opt, e.key);
|
|
167
168
|
const nextItemIndexIndex = (0, import_listHelper.findInCircularList)(filteredOptions, currentItemIndex, isOptionFocusableByLetter);
|
|
168
169
|
const nextItem = filteredOptions[nextItemIndexIndex];
|
|
169
|
-
console.log("nextItem", nextItem);
|
|
170
170
|
if (!nextItem) return;
|
|
171
171
|
setFocusOptionIdx(filteredOptions[nextItemIndexIndex].dsId);
|
|
172
172
|
scrollOptionIntoView(filteredOptions[nextItemIndexIndex].dsId);
|
|
@@ -194,6 +194,8 @@ const useKeyboardNavigation = () => {
|
|
|
194
194
|
setFocusOptionIdx,
|
|
195
195
|
selectedValues,
|
|
196
196
|
onChange,
|
|
197
|
+
selectAllCheckboxRef,
|
|
198
|
+
toggleSelectionButtonRef,
|
|
197
199
|
isNonClearable
|
|
198
200
|
]
|
|
199
201
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parts/controls-input/useKeyboardNavigation.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable max-depth */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport { useCallback, useContext } from 'react';\nimport type { DSComboboxT } from '../../react-desc-prop-types.js';\nimport { ComboBoxContext } from '../../ComboBoxCTX.js';\nimport {\n findInCircularList,\n getOptions,\n getSuggestedValueOnChange,\n getLastValueSelected,\n} from '../../utils/listHelper.js';\nimport { INTERNAL_MENU_OPTION_TYPES, MENU_OPTION_TYPES, MENU_CONTROL_REASONS } from '../../constants.js';\nconst isOptionFocuseable = (opt: DSComboboxT.OptionTypes): boolean =>\n !['section', 'separator'].includes(opt.type) && !opt.disabled;\n\nconst optionHasFirstLetter = (opt: DSComboboxT.OptionTypes, letter: string): boolean =>\n opt.label !== undefined && opt.label.toLowerCase().startsWith(letter.toLowerCase());\nexport const useKeyboardNavigation = () => {\n const {\n props: {\n allOptions,\n isNonClearable,\n onCancel,\n onKeyDown,\n onChange,\n onCreate,\n onFilter,\n onSelectAll,\n inline,\n selectedValues,\n withoutPortal,\n onlySelectable,\n applyAriaDisabled,\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADIvB,mBAAwC;AAExC,yBAAgC;AAChC,wBAKO;AACP,uBAAoF;AACpF,MAAM,qBAAqB,CAAC,QAC1B,CAAC,CAAC,WAAW,WAAW,EAAE,SAAS,IAAI,IAAI,KAAK,CAAC,IAAI;AAEvD,MAAM,uBAAuB,CAAC,KAA8B,WAC1D,IAAI,UAAU,UAAa,IAAI,MAAM,YAAY,EAAE,WAAW,OAAO,YAAY,CAAC;AAC7E,MAAM,wBAAwB,MAAM;AACzC,QAAM;AAAA,IACJ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,
|
|
4
|
+
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable max-depth */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport { useCallback, useContext } from 'react';\nimport type { DSComboboxT } from '../../react-desc-prop-types.js';\nimport { ComboBoxContext } from '../../ComboBoxCTX.js';\nimport {\n findInCircularList,\n getOptions,\n getSuggestedValueOnChange,\n getLastValueSelected,\n} from '../../utils/listHelper.js';\nimport { INTERNAL_MENU_OPTION_TYPES, MENU_OPTION_TYPES, MENU_CONTROL_REASONS } from '../../constants.js';\nconst isOptionFocuseable = (opt: DSComboboxT.OptionTypes): boolean =>\n !['section', 'separator'].includes(opt.type) && !opt.disabled;\n\nconst optionHasFirstLetter = (opt: DSComboboxT.OptionTypes, letter: string): boolean =>\n opt.label !== undefined && opt.label.toLowerCase().startsWith(letter.toLowerCase());\nexport const useKeyboardNavigation = () => {\n const {\n props: {\n allOptions,\n isNonClearable,\n onCancel,\n onKeyDown,\n onChange,\n onCreate,\n onFilter,\n onSelectAll,\n inline,\n selectedValues,\n withoutPortal,\n onlySelectable,\n applyAriaDisabled,\n },\n inputValue,\n correctOptions: filteredOptions,\n menuState,\n focusOptionIdx,\n listRef,\n selectAllCheckboxRef,\n toggleSelectionButtonRef,\n setMenuState,\n setInputValue,\n scrollOptionIntoView,\n setFocusOptionIdx,\n } = useContext(ComboBoxContext);\n\n const multiple = Array.isArray(selectedValues);\n const selectableOptions = getOptions(filteredOptions);\n const currentItemIndex = filteredOptions.findIndex((opt) => opt.dsId === focusOptionIdx);\n const currentItem = filteredOptions.find((item) => item.dsId === focusOptionIdx);\n\n const onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n if (applyAriaDisabled) return;\n\n // =============================================================================\n // CUSTOM KEYS\n // =============================================================================\n if (onKeyDown && currentItem?.type === MENU_OPTION_TYPES.OPTION) onKeyDown(e, currentItem);\n\n if (\n (['ArrowDown', 'ArrowUp', 'Enter', 'Spacebar'].includes(e.key) || (e.keyCode >= 48 && e.keyCode <= 90)) &&\n !menuState\n ) {\n setMenuState(true, MENU_CONTROL_REASONS.OPEN, e);\n }\n // =============================================================================\n // ESCAPE\n // =============================================================================\n if (e.key === 'Escape') {\n if (onCancel) onCancel();\n if (inputValue) {\n if (onFilter) onFilter(allOptions, inputValue);\n setInputValue('');\n }\n if (!inline) setMenuState(false, MENU_CONTROL_REASONS.CLOSE, e);\n }\n // =============================================================================\n // ENTER KEY TO CREATE ELEMENTS\n // =============================================================================\n if (e.key === 'Enter' && currentItem?.type === INTERNAL_MENU_OPTION_TYPES.CREATABLE && onCreate) {\n onCreate(inputValue);\n // blank active item to force search last one\n setFocusOptionIdx('');\n if (onFilter) onFilter(allOptions, '');\n setInputValue('');\n return;\n }\n\n // =============================================================================\n // Enter, space and Tab on selection\n // =============================================================================\n if (e.key === 'Enter' || (e.keyCode === 32 && e.altKey) || (e.key === 'Tab' && !multiple && !inline)) {\n if (currentItem?.applyAriaDisabled) return;\n\n if (e.key !== 'Tab') e.preventDefault();\n e.stopPropagation();\n\n if (\n focusOptionIdx !== '' &&\n (menuState || inline) &&\n currentItem?.type === MENU_OPTION_TYPES.OPTION &&\n !currentItem.disabled\n ) {\n if (onFilter) onFilter(allOptions, '');\n setInputValue('');\n if (!multiple) {\n setMenuState(false, MENU_CONTROL_REASONS.SELECT_OPTION, e);\n }\n onChange(getSuggestedValueOnChange(currentItem, selectedValues, isNonClearable), currentItem, e);\n }\n }\n\n if (e.key === 'Enter' && e.altKey) {\n setMenuState(false, 'selectOption', e);\n }\n\n if (e.key === 'a' && e.ctrlKey && multiple && onSelectAll) {\n onSelectAll(\n filteredOptions.filter((option) => option.type === 'option' && !option.disabled),\n e,\n );\n }\n // =============================================================================\n // ARROWS UP AND DOWN: LOGIC TO CALCULATE NEXT OR PREV ITEM TO PSEUDOFOCUS FROM INPUT\n // =============================================================================\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n e.stopPropagation();\n if ((menuState || inline) && selectableOptions.length) {\n const nextItemIndexIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocuseable);\n if (nextItemIndexIndex > -1) {\n setFocusOptionIdx(filteredOptions[nextItemIndexIndex].dsId);\n scrollOptionIntoView(filteredOptions[nextItemIndexIndex].dsId);\n }\n }\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n e.stopPropagation();\n if (!selectableOptions.length) return;\n const prevItemIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocuseable, -1);\n if (prevItemIndex > -1) {\n if (menuState || inline) {\n setFocusOptionIdx(filteredOptions[prevItemIndex].dsId);\n scrollOptionIntoView(filteredOptions[prevItemIndex].dsId);\n } else {\n // open menu and search last item to focused\n setMenuState(true, MENU_CONTROL_REASONS.OPEN, e);\n const lastItemIndex = findInCircularList(filteredOptions, 0, isOptionFocuseable, -1);\n setFocusOptionIdx(filteredOptions[lastItemIndex].dsId);\n setTimeout(() => {\n scrollOptionIntoView(filteredOptions[lastItemIndex].dsId);\n });\n }\n }\n }\n\n // =============================================================================\n // BACKSPACE\n // =============================================================================\n if (e.key === 'Backspace' && e.currentTarget.value.length <= 0 && !inline) {\n const lastValue = getLastValueSelected(selectedValues);\n if (!e.currentTarget.value && lastValue && !isNonClearable && !lastValue.applyAriaDisabled) {\n onChange(getSuggestedValueOnChange(lastValue, selectedValues), lastValue, e);\n }\n }\n\n if (e.key === 'Tab' && !inline && menuState) {\n const element = selectAllCheckboxRef.current ?? toggleSelectionButtonRef.current;\n if (element) {\n e.preventDefault();\n element.focus();\n } else {\n setMenuState(false, MENU_CONTROL_REASONS.BLUR, e);\n }\n }\n\n // =============================================================================\n // ONLYSELECTABLE LETTER/NUMBER KEYS TO FOCUS OPTIONS\n // =============================================================================\n\n if (onlySelectable && /^[a-zA-Z\\d]$/.test(e.key)) {\n if (!menuState) {\n setMenuState(true, MENU_CONTROL_REASONS.OPEN, e);\n }\n\n const isOptionFocusableByLetter = (opt: DSComboboxT.OptionTypes): boolean =>\n isOptionFocuseable(opt) && optionHasFirstLetter(opt, e.key);\n\n const nextItemIndexIndex = findInCircularList(filteredOptions, currentItemIndex, isOptionFocusableByLetter);\n const nextItem = filteredOptions[nextItemIndexIndex];\n if (!nextItem) return;\n setFocusOptionIdx(filteredOptions[nextItemIndexIndex].dsId);\n scrollOptionIntoView(filteredOptions[nextItemIndexIndex].dsId);\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n onKeyDown,\n currentItem,\n onCreate,\n multiple,\n inputValue,\n inline,\n withoutPortal,\n setMenuState,\n onCancel,\n onFilter,\n setInputValue,\n listRef,\n focusOptionIdx,\n menuState,\n selectableOptions.length,\n filteredOptions,\n currentItemIndex,\n setFocusOptionIdx,\n selectedValues,\n onChange,\n selectAllCheckboxRef,\n toggleSelectionButtonRef,\n isNonClearable,\n ],\n );\n\n return { onInputKeyDown };\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -40,27 +40,28 @@ const useMaskedOnChange = () => {
|
|
|
40
40
|
props: { useMask, onFilter, allOptions, applyAriaDisabled },
|
|
41
41
|
setMenuState,
|
|
42
42
|
setInputValue,
|
|
43
|
-
|
|
43
|
+
setShowSelectedOptions
|
|
44
44
|
} = (0, import_react.useContext)(import_ComboBoxCTX.default);
|
|
45
45
|
const handleOnChange = (0, import_react.useCallback)(
|
|
46
46
|
(e) => {
|
|
47
47
|
if (applyAriaDisabled) return;
|
|
48
|
+
setShowSelectedOptions(false);
|
|
48
49
|
setMenuState(true, "filter", e);
|
|
49
50
|
if (onFilter) {
|
|
50
51
|
onFilter((0, import_listHelper.filterOptions)(e.currentTarget.value, allOptions), e.currentTarget.value);
|
|
51
52
|
}
|
|
52
|
-
setFocusOptionIdx("");
|
|
53
53
|
setInputValue(e.currentTarget.value);
|
|
54
54
|
},
|
|
55
|
-
[
|
|
55
|
+
[allOptions, onFilter, setInputValue, setMenuState, setShowSelectedOptions, applyAriaDisabled]
|
|
56
56
|
);
|
|
57
57
|
const handleOnChangeMask = (0, import_react.useCallback)(
|
|
58
58
|
(e, mask) => {
|
|
59
|
+
setShowSelectedOptions(false);
|
|
59
60
|
setMenuState(true, "filter", e);
|
|
60
61
|
if (mask && onFilter) onFilter((0, import_listHelper.filterOptions)(mask, allOptions), mask);
|
|
61
62
|
else if (!mask && onFilter) onFilter(allOptions, "");
|
|
62
63
|
},
|
|
63
|
-
[allOptions, onFilter, setMenuState]
|
|
64
|
+
[allOptions, onFilter, setMenuState, setShowSelectedOptions]
|
|
64
65
|
);
|
|
65
66
|
const onChangeMask = useMask({ valueSetter: setInputValue, onChange: handleOnChangeMask });
|
|
66
67
|
return onChangeMask?.onChange || handleOnChange;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parts/controls-input/useMaskedOnChange.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useContext, useCallback } from 'react';\nimport ComboBoxContext from '../../ComboBoxCTX.js';\nimport { filterOptions } from '../../utils/listHelper.js';\n\nconst useMaskedOnChange = () => {\n const {\n props: { useMask, onFilter, allOptions, applyAriaDisabled },\n setMenuState,\n setInputValue,\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAwC;AACxC,yBAA4B;AAC5B,wBAA8B;AAE9B,MAAM,oBAAoB,MAAM;AAC9B,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,UAAU,YAAY,kBAAkB;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,yBAAW,mBAAAA,OAAe;AAG9B,QAAM,qBAAiB;AAAA,IACrB,CAAC,MAA2C;AAC1C,UAAI,kBAAmB;AACvB,mBAAa,MAAM,UAAU,CAAC;AAC9B,UAAI,UAAU;AAEZ,qBAAS,iCAAc,EAAE,cAAc,OAAO,UAAU,GAAG,EAAE,cAAc,KAAK;AAAA,MAClF;AACA,
|
|
4
|
+
"sourcesContent": ["import { useContext, useCallback } from 'react';\nimport ComboBoxContext from '../../ComboBoxCTX.js';\nimport { filterOptions } from '../../utils/listHelper.js';\n\nconst useMaskedOnChange = () => {\n const {\n props: { useMask, onFilter, allOptions, applyAriaDisabled },\n setMenuState,\n setInputValue,\n setShowSelectedOptions,\n } = useContext(ComboBoxContext);\n\n // default onchange when no mask provided\n const handleOnChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (applyAriaDisabled) return;\n setShowSelectedOptions(false);\n setMenuState(true, 'filter', e);\n if (onFilter) {\n // when filtering is controlled we suggest the basic filtering but let the user decide\n onFilter(filterOptions(e.currentTarget.value, allOptions), e.currentTarget.value);\n }\n setInputValue(e.currentTarget.value);\n },\n [allOptions, onFilter, setInputValue, setMenuState, setShowSelectedOptions, applyAriaDisabled],\n );\n\n // onchange used when mask is provided\n const handleOnChangeMask = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>, mask?: string) => {\n setShowSelectedOptions(false);\n setMenuState(true, 'filter', e);\n if (mask && onFilter) onFilter(filterOptions(mask, allOptions), mask);\n else if (!mask && onFilter) onFilter(allOptions, '');\n },\n [allOptions, onFilter, setMenuState, setShowSelectedOptions],\n );\n\n const onChangeMask = useMask({ valueSetter: setInputValue, onChange: handleOnChangeMask });\n\n return onChangeMask?.onChange || handleOnChange;\n};\n\nexport { useMaskedOnChange };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAwC;AACxC,yBAA4B;AAC5B,wBAA8B;AAE9B,MAAM,oBAAoB,MAAM;AAC9B,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,UAAU,YAAY,kBAAkB;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,yBAAW,mBAAAA,OAAe;AAG9B,QAAM,qBAAiB;AAAA,IACrB,CAAC,MAA2C;AAC1C,UAAI,kBAAmB;AACvB,6BAAuB,KAAK;AAC5B,mBAAa,MAAM,UAAU,CAAC;AAC9B,UAAI,UAAU;AAEZ,qBAAS,iCAAc,EAAE,cAAc,OAAO,UAAU,GAAG,EAAE,cAAc,KAAK;AAAA,MAClF;AACA,oBAAc,EAAE,cAAc,KAAK;AAAA,IACrC;AAAA,IACA,CAAC,YAAY,UAAU,eAAe,cAAc,wBAAwB,iBAAiB;AAAA,EAC/F;AAGA,QAAM,yBAAqB;AAAA,IACzB,CAAC,GAAwC,SAAkB;AACzD,6BAAuB,KAAK;AAC5B,mBAAa,MAAM,UAAU,CAAC;AAC9B,UAAI,QAAQ,SAAU,cAAS,iCAAc,MAAM,UAAU,GAAG,IAAI;AAAA,eAC3D,CAAC,QAAQ,SAAU,UAAS,YAAY,EAAE;AAAA,IACrD;AAAA,IACA,CAAC,YAAY,UAAU,cAAc,sBAAsB;AAAA,EAC7D;AAEA,QAAM,eAAe,QAAQ,EAAE,aAAa,eAAe,UAAU,mBAAmB,CAAC;AAEzF,SAAO,cAAc,YAAY;AACnC;",
|
|
6
6
|
"names": ["ComboBoxContext"]
|
|
7
7
|
}
|