@elliemae/ds-form-layout-autocomplete 3.16.0-next.7 → 3.16.0-next.8

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.
Files changed (54) hide show
  1. package/dist/cjs/AutocompleteCTX.js +2 -22
  2. package/dist/cjs/AutocompleteCTX.js.map +2 -2
  3. package/dist/cjs/config/useAutocomplete.js +20 -48
  4. package/dist/cjs/config/useAutocomplete.js.map +3 -3
  5. package/dist/cjs/config/usePopoverLogic.js +105 -0
  6. package/dist/cjs/config/usePopoverLogic.js.map +7 -0
  7. package/dist/cjs/{sharedTypes.js → config/useRefs.js} +16 -3
  8. package/dist/cjs/config/useRefs.js.map +7 -0
  9. package/dist/cjs/config/useVirtualization.js +62 -0
  10. package/dist/cjs/config/useVirtualization.js.map +7 -0
  11. package/dist/cjs/parts/A11yFocusedOption.js +3 -3
  12. package/dist/cjs/parts/A11yFocusedOption.js.map +2 -2
  13. package/dist/cjs/parts/container/Container.js +16 -15
  14. package/dist/cjs/parts/container/Container.js.map +2 -2
  15. package/dist/cjs/parts/container/useKeyboardNavigation.js +15 -18
  16. package/dist/cjs/parts/container/useKeyboardNavigation.js.map +2 -2
  17. package/dist/cjs/parts/menu-list/MenuList.js +6 -3
  18. package/dist/cjs/parts/menu-list/MenuList.js.map +2 -2
  19. package/dist/cjs/parts/menu-list/useItemRenderer.js +5 -3
  20. package/dist/cjs/parts/menu-list/useItemRenderer.js.map +2 -2
  21. package/dist/cjs/react-desc-prop-types.js +7 -0
  22. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  23. package/dist/esm/AutocompleteCTX.js +3 -23
  24. package/dist/esm/AutocompleteCTX.js.map +2 -2
  25. package/dist/esm/config/useAutocomplete.js +18 -46
  26. package/dist/esm/config/useAutocomplete.js.map +3 -3
  27. package/dist/esm/config/usePopoverLogic.js +79 -0
  28. package/dist/esm/config/usePopoverLogic.js.map +7 -0
  29. package/dist/esm/config/useRefs.js +11 -0
  30. package/dist/esm/config/useRefs.js.map +7 -0
  31. package/dist/esm/config/useVirtualization.js +36 -0
  32. package/dist/esm/config/useVirtualization.js.map +7 -0
  33. package/dist/esm/parts/A11yFocusedOption.js +3 -3
  34. package/dist/esm/parts/A11yFocusedOption.js.map +2 -2
  35. package/dist/esm/parts/container/Container.js +17 -16
  36. package/dist/esm/parts/container/Container.js.map +2 -2
  37. package/dist/esm/parts/container/useKeyboardNavigation.js +15 -18
  38. package/dist/esm/parts/container/useKeyboardNavigation.js.map +2 -2
  39. package/dist/esm/parts/menu-list/MenuList.js +6 -3
  40. package/dist/esm/parts/menu-list/MenuList.js.map +2 -2
  41. package/dist/esm/parts/menu-list/useItemRenderer.js +5 -3
  42. package/dist/esm/parts/menu-list/useItemRenderer.js.map +2 -2
  43. package/dist/esm/react-desc-prop-types.js +7 -0
  44. package/dist/esm/react-desc-prop-types.js.map +2 -2
  45. package/dist/types/AutocompleteCTX.d.ts +2 -4
  46. package/dist/types/config/useAutocomplete.d.ts +12 -2
  47. package/dist/types/config/usePopoverLogic.d.ts +12 -0
  48. package/dist/types/config/useRefs.d.ts +5 -0
  49. package/dist/types/react-desc-prop-types.d.ts +2 -1
  50. package/package.json +7 -7
  51. package/dist/cjs/sharedTypes.js.map +0 -7
  52. package/dist/esm/sharedTypes.js +0 -2
  53. package/dist/esm/sharedTypes.js.map +0 -7
  54. package/dist/types/sharedTypes.d.ts +0 -18
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import React2, { useCallback, useMemo, useEffect, useContext } from "react";
3
+ import React2, { useCallback, useMemo, useContext } from "react";
4
4
  import { DSPopperJS } from "@elliemae/ds-popperjs";
5
5
  import AutocompleteContext from "../../AutocompleteCTX";
6
6
  import { StyledContainer, StyledPopperWrapper } from "./styled";
@@ -11,28 +11,28 @@ import { A11yFocusedOption } from "../A11yFocusedOption";
11
11
  const Container = () => {
12
12
  const {
13
13
  props: { id, startPlacementPreference, children, filter, placementOrderPreference },
14
- showPopover,
14
+ isShowingPopover,
15
15
  setReferenceElement,
16
- setShowPopover,
16
+ setUserJustSelectedAnOption,
17
+ setUserTypedSomething,
18
+ setUserIsNavigatingWithArrows,
19
+ setForceClosePopover,
17
20
  focusOptionIdx,
18
21
  referenceElement
19
22
  } = useContext(AutocompleteContext);
20
- useEffect(() => {
21
- const closePopper = () => {
22
- setShowPopover(false);
23
- };
24
- window.addEventListener("blur", closePopper);
25
- return () => {
26
- window.removeEventListener("blur", closePopper);
27
- };
28
- }, [setShowPopover]);
29
23
  const handleCloseMenu = useCallback(() => {
30
- setShowPopover(false);
31
- }, [setShowPopover]);
24
+ setForceClosePopover(true);
25
+ }, [setForceClosePopover]);
32
26
  const { onInputKeyDown } = useKeyboardNavigation();
33
27
  const input = React2.Children.only(children);
34
28
  const childrenWithProps = React2.isValidElement(input) ? React2.cloneElement(input, { "aria-activedescendant": focusOptionIdx }) : input;
35
29
  const idList = useMemo(() => `${id ? `${id}-` : ""}listbox`, [id]);
