@elliemae/ds-form-layout-autocomplete 3.70.0-next.49 → 3.70.0-next.51
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/AutocompleteDataTestids.js +3 -1
- package/dist/cjs/AutocompleteDataTestids.js.map +2 -2
- package/dist/cjs/config/usePopoverLogic.js +2 -2
- package/dist/cjs/config/usePopoverLogic.js.map +2 -2
- package/dist/cjs/constants/index.js +4 -1
- package/dist/cjs/constants/index.js.map +2 -2
- package/dist/cjs/parts/menu-list/LoadingContainer.js +76 -0
- package/dist/cjs/parts/menu-list/LoadingContainer.js.map +7 -0
- package/dist/cjs/parts/menu-list/MenuList.js +23 -15
- package/dist/cjs/parts/menu-list/MenuList.js.map +2 -2
- package/dist/cjs/parts/menu-list/SkeletonContainer.js +69 -0
- package/dist/cjs/parts/menu-list/SkeletonContainer.js.map +7 -0
- package/dist/cjs/react-desc-prop-types.js +2 -0
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/typescript-testing/typescript-autocomplete-valid.js +2 -0
- package/dist/cjs/typescript-testing/typescript-autocomplete-valid.js.map +2 -2
- package/dist/esm/AutocompleteDataTestids.js +3 -1
- package/dist/esm/AutocompleteDataTestids.js.map +2 -2
- package/dist/esm/config/usePopoverLogic.js +2 -2
- package/dist/esm/config/usePopoverLogic.js.map +2 -2
- package/dist/esm/constants/index.js +4 -1
- package/dist/esm/constants/index.js.map +2 -2
- package/dist/esm/parts/menu-list/LoadingContainer.js +46 -0
- package/dist/esm/parts/menu-list/LoadingContainer.js.map +7 -0
- package/dist/esm/parts/menu-list/MenuList.js +23 -15
- package/dist/esm/parts/menu-list/MenuList.js.map +2 -2
- package/dist/esm/parts/menu-list/SkeletonContainer.js +39 -0
- package/dist/esm/parts/menu-list/SkeletonContainer.js.map +7 -0
- package/dist/esm/react-desc-prop-types.js +2 -0
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/esm/typescript-testing/typescript-autocomplete-valid.js +2 -0
- package/dist/esm/typescript-testing/typescript-autocomplete-valid.js.map +2 -2
- package/dist/types/AutocompleteDataTestids.d.ts +2 -0
- package/dist/types/constants/index.d.ts +3 -0
- package/dist/types/parts/menu-list/LoadingContainer.d.ts +5 -0
- package/dist/types/parts/menu-list/SkeletonContainer.d.ts +5 -0
- package/dist/types/react-desc-prop-types.d.ts +2 -0
- package/package.json +12 -11
|
@@ -36,6 +36,8 @@ const AutocompleteDataTestid = {
|
|
|
36
36
|
LIST: "autocomplete-menu-list",
|
|
37
37
|
OPTION: "autocomplete-option",
|
|
38
38
|
CONTAINER: "autocomplete-container",
|
|
39
|
-
INPUT: "ds-autocomplete-input"
|
|
39
|
+
INPUT: "ds-autocomplete-input",
|
|
40
|
+
LOADING: "autocomplete-loading",
|
|
41
|
+
SKELETON: "autocomplete-skeleton"
|
|
40
42
|
};
|
|
41
43
|
//# sourceMappingURL=AutocompleteDataTestids.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/AutocompleteDataTestids.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["export const AutocompleteDataTestid = {\n LIST: 'autocomplete-menu-list',\n OPTION: 'autocomplete-option',\n CONTAINER: 'autocomplete-container',\n INPUT: 'ds-autocomplete-input',\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;
|
|
4
|
+
"sourcesContent": ["export const AutocompleteDataTestid = {\n LIST: 'autocomplete-menu-list',\n OPTION: 'autocomplete-option',\n CONTAINER: 'autocomplete-container',\n INPUT: 'ds-autocomplete-input',\n LOADING: 'autocomplete-loading',\n SKELETON: 'autocomplete-skeleton',\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AACZ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -35,13 +35,13 @@ var React = __toESM(require("react"));
|
|
|
35
35
|
var import_react = __toESM(require("react"));
|
|
36
36
|
var import_useHandleFocusOnPopoverOpenLogic = require("./useHandleFocusOnPopoverOpenLogic.js");
|
|
37
37
|
const usePopoverLogic = (propsWithDefault, setCurrentOption) => {
|
|
38
|
-
const { options, filter, forceFocusFirstOptionOnType } = propsWithDefault;
|
|
38
|
+
const { options, filter, forceFocusFirstOptionOnType, isLoading, isSkeleton } = propsWithDefault;
|
|
39
39
|
const [forceClosePopover, setForceClosePopover] = (0, import_react.useState)(false);
|
|
40
40
|
const [userTypedSomething, setUserTypedSomething] = (0, import_react.useState)(false);
|
|
41
41
|
const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = (0, import_react.useState)(false);
|
|
42
42
|
const [userJustSelectedAnOption, setUserJustSelectedAnOption] = (0, import_react.useState)(false);
|
|
43
43
|
const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;
|
|
44
|
-
const popoverHasAnythingToShow = options.length > 0 && filter.length > 0;
|
|
44
|
+
const popoverHasAnythingToShow = (options.length > 0 || !!isLoading || !!isSkeleton) && filter.length > 0;
|
|
45
45
|
const isShowingPopover = !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover
|
|
46
46
|
popoverHasAnythingToShow && // nothing to show --> hide popover
|
|
47
47
|
!userSelectedAndDidNotType && // user just selected an option --> hide popover
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/config/usePopoverLogic.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import React, { useState, useEffect } from 'react';\nimport type { DSAutocompleteT } from '../react-desc-prop-types.js';\nimport { useHandleFocusOnPopoverOpenLogic } from './useHandleFocusOnPopoverOpenLogic.js';\n\n// we want to own all the popover logic in a single place\n// we handle global events via window.addEventListener/RemoveEventListener\n// the logic to show/hide the popover accounts for\n// show:\n// - the user just typed something (excluding special keys like arrows, enter, etc)\n// - any options are available\n// - the user did not just select an option\n// N.B. this must react to options.length changing in an async way\n// hide:\n// - the user just selected an option and did not type anything after\n// - no options are available\n// - the focus is not on the input\n// - the user pressed the escape key\nexport const usePopoverLogic = (\n propsWithDefault: DSAutocompleteT.InternalProps,\n setCurrentOption: React.Dispatch<React.SetStateAction<string>>,\n) => {\n const { options, filter, forceFocusFirstOptionOnType } = propsWithDefault;\n\n const [forceClosePopover, setForceClosePopover] = useState<boolean>(false);\n\n const [userTypedSomething, setUserTypedSomething] = useState<boolean>(false);\n const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = useState<boolean>(false);\n const [userJustSelectedAnOption, setUserJustSelectedAnOption] = useState<boolean>(false);\n\n const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;\n const popoverHasAnythingToShow = options.length > 0 && filter.length > 0;\n\n const isShowingPopover =\n !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover\n popoverHasAnythingToShow && // nothing to show --> hide popover\n !userSelectedAndDidNotType && // user just selected an option --> hide popover\n (userTypedSomething || // user typed something --> show popover\n userIsNavigatingWithArrows); // user is navigating with arrows --> show popover\n\n // we don't want to redeclar all the functions when the flag changes, the flag is relevant on invocation only\n // so we use a ref to store the value of the flag and use it in the functions\n const isShowingRef = React.useRef(isShowingPopover);\n isShowingRef.current = isShowingPopover;\n\n const trackUserTyping: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n // [...e.key].length === 1 -> \"printable\" characters including https://mathiasbynens.be/notes/javascript-unicode\n if ([...e.key].length === 1 || key === 'Backspace' || key === 'Delete') {\n setUserTypedSomething(true);\n setForceClosePopover(false);\n setUserJustSelectedAnOption(false);\n } else {\n setUserTypedSomething(false);\n }\n }, []);\n const trackUserNavigatingWithArrows: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (isShowingRef.current && (key === 'ArrowUp' || key === 'ArrowDown')) {\n setUserIsNavigatingWithArrows(true);\n } else {\n setUserIsNavigatingWithArrows(false);\n }\n }, []);\n const trackUserSelectingAnOption: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (key === 'Enter' && isShowingRef.current) {\n setUserJustSelectedAnOption(true);\n }\n }, []);\n\n const trackUserInteractingViaKeyboard: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback(\n (e) => {\n trackUserTyping(e);\n trackUserNavigatingWithArrows(e);\n trackUserSelectingAnOption(e);\n },\n [trackUserTyping, trackUserNavigatingWithArrows, trackUserSelectingAnOption],\n );\n const closePopover = React.useCallback(() => {\n setForceClosePopover(true);\n setCurrentOption('');\n }, [setCurrentOption]);\n\n // when the webpage is blurred, we want to close the popover\n // should be fixing iframes interactions?\n useEffect(() => {\n window.addEventListener('blur', closePopover);\n return () => {\n window.removeEventListener('blur', closePopover);\n };\n }, [closePopover]);\n\n useHandleFocusOnPopoverOpenLogic({\n options,\n forceFocusFirstOptionOnType,\n isShowingPopover,\n setCurrentOption,\n });\n\n return React.useMemo(\n () => ({\n isShowingPopover,\n forceClosePopover,\n setForceClosePopover,\n userTypedSomething,\n setUserTypedSomething,\n setUserJustSelectedAnOption,\n userIsNavigatingWithArrows,\n setUserIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n }),\n [\n isShowingPopover,\n forceClosePopover,\n userTypedSomething,\n userIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAA2C;AAE3C,8CAAiD;AAe1C,MAAM,kBAAkB,CAC7B,kBACA,qBACG;AACH,QAAM,EAAE,SAAS,QAAQ,
|
|
4
|
+
"sourcesContent": ["import React, { useState, useEffect } from 'react';\nimport type { DSAutocompleteT } from '../react-desc-prop-types.js';\nimport { useHandleFocusOnPopoverOpenLogic } from './useHandleFocusOnPopoverOpenLogic.js';\n\n// we want to own all the popover logic in a single place\n// we handle global events via window.addEventListener/RemoveEventListener\n// the logic to show/hide the popover accounts for\n// show:\n// - the user just typed something (excluding special keys like arrows, enter, etc)\n// - any options are available\n// - the user did not just select an option\n// N.B. this must react to options.length changing in an async way\n// hide:\n// - the user just selected an option and did not type anything after\n// - no options are available\n// - the focus is not on the input\n// - the user pressed the escape key\nexport const usePopoverLogic = (\n propsWithDefault: DSAutocompleteT.InternalProps,\n setCurrentOption: React.Dispatch<React.SetStateAction<string>>,\n) => {\n const { options, filter, forceFocusFirstOptionOnType, isLoading, isSkeleton } = propsWithDefault;\n\n const [forceClosePopover, setForceClosePopover] = useState<boolean>(false);\n\n const [userTypedSomething, setUserTypedSomething] = useState<boolean>(false);\n const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = useState<boolean>(false);\n const [userJustSelectedAnOption, setUserJustSelectedAnOption] = useState<boolean>(false);\n\n const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;\n // during async fetches options is still empty, so loading/skeleton must keep the popover\n // open on their own \u2014 otherwise the spinner/skeleton would never get a chance to render\n const popoverHasAnythingToShow = (options.length > 0 || !!isLoading || !!isSkeleton) && filter.length > 0;\n\n const isShowingPopover =\n !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover\n popoverHasAnythingToShow && // nothing to show --> hide popover\n !userSelectedAndDidNotType && // user just selected an option --> hide popover\n (userTypedSomething || // user typed something --> show popover\n userIsNavigatingWithArrows); // user is navigating with arrows --> show popover\n\n // we don't want to redeclar all the functions when the flag changes, the flag is relevant on invocation only\n // so we use a ref to store the value of the flag and use it in the functions\n const isShowingRef = React.useRef(isShowingPopover);\n isShowingRef.current = isShowingPopover;\n\n const trackUserTyping: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n // [...e.key].length === 1 -> \"printable\" characters including https://mathiasbynens.be/notes/javascript-unicode\n if ([...e.key].length === 1 || key === 'Backspace' || key === 'Delete') {\n setUserTypedSomething(true);\n setForceClosePopover(false);\n setUserJustSelectedAnOption(false);\n } else {\n setUserTypedSomething(false);\n }\n }, []);\n const trackUserNavigatingWithArrows: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (isShowingRef.current && (key === 'ArrowUp' || key === 'ArrowDown')) {\n setUserIsNavigatingWithArrows(true);\n } else {\n setUserIsNavigatingWithArrows(false);\n }\n }, []);\n const trackUserSelectingAnOption: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (key === 'Enter' && isShowingRef.current) {\n setUserJustSelectedAnOption(true);\n }\n }, []);\n\n const trackUserInteractingViaKeyboard: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback(\n (e) => {\n trackUserTyping(e);\n trackUserNavigatingWithArrows(e);\n trackUserSelectingAnOption(e);\n },\n [trackUserTyping, trackUserNavigatingWithArrows, trackUserSelectingAnOption],\n );\n const closePopover = React.useCallback(() => {\n setForceClosePopover(true);\n setCurrentOption('');\n }, [setCurrentOption]);\n\n // when the webpage is blurred, we want to close the popover\n // should be fixing iframes interactions?\n useEffect(() => {\n window.addEventListener('blur', closePopover);\n return () => {\n window.removeEventListener('blur', closePopover);\n };\n }, [closePopover]);\n\n useHandleFocusOnPopoverOpenLogic({\n options,\n forceFocusFirstOptionOnType,\n isShowingPopover,\n setCurrentOption,\n });\n\n return React.useMemo(\n () => ({\n isShowingPopover,\n forceClosePopover,\n setForceClosePopover,\n userTypedSomething,\n setUserTypedSomething,\n setUserJustSelectedAnOption,\n userIsNavigatingWithArrows,\n setUserIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n }),\n [\n isShowingPopover,\n forceClosePopover,\n userTypedSomething,\n userIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAA2C;AAE3C,8CAAiD;AAe1C,MAAM,kBAAkB,CAC7B,kBACA,qBACG;AACH,QAAM,EAAE,SAAS,QAAQ,6BAA6B,WAAW,WAAW,IAAI;AAEhF,QAAM,CAAC,mBAAmB,oBAAoB,QAAI,uBAAkB,KAAK;AAEzE,QAAM,CAAC,oBAAoB,qBAAqB,QAAI,uBAAkB,KAAK;AAC3E,QAAM,CAAC,4BAA4B,6BAA6B,QAAI,uBAAkB,KAAK;AAC3F,QAAM,CAAC,0BAA0B,2BAA2B,QAAI,uBAAkB,KAAK;AAEvF,QAAM,4BAA4B,4BAA4B,CAAC;AAG/D,QAAM,4BAA4B,QAAQ,SAAS,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,eAAe,OAAO,SAAS;AAExG,QAAM,mBACJ,CAAC;AAAA,EACD;AAAA,EACA,CAAC;AAAA,GACA;AAAA,EACC;AAIJ,QAAM,eAAe,aAAAA,QAAM,OAAO,gBAAgB;AAClD,eAAa,UAAU;AAEvB,QAAM,kBAAgE,aAAAA,QAAM,YAAY,CAAC,MAAM;AAC7F,UAAM,EAAE,IAAI,IAAI;AAEhB,QAAI,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,KAAK,QAAQ,eAAe,QAAQ,UAAU;AACtE,4BAAsB,IAAI;AAC1B,2BAAqB,KAAK;AAC1B,kCAA4B,KAAK;AAAA,IACnC,OAAO;AACL,4BAAsB,KAAK;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,CAAC;AACL,QAAM,gCAA8E,aAAAA,QAAM,YAAY,CAAC,MAAM;AAC3G,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,aAAa,YAAY,QAAQ,aAAa,QAAQ,cAAc;AACtE,oCAA8B,IAAI;AAAA,IACpC,OAAO;AACL,oCAA8B,KAAK;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,CAAC;AACL,QAAM,6BAA2E,aAAAA,QAAM,YAAY,CAAC,MAAM;AACxG,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,QAAQ,WAAW,aAAa,SAAS;AAC3C,kCAA4B,IAAI;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kCAAgF,aAAAA,QAAM;AAAA,IAC1F,CAAC,MAAM;AACL,sBAAgB,CAAC;AACjB,oCAA8B,CAAC;AAC/B,iCAA2B,CAAC;AAAA,IAC9B;AAAA,IACA,CAAC,iBAAiB,+BAA+B,0BAA0B;AAAA,EAC7E;AACA,QAAM,eAAe,aAAAA,QAAM,YAAY,MAAM;AAC3C,yBAAqB,IAAI;AACzB,qBAAiB,EAAE;AAAA,EACrB,GAAG,CAAC,gBAAgB,CAAC;AAIrB,8BAAU,MAAM;AACd,WAAO,iBAAiB,QAAQ,YAAY;AAC5C,WAAO,MAAM;AACX,aAAO,oBAAoB,QAAQ,YAAY;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,gFAAiC;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
|
@@ -38,6 +38,9 @@ const DSAutocompleteSlots = {
|
|
|
38
38
|
CONTAINER: "container",
|
|
39
39
|
INPUT: "input",
|
|
40
40
|
MENU_LIST: "menu-list",
|
|
41
|
-
OPTION: "option"
|
|
41
|
+
OPTION: "option",
|
|
42
|
+
LOADING_WRAPPER: "loading-wrapper",
|
|
43
|
+
LOADING_INDICATOR: "loading-indicator",
|
|
44
|
+
SKELETON_MENU_ITEM: "skeleton-menu-item"
|
|
42
45
|
};
|
|
43
46
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/constants/index.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["export const DSAutocompleteName = 'DSAutocomplete';\n\nexport const DSAutocompleteSlots = {\n CONTAINER: 'container',\n INPUT: 'input',\n MENU_LIST: 'menu-list',\n OPTION: 'option',\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAAA,EACjC,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;
|
|
4
|
+
"sourcesContent": ["export const DSAutocompleteName = 'DSAutocomplete';\n\nexport const DSAutocompleteSlots = {\n CONTAINER: 'container',\n INPUT: 'input',\n MENU_LIST: 'menu-list',\n OPTION: 'option',\n LOADING_WRAPPER: 'loading-wrapper',\n LOADING_INDICATOR: 'loading-indicator',\n SKELETON_MENU_ITEM: 'skeleton-menu-item',\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAhB,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAAA,EACjC,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,oBAAoB;AACtB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var LoadingContainer_exports = {};
|
|
30
|
+
__export(LoadingContainer_exports, {
|
|
31
|
+
LoadingContainer: () => LoadingContainer,
|
|
32
|
+
default: () => LoadingContainer_default
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(LoadingContainer_exports);
|
|
35
|
+
var React = __toESM(require("react"));
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
var import_ds_system = require("@elliemae/ds-system");
|
|
38
|
+
var import_ds_circular_progress_indicator = require("@elliemae/ds-circular-progress-indicator");
|
|
39
|
+
var import_constants = require("../../constants/index.js");
|
|
40
|
+
var import_AutocompleteDataTestids = require("../../AutocompleteDataTestids.js");
|
|
41
|
+
const Wrapper = (0, import_ds_system.styled)("div", {
|
|
42
|
+
name: import_constants.DSAutocompleteName,
|
|
43
|
+
slot: import_constants.DSAutocompleteSlots.LOADING_WRAPPER
|
|
44
|
+
})`
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
height: 56px;
|
|
48
|
+
`;
|
|
49
|
+
const StyledDSCircularIndeterminateIndicator = (0, import_ds_system.styled)(import_ds_circular_progress_indicator.DSCircularIndeterminateIndicator, {
|
|
50
|
+
name: import_constants.DSAutocompleteName,
|
|
51
|
+
slot: import_constants.DSAutocompleteSlots.LOADING_INDICATOR
|
|
52
|
+
})``;
|
|
53
|
+
const LoadingContainer = ({
|
|
54
|
+
autoCompleteId,
|
|
55
|
+
getOwnerProps
|
|
56
|
+
}) => (
|
|
57
|
+
/**
|
|
58
|
+
* Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a
|
|
59
|
+
* busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /
|
|
60
|
+
* StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.
|
|
61
|
+
*/
|
|
62
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
63
|
+
Wrapper,
|
|
64
|
+
{
|
|
65
|
+
id: `menu-list-${autoCompleteId}`,
|
|
66
|
+
"data-testid": import_AutocompleteDataTestids.AutocompleteDataTestid.LOADING,
|
|
67
|
+
role: "listbox",
|
|
68
|
+
"aria-busy": true,
|
|
69
|
+
"aria-label": "Loading options please wait",
|
|
70
|
+
getOwnerProps,
|
|
71
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyledDSCircularIndeterminateIndicator, { size: "m", "aria-hidden": "true", getOwnerProps })
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
);
|
|
75
|
+
var LoadingContainer_default = LoadingContainer;
|
|
76
|
+
//# sourceMappingURL=LoadingContainer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/parts/menu-list/LoadingContainer.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
+
"sourcesContent": ["import React from 'react';\nimport { styled } from '@elliemae/ds-system';\nimport { DSCircularIndeterminateIndicator } from '@elliemae/ds-circular-progress-indicator';\nimport { DSAutocompleteName, DSAutocompleteSlots } from '../../constants/index.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\n\nconst Wrapper = styled('div', {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.LOADING_WRAPPER,\n})`\n display: flex;\n justify-content: center;\n height: 56px;\n`;\n\nconst StyledDSCircularIndeterminateIndicator = styled(DSCircularIndeterminateIndicator, {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.LOADING_INDICATOR,\n})``;\n\nexport const LoadingContainer = ({\n autoCompleteId,\n getOwnerProps,\n}: {\n autoCompleteId: string;\n getOwnerProps: () => object;\n}): JSX.Element => (\n /**\n * Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a\n * busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /\n * StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.\n */\n <Wrapper\n id={`menu-list-${autoCompleteId}`}\n data-testid={AutocompleteDataTestid.LOADING}\n role=\"listbox\"\n aria-busy\n aria-label=\"Loading options please wait\"\n getOwnerProps={getOwnerProps}\n >\n {/**\n * The spinner exposes role=\"status\", which is a forbidden child of role=\"listbox\"\n * (aria-allowed-children, axe Critical). aria-hidden removes it from the accessibility tree so\n * it no longer counts as a listbox child; the listbox's own aria-busy + aria-label remains the\n * single loading announcement. The spinner stays purely visual.\n */}\n <StyledDSCircularIndeterminateIndicator size=\"m\" aria-hidden=\"true\" getOwnerProps={getOwnerProps} />\n </Wrapper>\n);\n\nexport default LoadingContainer;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD8CnB;AA7CJ,uBAAuB;AACvB,4CAAiD;AACjD,uBAAwD;AACxD,qCAAuC;AAEvC,MAAM,cAAU,yBAAO,OAAO;AAAA,EAC5B,MAAM;AAAA,EACN,MAAM,qCAAoB;AAC5B,CAAC;AAAA;AAAA;AAAA;AAAA;AAMD,MAAM,6CAAyC,yBAAO,wEAAkC;AAAA,EACtF,MAAM;AAAA,EACN,MAAM,qCAAoB;AAC5B,CAAC;AAEM,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,aAAa,cAAc;AAAA,MAC/B,eAAa,sDAAuB;AAAA,MACpC,MAAK;AAAA,MACL,aAAS;AAAA,MACT,cAAW;AAAA,MACX;AAAA,MAQA,sDAAC,0CAAuC,MAAK,KAAI,eAAY,QAAO,eAA8B;AAAA;AAAA,EACpG;AAAA;AAGF,IAAO,2BAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -39,9 +39,11 @@ var import_AutocompleteDataTestids = require("../../AutocompleteDataTestids.js")
|
|
|
39
39
|
var import_AutocompleteCTX = __toESM(require("../../AutocompleteCTX.js"));
|
|
40
40
|
var import_useItemRenderer = require("./useItemRenderer.js");
|
|
41
41
|
var import_useOnElementResize = require("../../utils/useOnElementResize.js");
|
|
42
|
+
var import_LoadingContainer = require("./LoadingContainer.js");
|
|
43
|
+
var import_SkeletonContainer = require("./SkeletonContainer.js");
|
|
42
44
|
const MenuList = () => {
|
|
43
45
|
const {
|
|
44
|
-
props: { options },
|
|
46
|
+
props: { options, isLoading, isSkeleton },
|
|
45
47
|
referenceElement,
|
|
46
48
|
inputRef,
|
|
47
49
|
listRef,
|
|
@@ -62,19 +64,25 @@ const MenuList = () => {
|
|
|
62
64
|
const rafId = requestAnimationFrame(() => measure());
|
|
63
65
|
return () => cancelAnimationFrame(rafId);
|
|
64
66
|
}, [width]);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
const renderMenuContent = () => {
|
|
68
|
+
if (isSkeleton) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_SkeletonContainer.SkeletonContainer, { autoCompleteId, getOwnerProps });
|
|
69
|
+
if (isLoading) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_LoadingContainer.LoadingContainer, { autoCompleteId, getOwnerProps });
|
|
70
|
+
if (options.length === 0) return null;
|
|
71
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledVirtualListWrapper, { tabIndex: -1, innerRef: listRef, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
72
|
+
import_styled.StyledList,
|
|
73
|
+
{
|
|
74
|
+
role: "listbox",
|
|
75
|
+
id: `menu-list-${autoCompleteId}`,
|
|
76
|
+
"aria-label": "autocomplete option lists",
|
|
77
|
+
onFocus: handleOnFocus,
|
|
78
|
+
"data-testid": import_AutocompleteDataTestids.AutocompleteDataTestid.LIST,
|
|
79
|
+
style: { height: totalSize, margin: "8px 0px" },
|
|
80
|
+
getOwnerProps,
|
|
81
|
+
children: ItemRenderer
|
|
82
|
+
},
|
|
83
|
+
options.length
|
|
84
|
+
) });
|
|
85
|
+
};
|
|
86
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled.StyledListWrapper, { onMouseDown: preventMouseDown, minWidth: referenceElement?.offsetWidth, children: renderMenuContent() });
|
|
79
87
|
};
|
|
80
88
|
//# sourceMappingURL=MenuList.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parts/menu-list/MenuList.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import React, { useContext, useCallback, useEffect } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\nimport AutocompleteContext from '../../AutocompleteCTX.js';\nimport { useItemRenderer } from './useItemRenderer.js';\nimport { useOnElementResize } from '../../utils/useOnElementResize.js';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options },\n referenceElement,\n inputRef,\n listRef,\n autoCompleteId,\n getOwnerProps,\n virtualListHelpers: { totalSize, measure },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n const { width } = useOnElementResize(referenceElement);\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const preventMouseDown: React.MouseEventHandler<HTMLDivElement> = useCallback((e) => {\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n if (!measure) return undefined;\n // Defer measure() to the next animation frame so it never runs inside an active\n // React sync flush (React 17 / legacy mode). Without the deferral, the call chain\n // outputsize \u2192 setWidth \u2192 [flushSyncCallbackQueue] \u2192 commit \u2192 measureRef \u2192\n // setMeasuredCache \u2192 [new syncQueue entry] \u2192 commit \u2192 measureRef \u2192 \u2026\n // keeps adding entries to the live syncQueue array that flushSyncCallbackQueue\n // is iterating over, producing 25+ nested commits and the\n // \"Maximum update depth exceeded\" crash. requestAnimationFrame breaks that chain\n // by scheduling measure() for after the current flush completes.\n const rafId = requestAnimationFrame(() => measure());\n return () => cancelAnimationFrame(rafId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [width]);\n\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
4
|
+
"sourcesContent": ["import React, { useContext, useCallback, useEffect } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\nimport AutocompleteContext from '../../AutocompleteCTX.js';\nimport { useItemRenderer } from './useItemRenderer.js';\nimport { useOnElementResize } from '../../utils/useOnElementResize.js';\nimport { LoadingContainer } from './LoadingContainer.js';\nimport { SkeletonContainer } from './SkeletonContainer.js';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options, isLoading, isSkeleton },\n referenceElement,\n inputRef,\n listRef,\n autoCompleteId,\n getOwnerProps,\n virtualListHelpers: { totalSize, measure },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n const { width } = useOnElementResize(referenceElement);\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const preventMouseDown: React.MouseEventHandler<HTMLDivElement> = useCallback((e) => {\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n if (!measure) return undefined;\n // Defer measure() to the next animation frame so it never runs inside an active\n // React sync flush (React 17 / legacy mode). Without the deferral, the call chain\n // outputsize \u2192 setWidth \u2192 [flushSyncCallbackQueue] \u2192 commit \u2192 measureRef \u2192\n // setMeasuredCache \u2192 [new syncQueue entry] \u2192 commit \u2192 measureRef \u2192 \u2026\n // keeps adding entries to the live syncQueue array that flushSyncCallbackQueue\n // is iterating over, producing 25+ nested commits and the\n // \"Maximum update depth exceeded\" crash. requestAnimationFrame breaks that chain\n // by scheduling measure() for after the current flush completes.\n const rafId = requestAnimationFrame(() => measure());\n return () => cancelAnimationFrame(rafId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [width]);\n\n const renderMenuContent = () => {\n // Loading/skeleton own the listbox id + role + aria-busy while options are being fetched;\n // only one of skeleton / loading / list is ever mounted at a time (see the containers).\n if (isSkeleton) return <SkeletonContainer autoCompleteId={autoCompleteId} getOwnerProps={getOwnerProps} />;\n if (isLoading) return <LoadingContainer autoCompleteId={autoCompleteId} getOwnerProps={getOwnerProps} />;\n if (options.length === 0) return null;\n return (\n <StyledVirtualListWrapper tabIndex={-1} innerRef={listRef}>\n <StyledList\n // recalculate the key to force the re-render of the list and update virtualization\n key={options.length}\n role=\"listbox\"\n id={`menu-list-${autoCompleteId}`}\n // default aria label until we integrate the aria props on autocomplete\n // this is for the axe core to pass\n aria-label=\"autocomplete option lists\"\n onFocus={handleOnFocus}\n data-testid={AutocompleteDataTestid.LIST}\n style={{ height: totalSize, margin: '8px 0px' }}\n getOwnerProps={getOwnerProps}\n >\n {ItemRenderer}\n </StyledList>\n </StyledVirtualListWrapper>\n );\n };\n\n return (\n <StyledListWrapper onMouseDown={preventMouseDown} minWidth={referenceElement?.offsetWidth}>\n {renderMenuContent()}\n </StyledListWrapper>\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADiDI;AAjD3B,mBAA0D;AAC1D,oBAAwE;AACxE,qCAAuC;AACvC,6BAAgC;AAChC,6BAAgC;AAChC,gCAAmC;AACnC,8BAAiC;AACjC,+BAAkC;AAE3B,MAAM,WAAW,MAAmB;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,WAAW,WAAW;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,EAAE,WAAW,QAAQ;AAAA,EAC3C,QAAI,yBAAW,uBAAAA,OAAmB;AAElC,QAAM,mBAAe,wCAAgB;AACrC,QAAM,EAAE,MAAM,QAAI,8CAAmB,gBAAgB;AAErD,QAAM,oBAAgB,0BAAY,MAAM;AACtC,aAAS,SAAS,MAAM;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,uBAA4D,0BAAY,CAAC,MAAM;AACnF,MAAE,eAAe;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACd,QAAI,CAAC,QAAS,QAAO;AASrB,UAAM,QAAQ,sBAAsB,MAAM,QAAQ,CAAC;AACnD,WAAO,MAAM,qBAAqB,KAAK;AAAA,EAEzC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,oBAAoB,MAAM;AAG9B,QAAI,WAAY,QAAO,4CAAC,8CAAkB,gBAAgC,eAA8B;AACxG,QAAI,UAAW,QAAO,4CAAC,4CAAiB,gBAAgC,eAA8B;AACtG,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WACE,4CAAC,0CAAyB,UAAU,IAAI,UAAU,SAChD;AAAA,MAAC;AAAA;AAAA,QAGC,MAAK;AAAA,QACL,IAAI,aAAa,cAAc;AAAA,QAG/B,cAAW;AAAA,QACX,SAAS;AAAA,QACT,eAAa,sDAAuB;AAAA,QACpC,OAAO,EAAE,QAAQ,WAAW,QAAQ,UAAU;AAAA,QAC9C;AAAA,QAEC;AAAA;AAAA,MAXI,QAAQ;AAAA,IAYf,GACF;AAAA,EAEJ;AAEA,SACE,4CAAC,mCAAkB,aAAa,kBAAkB,UAAU,kBAAkB,aAC3E,4BAAkB,GACrB;AAEJ;",
|
|
6
6
|
"names": ["AutocompleteContext"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var SkeletonContainer_exports = {};
|
|
30
|
+
__export(SkeletonContainer_exports, {
|
|
31
|
+
SkeletonContainer: () => SkeletonContainer,
|
|
32
|
+
default: () => SkeletonContainer_default
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(SkeletonContainer_exports);
|
|
35
|
+
var React = __toESM(require("react"));
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
var import_ds_menu_items = require("@elliemae/ds-menu-items");
|
|
38
|
+
var import_ds_grid = require("@elliemae/ds-grid");
|
|
39
|
+
var import_ds_system = require("@elliemae/ds-system");
|
|
40
|
+
var import_constants = require("../../constants/index.js");
|
|
41
|
+
var import_AutocompleteDataTestids = require("../../AutocompleteDataTestids.js");
|
|
42
|
+
const StyledSkeletonMenuItem = (0, import_ds_system.styled)(import_ds_menu_items.SkeletonMenuItem, {
|
|
43
|
+
name: import_constants.DSAutocompleteName,
|
|
44
|
+
slot: import_constants.DSAutocompleteSlots.SKELETON_MENU_ITEM
|
|
45
|
+
})``;
|
|
46
|
+
const SKELETON_AMOUNT = [0, 1, 2, 3, 4];
|
|
47
|
+
const SkeletonContainer = ({
|
|
48
|
+
autoCompleteId,
|
|
49
|
+
getOwnerProps
|
|
50
|
+
}) => (
|
|
51
|
+
/**
|
|
52
|
+
* Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a
|
|
53
|
+
* busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /
|
|
54
|
+
* StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.
|
|
55
|
+
*/
|
|
56
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
57
|
+
import_ds_grid.Grid,
|
|
58
|
+
{
|
|
59
|
+
id: `menu-list-${autoCompleteId}`,
|
|
60
|
+
"data-testid": import_AutocompleteDataTestids.AutocompleteDataTestid.SKELETON,
|
|
61
|
+
role: "listbox",
|
|
62
|
+
"aria-busy": true,
|
|
63
|
+
"aria-label": "Loading options please wait",
|
|
64
|
+
children: SKELETON_AMOUNT.map((n, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyledSkeletonMenuItem, { dsId: index.toString(), role: "presentation", getOwnerProps }, n))
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
var SkeletonContainer_default = SkeletonContainer;
|
|
69
|
+
//# sourceMappingURL=SkeletonContainer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/parts/menu-list/SkeletonContainer.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
+
"sourcesContent": ["import React from 'react';\nimport { SkeletonMenuItem } from '@elliemae/ds-menu-items';\nimport { Grid } from '@elliemae/ds-grid';\nimport { styled } from '@elliemae/ds-system';\nimport { DSAutocompleteName, DSAutocompleteSlots } from '../../constants/index.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\n\nconst StyledSkeletonMenuItem = styled(SkeletonMenuItem, {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.SKELETON_MENU_ITEM,\n})``;\n\nconst SKELETON_AMOUNT = [0, 1, 2, 3, 4] as const;\n\nexport const SkeletonContainer = ({\n autoCompleteId,\n getOwnerProps,\n}: {\n autoCompleteId: string;\n getOwnerProps: () => object;\n}): JSX.Element => (\n /**\n * Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a\n * busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /\n * StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.\n */\n <Grid\n id={`menu-list-${autoCompleteId}`}\n data-testid={AutocompleteDataTestid.SKELETON}\n role=\"listbox\"\n aria-busy\n aria-label=\"Loading options please wait\"\n >\n {SKELETON_AMOUNT.map((n, index) => (\n <StyledSkeletonMenuItem key={n} dsId={index.toString()} role=\"presentation\" getOwnerProps={getOwnerProps} />\n ))}\n </Grid>\n);\n\nexport default SkeletonContainer;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADkCjB;AAjCN,2BAAiC;AACjC,qBAAqB;AACrB,uBAAuB;AACvB,uBAAwD;AACxD,qCAAuC;AAEvC,MAAM,6BAAyB,yBAAO,uCAAkB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,qCAAoB;AAC5B,CAAC;AAED,MAAM,kBAAkB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/B,MAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,aAAa,cAAc;AAAA,MAC/B,eAAa,sDAAuB;AAAA,MACpC,MAAK;AAAA,MACL,aAAS;AAAA,MACT,cAAW;AAAA,MAEV,0BAAgB,IAAI,CAAC,GAAG,UACvB,4CAAC,0BAA+B,MAAM,MAAM,SAAS,GAAG,MAAK,gBAAe,iBAA/C,CAA6E,CAC3G;AAAA;AAAA,EACH;AAAA;AAGF,IAAO,4BAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -52,6 +52,8 @@ const DSAutocompletePropTypes = {
|
|
|
52
52
|
inputProps: import_ds_props_helpers.PropTypes.object.description("Props to pass to the input component").defaultValue({}),
|
|
53
53
|
onValueChange: import_ds_props_helpers.PropTypes.func.description("Function triggered when the value of the input changes").defaultValue(""),
|
|
54
54
|
renderInput: import_ds_props_helpers.PropTypes.func.description("Function to render the input").defaultValue(""),
|
|
55
|
+
isLoading: import_ds_props_helpers.PropTypes.bool.description("Shows a loading spinner in the menu while options are being fetched.").defaultValue("false"),
|
|
56
|
+
isSkeleton: import_ds_props_helpers.PropTypes.bool.description("Displays the menu in skeleton loading mode.").defaultValue("false"),
|
|
55
57
|
startPlacementPreference: import_ds_props_helpers.PropTypes.string.description("Ideal preference for context placement").defaultValue("bottom-start"),
|
|
56
58
|
placementOrderPreference: import_ds_props_helpers.PropTypes.arrayOf(import_ds_props_helpers.PropTypes.string).description("Placement preferences for the context menu in order of most preferred to least preferred").defaultValue("['bottom-start', 'bottom-end']"),
|
|
57
59
|
withoutPortal: import_ds_props_helpers.PropTypes.bool.description("Whether to render the context menu in a react portal or next to the input DOM element").defaultValue("false (next to the input)"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/react-desc-prop-types.ts", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable no-unused-vars */\nimport type React from 'react';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport type { DSHookFloatingContextT } from '@elliemae/ds-floating-context';\n\nimport { globalAttributesPropTypes, PropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type { DSInputTextT } from '@elliemae/ds-form-input-text';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n // this was never implemented?\n // packages/forms/ds-form-layout-autocomplete/src/parts/menu-list/useItemRenderer.tsx\n // only have code for ItemOption and ItemSectionOptions...\n // export interface ItemSeparatorOptions extends CommonItemOptions {\n // type: 'separator';\n // }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\n options: ItemOption[];\n }\n\n export interface ItemOption extends CommonItemOptions {\n value: string;\n label: string;\n type: 'option';\n }\n\n export type OptionTypes = ItemOption | ItemSectionOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n filter: string;\n onSelect: (\n suggestedValue: string,\n e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>,\n ) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: DSHookFloatingContextT.PopperPlacementsT[];\n withoutPortal: boolean;\n zIndex: number;\n forceFocusFirstOptionOnType: boolean;\n }\n\n export interface OptionalProps {\n children?: React.ReactNode;\n inputProps?: DSInputTextT.Props;\n onValueChange?: (nextValue: string | number, e: React.ChangeEvent<HTMLInputElement>) => void;\n renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n}\n\nexport const defaultProps: DSAutocompleteT.DefaultProps = {\n zIndex: 10,\n withoutPortal: false,\n forceFocusFirstOptionOnType: false,\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n};\n\nexport const DSAutocompletePropTypes: DSPropTypesSchema<DSAutocompleteT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n options: PropTypes.oneOfType([PropTypes.array, PropTypes.object])\n .isRequired.description('List of options')\n .defaultValue([]),\n filter: PropTypes.string.isRequired.description('String value to filter the options').defaultValue(''),\n onSelect: PropTypes.func.isRequired\n .description('function triggered when an option is selected it will send the options selected')\n .defaultValue(''),\n children: PropTypes.node\n .description('React component to apply autocomplete functionality')\n .defaultValue('')\n .deprecated({ version: '3.x' }),\n inputProps: PropTypes.object.description('Props to pass to the input component').defaultValue({}),\n onValueChange: PropTypes.func.description('Function triggered when the value of the input changes').defaultValue(''),\n renderInput: PropTypes.func.description('Function to render the input').defaultValue(''),\n startPlacementPreference: PropTypes.string\n .description('Ideal preference for context placement')\n .defaultValue('bottom-start'),\n placementOrderPreference: PropTypes.arrayOf(PropTypes.string)\n .description('Placement preferences for the context menu in order of most preferred to least preferred')\n .defaultValue(\"['bottom-start', 'bottom-end']\"),\n withoutPortal: PropTypes.bool\n .description('Whether to render the context menu in a react portal or next to the input DOM element')\n .defaultValue('false (next to the input)'),\n forceFocusFirstOptionOnType: PropTypes.bool\n .description(\n 'Whether to focus the first option when typing (NOT RECOMMENDED AND BREAKING A11Y STANDARDS + ALL USERS USABILITY)',\n )\n .defaultValue('false'),\n};\n\nexport const DSAutocompletePropTypesSchema = DSAutocompletePropTypes as unknown as ValidationMap<DSAutocompleteT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADMvB,8BAAuE;
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable no-unused-vars */\nimport type React from 'react';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport type { DSHookFloatingContextT } from '@elliemae/ds-floating-context';\n\nimport { globalAttributesPropTypes, PropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type { DSInputTextT } from '@elliemae/ds-form-input-text';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n // this was never implemented?\n // packages/forms/ds-form-layout-autocomplete/src/parts/menu-list/useItemRenderer.tsx\n // only have code for ItemOption and ItemSectionOptions...\n // export interface ItemSeparatorOptions extends CommonItemOptions {\n // type: 'separator';\n // }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\n options: ItemOption[];\n }\n\n export interface ItemOption extends CommonItemOptions {\n value: string;\n label: string;\n type: 'option';\n }\n\n export type OptionTypes = ItemOption | ItemSectionOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n filter: string;\n onSelect: (\n suggestedValue: string,\n e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>,\n ) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: DSHookFloatingContextT.PopperPlacementsT[];\n withoutPortal: boolean;\n zIndex: number;\n forceFocusFirstOptionOnType: boolean;\n }\n\n export interface OptionalProps {\n children?: React.ReactNode;\n inputProps?: DSInputTextT.Props;\n onValueChange?: (nextValue: string | number, e: React.ChangeEvent<HTMLInputElement>) => void;\n renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;\n isLoading?: boolean;\n isSkeleton?: boolean;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n}\n\nexport const defaultProps: DSAutocompleteT.DefaultProps = {\n zIndex: 10,\n withoutPortal: false,\n forceFocusFirstOptionOnType: false,\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n};\n\nexport const DSAutocompletePropTypes: DSPropTypesSchema<DSAutocompleteT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n options: PropTypes.oneOfType([PropTypes.array, PropTypes.object])\n .isRequired.description('List of options')\n .defaultValue([]),\n filter: PropTypes.string.isRequired.description('String value to filter the options').defaultValue(''),\n onSelect: PropTypes.func.isRequired\n .description('function triggered when an option is selected it will send the options selected')\n .defaultValue(''),\n children: PropTypes.node\n .description('React component to apply autocomplete functionality')\n .defaultValue('')\n .deprecated({ version: '3.x' }),\n inputProps: PropTypes.object.description('Props to pass to the input component').defaultValue({}),\n onValueChange: PropTypes.func.description('Function triggered when the value of the input changes').defaultValue(''),\n renderInput: PropTypes.func.description('Function to render the input').defaultValue(''),\n isLoading: PropTypes.bool\n .description('Shows a loading spinner in the menu while options are being fetched.')\n .defaultValue('false'),\n isSkeleton: PropTypes.bool.description('Displays the menu in skeleton loading mode.').defaultValue('false'),\n startPlacementPreference: PropTypes.string\n .description('Ideal preference for context placement')\n .defaultValue('bottom-start'),\n placementOrderPreference: PropTypes.arrayOf(PropTypes.string)\n .description('Placement preferences for the context menu in order of most preferred to least preferred')\n .defaultValue(\"['bottom-start', 'bottom-end']\"),\n withoutPortal: PropTypes.bool\n .description('Whether to render the context menu in a react portal or next to the input DOM element')\n .defaultValue('false (next to the input)'),\n forceFocusFirstOptionOnType: PropTypes.bool\n .description(\n 'Whether to focus the first option when typing (NOT RECOMMENDED AND BREAKING A11Y STANDARDS + ALL USERS USABILITY)',\n )\n .defaultValue('false'),\n};\n\nexport const DSAutocompletePropTypesSchema = DSAutocompletePropTypes as unknown as ValidationMap<DSAutocompleteT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADMvB,8BAAuE;AA4EhE,MAAM,eAA6C;AAAA,EACxD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,6BAA6B;AAAA,EAC7B,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,gBAAgB,WAAW;AACxD;AAEO,MAAM,0BAAoE;AAAA,EAC/E,GAAG;AAAA,EACH,GAAG;AAAA,EACH,SAAS,kCAAU,UAAU,CAAC,kCAAU,OAAO,kCAAU,MAAM,CAAC,EAC7D,WAAW,YAAY,iBAAiB,EACxC,aAAa,CAAC,CAAC;AAAA,EAClB,QAAQ,kCAAU,OAAO,WAAW,YAAY,oCAAoC,EAAE,aAAa,EAAE;AAAA,EACrG,UAAU,kCAAU,KAAK,WACtB,YAAY,iFAAiF,EAC7F,aAAa,EAAE;AAAA,EAClB,UAAU,kCAAU,KACjB,YAAY,qDAAqD,EACjE,aAAa,EAAE,EACf,WAAW,EAAE,SAAS,MAAM,CAAC;AAAA,EAChC,YAAY,kCAAU,OAAO,YAAY,sCAAsC,EAAE,aAAa,CAAC,CAAC;AAAA,EAChG,eAAe,kCAAU,KAAK,YAAY,wDAAwD,EAAE,aAAa,EAAE;AAAA,EACnH,aAAa,kCAAU,KAAK,YAAY,8BAA8B,EAAE,aAAa,EAAE;AAAA,EACvF,WAAW,kCAAU,KAClB,YAAY,sEAAsE,EAClF,aAAa,OAAO;AAAA,EACvB,YAAY,kCAAU,KAAK,YAAY,6CAA6C,EAAE,aAAa,OAAO;AAAA,EAC1G,0BAA0B,kCAAU,OACjC,YAAY,wCAAwC,EACpD,aAAa,cAAc;AAAA,EAC9B,0BAA0B,kCAAU,QAAQ,kCAAU,MAAM,EACzD,YAAY,0FAA0F,EACtG,aAAa,gCAAgC;AAAA,EAChD,eAAe,kCAAU,KACtB,YAAY,uFAAuF,EACnG,aAAa,2BAA2B;AAAA,EAC3C,6BAA6B,kCAAU,KACpC;AAAA,IACC;AAAA,EACF,EACC,aAAa,OAAO;AACzB;AAEO,MAAM,gCAAgC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -93,6 +93,8 @@ const ExampleUsageComponent = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)
|
|
|
93
93
|
placementOrderPreference: ["bottom", "top"],
|
|
94
94
|
withoutPortal: false,
|
|
95
95
|
zIndex: 1e3,
|
|
96
|
+
isLoading: false,
|
|
97
|
+
isSkeleton: false,
|
|
96
98
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", {})
|
|
97
99
|
}
|
|
98
100
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/typescript-testing/typescript-autocomplete-valid.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { DSAutocomplete } from '../index.js';\nimport type { DSAutocompleteT } from '../index.js';\n\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSAutocompleteT.Props;\ntype ComponentPropsInternals = DSAutocompleteT.InternalProps;\ntype ComponentPropsDefaultProps = DSAutocompleteT.DefaultProps;\ntype ComponentPropsRequiredProps = DSAutocompleteT.RequiredProps;\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n options: [],\n onSelect: () => {},\n filter: '',\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testPartialDefaults,\n};\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n forceFocusFirstOptionOnType: false,\n};\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n};\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferedTypeCompatibility = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n} as ComponentPropsForApp;\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSAutocomplete {...testExplicitDefinition} />\n <DSAutocomplete {...testInferedTypeCompatibility} />\n {/* works with inline values */}\n <DSAutocomplete\n options={[]}\n onSelect={() => {}}\n filter=\"\"\n startPlacementPreference=\"bottom\"\n placementOrderPreference={['bottom', 'top']}\n withoutPortal={false}\n zIndex={1000}\n >\n <input />\n </DSAutocomplete>\n </>\n);\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA,YAAuB;ACkDX;AAjDZ,eAA+B;AAS/B,MAAM,oBAAiD;AAAA,EACrD,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AACV;AAIA,MAAM,sBAA2D;AAAA,EAC/D,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAC5C;AAEA,MAAM,YAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,uBAA6D;AAAA,EACjE,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,6BAA6B;AAC/B;AACA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,UAAU,4CAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAGA,MAAM,+BAA+B;AAAA,EACnC,UAAU,4CAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAEA,MAAM,wBAAwB,MAC5B,4EAEE;AAAA,8CAAC,2BAAgB,GAAG,wBAAwB;AAAA,EAC5C,4CAAC,2BAAgB,GAAG,8BAA8B;AAAA,EAElD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,CAAC;AAAA,MACV,UAAU,MAAM;AAAA,MAAC;AAAA,MACjB,QAAO;AAAA,MACP,0BAAyB;AAAA,MACzB,0BAA0B,CAAC,UAAU,KAAK;AAAA,MAC1C,eAAe;AAAA,MACf,QAAQ;AAAA,
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { DSAutocomplete } from '../index.js';\nimport type { DSAutocompleteT } from '../index.js';\n\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSAutocompleteT.Props;\ntype ComponentPropsInternals = DSAutocompleteT.InternalProps;\ntype ComponentPropsDefaultProps = DSAutocompleteT.DefaultProps;\ntype ComponentPropsRequiredProps = DSAutocompleteT.RequiredProps;\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n options: [],\n onSelect: () => {},\n filter: '',\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testPartialDefaults,\n};\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n forceFocusFirstOptionOnType: false,\n};\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n};\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferedTypeCompatibility = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n} as ComponentPropsForApp;\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSAutocomplete {...testExplicitDefinition} />\n <DSAutocomplete {...testInferedTypeCompatibility} />\n {/* works with inline values */}\n <DSAutocomplete\n options={[]}\n onSelect={() => {}}\n filter=\"\"\n startPlacementPreference=\"bottom\"\n placementOrderPreference={['bottom', 'top']}\n withoutPortal={false}\n zIndex={1000}\n isLoading={false}\n isSkeleton={false}\n >\n <input />\n </DSAutocomplete>\n </>\n);\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA,YAAuB;ACkDX;AAjDZ,eAA+B;AAS/B,MAAM,oBAAiD;AAAA,EACrD,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AACV;AAIA,MAAM,sBAA2D;AAAA,EAC/D,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAC5C;AAEA,MAAM,YAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,uBAA6D;AAAA,EACjE,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,6BAA6B;AAC/B;AACA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,UAAU,4CAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAGA,MAAM,+BAA+B;AAAA,EACnC,UAAU,4CAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAEA,MAAM,wBAAwB,MAC5B,4EAEE;AAAA,8CAAC,2BAAgB,GAAG,wBAAwB;AAAA,EAC5C,4CAAC,2BAAgB,GAAG,8BAA8B;AAAA,EAElD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,CAAC;AAAA,MACV,UAAU,MAAM;AAAA,MAAC;AAAA,MACjB,QAAO;AAAA,MACP,0BAAyB;AAAA,MACzB,0BAA0B,CAAC,UAAU,KAAK;AAAA,MAC1C,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MAEZ,sDAAC,WAAM;AAAA;AAAA,EACT;AAAA,GACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,7 +3,9 @@ const AutocompleteDataTestid = {
|
|
|
3
3
|
LIST: "autocomplete-menu-list",
|
|
4
4
|
OPTION: "autocomplete-option",
|
|
5
5
|
CONTAINER: "autocomplete-container",
|
|
6
|
-
INPUT: "ds-autocomplete-input"
|
|
6
|
+
INPUT: "ds-autocomplete-input",
|
|
7
|
+
LOADING: "autocomplete-loading",
|
|
8
|
+
SKELETON: "autocomplete-skeleton"
|
|
7
9
|
};
|
|
8
10
|
export {
|
|
9
11
|
AutocompleteDataTestid
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/AutocompleteDataTestids.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export const AutocompleteDataTestid = {\n LIST: 'autocomplete-menu-list',\n OPTION: 'autocomplete-option',\n CONTAINER: 'autocomplete-container',\n INPUT: 'ds-autocomplete-input',\n};\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACAhB,MAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export const AutocompleteDataTestid = {\n LIST: 'autocomplete-menu-list',\n OPTION: 'autocomplete-option',\n CONTAINER: 'autocomplete-container',\n INPUT: 'ds-autocomplete-input',\n LOADING: 'autocomplete-loading',\n SKELETON: 'autocomplete-skeleton',\n};\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACAhB,MAAM,yBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AACZ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,13 +2,13 @@ import * as React from "react";
|
|
|
2
2
|
import React2, { useState, useEffect } from "react";
|
|
3
3
|
import { useHandleFocusOnPopoverOpenLogic } from "./useHandleFocusOnPopoverOpenLogic.js";
|
|
4
4
|
const usePopoverLogic = (propsWithDefault, setCurrentOption) => {
|
|
5
|
-
const { options, filter, forceFocusFirstOptionOnType } = propsWithDefault;
|
|
5
|
+
const { options, filter, forceFocusFirstOptionOnType, isLoading, isSkeleton } = propsWithDefault;
|
|
6
6
|
const [forceClosePopover, setForceClosePopover] = useState(false);
|
|
7
7
|
const [userTypedSomething, setUserTypedSomething] = useState(false);
|
|
8
8
|
const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = useState(false);
|
|
9
9
|
const [userJustSelectedAnOption, setUserJustSelectedAnOption] = useState(false);
|
|
10
10
|
const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;
|
|
11
|
-
const popoverHasAnythingToShow = options.length > 0 && filter.length > 0;
|
|
11
|
+
const popoverHasAnythingToShow = (options.length > 0 || !!isLoading || !!isSkeleton) && filter.length > 0;
|
|
12
12
|
const isShowingPopover = !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover
|
|
13
13
|
popoverHasAnythingToShow && // nothing to show --> hide popover
|
|
14
14
|
!userSelectedAndDidNotType && // user just selected an option --> hide popover
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/usePopoverLogic.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useState, useEffect } from 'react';\nimport type { DSAutocompleteT } from '../react-desc-prop-types.js';\nimport { useHandleFocusOnPopoverOpenLogic } from './useHandleFocusOnPopoverOpenLogic.js';\n\n// we want to own all the popover logic in a single place\n// we handle global events via window.addEventListener/RemoveEventListener\n// the logic to show/hide the popover accounts for\n// show:\n// - the user just typed something (excluding special keys like arrows, enter, etc)\n// - any options are available\n// - the user did not just select an option\n// N.B. this must react to options.length changing in an async way\n// hide:\n// - the user just selected an option and did not type anything after\n// - no options are available\n// - the focus is not on the input\n// - the user pressed the escape key\nexport const usePopoverLogic = (\n propsWithDefault: DSAutocompleteT.InternalProps,\n setCurrentOption: React.Dispatch<React.SetStateAction<string>>,\n) => {\n const { options, filter, forceFocusFirstOptionOnType } = propsWithDefault;\n\n const [forceClosePopover, setForceClosePopover] = useState<boolean>(false);\n\n const [userTypedSomething, setUserTypedSomething] = useState<boolean>(false);\n const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = useState<boolean>(false);\n const [userJustSelectedAnOption, setUserJustSelectedAnOption] = useState<boolean>(false);\n\n const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;\n const popoverHasAnythingToShow = options.length > 0 && filter.length > 0;\n\n const isShowingPopover =\n !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover\n popoverHasAnythingToShow && // nothing to show --> hide popover\n !userSelectedAndDidNotType && // user just selected an option --> hide popover\n (userTypedSomething || // user typed something --> show popover\n userIsNavigatingWithArrows); // user is navigating with arrows --> show popover\n\n // we don't want to redeclar all the functions when the flag changes, the flag is relevant on invocation only\n // so we use a ref to store the value of the flag and use it in the functions\n const isShowingRef = React.useRef(isShowingPopover);\n isShowingRef.current = isShowingPopover;\n\n const trackUserTyping: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n // [...e.key].length === 1 -> \"printable\" characters including https://mathiasbynens.be/notes/javascript-unicode\n if ([...e.key].length === 1 || key === 'Backspace' || key === 'Delete') {\n setUserTypedSomething(true);\n setForceClosePopover(false);\n setUserJustSelectedAnOption(false);\n } else {\n setUserTypedSomething(false);\n }\n }, []);\n const trackUserNavigatingWithArrows: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (isShowingRef.current && (key === 'ArrowUp' || key === 'ArrowDown')) {\n setUserIsNavigatingWithArrows(true);\n } else {\n setUserIsNavigatingWithArrows(false);\n }\n }, []);\n const trackUserSelectingAnOption: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (key === 'Enter' && isShowingRef.current) {\n setUserJustSelectedAnOption(true);\n }\n }, []);\n\n const trackUserInteractingViaKeyboard: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback(\n (e) => {\n trackUserTyping(e);\n trackUserNavigatingWithArrows(e);\n trackUserSelectingAnOption(e);\n },\n [trackUserTyping, trackUserNavigatingWithArrows, trackUserSelectingAnOption],\n );\n const closePopover = React.useCallback(() => {\n setForceClosePopover(true);\n setCurrentOption('');\n }, [setCurrentOption]);\n\n // when the webpage is blurred, we want to close the popover\n // should be fixing iframes interactions?\n useEffect(() => {\n window.addEventListener('blur', closePopover);\n return () => {\n window.removeEventListener('blur', closePopover);\n };\n }, [closePopover]);\n\n useHandleFocusOnPopoverOpenLogic({\n options,\n forceFocusFirstOptionOnType,\n isShowingPopover,\n setCurrentOption,\n });\n\n return React.useMemo(\n () => ({\n isShowingPopover,\n forceClosePopover,\n setForceClosePopover,\n userTypedSomething,\n setUserTypedSomething,\n setUserJustSelectedAnOption,\n userIsNavigatingWithArrows,\n setUserIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n }),\n [\n isShowingPopover,\n forceClosePopover,\n userTypedSomething,\n userIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n ],\n );\n};\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,UAAS,UAAU,iBAAiB;AAE3C,SAAS,wCAAwC;AAe1C,MAAM,kBAAkB,CAC7B,kBACA,qBACG;AACH,QAAM,EAAE,SAAS,QAAQ,
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useState, useEffect } from 'react';\nimport type { DSAutocompleteT } from '../react-desc-prop-types.js';\nimport { useHandleFocusOnPopoverOpenLogic } from './useHandleFocusOnPopoverOpenLogic.js';\n\n// we want to own all the popover logic in a single place\n// we handle global events via window.addEventListener/RemoveEventListener\n// the logic to show/hide the popover accounts for\n// show:\n// - the user just typed something (excluding special keys like arrows, enter, etc)\n// - any options are available\n// - the user did not just select an option\n// N.B. this must react to options.length changing in an async way\n// hide:\n// - the user just selected an option and did not type anything after\n// - no options are available\n// - the focus is not on the input\n// - the user pressed the escape key\nexport const usePopoverLogic = (\n propsWithDefault: DSAutocompleteT.InternalProps,\n setCurrentOption: React.Dispatch<React.SetStateAction<string>>,\n) => {\n const { options, filter, forceFocusFirstOptionOnType, isLoading, isSkeleton } = propsWithDefault;\n\n const [forceClosePopover, setForceClosePopover] = useState<boolean>(false);\n\n const [userTypedSomething, setUserTypedSomething] = useState<boolean>(false);\n const [userIsNavigatingWithArrows, setUserIsNavigatingWithArrows] = useState<boolean>(false);\n const [userJustSelectedAnOption, setUserJustSelectedAnOption] = useState<boolean>(false);\n\n const userSelectedAndDidNotType = userJustSelectedAnOption && !userTypedSomething;\n // during async fetches options is still empty, so loading/skeleton must keep the popover\n // open on their own \u2014 otherwise the spinner/skeleton would never get a chance to render\n const popoverHasAnythingToShow = (options.length > 0 || !!isLoading || !!isSkeleton) && filter.length > 0;\n\n const isShowingPopover =\n !forceClosePopover && // user pressed escape (or other interaction that forces close) --> hide popover\n popoverHasAnythingToShow && // nothing to show --> hide popover\n !userSelectedAndDidNotType && // user just selected an option --> hide popover\n (userTypedSomething || // user typed something --> show popover\n userIsNavigatingWithArrows); // user is navigating with arrows --> show popover\n\n // we don't want to redeclar all the functions when the flag changes, the flag is relevant on invocation only\n // so we use a ref to store the value of the flag and use it in the functions\n const isShowingRef = React.useRef(isShowingPopover);\n isShowingRef.current = isShowingPopover;\n\n const trackUserTyping: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n // [...e.key].length === 1 -> \"printable\" characters including https://mathiasbynens.be/notes/javascript-unicode\n if ([...e.key].length === 1 || key === 'Backspace' || key === 'Delete') {\n setUserTypedSomething(true);\n setForceClosePopover(false);\n setUserJustSelectedAnOption(false);\n } else {\n setUserTypedSomething(false);\n }\n }, []);\n const trackUserNavigatingWithArrows: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (isShowingRef.current && (key === 'ArrowUp' || key === 'ArrowDown')) {\n setUserIsNavigatingWithArrows(true);\n } else {\n setUserIsNavigatingWithArrows(false);\n }\n }, []);\n const trackUserSelectingAnOption: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback((e) => {\n const { key } = e;\n if (key === 'Enter' && isShowingRef.current) {\n setUserJustSelectedAnOption(true);\n }\n }, []);\n\n const trackUserInteractingViaKeyboard: React.KeyboardEventHandler<HTMLInputElement> = React.useCallback(\n (e) => {\n trackUserTyping(e);\n trackUserNavigatingWithArrows(e);\n trackUserSelectingAnOption(e);\n },\n [trackUserTyping, trackUserNavigatingWithArrows, trackUserSelectingAnOption],\n );\n const closePopover = React.useCallback(() => {\n setForceClosePopover(true);\n setCurrentOption('');\n }, [setCurrentOption]);\n\n // when the webpage is blurred, we want to close the popover\n // should be fixing iframes interactions?\n useEffect(() => {\n window.addEventListener('blur', closePopover);\n return () => {\n window.removeEventListener('blur', closePopover);\n };\n }, [closePopover]);\n\n useHandleFocusOnPopoverOpenLogic({\n options,\n forceFocusFirstOptionOnType,\n isShowingPopover,\n setCurrentOption,\n });\n\n return React.useMemo(\n () => ({\n isShowingPopover,\n forceClosePopover,\n setForceClosePopover,\n userTypedSomething,\n setUserTypedSomething,\n setUserJustSelectedAnOption,\n userIsNavigatingWithArrows,\n setUserIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n }),\n [\n isShowingPopover,\n forceClosePopover,\n userTypedSomething,\n userIsNavigatingWithArrows,\n trackUserInteractingViaKeyboard,\n ],\n );\n};\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,UAAS,UAAU,iBAAiB;AAE3C,SAAS,wCAAwC;AAe1C,MAAM,kBAAkB,CAC7B,kBACA,qBACG;AACH,QAAM,EAAE,SAAS,QAAQ,6BAA6B,WAAW,WAAW,IAAI;AAEhF,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAkB,KAAK;AAEzE,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAkB,KAAK;AAC3E,QAAM,CAAC,4BAA4B,6BAA6B,IAAI,SAAkB,KAAK;AAC3F,QAAM,CAAC,0BAA0B,2BAA2B,IAAI,SAAkB,KAAK;AAEvF,QAAM,4BAA4B,4BAA4B,CAAC;AAG/D,QAAM,4BAA4B,QAAQ,SAAS,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,eAAe,OAAO,SAAS;AAExG,QAAM,mBACJ,CAAC;AAAA,EACD;AAAA,EACA,CAAC;AAAA,GACA;AAAA,EACC;AAIJ,QAAM,eAAeA,OAAM,OAAO,gBAAgB;AAClD,eAAa,UAAU;AAEvB,QAAM,kBAAgEA,OAAM,YAAY,CAAC,MAAM;AAC7F,UAAM,EAAE,IAAI,IAAI;AAEhB,QAAI,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,KAAK,QAAQ,eAAe,QAAQ,UAAU;AACtE,4BAAsB,IAAI;AAC1B,2BAAqB,KAAK;AAC1B,kCAA4B,KAAK;AAAA,IACnC,OAAO;AACL,4BAAsB,KAAK;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,CAAC;AACL,QAAM,gCAA8EA,OAAM,YAAY,CAAC,MAAM;AAC3G,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,aAAa,YAAY,QAAQ,aAAa,QAAQ,cAAc;AACtE,oCAA8B,IAAI;AAAA,IACpC,OAAO;AACL,oCAA8B,KAAK;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,CAAC;AACL,QAAM,6BAA2EA,OAAM,YAAY,CAAC,MAAM;AACxG,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,QAAQ,WAAW,aAAa,SAAS;AAC3C,kCAA4B,IAAI;AAAA,IAClC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kCAAgFA,OAAM;AAAA,IAC1F,CAAC,MAAM;AACL,sBAAgB,CAAC;AACjB,oCAA8B,CAAC;AAC/B,iCAA2B,CAAC;AAAA,IAC9B;AAAA,IACA,CAAC,iBAAiB,+BAA+B,0BAA0B;AAAA,EAC7E;AACA,QAAM,eAAeA,OAAM,YAAY,MAAM;AAC3C,yBAAqB,IAAI;AACzB,qBAAiB,EAAE;AAAA,EACrB,GAAG,CAAC,gBAAgB,CAAC;AAIrB,YAAU,MAAM;AACd,WAAO,iBAAiB,QAAQ,YAAY;AAC5C,WAAO,MAAM;AACX,aAAO,oBAAoB,QAAQ,YAAY;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AAEjB,mCAAiC;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
|
@@ -4,7 +4,10 @@ const DSAutocompleteSlots = {
|
|
|
4
4
|
CONTAINER: "container",
|
|
5
5
|
INPUT: "input",
|
|
6
6
|
MENU_LIST: "menu-list",
|
|
7
|
-
OPTION: "option"
|
|
7
|
+
OPTION: "option",
|
|
8
|
+
LOADING_WRAPPER: "loading-wrapper",
|
|
9
|
+
LOADING_INDICATOR: "loading-indicator",
|
|
10
|
+
SKELETON_MENU_ITEM: "skeleton-menu-item"
|
|
8
11
|
};
|
|
9
12
|
export {
|
|
10
13
|
DSAutocompleteName,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/constants/index.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export const DSAutocompleteName = 'DSAutocomplete';\n\nexport const DSAutocompleteSlots = {\n CONTAINER: 'container',\n INPUT: 'input',\n MENU_LIST: 'menu-list',\n OPTION: 'option',\n};\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACAhB,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAAA,EACjC,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export const DSAutocompleteName = 'DSAutocomplete';\n\nexport const DSAutocompleteSlots = {\n CONTAINER: 'container',\n INPUT: 'input',\n MENU_LIST: 'menu-list',\n OPTION: 'option',\n LOADING_WRAPPER: 'loading-wrapper',\n LOADING_INDICATOR: 'loading-indicator',\n SKELETON_MENU_ITEM: 'skeleton-menu-item',\n};\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACAhB,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAAA,EACjC,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,oBAAoB;AACtB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { styled } from "@elliemae/ds-system";
|
|
4
|
+
import { DSCircularIndeterminateIndicator } from "@elliemae/ds-circular-progress-indicator";
|
|
5
|
+
import { DSAutocompleteName, DSAutocompleteSlots } from "../../constants/index.js";
|
|
6
|
+
import { AutocompleteDataTestid } from "../../AutocompleteDataTestids.js";
|
|
7
|
+
const Wrapper = styled("div", {
|
|
8
|
+
name: DSAutocompleteName,
|
|
9
|
+
slot: DSAutocompleteSlots.LOADING_WRAPPER
|
|
10
|
+
})`
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
height: 56px;
|
|
14
|
+
`;
|
|
15
|
+
const StyledDSCircularIndeterminateIndicator = styled(DSCircularIndeterminateIndicator, {
|
|
16
|
+
name: DSAutocompleteName,
|
|
17
|
+
slot: DSAutocompleteSlots.LOADING_INDICATOR
|
|
18
|
+
})``;
|
|
19
|
+
const LoadingContainer = ({
|
|
20
|
+
autoCompleteId,
|
|
21
|
+
getOwnerProps
|
|
22
|
+
}) => (
|
|
23
|
+
/**
|
|
24
|
+
* Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a
|
|
25
|
+
* busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /
|
|
26
|
+
* StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.
|
|
27
|
+
*/
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
Wrapper,
|
|
30
|
+
{
|
|
31
|
+
id: `menu-list-${autoCompleteId}`,
|
|
32
|
+
"data-testid": AutocompleteDataTestid.LOADING,
|
|
33
|
+
role: "listbox",
|
|
34
|
+
"aria-busy": true,
|
|
35
|
+
"aria-label": "Loading options please wait",
|
|
36
|
+
getOwnerProps,
|
|
37
|
+
children: /* @__PURE__ */ jsx(StyledDSCircularIndeterminateIndicator, { size: "m", "aria-hidden": "true", getOwnerProps })
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
var LoadingContainer_default = LoadingContainer;
|
|
42
|
+
export {
|
|
43
|
+
LoadingContainer,
|
|
44
|
+
LoadingContainer_default as default
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=LoadingContainer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/menu-list/LoadingContainer.tsx"],
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { styled } from '@elliemae/ds-system';\nimport { DSCircularIndeterminateIndicator } from '@elliemae/ds-circular-progress-indicator';\nimport { DSAutocompleteName, DSAutocompleteSlots } from '../../constants/index.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\n\nconst Wrapper = styled('div', {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.LOADING_WRAPPER,\n})`\n display: flex;\n justify-content: center;\n height: 56px;\n`;\n\nconst StyledDSCircularIndeterminateIndicator = styled(DSCircularIndeterminateIndicator, {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.LOADING_INDICATOR,\n})``;\n\nexport const LoadingContainer = ({\n autoCompleteId,\n getOwnerProps,\n}: {\n autoCompleteId: string;\n getOwnerProps: () => object;\n}): JSX.Element => (\n /**\n * Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a\n * busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /\n * StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.\n */\n <Wrapper\n id={`menu-list-${autoCompleteId}`}\n data-testid={AutocompleteDataTestid.LOADING}\n role=\"listbox\"\n aria-busy\n aria-label=\"Loading options please wait\"\n getOwnerProps={getOwnerProps}\n >\n {/**\n * The spinner exposes role=\"status\", which is a forbidden child of role=\"listbox\"\n * (aria-allowed-children, axe Critical). aria-hidden removes it from the accessibility tree so\n * it no longer counts as a listbox child; the listbox's own aria-busy + aria-label remains the\n * single loading announcement. The spinner stays purely visual.\n */}\n <StyledDSCircularIndeterminateIndicator size=\"m\" aria-hidden=\"true\" getOwnerProps={getOwnerProps} />\n </Wrapper>\n);\n\nexport default LoadingContainer;\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;AC8CnB;AA7CJ,SAAS,cAAc;AACvB,SAAS,wCAAwC;AACjD,SAAS,oBAAoB,2BAA2B;AACxD,SAAS,8BAA8B;AAEvC,MAAM,UAAU,OAAO,OAAO;AAAA,EAC5B,MAAM;AAAA,EACN,MAAM,oBAAoB;AAC5B,CAAC;AAAA;AAAA;AAAA;AAAA;AAMD,MAAM,yCAAyC,OAAO,kCAAkC;AAAA,EACtF,MAAM;AAAA,EACN,MAAM,oBAAoB;AAC5B,CAAC;AAEM,MAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,aAAa,cAAc;AAAA,MAC/B,eAAa,uBAAuB;AAAA,MACpC,MAAK;AAAA,MACL,aAAS;AAAA,MACT,cAAW;AAAA,MACX;AAAA,MAQA,8BAAC,0CAAuC,MAAK,KAAI,eAAY,QAAO,eAA8B;AAAA;AAAA,EACpG;AAAA;AAGF,IAAO,2BAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -6,9 +6,11 @@ import { AutocompleteDataTestid } from "../../AutocompleteDataTestids.js";
|
|
|
6
6
|
import AutocompleteContext from "../../AutocompleteCTX.js";
|
|
7
7
|
import { useItemRenderer } from "./useItemRenderer.js";
|
|
8
8
|
import { useOnElementResize } from "../../utils/useOnElementResize.js";
|
|
9
|
+
import { LoadingContainer } from "./LoadingContainer.js";
|
|
10
|
+
import { SkeletonContainer } from "./SkeletonContainer.js";
|
|
9
11
|
const MenuList = () => {
|
|
10
12
|
const {
|
|
11
|
-
props: { options },
|
|
13
|
+
props: { options, isLoading, isSkeleton },
|
|
12
14
|
referenceElement,
|
|
13
15
|
inputRef,
|
|
14
16
|
listRef,
|
|
@@ -29,20 +31,26 @@ const MenuList = () => {
|
|
|
29
31
|
const rafId = requestAnimationFrame(() => measure());
|
|
30
32
|
return () => cancelAnimationFrame(rafId);
|
|
31
33
|
}, [width]);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
const renderMenuContent = () => {
|
|
35
|
+
if (isSkeleton) return /* @__PURE__ */ jsx(SkeletonContainer, { autoCompleteId, getOwnerProps });
|
|
36
|
+
if (isLoading) return /* @__PURE__ */ jsx(LoadingContainer, { autoCompleteId, getOwnerProps });
|
|
37
|
+
if (options.length === 0) return null;
|
|
38
|
+
return /* @__PURE__ */ jsx(StyledVirtualListWrapper, { tabIndex: -1, innerRef: listRef, children: /* @__PURE__ */ jsx(
|
|
39
|
+
StyledList,
|
|
40
|
+
{
|
|
41
|
+
role: "listbox",
|
|
42
|
+
id: `menu-list-${autoCompleteId}`,
|
|
43
|
+
"aria-label": "autocomplete option lists",
|
|
44
|
+
onFocus: handleOnFocus,
|
|
45
|
+
"data-testid": AutocompleteDataTestid.LIST,
|
|
46
|
+
style: { height: totalSize, margin: "8px 0px" },
|
|
47
|
+
getOwnerProps,
|
|
48
|
+
children: ItemRenderer
|
|
49
|
+
},
|
|
50
|
+
options.length
|
|
51
|
+
) });
|
|
52
|
+
};
|
|
53
|
+
return /* @__PURE__ */ jsx(StyledListWrapper, { onMouseDown: preventMouseDown, minWidth: referenceElement?.offsetWidth, children: renderMenuContent() });
|
|
46
54
|
};
|
|
47
55
|
export {
|
|
48
56
|
MenuList
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/menu-list/MenuList.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useContext, useCallback, useEffect } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\nimport AutocompleteContext from '../../AutocompleteCTX.js';\nimport { useItemRenderer } from './useItemRenderer.js';\nimport { useOnElementResize } from '../../utils/useOnElementResize.js';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options },\n referenceElement,\n inputRef,\n listRef,\n autoCompleteId,\n getOwnerProps,\n virtualListHelpers: { totalSize, measure },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n const { width } = useOnElementResize(referenceElement);\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const preventMouseDown: React.MouseEventHandler<HTMLDivElement> = useCallback((e) => {\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n if (!measure) return undefined;\n // Defer measure() to the next animation frame so it never runs inside an active\n // React sync flush (React 17 / legacy mode). Without the deferral, the call chain\n // outputsize \u2192 setWidth \u2192 [flushSyncCallbackQueue] \u2192 commit \u2192 measureRef \u2192\n // setMeasuredCache \u2192 [new syncQueue entry] \u2192 commit \u2192 measureRef \u2192 \u2026\n // keeps adding entries to the live syncQueue array that flushSyncCallbackQueue\n // is iterating over, producing 25+ nested commits and the\n // \"Maximum update depth exceeded\" crash. requestAnimationFrame breaks that chain\n // by scheduling measure() for after the current flush completes.\n const rafId = requestAnimationFrame(() => measure());\n return () => cancelAnimationFrame(rafId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [width]);\n\n
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useContext, useCallback, useEffect } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\nimport AutocompleteContext from '../../AutocompleteCTX.js';\nimport { useItemRenderer } from './useItemRenderer.js';\nimport { useOnElementResize } from '../../utils/useOnElementResize.js';\nimport { LoadingContainer } from './LoadingContainer.js';\nimport { SkeletonContainer } from './SkeletonContainer.js';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options, isLoading, isSkeleton },\n referenceElement,\n inputRef,\n listRef,\n autoCompleteId,\n getOwnerProps,\n virtualListHelpers: { totalSize, measure },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n const { width } = useOnElementResize(referenceElement);\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const preventMouseDown: React.MouseEventHandler<HTMLDivElement> = useCallback((e) => {\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n if (!measure) return undefined;\n // Defer measure() to the next animation frame so it never runs inside an active\n // React sync flush (React 17 / legacy mode). Without the deferral, the call chain\n // outputsize \u2192 setWidth \u2192 [flushSyncCallbackQueue] \u2192 commit \u2192 measureRef \u2192\n // setMeasuredCache \u2192 [new syncQueue entry] \u2192 commit \u2192 measureRef \u2192 \u2026\n // keeps adding entries to the live syncQueue array that flushSyncCallbackQueue\n // is iterating over, producing 25+ nested commits and the\n // \"Maximum update depth exceeded\" crash. requestAnimationFrame breaks that chain\n // by scheduling measure() for after the current flush completes.\n const rafId = requestAnimationFrame(() => measure());\n return () => cancelAnimationFrame(rafId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [width]);\n\n const renderMenuContent = () => {\n // Loading/skeleton own the listbox id + role + aria-busy while options are being fetched;\n // only one of skeleton / loading / list is ever mounted at a time (see the containers).\n if (isSkeleton) return <SkeletonContainer autoCompleteId={autoCompleteId} getOwnerProps={getOwnerProps} />;\n if (isLoading) return <LoadingContainer autoCompleteId={autoCompleteId} getOwnerProps={getOwnerProps} />;\n if (options.length === 0) return null;\n return (\n <StyledVirtualListWrapper tabIndex={-1} innerRef={listRef}>\n <StyledList\n // recalculate the key to force the re-render of the list and update virtualization\n key={options.length}\n role=\"listbox\"\n id={`menu-list-${autoCompleteId}`}\n // default aria label until we integrate the aria props on autocomplete\n // this is for the axe core to pass\n aria-label=\"autocomplete option lists\"\n onFocus={handleOnFocus}\n data-testid={AutocompleteDataTestid.LIST}\n style={{ height: totalSize, margin: '8px 0px' }}\n getOwnerProps={getOwnerProps}\n >\n {ItemRenderer}\n </StyledList>\n </StyledVirtualListWrapper>\n );\n };\n\n return (\n <StyledListWrapper onMouseDown={preventMouseDown} minWidth={referenceElement?.offsetWidth}>\n {renderMenuContent()}\n </StyledListWrapper>\n );\n};\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACiDI;AAjD3B,SAAgB,YAAY,aAAa,iBAAiB;AAC1D,SAAS,mBAAmB,YAAY,gCAAgC;AACxE,SAAS,8BAA8B;AACvC,OAAO,yBAAyB;AAChC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAE3B,MAAM,WAAW,MAAmB;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,WAAW,WAAW;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,EAAE,WAAW,QAAQ;AAAA,EAC3C,IAAI,WAAW,mBAAmB;AAElC,QAAM,eAAe,gBAAgB;AACrC,QAAM,EAAE,MAAM,IAAI,mBAAmB,gBAAgB;AAErD,QAAM,gBAAgB,YAAY,MAAM;AACtC,aAAS,SAAS,MAAM;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,mBAA4D,YAAY,CAAC,MAAM;AACnF,MAAE,eAAe;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,CAAC,QAAS,QAAO;AASrB,UAAM,QAAQ,sBAAsB,MAAM,QAAQ,CAAC;AACnD,WAAO,MAAM,qBAAqB,KAAK;AAAA,EAEzC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,oBAAoB,MAAM;AAG9B,QAAI,WAAY,QAAO,oBAAC,qBAAkB,gBAAgC,eAA8B;AACxG,QAAI,UAAW,QAAO,oBAAC,oBAAiB,gBAAgC,eAA8B;AACtG,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,WACE,oBAAC,4BAAyB,UAAU,IAAI,UAAU,SAChD;AAAA,MAAC;AAAA;AAAA,QAGC,MAAK;AAAA,QACL,IAAI,aAAa,cAAc;AAAA,QAG/B,cAAW;AAAA,QACX,SAAS;AAAA,QACT,eAAa,uBAAuB;AAAA,QACpC,OAAO,EAAE,QAAQ,WAAW,QAAQ,UAAU;AAAA,QAC9C;AAAA,QAEC;AAAA;AAAA,MAXI,QAAQ;AAAA,IAYf,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,qBAAkB,aAAa,kBAAkB,UAAU,kBAAkB,aAC3E,4BAAkB,GACrB;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { SkeletonMenuItem } from "@elliemae/ds-menu-items";
|
|
4
|
+
import { Grid } from "@elliemae/ds-grid";
|
|
5
|
+
import { styled } from "@elliemae/ds-system";
|
|
6
|
+
import { DSAutocompleteName, DSAutocompleteSlots } from "../../constants/index.js";
|
|
7
|
+
import { AutocompleteDataTestid } from "../../AutocompleteDataTestids.js";
|
|
8
|
+
const StyledSkeletonMenuItem = styled(SkeletonMenuItem, {
|
|
9
|
+
name: DSAutocompleteName,
|
|
10
|
+
slot: DSAutocompleteSlots.SKELETON_MENU_ITEM
|
|
11
|
+
})``;
|
|
12
|
+
const SKELETON_AMOUNT = [0, 1, 2, 3, 4];
|
|
13
|
+
const SkeletonContainer = ({
|
|
14
|
+
autoCompleteId,
|
|
15
|
+
getOwnerProps
|
|
16
|
+
}) => (
|
|
17
|
+
/**
|
|
18
|
+
* Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a
|
|
19
|
+
* busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /
|
|
20
|
+
* StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.
|
|
21
|
+
*/
|
|
22
|
+
/* @__PURE__ */ jsx(
|
|
23
|
+
Grid,
|
|
24
|
+
{
|
|
25
|
+
id: `menu-list-${autoCompleteId}`,
|
|
26
|
+
"data-testid": AutocompleteDataTestid.SKELETON,
|
|
27
|
+
role: "listbox",
|
|
28
|
+
"aria-busy": true,
|
|
29
|
+
"aria-label": "Loading options please wait",
|
|
30
|
+
children: SKELETON_AMOUNT.map((n, index) => /* @__PURE__ */ jsx(StyledSkeletonMenuItem, { dsId: index.toString(), role: "presentation", getOwnerProps }, n))
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
var SkeletonContainer_default = SkeletonContainer;
|
|
35
|
+
export {
|
|
36
|
+
SkeletonContainer,
|
|
37
|
+
SkeletonContainer_default as default
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=SkeletonContainer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/menu-list/SkeletonContainer.tsx"],
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { SkeletonMenuItem } from '@elliemae/ds-menu-items';\nimport { Grid } from '@elliemae/ds-grid';\nimport { styled } from '@elliemae/ds-system';\nimport { DSAutocompleteName, DSAutocompleteSlots } from '../../constants/index.js';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids.js';\n\nconst StyledSkeletonMenuItem = styled(SkeletonMenuItem, {\n name: DSAutocompleteName,\n slot: DSAutocompleteSlots.SKELETON_MENU_ITEM,\n})``;\n\nconst SKELETON_AMOUNT = [0, 1, 2, 3, 4] as const;\n\nexport const SkeletonContainer = ({\n autoCompleteId,\n getOwnerProps,\n}: {\n autoCompleteId: string;\n getOwnerProps: () => object;\n}): JSX.Element => (\n /**\n * Carries the listbox id + role + aria-busy so the input's aria-controls always resolves to a\n * busy listbox while options are being fetched. Only one of LoadingContainer / SkeletonContainer /\n * StyledList ever renders at a time, so the canonical listbox id is never duplicated in the DOM.\n */\n <Grid\n id={`menu-list-${autoCompleteId}`}\n data-testid={AutocompleteDataTestid.SKELETON}\n role=\"listbox\"\n aria-busy\n aria-label=\"Loading options please wait\"\n >\n {SKELETON_AMOUNT.map((n, index) => (\n <StyledSkeletonMenuItem key={n} dsId={index.toString()} role=\"presentation\" getOwnerProps={getOwnerProps} />\n ))}\n </Grid>\n);\n\nexport default SkeletonContainer;\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACkCjB;AAjCN,SAAS,wBAAwB;AACjC,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,oBAAoB,2BAA2B;AACxD,SAAS,8BAA8B;AAEvC,MAAM,yBAAyB,OAAO,kBAAkB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,oBAAoB;AAC5B,CAAC;AAED,MAAM,kBAAkB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAE/B,MAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,aAAa,cAAc;AAAA,MAC/B,eAAa,uBAAuB;AAAA,MACpC,MAAK;AAAA,MACL,aAAS;AAAA,MACT,cAAW;AAAA,MAEV,0BAAgB,IAAI,CAAC,GAAG,UACvB,oBAAC,0BAA+B,MAAM,MAAM,SAAS,GAAG,MAAK,gBAAe,iBAA/C,CAA6E,CAC3G;AAAA;AAAA,EACH;AAAA;AAGF,IAAO,4BAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -17,6 +17,8 @@ const DSAutocompletePropTypes = {
|
|
|
17
17
|
inputProps: PropTypes.object.description("Props to pass to the input component").defaultValue({}),
|
|
18
18
|
onValueChange: PropTypes.func.description("Function triggered when the value of the input changes").defaultValue(""),
|
|
19
19
|
renderInput: PropTypes.func.description("Function to render the input").defaultValue(""),
|
|
20
|
+
isLoading: PropTypes.bool.description("Shows a loading spinner in the menu while options are being fetched.").defaultValue("false"),
|
|
21
|
+
isSkeleton: PropTypes.bool.description("Displays the menu in skeleton loading mode.").defaultValue("false"),
|
|
20
22
|
startPlacementPreference: PropTypes.string.description("Ideal preference for context placement").defaultValue("bottom-start"),
|
|
21
23
|
placementOrderPreference: PropTypes.arrayOf(PropTypes.string).description("Placement preferences for the context menu in order of most preferred to least preferred").defaultValue("['bottom-start', 'bottom-end']"),
|
|
22
24
|
withoutPortal: PropTypes.bool.description("Whether to render the context menu in a react portal or next to the input DOM element").defaultValue("false (next to the input)"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/react-desc-prop-types.ts"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable no-unused-vars */\nimport type React from 'react';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport type { DSHookFloatingContextT } from '@elliemae/ds-floating-context';\n\nimport { globalAttributesPropTypes, PropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type { DSInputTextT } from '@elliemae/ds-form-input-text';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n // this was never implemented?\n // packages/forms/ds-form-layout-autocomplete/src/parts/menu-list/useItemRenderer.tsx\n // only have code for ItemOption and ItemSectionOptions...\n // export interface ItemSeparatorOptions extends CommonItemOptions {\n // type: 'separator';\n // }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\n options: ItemOption[];\n }\n\n export interface ItemOption extends CommonItemOptions {\n value: string;\n label: string;\n type: 'option';\n }\n\n export type OptionTypes = ItemOption | ItemSectionOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n filter: string;\n onSelect: (\n suggestedValue: string,\n e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>,\n ) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: DSHookFloatingContextT.PopperPlacementsT[];\n withoutPortal: boolean;\n zIndex: number;\n forceFocusFirstOptionOnType: boolean;\n }\n\n export interface OptionalProps {\n children?: React.ReactNode;\n inputProps?: DSInputTextT.Props;\n onValueChange?: (nextValue: string | number, e: React.ChangeEvent<HTMLInputElement>) => void;\n renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n}\n\nexport const defaultProps: DSAutocompleteT.DefaultProps = {\n zIndex: 10,\n withoutPortal: false,\n forceFocusFirstOptionOnType: false,\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n};\n\nexport const DSAutocompletePropTypes: DSPropTypesSchema<DSAutocompleteT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n options: PropTypes.oneOfType([PropTypes.array, PropTypes.object])\n .isRequired.description('List of options')\n .defaultValue([]),\n filter: PropTypes.string.isRequired.description('String value to filter the options').defaultValue(''),\n onSelect: PropTypes.func.isRequired\n .description('function triggered when an option is selected it will send the options selected')\n .defaultValue(''),\n children: PropTypes.node\n .description('React component to apply autocomplete functionality')\n .defaultValue('')\n .deprecated({ version: '3.x' }),\n inputProps: PropTypes.object.description('Props to pass to the input component').defaultValue({}),\n onValueChange: PropTypes.func.description('Function triggered when the value of the input changes').defaultValue(''),\n renderInput: PropTypes.func.description('Function to render the input').defaultValue(''),\n startPlacementPreference: PropTypes.string\n .description('Ideal preference for context placement')\n .defaultValue('bottom-start'),\n placementOrderPreference: PropTypes.arrayOf(PropTypes.string)\n .description('Placement preferences for the context menu in order of most preferred to least preferred')\n .defaultValue(\"['bottom-start', 'bottom-end']\"),\n withoutPortal: PropTypes.bool\n .description('Whether to render the context menu in a react portal or next to the input DOM element')\n .defaultValue('false (next to the input)'),\n forceFocusFirstOptionOnType: PropTypes.bool\n .description(\n 'Whether to focus the first option when typing (NOT RECOMMENDED AND BREAKING A11Y STANDARDS + ALL USERS USABILITY)',\n )\n .defaultValue('false'),\n};\n\nexport const DSAutocompletePropTypesSchema = DSAutocompletePropTypes as unknown as ValidationMap<DSAutocompleteT.Props>;\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACMvB,SAAS,2BAA2B,WAAW,wBAAwB;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable no-unused-vars */\nimport type React from 'react';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport type { DSHookFloatingContextT } from '@elliemae/ds-floating-context';\n\nimport { globalAttributesPropTypes, PropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type { DSInputTextT } from '@elliemae/ds-form-input-text';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n // this was never implemented?\n // packages/forms/ds-form-layout-autocomplete/src/parts/menu-list/useItemRenderer.tsx\n // only have code for ItemOption and ItemSectionOptions...\n // export interface ItemSeparatorOptions extends CommonItemOptions {\n // type: 'separator';\n // }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\n options: ItemOption[];\n }\n\n export interface ItemOption extends CommonItemOptions {\n value: string;\n label: string;\n type: 'option';\n }\n\n export type OptionTypes = ItemOption | ItemSectionOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n filter: string;\n onSelect: (\n suggestedValue: string,\n e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>,\n ) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: DSHookFloatingContextT.PopperPlacementsT[];\n withoutPortal: boolean;\n zIndex: number;\n forceFocusFirstOptionOnType: boolean;\n }\n\n export interface OptionalProps {\n children?: React.ReactNode;\n inputProps?: DSInputTextT.Props;\n onValueChange?: (nextValue: string | number, e: React.ChangeEvent<HTMLInputElement>) => void;\n renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;\n isLoading?: boolean;\n isSkeleton?: boolean;\n }\n\n export interface Props\n extends Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n\n export interface InternalProps\n extends DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>,\n Omit<XstyledProps, keyof DefaultProps> {}\n}\n\nexport const defaultProps: DSAutocompleteT.DefaultProps = {\n zIndex: 10,\n withoutPortal: false,\n forceFocusFirstOptionOnType: false,\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'top-start'],\n};\n\nexport const DSAutocompletePropTypes: DSPropTypesSchema<DSAutocompleteT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n options: PropTypes.oneOfType([PropTypes.array, PropTypes.object])\n .isRequired.description('List of options')\n .defaultValue([]),\n filter: PropTypes.string.isRequired.description('String value to filter the options').defaultValue(''),\n onSelect: PropTypes.func.isRequired\n .description('function triggered when an option is selected it will send the options selected')\n .defaultValue(''),\n children: PropTypes.node\n .description('React component to apply autocomplete functionality')\n .defaultValue('')\n .deprecated({ version: '3.x' }),\n inputProps: PropTypes.object.description('Props to pass to the input component').defaultValue({}),\n onValueChange: PropTypes.func.description('Function triggered when the value of the input changes').defaultValue(''),\n renderInput: PropTypes.func.description('Function to render the input').defaultValue(''),\n isLoading: PropTypes.bool\n .description('Shows a loading spinner in the menu while options are being fetched.')\n .defaultValue('false'),\n isSkeleton: PropTypes.bool.description('Displays the menu in skeleton loading mode.').defaultValue('false'),\n startPlacementPreference: PropTypes.string\n .description('Ideal preference for context placement')\n .defaultValue('bottom-start'),\n placementOrderPreference: PropTypes.arrayOf(PropTypes.string)\n .description('Placement preferences for the context menu in order of most preferred to least preferred')\n .defaultValue(\"['bottom-start', 'bottom-end']\"),\n withoutPortal: PropTypes.bool\n .description('Whether to render the context menu in a react portal or next to the input DOM element')\n .defaultValue('false (next to the input)'),\n forceFocusFirstOptionOnType: PropTypes.bool\n .description(\n 'Whether to focus the first option when typing (NOT RECOMMENDED AND BREAKING A11Y STANDARDS + ALL USERS USABILITY)',\n )\n .defaultValue('false'),\n};\n\nexport const DSAutocompletePropTypesSchema = DSAutocompletePropTypes as unknown as ValidationMap<DSAutocompleteT.Props>;\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACMvB,SAAS,2BAA2B,WAAW,wBAAwB;AA4EhE,MAAM,eAA6C;AAAA,EACxD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,6BAA6B;AAAA,EAC7B,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,gBAAgB,WAAW;AACxD;AAEO,MAAM,0BAAoE;AAAA,EAC/E,GAAG;AAAA,EACH,GAAG;AAAA,EACH,SAAS,UAAU,UAAU,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC,EAC7D,WAAW,YAAY,iBAAiB,EACxC,aAAa,CAAC,CAAC;AAAA,EAClB,QAAQ,UAAU,OAAO,WAAW,YAAY,oCAAoC,EAAE,aAAa,EAAE;AAAA,EACrG,UAAU,UAAU,KAAK,WACtB,YAAY,iFAAiF,EAC7F,aAAa,EAAE;AAAA,EAClB,UAAU,UAAU,KACjB,YAAY,qDAAqD,EACjE,aAAa,EAAE,EACf,WAAW,EAAE,SAAS,MAAM,CAAC;AAAA,EAChC,YAAY,UAAU,OAAO,YAAY,sCAAsC,EAAE,aAAa,CAAC,CAAC;AAAA,EAChG,eAAe,UAAU,KAAK,YAAY,wDAAwD,EAAE,aAAa,EAAE;AAAA,EACnH,aAAa,UAAU,KAAK,YAAY,8BAA8B,EAAE,aAAa,EAAE;AAAA,EACvF,WAAW,UAAU,KAClB,YAAY,sEAAsE,EAClF,aAAa,OAAO;AAAA,EACvB,YAAY,UAAU,KAAK,YAAY,6CAA6C,EAAE,aAAa,OAAO;AAAA,EAC1G,0BAA0B,UAAU,OACjC,YAAY,wCAAwC,EACpD,aAAa,cAAc;AAAA,EAC9B,0BAA0B,UAAU,QAAQ,UAAU,MAAM,EACzD,YAAY,0FAA0F,EACtG,aAAa,gCAAgC;AAAA,EAChD,eAAe,UAAU,KACtB,YAAY,uFAAuF,EACnG,aAAa,2BAA2B;AAAA,EAC3C,6BAA6B,UAAU,KACpC;AAAA,IACC;AAAA,EACF,EACC,aAAa,OAAO;AACzB;AAEO,MAAM,gCAAgC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -70,6 +70,8 @@ const ExampleUsageComponent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
|
70
70
|
placementOrderPreference: ["bottom", "top"],
|
|
71
71
|
withoutPortal: false,
|
|
72
72
|
zIndex: 1e3,
|
|
73
|
+
isLoading: false,
|
|
74
|
+
isSkeleton: false,
|
|
73
75
|
children: /* @__PURE__ */ jsx("input", {})
|
|
74
76
|
}
|
|
75
77
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/typescript-testing/typescript-autocomplete-valid.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { DSAutocomplete } from '../index.js';\nimport type { DSAutocompleteT } from '../index.js';\n\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSAutocompleteT.Props;\ntype ComponentPropsInternals = DSAutocompleteT.InternalProps;\ntype ComponentPropsDefaultProps = DSAutocompleteT.DefaultProps;\ntype ComponentPropsRequiredProps = DSAutocompleteT.RequiredProps;\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n options: [],\n onSelect: () => {},\n filter: '',\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testPartialDefaults,\n};\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n forceFocusFirstOptionOnType: false,\n};\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n};\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferedTypeCompatibility = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n} as ComponentPropsForApp;\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSAutocomplete {...testExplicitDefinition} />\n <DSAutocomplete {...testInferedTypeCompatibility} />\n {/* works with inline values */}\n <DSAutocomplete\n options={[]}\n onSelect={() => {}}\n filter=\"\"\n startPlacementPreference=\"bottom\"\n placementOrderPreference={['bottom', 'top']}\n withoutPortal={false}\n zIndex={1000}\n >\n <input />\n </DSAutocomplete>\n </>\n);\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACkDX,SAuBV,UAvBU,KAuBV,YAvBU;AAjDZ,SAAS,sBAAsB;AAS/B,MAAM,oBAAiD;AAAA,EACrD,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AACV;AAIA,MAAM,sBAA2D;AAAA,EAC/D,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAC5C;AAEA,MAAM,YAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,uBAA6D;AAAA,EACjE,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,6BAA6B;AAC/B;AACA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,UAAU,oBAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAGA,MAAM,+BAA+B;AAAA,EACnC,UAAU,oBAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAEA,MAAM,wBAAwB,MAC5B,iCAEE;AAAA,sBAAC,kBAAgB,GAAG,wBAAwB;AAAA,EAC5C,oBAAC,kBAAgB,GAAG,8BAA8B;AAAA,EAElD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,CAAC;AAAA,MACV,UAAU,MAAM;AAAA,MAAC;AAAA,MACjB,QAAO;AAAA,MACP,0BAAyB;AAAA,MACzB,0BAA0B,CAAC,UAAU,KAAK;AAAA,MAC1C,eAAe;AAAA,MACf,QAAQ;AAAA,
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-unused-vars, no-unused-vars */\nimport { DSAutocomplete } from '../index.js';\nimport type { DSAutocompleteT } from '../index.js';\n\n// test we expose the namespace and the namespace follows our deliverable conventions\ntype ComponentPropsForApp = DSAutocompleteT.Props;\ntype ComponentPropsInternals = DSAutocompleteT.InternalProps;\ntype ComponentPropsDefaultProps = DSAutocompleteT.DefaultProps;\ntype ComponentPropsRequiredProps = DSAutocompleteT.RequiredProps;\n\nconst testRequiredProps: ComponentPropsRequiredProps = {\n options: [],\n onSelect: () => {},\n filter: '',\n};\n\n// difference Props and InternalProps is that InternalProps has all the default props filled in\n// Props allows for partial defaults\nconst testPartialDefaults: Partial<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n};\n\nconst testProps: ComponentPropsForApp = {\n ...testRequiredProps,\n ...testPartialDefaults,\n};\nconst testPropsAsSyntax = {\n ...testRequiredProps,\n ...testPartialDefaults,\n} as ComponentPropsForApp;\n// InternalProps requires all defaults to be filled in\nconst testCompleteDefaults: Required<ComponentPropsDefaultProps> = {\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n forceFocusFirstOptionOnType: false,\n};\nconst testInternalProps: ComponentPropsInternals = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n};\nconst testInternalPropsAsSyntax = {\n ...testRequiredProps,\n ...testCompleteDefaults,\n} as ComponentPropsInternals;\n\n// using the explicit type definition, if there is an error, it will be marked on the key that is wrong\nconst testExplicitDefinition: ComponentPropsForApp = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n};\n\n// using the \"as\" syntax, if there is an error, it will be marking the whole object as wrong because it is not compatible with the type\nconst testInferedTypeCompatibility = {\n children: <div />,\n options: [],\n onSelect: () => {},\n filter: '',\n startPlacementPreference: 'bottom',\n placementOrderPreference: ['bottom', 'top'],\n withoutPortal: false,\n zIndex: 1000,\n} as ComponentPropsForApp;\n\nconst ExampleUsageComponent = () => (\n <>\n {/* works with explicitly casted props, all syntaxes */}\n <DSAutocomplete {...testExplicitDefinition} />\n <DSAutocomplete {...testInferedTypeCompatibility} />\n {/* works with inline values */}\n <DSAutocomplete\n options={[]}\n onSelect={() => {}}\n filter=\"\"\n startPlacementPreference=\"bottom\"\n placementOrderPreference={['bottom', 'top']}\n withoutPortal={false}\n zIndex={1000}\n isLoading={false}\n isSkeleton={false}\n >\n <input />\n </DSAutocomplete>\n </>\n);\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,WAAW;ACkDX,SAuBV,UAvBU,KAuBV,YAvBU;AAjDZ,SAAS,sBAAsB;AAS/B,MAAM,oBAAiD;AAAA,EACrD,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AACV;AAIA,MAAM,sBAA2D;AAAA,EAC/D,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAC5C;AAEA,MAAM,YAAkC;AAAA,EACtC,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,MAAM,uBAA6D;AAAA,EACjE,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,6BAA6B;AAC/B;AACA,MAAM,oBAA6C;AAAA,EACjD,GAAG;AAAA,EACH,GAAG;AACL;AACA,MAAM,4BAA4B;AAAA,EAChC,GAAG;AAAA,EACH,GAAG;AACL;AAGA,MAAM,yBAA+C;AAAA,EACnD,UAAU,oBAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAGA,MAAM,+BAA+B;AAAA,EACnC,UAAU,oBAAC,SAAI;AAAA,EACf,SAAS,CAAC;AAAA,EACV,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,QAAQ;AAAA,EACR,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,UAAU,KAAK;AAAA,EAC1C,eAAe;AAAA,EACf,QAAQ;AACV;AAEA,MAAM,wBAAwB,MAC5B,iCAEE;AAAA,sBAAC,kBAAgB,GAAG,wBAAwB;AAAA,EAC5C,oBAAC,kBAAgB,GAAG,8BAA8B;AAAA,EAElD;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,CAAC;AAAA,MACV,UAAU,MAAM;AAAA,MAAC;AAAA,MACjB,QAAO;AAAA,MACP,0BAAyB;AAAA,MACzB,0BAA0B,CAAC,UAAU,KAAK;AAAA,MAC1C,eAAe;AAAA,MACf,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,YAAY;AAAA,MAEZ,8BAAC,WAAM;AAAA;AAAA,EACT;AAAA,GACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -40,6 +40,8 @@ export declare namespace DSAutocompleteT {
|
|
|
40
40
|
inputProps?: DSInputTextT.Props;
|
|
41
41
|
onValueChange?: (nextValue: string | number, e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
42
42
|
renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;
|
|
43
|
+
isLoading?: boolean;
|
|
44
|
+
isSkeleton?: boolean;
|
|
43
45
|
}
|
|
44
46
|
interface Props extends Partial<DefaultProps>, RequiredProps, OptionalProps, Omit<GlobalAttributesT, keyof DefaultProps | keyof RequiredProps | keyof OptionalProps>, Omit<XstyledProps, keyof DefaultProps> {
|
|
45
47
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliemae/ds-form-layout-autocomplete",
|
|
3
|
-
"version": "3.70.0-next.
|
|
3
|
+
"version": "3.70.0-next.51",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "ICE MT - Dimsum - Form Layout - Autocomplete",
|
|
6
6
|
"files": [
|
|
@@ -38,22 +38,23 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"react-virtual": "~2.10.4",
|
|
40
40
|
"uid": "^2.0.2",
|
|
41
|
-
"@elliemae/ds-
|
|
42
|
-
"@elliemae/ds-floating-context": "3.70.0-next.
|
|
43
|
-
"@elliemae/ds-
|
|
44
|
-
"@elliemae/ds-
|
|
45
|
-
"@elliemae/ds-
|
|
46
|
-
"@elliemae/ds-typography": "3.70.0-next.
|
|
47
|
-
"@elliemae/ds-menu-items": "3.70.0-next.
|
|
41
|
+
"@elliemae/ds-circular-progress-indicator": "3.70.0-next.51",
|
|
42
|
+
"@elliemae/ds-floating-context": "3.70.0-next.51",
|
|
43
|
+
"@elliemae/ds-form-input-text": "3.70.0-next.51",
|
|
44
|
+
"@elliemae/ds-grid": "3.70.0-next.51",
|
|
45
|
+
"@elliemae/ds-props-helpers": "3.70.0-next.51",
|
|
46
|
+
"@elliemae/ds-typography": "3.70.0-next.51",
|
|
47
|
+
"@elliemae/ds-menu-items": "3.70.0-next.51",
|
|
48
|
+
"@elliemae/ds-system": "3.70.0-next.51"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@elliemae/pui-theme": "~2.13.0",
|
|
51
52
|
"jest": "^30.0.0",
|
|
52
53
|
"styled-components": "~5.3.9",
|
|
53
54
|
"styled-system": "^5.1.5",
|
|
54
|
-
"@elliemae/ds-
|
|
55
|
-
"@elliemae/ds-
|
|
56
|
-
"@elliemae/ds-monorepo-devops": "3.70.0-next.
|
|
55
|
+
"@elliemae/ds-test-utils": "3.70.0-next.51",
|
|
56
|
+
"@elliemae/ds-form-input-text": "3.70.0-next.51",
|
|
57
|
+
"@elliemae/ds-monorepo-devops": "3.70.0-next.51"
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
60
|
"@elliemae/pui-theme": "~2.13.0",
|