30
+ const onFocusPopoverStatusSync = useCallback(() => {
31
+ setForceClosePopover(false);
32
+ setUserJustSelectedAnOption(false);
33
+ setUserTypedSomething(false);
34
+ setUserIsNavigatingWithArrows(false);
35
+ }, [setForceClosePopover, setUserIsNavigatingWithArrows, setUserJustSelectedAnOption, setUserTypedSomething]);
36
36
  return /* @__PURE__ */ jsxs(Fragment, { children: [
37
37
  /* @__PURE__ */ jsx(A11yFocusedOption, {}),
38
38
  /* @__PURE__ */ jsxs(
@@ -43,10 +43,11 @@ const Container = () => {
43
43
  role: "combobox",
44
44
  "aria-autocomplete": "list",
45
45
  "aria-controls": "autocomplete-listbox",
46
- "aria-expanded": showPopover,
46
+ "aria-expanded": isShowingPopover,
47
47
  "aria-haspopup": "listbox",
48
48
  "aria-owns": idList,
49
49
  onKeyDown: onInputKeyDown,
50
+ onFocus: onFocusPopoverStatusSync,
50
51
  "data-testid": AutocompleteDataTestid.CONTAINER,
51
52
  children: [
52
53
  childrenWithProps,
@@ -56,7 +57,7 @@ const Container = () => {
56
57
  customOffset: [0, 5],
57
58
  closeContextMenu: handleCloseMenu,
58
59
  referenceElement,
59
- showPopover,
60
+ showPopover: isShowingPopover,
60
61
  startPlacementPreference,
61
62
  placementOrderPreference,
62
63
  withoutPortal: true,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/container/Container.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\nimport React, { useCallback, useMemo, useEffect, useContext } from 'react';\nimport { DSPopperJS } from '@elliemae/ds-popperjs';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { StyledContainer, StyledPopperWrapper } from './styled';\nimport { MenuList } from '../menu-list';\nimport { useKeyboardNavigation } from './useKeyboardNavigation';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport { A11yFocusedOption } from '../A11yFocusedOption';\nexport const Container = (): JSX.Element => {\n const {\n props: { id, startPlacementPreference, children, filter, placementOrderPreference },\n showPopover,\n setReferenceElement,\n setShowPopover,\n focusOptionIdx,\n referenceElement,\n } = useContext(AutocompleteContext);\n\n useEffect(() => {\n const closePopper = () => {\n setShowPopover(false);\n };\n window.addEventListener('blur', closePopper);\n\n return () => {\n window.removeEventListener('blur', closePopper);\n };\n }, [setShowPopover]);\n\n const handleCloseMenu = useCallback(() => {\n setShowPopover(false);\n }, [setShowPopover]);\n\n const { onInputKeyDown } = useKeyboardNavigation();\n\n const input = React.Children.only(children);\n\n const childrenWithProps = React.isValidElement(input)\n ? React.cloneElement(input, { 'aria-activedescendant': focusOptionIdx })\n : input;\n\n const idList = useMemo(() => `${id ? `${id}-` : ''}listbox`, [id]);\n\n return (\n <>\n <A11yFocusedOption />\n\n <StyledContainer\n id={id}\n ref={setReferenceElement}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-controls=\"autocomplete-listbox\"\n aria-expanded={showPopover}\n aria-haspopup=\"listbox\"\n aria-owns={idList}\n onKeyDown={onInputKeyDown}\n data-testid={AutocompleteDataTestid.CONTAINER}\n >\n {childrenWithProps}\n {filter && (\n <DSPopperJS\n customOffset={[0, 5]}\n closeContextMenu={handleCloseMenu}\n referenceElement={referenceElement}\n showPopover={showPopover}\n startPlacementPreference={startPlacementPreference}\n placementOrderPreference={placementOrderPreference}\n withoutPortal\n withoutArrow\n withoutAnimation\n zIndex={10}\n >\n <StyledPopperWrapper tabIndex={-1}>\n <MenuList />\n </StyledPopperWrapper>\n </DSPopperJS>\n )}\n </StyledContainer>\n </>\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC6CnB,mBACE,KAEA,YAHF;AA5CJ,OAAOA,UAAS,aAAa,SAAS,WAAW,kBAAkB;AACnE,SAAS,kBAAkB;AAC3B,OAAO,yBAAyB;AAChC,SAAS,iBAAiB,2BAA2B;AACrD,SAAS,gBAAgB;AACzB,SAAS,6BAA6B;AACtC,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAC3B,MAAM,YAAY,MAAmB;AAC1C,QAAM;AAAA,IACJ,OAAO,EAAE,IAAI,0BAA0B,UAAU,QAAQ,yBAAyB;AAAA,IAClF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,YAAU,MAAM;AACd,UAAM,cAAc,MAAM;AACxB,qBAAe,KAAK;AAAA,IACtB;AACA,WAAO,iBAAiB,QAAQ,WAAW;AAE3C,WAAO,MAAM;AACX,aAAO,oBAAoB,QAAQ,WAAW;AAAA,IAChD;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,kBAAkB,YAAY,MAAM;AACxC,mBAAe,KAAK;AAAA,EACtB,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,EAAE,eAAe,IAAI,sBAAsB;AAEjD,QAAM,QAAQA,OAAM,SAAS,KAAK,QAAQ;AAE1C,QAAM,oBAAoBA,OAAM,eAAe,KAAK,IAChDA,OAAM,aAAa,OAAO,EAAE,yBAAyB,eAAe,CAAC,IACrE;AAEJ,QAAM,SAAS,QAAQ,MAAM,GAAG,KAAK,GAAG,QAAQ,aAAa,CAAC,EAAE,CAAC;AAEjE,SACE,iCACE;AAAA,wBAAC,qBAAkB;AAAA,IAEnB;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,KAAK;AAAA,QACL,MAAK;AAAA,QACL,qBAAkB;AAAA,QAClB,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,iBAAc;AAAA,QACd,aAAW;AAAA,QACX,WAAW;AAAA,QACX,eAAa,uBAAuB;AAAA,QAEnC;AAAA;AAAA,UACA,UACC;AAAA,YAAC;AAAA;AAAA,cACC,cAAc,CAAC,GAAG,CAAC;AAAA,cACnB,kBAAkB;AAAA,cAClB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,eAAa;AAAA,cACb,cAAY;AAAA,cACZ,kBAAgB;AAAA,cAChB,QAAQ;AAAA,cAER,8BAAC,uBAAoB,UAAU,IAC7B,8BAAC,YAAS,GACZ;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\nimport React, { useCallback, useMemo, useContext } from 'react';\nimport { DSPopperJS } from '@elliemae/ds-popperjs';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { StyledContainer, StyledPopperWrapper } from './styled';\nimport { MenuList } from '../menu-list';\nimport { useKeyboardNavigation } from './useKeyboardNavigation';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport { A11yFocusedOption } from '../A11yFocusedOption';\nexport const Container = (): JSX.Element => {\n const {\n props: { id, startPlacementPreference, children, filter, placementOrderPreference },\n isShowingPopover,\n setReferenceElement,\n setUserJustSelectedAnOption,\n setUserTypedSomething,\n setUserIsNavigatingWithArrows,\n setForceClosePopover,\n focusOptionIdx,\n referenceElement,\n } = useContext(AutocompleteContext);\n\n const handleCloseMenu = useCallback(() => {\n setForceClosePopover(true);\n }, [setForceClosePopover]);\n\n const { onInputKeyDown } = useKeyboardNavigation();\n\n const input = React.Children.only(children);\n\n const childrenWithProps = React.isValidElement(input)\n ? React.cloneElement(input, { 'aria-activedescendant': focusOptionIdx })\n : input;\n\n const idList = useMemo(() => `${id ? `${id}-` : ''}listbox`, [id]);\n\n const onFocusPopoverStatusSync = useCallback(() => {\n setForceClosePopover(false);\n setUserJustSelectedAnOption(false);\n setUserTypedSomething(false);\n setUserIsNavigatingWithArrows(false);\n }, [setForceClosePopover, setUserIsNavigatingWithArrows, setUserJustSelectedAnOption, setUserTypedSomething]);\n\n return (\n <>\n <A11yFocusedOption />\n\n <StyledContainer\n id={id}\n ref={setReferenceElement}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-controls=\"autocomplete-listbox\"\n aria-expanded={isShowingPopover}\n aria-haspopup=\"listbox\"\n aria-owns={idList}\n onKeyDown={onInputKeyDown}\n onFocus={onFocusPopoverStatusSync}\n data-testid={AutocompleteDataTestid.CONTAINER}\n >\n {childrenWithProps}\n {filter && (\n <DSPopperJS\n customOffset={[0, 5]}\n closeContextMenu={handleCloseMenu}\n referenceElement={referenceElement}\n showPopover={isShowingPopover}\n startPlacementPreference={startPlacementPreference}\n placementOrderPreference={placementOrderPreference}\n withoutPortal\n withoutArrow\n withoutAnimation\n zIndex={10}\n >\n <StyledPopperWrapper tabIndex={-1}>\n <MenuList />\n </StyledPopperWrapper>\n </DSPopperJS>\n )}\n </StyledContainer>\n </>\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC4CnB,mBACE,KAEA,YAHF;AA3CJ,OAAOA,UAAS,aAAa,SAAS,kBAAkB;AACxD,SAAS,kBAAkB;AAC3B,OAAO,yBAAyB;AAChC,SAAS,iBAAiB,2BAA2B;AACrD,SAAS,gBAAgB;AACzB,SAAS,6BAA6B;AACtC,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAC3B,MAAM,YAAY,MAAmB;AAC1C,QAAM;AAAA,IACJ,OAAO,EAAE,IAAI,0BAA0B,UAAU,QAAQ,yBAAyB;AAAA,IAClF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,QAAM,kBAAkB,YAAY,MAAM;AACxC,yBAAqB,IAAI;AAAA,EAC3B,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,EAAE,eAAe,IAAI,sBAAsB;AAEjD,QAAM,QAAQA,OAAM,SAAS,KAAK,QAAQ;AAE1C,QAAM,oBAAoBA,OAAM,eAAe,KAAK,IAChDA,OAAM,aAAa,OAAO,EAAE,yBAAyB,eAAe,CAAC,IACrE;AAEJ,QAAM,SAAS,QAAQ,MAAM,GAAG,KAAK,GAAG,QAAQ,aAAa,CAAC,EAAE,CAAC;AAEjE,QAAM,2BAA2B,YAAY,MAAM;AACjD,yBAAqB,KAAK;AAC1B,gCAA4B,KAAK;AACjC,0BAAsB,KAAK;AAC3B,kCAA8B,KAAK;AAAA,EACrC,GAAG,CAAC,sBAAsB,+BAA+B,6BAA6B,qBAAqB,CAAC;AAE5G,SACE,iCACE;AAAA,wBAAC,qBAAkB;AAAA,IAEnB;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,KAAK;AAAA,QACL,MAAK;AAAA,QACL,qBAAkB;AAAA,QAClB,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,iBAAc;AAAA,QACd,aAAW;AAAA,QACX,WAAW;AAAA,QACX,SAAS;AAAA,QACT,eAAa,uBAAuB;AAAA,QAEnC;AAAA;AAAA,UACA,UACC;AAAA,YAAC;AAAA;AAAA,cACC,cAAc,CAAC,GAAG,CAAC;AAAA,cACnB,kBAAkB;AAAA,cAClB;AAAA,cACA,aAAa;AAAA,cACb;AAAA,cACA;AAAA,cACA,eAAa;AAAA,cACb,cAAY;AAAA,cACZ,kBAAgB;AAAA,cAChB,QAAQ;AAAA,cAER,8BAAC,uBAAoB,UAAU,IAC7B,8BAAC,YAAS,GACZ;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;",
6
6
  "names": ["React"]
7
7
  }
@@ -6,8 +6,9 @@ const isOptionFocuseable = (opt) => !["section", "separator"].includes(opt.type)
6
6
  const useKeyboardNavigation = () => {
7
7
  const {
8
8
  props: { onSelect, options },
9
- setShowPopover,
10
- showPopover,
9
+ trackUserInteractingViaKeyboard,
10
+ setForceClosePopover,
11
+ isShowingPopover,
11
12
  focusOptionIdx,
12
13
  setCurrentOption,
13
14
  scrollOptionIntoView
@@ -18,18 +19,16 @@ const useKeyboardNavigation = () => {
18
19
  );
19
20
  const onInputKeyDown = useCallback(
20
21
  (e) => {
21
- if ((e.keyCode >= 48 && e.keyCode <= 90 || e.key === "Backspace") && !showPopover) {
22
- setShowPopover(true);
23
- } else if (e.key === "Tab")
24
- setShowPopover(false);
25
- if (e.key === "Enter" && showPopover) {
22
+ trackUserInteractingViaKeyboard(e);
23
+ if (e.key === "Tab" || e.key === "Escape")
24
+ setForceClosePopover(true);
25
+ if (e.key === "Enter" && isShowingPopover) {
26
26
  e.preventDefault();
27
27
  onSelect(currentItem?.label, e);
28
- setShowPopover(false);
29
28
  }
30
29
  if (e.key === "ArrowDown") {
31
30
  e.preventDefault();
32
- if (showPopover) {
31
+ if (isShowingPopover) {
33
32
  const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable);
34
33
  setCurrentOption(options[nextItemIndex].dsId);
35
34
  scrollOptionIntoView(options[nextItemIndex].dsId);
@@ -37,25 +36,23 @@ const useKeyboardNavigation = () => {
37
36
  }
38
37
  if (e.key === "ArrowUp") {
39
38
  e.preventDefault();
40
- if (showPopover) {
39
+ if (isShowingPopover) {
41
40
  const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable, -1);
42
41
  setCurrentOption(options[nextItemIndex].dsId);
43
42
  scrollOptionIntoView(options[nextItemIndex].dsId);
44
43
  }
45
44
  }
46
- if (e.key === "Escape") {
47
- setShowPopover(false);
48
- }
49
45
  },
50
46
  [
51
- currentItem?.label,
52
- currentItemIndex,
47
+ trackUserInteractingViaKeyboard,
48
+ setForceClosePopover,
49
+ isShowingPopover,
53
50
  onSelect,
51
+ currentItem?.label,
54
52
  options,
55
- scrollOptionIntoView,
53
+ currentItemIndex,
56
54
  setCurrentOption,
57
- setShowPopover,
58
- showPopover
55
+ scrollOptionIntoView
59
56
  ]
60
57
  );
61
58
  return { onInputKeyDown };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/container/useKeyboardNavigation.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable max-depth */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useContext } from 'react';\nimport type { DSAutocompleteT } from '../../react-desc-prop-types';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { findInCircularList } from '../../utils/listHelper';\n\nconst isOptionFocuseable = (opt: DSAutocompleteT.OptionTypes): boolean => !['section', 'separator'].includes(opt.type);\n\nexport const useKeyboardNavigation = () => {\n const {\n props: { onSelect, options },\n setShowPopover,\n showPopover,\n focusOptionIdx,\n setCurrentOption,\n scrollOptionIntoView,\n } = useContext(AutocompleteContext);\n\n const currentItemIndex = options.findIndex((opt) => opt.dsId === focusOptionIdx);\n const currentItem = options.find(\n (item) => item.type === 'option' && item.dsId === focusOptionIdx,\n ) as DSAutocompleteT.ItemOption;\n\n const onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n if (((e.keyCode >= 48 && e.keyCode <= 90) || e.key === 'Backspace') && !showPopover) {\n setShowPopover(true);\n } else if (e.key === 'Tab') setShowPopover(false);\n\n // =============================================================================\n // ENTER AND SPACE KEY SELECT OPTIONS AND OPEN CLOSE THE POPOVER\n // =============================================================================\n if (e.key === 'Enter' && showPopover) {\n e.preventDefault();\n onSelect(currentItem?.label, e);\n setShowPopover(false);\n }\n\n // =============================================================================\n // ARROWS UP AND DOWN\n // =============================================================================\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (showPopover) {\n const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable);\n setCurrentOption(options[nextItemIndex].dsId);\n scrollOptionIntoView(options[nextItemIndex].dsId);\n }\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (showPopover) {\n const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable, -1);\n setCurrentOption(options[nextItemIndex].dsId);\n scrollOptionIntoView(options[nextItemIndex].dsId);\n }\n }\n // =============================================================================\n // ESCAPE\n // =============================================================================\n if (e.key === 'Escape') {\n setShowPopover(false);\n }\n },\n [\n currentItem?.label,\n currentItemIndex,\n onSelect,\n options,\n scrollOptionIntoView,\n setCurrentOption,\n setShowPopover,\n showPopover,\n ],\n );\n\n return { onInputKeyDown };\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACKvB,SAAS,aAAa,kBAAkB;AAExC,OAAO,yBAAyB;AAChC,SAAS,0BAA0B;AAEnC,MAAM,qBAAqB,CAAC,QAA8C,CAAC,CAAC,WAAW,WAAW,EAAE,SAAS,IAAI,IAAI;AAE9G,MAAM,wBAAwB,MAAM;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,UAAU,QAAQ;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,QAAM,mBAAmB,QAAQ,UAAU,CAAC,QAAQ,IAAI,SAAS,cAAc;AAC/E,QAAM,cAAc,QAAQ;AAAA,IAC1B,CAAC,SAAS,KAAK,SAAS,YAAY,KAAK,SAAS;AAAA,EACpD;AAEA,QAAM,iBAA+D;AAAA,IACnE,CAAC,MAAM;AACL,WAAM,EAAE,WAAW,MAAM,EAAE,WAAW,MAAO,EAAE,QAAQ,gBAAgB,CAAC,aAAa;AACnF,uBAAe,IAAI;AAAA,MACrB,WAAW,EAAE,QAAQ;AAAO,uBAAe,KAAK;AAKhD,UAAI,EAAE,QAAQ,WAAW,aAAa;AACpC,UAAE,eAAe;AACjB,iBAAS,aAAa,OAAO,CAAC;AAC9B,uBAAe,KAAK;AAAA,MACtB;AAKA,UAAI,EAAE,QAAQ,aAAa;AACzB,UAAE,eAAe;AACjB,YAAI,aAAa;AACf,gBAAM,gBAAgB,mBAAmB,SAAS,kBAAkB,kBAAkB;AACtF,2BAAiB,QAAQ,eAAe,IAAI;AAC5C,+BAAqB,QAAQ,eAAe,IAAI;AAAA,QAClD;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,WAAW;AACvB,UAAE,eAAe;AACjB,YAAI,aAAa;AACf,gBAAM,gBAAgB,mBAAmB,SAAS,kBAAkB,oBAAoB,EAAE;AAC1F,2BAAiB,QAAQ,eAAe,IAAI;AAC5C,+BAAqB,QAAQ,eAAe,IAAI;AAAA,QAClD;AAAA,MACF;AAIA,UAAI,EAAE,QAAQ,UAAU;AACtB,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,eAAe;AAC1B;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-lines */\n/* eslint-disable max-depth */\n/* eslint-disable max-statements */\n/* eslint-disable complexity */\nimport type React from 'react';\nimport { useCallback, useContext } from 'react';\nimport type { DSAutocompleteT } from '../../react-desc-prop-types';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { findInCircularList } from '../../utils/listHelper';\n\nconst isOptionFocuseable = (opt: DSAutocompleteT.OptionTypes): boolean => !['section', 'separator'].includes(opt.type);\n\nexport const useKeyboardNavigation = () => {\n const {\n props: { onSelect, options },\n trackUserInteractingViaKeyboard,\n setForceClosePopover,\n isShowingPopover,\n focusOptionIdx,\n setCurrentOption,\n scrollOptionIntoView,\n } = useContext(AutocompleteContext);\n\n const currentItemIndex = options.findIndex((opt) => opt.dsId === focusOptionIdx);\n const currentItem = options.find(\n (item) => item.type === 'option' && item.dsId === focusOptionIdx,\n ) as DSAutocompleteT.ItemOption;\n\n const onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(\n (e) => {\n // =============================================================================\n // TRACK STATE OF POPOVER SHOWING OR NOT\n // =============================================================================\n trackUserInteractingViaKeyboard(e);\n\n if (e.key === 'Tab' || e.key === 'Escape') setForceClosePopover(true);\n\n // =============================================================================\n // ENTER AND SPACE KEY SELECT OPTIONS AND OPEN CLOSE THE POPOVER\n // =============================================================================\n if (e.key === 'Enter' && isShowingPopover) {\n e.preventDefault();\n onSelect(currentItem?.label, e);\n }\n\n // =============================================================================\n // ARROWS UP AND DOWN\n // =============================================================================\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (isShowingPopover) {\n const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable);\n setCurrentOption(options[nextItemIndex].dsId);\n scrollOptionIntoView(options[nextItemIndex].dsId);\n }\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (isShowingPopover) {\n const nextItemIndex = findInCircularList(options, currentItemIndex, isOptionFocuseable, -1);\n setCurrentOption(options[nextItemIndex].dsId);\n scrollOptionIntoView(options[nextItemIndex].dsId);\n }\n }\n },\n [\n trackUserInteractingViaKeyboard,\n setForceClosePopover,\n isShowingPopover,\n onSelect,\n currentItem?.label,\n options,\n currentItemIndex,\n setCurrentOption,\n scrollOptionIntoView,\n ],\n );\n\n return { onInputKeyDown };\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACKvB,SAAS,aAAa,kBAAkB;AAExC,OAAO,yBAAyB;AAChC,SAAS,0BAA0B;AAEnC,MAAM,qBAAqB,CAAC,QAA8C,CAAC,CAAC,WAAW,WAAW,EAAE,SAAS,IAAI,IAAI;AAE9G,MAAM,wBAAwB,MAAM;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,UAAU,QAAQ;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,QAAM,mBAAmB,QAAQ,UAAU,CAAC,QAAQ,IAAI,SAAS,cAAc;AAC/E,QAAM,cAAc,QAAQ;AAAA,IAC1B,CAAC,SAAS,KAAK,SAAS,YAAY,KAAK,SAAS;AAAA,EACpD;AAEA,QAAM,iBAA+D;AAAA,IACnE,CAAC,MAAM;AAIL,sCAAgC,CAAC;AAEjC,UAAI,EAAE,QAAQ,SAAS,EAAE,QAAQ;AAAU,6BAAqB,IAAI;AAKpE,UAAI,EAAE,QAAQ,WAAW,kBAAkB;AACzC,UAAE,eAAe;AACjB,iBAAS,aAAa,OAAO,CAAC;AAAA,MAChC;AAKA,UAAI,EAAE,QAAQ,aAAa;AACzB,UAAE,eAAe;AACjB,YAAI,kBAAkB;AACpB,gBAAM,gBAAgB,mBAAmB,SAAS,kBAAkB,kBAAkB;AACtF,2BAAiB,QAAQ,eAAe,IAAI;AAC5C,+BAAqB,QAAQ,eAAe,IAAI;AAAA,QAClD;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,WAAW;AACvB,UAAE,eAAe;AACjB,YAAI,kBAAkB;AACpB,gBAAM,gBAAgB,mBAAmB,SAAS,kBAAkB,oBAAoB,EAAE;AAC1F,2BAAiB,QAAQ,eAAe,IAAI;AAC5C,+BAAqB,QAAQ,eAAe,IAAI;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,eAAe;AAC1B;",
6
6
  "names": []
7
7
  }
@@ -11,7 +11,7 @@ const MenuList = () => {
11
11
  referenceElement,
12
12
  inputRef,
13
13
  listRef,
14
- showPopover,
14
+ isShowingPopover,
15
15
  virtualListHelpers: { totalSize }
16
16
  } = useContext(AutocompleteContext);
17
17
  const ItemRenderer = useItemRenderer();
@@ -19,11 +19,14 @@ const MenuList = () => {
19
19
  inputRef.current?.focus();
20
20
  }, [inputRef]);
21
21
  const idList = useMemo(() => `${id ? `${id}-` : ""}listbox`, [id]);
22
+ const preventMouseDown = useCallback((e) => {
23
+ e.preventDefault();
24
+ }, []);
22
25
  return /* @__PURE__ */ jsx(
23
26
  StyledListWrapper,
24
27
  {
25
28
  tabIndex: -1,
26
- onMouseDown: (e) => e.preventDefault(),
29
+ onMouseDown: preventMouseDown,
27
30
  minWidth: referenceElement?.offsetWidth,
28
31
  id: idList,
29
32
  role: "listbox",
@@ -31,7 +34,7 @@ const MenuList = () => {
31
34
  StyledList,
32
35
  {
33
36
  tabIndex: -1,
34
- "aria-expanded": showPopover,
37
+ "aria-expanded": isShowingPopover,
35
38
  onFocus: handleOnFocus,
36
39
  "data-testid": AutocompleteDataTestid.LIST,
37
40
  style: { height: totalSize, margin: "8px 0px" },
@@ -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, useMemo, useCallback } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { useItemRenderer } from './useItemRenderer';\nimport { A11yFocusedOption } from '../A11yFocusedOption';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options, id },\n referenceElement,\n inputRef,\n listRef,\n showPopover,\n virtualListHelpers: { totalSize },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const idList = useMemo(() => `${id ? `${id}-` : ''}listbox`, [id]);\n return (\n <StyledListWrapper\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()}\n minWidth={referenceElement?.offsetWidth}\n id={idList}\n role=\"listbox\"\n >\n {options.length > 0 && (\n <StyledVirtualListWrapper tabIndex={-1} ref={listRef}>\n <StyledList\n tabIndex={-1}\n aria-expanded={showPopover}\n onFocus={handleOnFocus}\n data-testid={AutocompleteDataTestid.LIST}\n style={{ height: totalSize, margin: '8px 0px' }}\n >\n {ItemRenderer}\n </StyledList>\n </StyledVirtualListWrapper>\n )}\n </StyledListWrapper>\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACkCb;AAlCV,SAAgB,YAAY,SAAS,mBAAmB;AACxD,SAAS,mBAAmB,YAAY,gCAAgC;AACxE,SAAS,8BAA8B;AACvC,OAAO,yBAAyB;AAChC,SAAS,uBAAuB;AAGzB,MAAM,WAAW,MAAmB;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,GAAG;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,EAAE,UAAU;AAAA,EAClC,IAAI,WAAW,mBAAmB;AAElC,QAAM,eAAe,gBAAgB;AAErC,QAAM,gBAAgB,YAAY,MAAM;AACtC,aAAS,SAAS,MAAM;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,SAAS,QAAQ,MAAM,GAAG,KAAK,GAAG,QAAQ,aAAa,CAAC,EAAE,CAAC;AACjE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,aAAa,CAAC,MAAM,EAAE,eAAe;AAAA,MACrC,UAAU,kBAAkB;AAAA,MAC5B,IAAI;AAAA,MACJ,MAAK;AAAA,MAEJ,kBAAQ,SAAS,KAChB,oBAAC,4BAAyB,UAAU,IAAI,KAAK,SAC3C;AAAA,QAAC;AAAA;AAAA,UACC,UAAU;AAAA,UACV,iBAAe;AAAA,UACf,SAAS;AAAA,UACT,eAAa,uBAAuB;AAAA,UACpC,OAAO,EAAE,QAAQ,WAAW,QAAQ,UAAU;AAAA,UAE7C;AAAA;AAAA,MACH,GACF;AAAA;AAAA,EAEJ;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useContext, useMemo, useCallback } from 'react';\nimport { StyledListWrapper, StyledList, StyledVirtualListWrapper } from './styled';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { useItemRenderer } from './useItemRenderer';\n\nexport const MenuList = (): JSX.Element => {\n const {\n props: { options, id },\n referenceElement,\n inputRef,\n listRef,\n isShowingPopover,\n virtualListHelpers: { totalSize },\n } = useContext(AutocompleteContext);\n\n const ItemRenderer = useItemRenderer();\n\n const handleOnFocus = useCallback(() => {\n inputRef.current?.focus();\n }, [inputRef]);\n\n const idList = useMemo(() => `${id ? `${id}-` : ''}listbox`, [id]);\n const preventMouseDown: React.MouseEventHandler<HTMLDivElement> = useCallback((e) => {\n e.preventDefault();\n }, []);\n\n return (\n <StyledListWrapper\n tabIndex={-1}\n onMouseDown={preventMouseDown}\n minWidth={referenceElement?.offsetWidth}\n id={idList}\n role=\"listbox\"\n >\n {options.length > 0 && (\n <StyledVirtualListWrapper tabIndex={-1} ref={listRef}>\n <StyledList\n tabIndex={-1}\n aria-expanded={isShowingPopover}\n onFocus={handleOnFocus}\n data-testid={AutocompleteDataTestid.LIST}\n style={{ height: totalSize, margin: '8px 0px' }}\n >\n {ItemRenderer}\n </StyledList>\n </StyledVirtualListWrapper>\n )}\n </StyledListWrapper>\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACqCb;AArCV,SAAgB,YAAY,SAAS,mBAAmB;AACxD,SAAS,mBAAmB,YAAY,gCAAgC;AACxE,SAAS,8BAA8B;AACvC,OAAO,yBAAyB;AAChC,SAAS,uBAAuB;AAEzB,MAAM,WAAW,MAAmB;AACzC,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,GAAG;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,EAAE,UAAU;AAAA,EAClC,IAAI,WAAW,mBAAmB;AAElC,QAAM,eAAe,gBAAgB;AAErC,QAAM,gBAAgB,YAAY,MAAM;AACtC,aAAS,SAAS,MAAM;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,SAAS,QAAQ,MAAM,GAAG,KAAK,GAAG,QAAQ,aAAa,CAAC,EAAE,CAAC;AACjE,QAAM,mBAA4D,YAAY,CAAC,MAAM;AACnF,MAAE,eAAe;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,aAAa;AAAA,MACb,UAAU,kBAAkB;AAAA,MAC5B,IAAI;AAAA,MACJ,MAAK;AAAA,MAEJ,kBAAQ,SAAS,KAChB,oBAAC,4BAAyB,UAAU,IAAI,KAAK,SAC3C;AAAA,QAAC;AAAA;AAAA,UACC,UAAU;AAAA,UACV,iBAAe;AAAA,UACf,SAAS;AAAA,UACT,eAAa,uBAAuB;AAAA,UACpC,OAAO,EAAE,QAAQ,WAAW,QAAQ,UAAU;AAAA,UAE7C;AAAA;AAAA,MACH,GACF;AAAA;AAAA,EAEJ;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -8,18 +8,20 @@ const useItemRenderer = () => {
8
8
  const {
9
9
  props: { options, onSelect },
10
10
  inputRef,
11
- setShowPopover,
11
+ setUserTypedSomething,
12
+ setUserJustSelectedAnOption,
12
13
  focusOptionIdx,
13
14
  virtualListHelpers
14
15
  } = useContext(AutocompleteContext);
15
16
  const handleClick = useCallback(
16
17
  (option, e) => {
17
18
  onSelect(option.label, e);
18
- setShowPopover(false);
19
+ setUserJustSelectedAnOption(true);
20
+ setUserTypedSomething(false);
19
21
  e.stopPropagation();
20
22
  e.preventDefault();
21
23
  },
22
- [onSelect, setShowPopover]
24
+ [onSelect, setUserTypedSomething, setUserJustSelectedAnOption]
23
25
  );
24
26
  return useMemo(() => {
25
27
  if (virtualListHelpers) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/menu-list/useItemRenderer.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable react-hooks/exhaustive-deps */\nimport React, { useMemo, useContext, useCallback } from 'react';\nimport { SingleMenuItem, Section } from '@elliemae/ds-menu-items';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport type { DSAutocompleteT } from '../../react-desc-prop-types';\n\nexport const useItemRenderer = (): Array<JSX.Element> | null => {\n const {\n props: { options, onSelect },\n inputRef,\n setShowPopover,\n focusOptionIdx,\n virtualListHelpers,\n } = useContext(AutocompleteContext);\n\n const handleClick = useCallback(\n (option: DSAutocompleteT.ItemOption, e: React.ChangeEvent<HTMLInputElement>) => {\n onSelect(option.label, e);\n setShowPopover(false);\n e.stopPropagation();\n e.preventDefault();\n },\n [onSelect, setShowPopover],\n );\n\n return useMemo(() => {\n if (virtualListHelpers) {\n return virtualListHelpers.virtualItems.map((vItem) => {\n const option = options[vItem.index];\n const generalProps = {\n wrapperStyles: { position: 'absolute', top: vItem.start, left: 0, width: '100%' },\n key: `${option.dsId}`,\n innerRef: vItem.measureRef,\n };\n if (option.type === 'section') {\n return <Section label={option.label} {...generalProps} />;\n }\n if (option.type === 'option') {\n return (\n <SingleMenuItem\n {...generalProps}\n value={option.value}\n label={option.label}\n dataTestid={AutocompleteDataTestid.OPTION}\n disabled={option.disabled}\n onClick={(e: React.ChangeEvent<HTMLInputElement>) => handleClick(option, e)}\n isActive={option.dsId === focusOptionIdx}\n />\n );\n }\n return <></>;\n });\n }\n return null;\n }, [options, focusOptionIdx, inputRef, virtualListHelpers]);\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACoCN,SAeF,UAfE;AAnCjB,SAAgB,SAAS,YAAY,mBAAmB;AACxD,SAAS,gBAAgB,eAAe;AACxC,OAAO,yBAAyB;AAChC,SAAS,8BAA8B;AAGhC,MAAM,kBAAkB,MAAiC;AAC9D,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,SAAS;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,QAAM,cAAc;AAAA,IAClB,CAAC,QAAoC,MAA2C;AAC9E,eAAS,OAAO,OAAO,CAAC;AACxB,qBAAe,KAAK;AACpB,QAAE,gBAAgB;AAClB,QAAE,eAAe;AAAA,IACnB;AAAA,IACA,CAAC,UAAU,cAAc;AAAA,EAC3B;AAEA,SAAO,QAAQ,MAAM;AACnB,QAAI,oBAAoB;AACtB,aAAO,mBAAmB,aAAa,IAAI,CAAC,UAAU;AACpD,cAAM,SAAS,QAAQ,MAAM;AAC7B,cAAM,eAAe;AAAA,UACnB,eAAe,EAAE,UAAU,YAAY,KAAK,MAAM,OAAO,MAAM,GAAG,OAAO,OAAO;AAAA,UAChF,KAAK,GAAG,OAAO;AAAA,UACf,UAAU,MAAM;AAAA,QAClB;AACA,YAAI,OAAO,SAAS,WAAW;AAC7B,iBAAO,oBAAC,WAAQ,OAAO,OAAO,OAAQ,GAAG,cAAc;AAAA,QACzD;AACA,YAAI,OAAO,SAAS,UAAU;AAC5B,iBACE;AAAA,YAAC;AAAA;AAAA,cACE,GAAG;AAAA,cACJ,OAAO,OAAO;AAAA,cACd,OAAO,OAAO;AAAA,cACd,YAAY,uBAAuB;AAAA,cACnC,UAAU,OAAO;AAAA,cACjB,SAAS,CAAC,MAA2C,YAAY,QAAQ,CAAC;AAAA,cAC1E,UAAU,OAAO,SAAS;AAAA;AAAA,UAC5B;AAAA,QAEJ;AACA,eAAO,gCAAE;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,gBAAgB,UAAU,kBAAkB,CAAC;AAC5D;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable react-hooks/exhaustive-deps */\nimport React, { useMemo, useContext, useCallback } from 'react';\nimport { SingleMenuItem, Section } from '@elliemae/ds-menu-items';\nimport AutocompleteContext from '../../AutocompleteCTX';\nimport { AutocompleteDataTestid } from '../../AutocompleteDataTestids';\nimport type { DSAutocompleteT } from '../../react-desc-prop-types';\n\nexport const useItemRenderer = (): Array<JSX.Element> | null => {\n const {\n props: { options, onSelect },\n inputRef,\n setUserTypedSomething,\n setUserJustSelectedAnOption,\n focusOptionIdx,\n virtualListHelpers,\n } = useContext(AutocompleteContext);\n\n const handleClick = useCallback(\n (option: DSAutocompleteT.ItemOption, e: React.MouseEvent<HTMLInputElement>) => {\n onSelect(option.label, e);\n setUserJustSelectedAnOption(true);\n setUserTypedSomething(false);\n e.stopPropagation();\n e.preventDefault();\n },\n [onSelect, setUserTypedSomething, setUserJustSelectedAnOption],\n );\n\n return useMemo(() => {\n if (virtualListHelpers) {\n return virtualListHelpers.virtualItems.map((vItem) => {\n const option = options[vItem.index];\n const generalProps = {\n wrapperStyles: { position: 'absolute', top: vItem.start, left: 0, width: '100%' },\n key: `${option.dsId}`,\n innerRef: vItem.measureRef,\n };\n if (option.type === 'section') {\n return <Section label={option.label} {...generalProps} />;\n }\n if (option.type === 'option') {\n return (\n <SingleMenuItem\n {...generalProps}\n value={option.value}\n label={option.label}\n dataTestid={AutocompleteDataTestid.OPTION}\n disabled={option.disabled}\n onClick={(e: React.MouseEvent<HTMLInputElement>) => handleClick(option, e)}\n isActive={option.dsId === focusOptionIdx}\n />\n );\n }\n return <></>;\n });\n }\n return null;\n }, [options, focusOptionIdx, inputRef, virtualListHelpers]);\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACsCN,SAeF,UAfE;AArCjB,SAAgB,SAAS,YAAY,mBAAmB;AACxD,SAAS,gBAAgB,eAAe;AACxC,OAAO,yBAAyB;AAChC,SAAS,8BAA8B;AAGhC,MAAM,kBAAkB,MAAiC;AAC9D,QAAM;AAAA,IACJ,OAAO,EAAE,SAAS,SAAS;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,mBAAmB;AAElC,QAAM,cAAc;AAAA,IAClB,CAAC,QAAoC,MAA0C;AAC7E,eAAS,OAAO,OAAO,CAAC;AACxB,kCAA4B,IAAI;AAChC,4BAAsB,KAAK;AAC3B,QAAE,gBAAgB;AAClB,QAAE,eAAe;AAAA,IACnB;AAAA,IACA,CAAC,UAAU,uBAAuB,2BAA2B;AAAA,EAC/D;AAEA,SAAO,QAAQ,MAAM;AACnB,QAAI,oBAAoB;AACtB,aAAO,mBAAmB,aAAa,IAAI,CAAC,UAAU;AACpD,cAAM,SAAS,QAAQ,MAAM;AAC7B,cAAM,eAAe;AAAA,UACnB,eAAe,EAAE,UAAU,YAAY,KAAK,MAAM,OAAO,MAAM,GAAG,OAAO,OAAO;AAAA,UAChF,KAAK,GAAG,OAAO;AAAA,UACf,UAAU,MAAM;AAAA,QAClB;AACA,YAAI,OAAO,SAAS,WAAW;AAC7B,iBAAO,oBAAC,WAAQ,OAAO,OAAO,OAAQ,GAAG,cAAc;AAAA,QACzD;AACA,YAAI,OAAO,SAAS,UAAU;AAC5B,iBACE;AAAA,YAAC;AAAA;AAAA,cACE,GAAG;AAAA,cACJ,OAAO,OAAO;AAAA,cACd,OAAO,OAAO;AAAA,cACd,YAAY,uBAAuB;AAAA,cACnC,UAAU,OAAO;AAAA,cACjB,SAAS,CAAC,MAA0C,YAAY,QAAQ,CAAC;AAAA,cACzE,UAAU,OAAO,SAAS;AAAA;AAAA,UAC5B;AAAA,QAEJ;AACA,eAAO,gCAAE;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,gBAAgB,UAAU,kBAAkB,CAAC;AAC5D;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,11 @@
1
1
  import * as React from "react";
2
2
  import { PropTypes } from "@elliemae/ds-props-helpers";
3
+ const defaultProps = {
4
+ zIndex: 10,
5
+ withoutPortal: false,
6
+ startPlacementPreference: "bottom-start",
7
+ placementOrderPreference: ["bottom-start", "bottom-end"]
8
+ };
3
9
  const propTypes = {
4
10
  options: PropTypes.oneOfType([PropTypes.array, PropTypes.object]).isRequired.description("List of options").defaultValue([]),
5
11
  filter: PropTypes.string.isRequired.description("String value to filter the options").defaultValue(""),
@@ -7,6 +13,7 @@ const propTypes = {
7
13
  children: PropTypes.node.isRequired.description("React component to apply autocomplete functionality").defaultValue("")
8
14
  };
9
15
  export {
16
+ defaultProps,
10
17
  propTypes
11
18
  };
12
19
  //# sourceMappingURL=react-desc-prop-types.js.map
@@ -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 { PropTypes } from '@elliemae/ds-props-helpers';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\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 | ItemSeparatorOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n children: React.ReactChild;\n filter: string;\n onSelect: (suggestedValue: string | number, e: React.KeyboardEvent<HTMLInputElement>) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: string[];\n withoutPortal: boolean;\n zIndex: number;\n }\n\n export interface Props extends Partial<DefaultProps>, RequiredProps {}\n\n export interface InternalProps extends DefaultProps, RequiredProps {}\n}\n\nexport const propTypes = {\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.isRequired\n .description('React component to apply autocomplete functionality')\n .defaultValue(''),\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACGvB,SAAS,iBAAiB;AA6CnB,MAAM,YAAY;AAAA,EACvB,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,KAAK,WACtB,YAAY,qDAAqD,EACjE,aAAa,EAAE;AACpB;",
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 { PropTypes } from '@elliemae/ds-props-helpers';\n\nexport declare namespace DSAutocompleteT {\n export interface CommonItemOptions {\n dsId: string;\n disabled?: boolean;\n render?: React.ComponentType<unknown>;\n }\n export interface ItemSeparatorOptions extends CommonItemOptions {\n type: 'separator';\n }\n\n export interface ItemSectionOptions extends CommonItemOptions {\n type: 'section';\n label: string;\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 | ItemSeparatorOptions;\n\n export type SelectedOptionsT = ItemOption[] | ItemOption | null;\n\n export interface RequiredProps {\n options: OptionTypes[];\n children: React.ReactChild;\n filter: string;\n onSelect: (\n suggestedValue: string | number,\n e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>,\n ) => void;\n }\n export interface DefaultProps {\n startPlacementPreference: string;\n placementOrderPreference: string[];\n withoutPortal: boolean;\n zIndex: number;\n }\n\n export interface Props extends Partial<DefaultProps>, RequiredProps {}\n\n export interface InternalProps extends DefaultProps, RequiredProps {}\n}\n\nexport const defaultProps: DSAutocompleteT.DefaultProps = {\n zIndex: 10,\n withoutPortal: false,\n startPlacementPreference: 'bottom-start',\n placementOrderPreference: ['bottom-start', 'bottom-end'],\n};\n\nexport const propTypes = {\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.isRequired\n .description('React component to apply autocomplete functionality')\n .defaultValue(''),\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACGvB,SAAS,iBAAiB;AAgDnB,MAAM,eAA6C;AAAA,EACxD,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,0BAA0B;AAAA,EAC1B,0BAA0B,CAAC,gBAAgB,YAAY;AACzD;AAEO,MAAM,YAAY;AAAA,EACvB,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,KAAK,WACtB,YAAY,qDAAqD,EACjE,aAAa,EAAE;AACpB;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,5 @@
1
1
  /// <reference types="react" />
2
- import type { DSAutocompleteT } from './react-desc-prop-types';
3
- import type { DSAutoCompleteInternalsT } from './sharedTypes';
4
- export declare const defaultProps: DSAutocompleteT.DefaultProps;
2
+ import type { AutocompleteContextT } from './config/useAutocomplete';
5
3
  /** Context for cross component communication */
6
- export declare const AutocompleteContext: import("react").Context<DSAutoCompleteInternalsT.AutocompleteContext>;
4
+ export declare const AutocompleteContext: import("react").Context<AutocompleteContextT>;
7
5
  export default AutocompleteContext;
@@ -1,3 +1,13 @@
1
+ import React from 'react';
1
2
  import type { DSAutocompleteT } from '../react-desc-prop-types';
2
- import type { DSAutoCompleteInternalsT } from '../sharedTypes';
3
- export declare const useAutocomplete: (props: DSAutocompleteT.Props) => DSAutoCompleteInternalsT.AutocompleteContext;
3
+ import { useRefs } from './useRefs';
4
+ import { useVirtualization } from './useVirtualization';
5
+ import { usePopoverLogic } from './usePopoverLogic';
6
+ export type AutocompleteContextT = ReturnType<typeof useRefs> & ReturnType<typeof useVirtualization> & ReturnType<typeof usePopoverLogic> & {
7
+ props: DSAutocompleteT.InternalProps;
8
+ referenceElement: HTMLElement | null;
9
+ focusOptionIdx: string;
10
+ setCurrentOption: React.Dispatch<React.SetStateAction<string>>;
11
+ setReferenceElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
12
+ };
13
+ export declare const useAutocomplete: (props: DSAutocompleteT.Props) => AutocompleteContextT;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { DSAutocompleteT } from '../react-desc-prop-types';
3
+ export declare const usePopoverLogic: (propsWithDefault: DSAutocompleteT.InternalProps) => {
4
+ isShowingPopover: boolean;
5
+ forceClosePopover: boolean;
6
+ setForceClosePopover: React.Dispatch<React.SetStateAction<boolean>>;
7
+ userTypedSomething: boolean;
8
+ setUserTypedSomething: React.Dispatch<React.SetStateAction<boolean>>;
9
+ setUserJustSelectedAnOption: React.Dispatch<React.SetStateAction<boolean>>;
10
+ setUserIsNavigatingWithArrows: React.Dispatch<React.SetStateAction<boolean>>;
11
+ trackUserInteractingViaKeyboard: React.KeyboardEventHandler<HTMLInputElement>;
12
+ };
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const useRefs: () => {
3
+ inputRef: React.RefObject<HTMLInputElement>;
4
+ listRef: React.RefObject<HTMLDivElement>;
5
+ };
@@ -23,7 +23,7 @@ export declare namespace DSAutocompleteT {
23
23
  options: OptionTypes[];
24
24
  children: React.ReactChild;
25
25
  filter: string;
26
- onSelect: (suggestedValue: string | number, e: React.KeyboardEvent<HTMLInputElement>) => void;
26
+ onSelect: (suggestedValue: string | number, e: React.KeyboardEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>) => void;
27
27
  }
28
28
  interface DefaultProps {
29
29
  startPlacementPreference: string;
@@ -36,6 +36,7 @@ export declare namespace DSAutocompleteT {
36
36
  interface InternalProps extends DefaultProps, RequiredProps {
37
37
  }
38
38
  }
39
+ export declare const defaultProps: DSAutocompleteT.DefaultProps;
39
40
  export declare const propTypes: {
40
41
  options: import("@elliemae/ds-props-helpers/dist/types/propTypes/types").ReactDescT;
41
42
  filter: import("@elliemae/ds-props-helpers/dist/types/propTypes/types").ReactDescT;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-form-layout-autocomplete",
3
- "version": "3.16.0-next.7",
3
+ "version": "3.16.0-next.8",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Form Layout - Autocomplete",
6
6
  "files": [
@@ -37,11 +37,11 @@
37
37
  "dependencies": {
38
38
  "react-virtual": "~2.10.4",
39
39
  "styled-components": "~5.3.6",
40
- "@elliemae/ds-menu-items": "3.16.0-next.7",
41
- "@elliemae/ds-popperjs": "3.16.0-next.7",
42
- "@elliemae/ds-system": "3.16.0-next.7",
43
- "@elliemae/ds-props-helpers": "3.16.0-next.7",
44
- "@elliemae/ds-utilities": "3.16.0-next.7"
40
+ "@elliemae/ds-menu-items": "3.16.0-next.8",
41
+ "@elliemae/ds-props-helpers": "3.16.0-next.8",
42
+ "@elliemae/ds-popperjs": "3.16.0-next.8",
43
+ "@elliemae/ds-system": "3.16.0-next.8",
44
+ "@elliemae/ds-utilities": "3.16.0-next.8"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@elliemae/pui-theme": "~2.6.0",
@@ -51,7 +51,7 @@
51
51
  "@testing-library/user-event": "~13.5.0",
52
52
  "styled-components": "~5.3.6",
53
53
  "styled-system": "~5.1.5",
54
- "@elliemae/ds-form-input-text": "3.16.0-next.7"
54
+ "@elliemae/ds-form-input-text": "3.16.0-next.8"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@elliemae/pui-theme": "~2.6.0",
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/sharedTypes.ts", "../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import type React from 'react';\nimport type { useVirtual } from 'react-virtual';\nimport type { DSAutocompleteT } from './react-desc-prop-types';\n\nexport declare namespace DSAutoCompleteInternalsT {\n export interface AutocompleteContext {\n props: DSAutocompleteT.InternalProps;\n virtualListHelpers?: ReturnType<typeof useVirtual>;\n showPopover: boolean;\n setShowPopover: React.Dispatch<React.SetStateAction<boolean>>;\n referenceElement: HTMLElement | null;\n setReferenceElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;\n scrollOptionIntoView: (dsId: string, opts?: any) => void;\n inputRef: React.RefObject<HTMLInputElement>;\n listRef: React.RefObject<HTMLDivElement>;\n focusOptionIdx: string;\n setCurrentOption: React.Dispatch<React.SetStateAction<string>>;\n }\n}\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;ACAA,YAAuB;",
6
- "names": []
7
- }
@@ -1,2 +0,0 @@
1
- import * as React from "react";
2
- //# sourceMappingURL=sharedTypes.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n"],
5
- "mappings": "AAAA,YAAY,WAAW;",
6
- "names": []
7
- }
@@ -1,18 +0,0 @@
1
- import type React from 'react';
2
- import type { useVirtual } from 'react-virtual';
3
- import type { DSAutocompleteT } from './react-desc-prop-types';
4
- export declare namespace DSAutoCompleteInternalsT {
5
- interface AutocompleteContext {
6
- props: DSAutocompleteT.InternalProps;
7
- virtualListHelpers?: ReturnType<typeof useVirtual>;
8
- showPopover: boolean;
9
- setShowPopover: React.Dispatch<React.SetStateAction<boolean>>;
10
- referenceElement: HTMLElement | null;
11
- setReferenceElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
12
- scrollOptionIntoView: (dsId: string, opts?: any) => void;
13
- inputRef: React.RefObject<HTMLInputElement>;
14
- listRef: React.RefObject<HTMLDivElement>;
15
- focusOptionIdx: string;
16
- setCurrentOption: React.Dispatch<React.SetStateAction<string>>;
17
- }
18
- }