@elliemae/ds-app-picker 3.70.0-next.53 → 3.70.0-next.54

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 (80) hide show
  1. package/dist/cjs/DSAppPicker.js +6 -64
  2. package/dist/cjs/DSAppPicker.js.map +3 -3
  3. package/dist/cjs/DSAppPickerCTX.js +2 -22
  4. package/dist/cjs/DSAppPickerCTX.js.map +2 -2
  5. package/dist/cjs/config/useAppPicker.js +19 -5
  6. package/dist/cjs/config/useAppPicker.js.map +2 -2
  7. package/dist/cjs/config/useFocusTracker.js +24 -35
  8. package/dist/cjs/config/useFocusTracker.js.map +2 -2
  9. package/dist/cjs/constants/index.js +2 -0
  10. package/dist/cjs/constants/index.js.map +2 -2
  11. package/dist/cjs/parts/AppPanel.js +60 -43
  12. package/dist/cjs/parts/AppPanel.js.map +3 -3
  13. package/dist/cjs/parts/AppPickerFloatingContext/AppPickerContent.js +83 -0
  14. package/dist/cjs/parts/AppPickerFloatingContext/AppPickerContent.js.map +7 -0
  15. package/dist/cjs/parts/AppPickerFloatingContext/useAppPickerFloatingContext.js +171 -0
  16. package/dist/cjs/parts/AppPickerFloatingContext/useAppPickerFloatingContext.js.map +7 -0
  17. package/dist/cjs/parts/AppPickerItem.js +6 -10
  18. package/dist/cjs/parts/AppPickerItem.js.map +2 -2
  19. package/dist/cjs/parts/AppSection.js +2 -0
  20. package/dist/cjs/parts/AppSection.js.map +2 -2
  21. package/dist/cjs/parts/Trigger.js +14 -8
  22. package/dist/cjs/parts/Trigger.js.map +2 -2
  23. package/dist/cjs/parts/style.js +1 -7
  24. package/dist/cjs/parts/style.js.map +2 -2
  25. package/dist/cjs/react-desc-prop-types.js +6 -1
  26. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  27. package/dist/cjs/util/getChipId.js +36 -0
  28. package/dist/cjs/util/getChipId.js.map +7 -0
  29. package/dist/cjs/util/getChipRegionId.js +37 -0
  30. package/dist/cjs/util/getChipRegionId.js.map +7 -0
  31. package/dist/esm/DSAppPicker.js +7 -65
  32. package/dist/esm/DSAppPicker.js.map +3 -3
  33. package/dist/esm/DSAppPickerCTX.js +2 -22
  34. package/dist/esm/DSAppPickerCTX.js.map +2 -2
  35. package/dist/esm/config/useAppPicker.js +22 -8
  36. package/dist/esm/config/useAppPicker.js.map +2 -2
  37. package/dist/esm/config/useFocusTracker.js +23 -34
  38. package/dist/esm/config/useFocusTracker.js.map +2 -2
  39. package/dist/esm/constants/index.js +2 -0
  40. package/dist/esm/constants/index.js.map +2 -2
  41. package/dist/esm/parts/AppPanel.js +61 -44
  42. package/dist/esm/parts/AppPanel.js.map +3 -3
  43. package/dist/esm/parts/AppPickerFloatingContext/AppPickerContent.js +53 -0
  44. package/dist/esm/parts/AppPickerFloatingContext/AppPickerContent.js.map +7 -0
  45. package/dist/esm/parts/AppPickerFloatingContext/useAppPickerFloatingContext.js +141 -0
  46. package/dist/esm/parts/AppPickerFloatingContext/useAppPickerFloatingContext.js.map +7 -0
  47. package/dist/esm/parts/AppPickerItem.js +5 -9
  48. package/dist/esm/parts/AppPickerItem.js.map +2 -2
  49. package/dist/esm/parts/AppSection.js +2 -0
  50. package/dist/esm/parts/AppSection.js.map +2 -2
  51. package/dist/esm/parts/Trigger.js +15 -9
  52. package/dist/esm/parts/Trigger.js.map +2 -2
  53. package/dist/esm/parts/style.js +1 -7
  54. package/dist/esm/parts/style.js.map +2 -2
  55. package/dist/esm/react-desc-prop-types.js +6 -1
  56. package/dist/esm/react-desc-prop-types.js.map +2 -2
  57. package/dist/esm/util/getChipId.js +6 -0
  58. package/dist/esm/util/getChipId.js.map +7 -0
  59. package/dist/esm/util/getChipRegionId.js +7 -0
  60. package/dist/esm/util/getChipRegionId.js.map +7 -0
  61. package/dist/types/DSAppPicker.d.ts +1 -1
  62. package/dist/types/DSAppPickerCTX.d.ts +6 -17
  63. package/dist/types/config/useAppPicker.d.ts +109 -91
  64. package/dist/types/config/useFocusTracker.d.ts +10 -6
  65. package/dist/types/constants/index.d.ts +1 -0
  66. package/dist/types/parts/AppPanel.d.ts +1 -8
  67. package/dist/types/parts/AppPickerFloatingContext/AppPickerContent.d.ts +3 -0
  68. package/dist/types/parts/AppPickerFloatingContext/useAppPickerFloatingContext.d.ts +170 -0
  69. package/dist/types/parts/AppPickerItem.d.ts +1 -0
  70. package/dist/types/parts/Trigger.d.ts +10 -14
  71. package/dist/types/parts/style.d.ts +0 -1
  72. package/dist/types/react-desc-prop-types.d.ts +31 -1
  73. package/dist/types/util/getChipId.d.ts +2 -0
  74. package/dist/types/util/getChipRegionId.d.ts +1 -0
  75. package/package.json +13 -14
  76. package/dist/cjs/config/useAppPickerBehavior.js +0 -156
  77. package/dist/cjs/config/useAppPickerBehavior.js.map +0 -7
  78. package/dist/esm/config/useAppPickerBehavior.js +0 -126
  79. package/dist/esm/config/useAppPickerBehavior.js.map +0 -7
  80. package/dist/types/config/useAppPickerBehavior.d.ts +0 -39
@@ -35,74 +35,16 @@ module.exports = __toCommonJS(DSAppPicker_exports);
35
35
  var React = __toESM(require("react"));
36
36
  var import_jsx_runtime = require("react/jsx-runtime");
37
37
  var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
38
- var import_ds_floating_context = require("@elliemae/ds-floating-context");
39
- var import_AppPanel = require("./parts/AppPanel.js");
40
- var import_react_desc_prop_types = require("./react-desc-prop-types.js");
41
- var import_constants = require("./constants/index.js");
38
+ var import_react = __toESM(require("react"));
42
39
  var import_useAppPicker = require("./config/useAppPicker.js");
43
- var import_useAppPickerBehavior = require("./config/useAppPickerBehavior.js");
40
+ var import_constants = require("./constants/index.js");
44
41
  var import_DSAppPickerCTX = require("./DSAppPickerCTX.js");
45
- var import_style = require("./parts/style.js");
46
- var import_Trigger = require("./parts/Trigger.js");
42
+ var import_AppPickerContent = require("./parts/AppPickerFloatingContext/AppPickerContent.js");
43
+ var import_react_desc_prop_types = require("./react-desc-prop-types.js");
47
44
  const DSAppPicker = (props) => {
48
45
  const appPickerConfig = (0, import_useAppPicker.useAppPicker)(props);
49
- const {
50
- Icon,
51
- renderTrigger,
52
- resolvedIsOpen,
53
- floatingStyles,
54
- arrowStyles,
55
- floatingContext,
56
- ownerPropsConfig,
57
- defaultTriggerRef,
58
- triggerRef,
59
- wasOpenedByKeyboardRef,
60
- handleClose,
61
- handleTriggerRef,
62
- handleTriggerClick,
63
- floatingInnerRef,
64
- focusTracker
65
- } = (0, import_useAppPickerBehavior.useAppPickerBehavior)(appPickerConfig);
66
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_DSAppPickerCTX.DSAppPickerContext.Provider, { value: focusTracker, children: [
67
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
- import_Trigger.Trigger,
69
- {
70
- Icon,
71
- isOpen: resolvedIsOpen,
72
- setRef: handleTriggerRef,
73
- ownerProps: ownerPropsConfig,
74
- onClick: handleTriggerClick,
75
- renderTrigger
76
- }
77
- ),
78
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
79
- import_style.StyledAppPickerFloating,
80
- {
81
- innerRef: floatingInnerRef,
82
- isOpen: resolvedIsOpen,
83
- floatingStyles,
84
- context: floatingContext,
85
- getOwnerProps: ownerPropsConfig.getOwnerProps,
86
- getOwnerPropsArguments: ownerPropsConfig.getOwnerPropsArguments,
87
- children: [
88
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
89
- import_AppPanel.AppPanel,
90
- {
91
- ...appPickerConfig.propsWithDefault,
92
- ownerPropsConfig,
93
- globalAttributes: appPickerConfig.globalAttributes,
94
- xstyledProps: appPickerConfig.xstyledProps,
95
- close: handleClose,
96
- triggerRef: triggerRef || defaultTriggerRef,
97
- triggerIsInternal: !renderTrigger,
98
- wasOpenedByKeyboardRef
99
- }
100
- ),
101
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_floating_context.PopoverArrow, { ...arrowStyles })
102
- ]
103
- }
104
- )
105
- ] });
46
+ const ctx = import_react.default.useMemo(() => ({ ...appPickerConfig }), [appPickerConfig]);
47
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_DSAppPickerCTX.DSAppPickerContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_AppPickerContent.AppPickerContent, {}) });
106
48
  };
107
49
  DSAppPicker.displayName = import_constants.DSAppPickerName;
108
50
  const AppPickerWithSchema = (0, import_ds_props_helpers.describe)(DSAppPicker);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/DSAppPicker.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import React from 'react';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { PopoverArrow } from '@elliemae/ds-floating-context';\nimport { AppPanel } from './parts/AppPanel.js';\nimport type { DSAppPickerT } from './react-desc-prop-types.js';\nimport { DSAppPickerPropTypesSchema } from './react-desc-prop-types.js';\nimport { DSAppPickerName } from './constants/index.js';\nimport { useAppPicker } from './config/useAppPicker.js';\nimport { useAppPickerBehavior } from './config/useAppPickerBehavior.js';\nimport { DSAppPickerContext } from './DSAppPickerCTX.js';\nimport { StyledAppPickerFloating } from './parts/style.js';\nimport { Trigger } from './parts/Trigger.js';\n\nconst DSAppPicker: React.ComponentType<DSAppPickerT.Props> = (props) => {\n const appPickerConfig = useAppPicker(props);\n const {\n Icon,\n renderTrigger,\n resolvedIsOpen,\n floatingStyles,\n arrowStyles,\n floatingContext,\n ownerPropsConfig,\n defaultTriggerRef,\n triggerRef,\n wasOpenedByKeyboardRef,\n handleClose,\n handleTriggerRef,\n handleTriggerClick,\n floatingInnerRef,\n focusTracker,\n } = useAppPickerBehavior(appPickerConfig);\n\n return (\n <DSAppPickerContext.Provider value={focusTracker}>\n <Trigger\n Icon={Icon}\n isOpen={resolvedIsOpen}\n setRef={handleTriggerRef}\n ownerProps={ownerPropsConfig}\n onClick={handleTriggerClick}\n renderTrigger={renderTrigger}\n />\n <StyledAppPickerFloating\n innerRef={floatingInnerRef}\n isOpen={resolvedIsOpen}\n floatingStyles={floatingStyles}\n context={floatingContext}\n getOwnerProps={ownerPropsConfig.getOwnerProps}\n getOwnerPropsArguments={ownerPropsConfig.getOwnerPropsArguments}\n >\n <AppPanel\n {...appPickerConfig.propsWithDefault}\n ownerPropsConfig={ownerPropsConfig}\n globalAttributes={appPickerConfig.globalAttributes}\n xstyledProps={appPickerConfig.xstyledProps}\n close={handleClose}\n triggerRef={triggerRef || defaultTriggerRef}\n triggerIsInternal={!renderTrigger}\n wasOpenedByKeyboardRef={wasOpenedByKeyboardRef}\n />\n <PopoverArrow {...arrowStyles} />\n </StyledAppPickerFloating>\n </DSAppPickerContext.Provider>\n );\n};\n\nDSAppPicker.displayName = DSAppPickerName;\nconst AppPickerWithSchema = describe(DSAppPicker);\nAppPickerWithSchema.propTypes = DSAppPickerPropTypesSchema;\n\nexport { DSAppPicker, AppPickerWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADmCjB;AAlCN,8BAAyB;AACzB,iCAA6B;AAC7B,sBAAyB;AAEzB,mCAA2C;AAC3C,uBAAgC;AAChC,0BAA6B;AAC7B,kCAAqC;AACrC,4BAAmC;AACnC,mBAAwC;AACxC,qBAAwB;AAExB,MAAM,cAAuD,CAAC,UAAU;AACtE,QAAM,sBAAkB,kCAAa,KAAK;AAC1C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,kDAAqB,eAAe;AAExC,SACE,6CAAC,yCAAmB,UAAnB,EAA4B,OAAO,cAClC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,SAAS;AAAA,QACT;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR;AAAA,QACA,SAAS;AAAA,QACT,eAAe,iBAAiB;AAAA,QAChC,wBAAwB,iBAAiB;AAAA,QAEzC;AAAA;AAAA,YAAC;AAAA;AAAA,cACE,GAAG,gBAAgB;AAAA,cACpB;AAAA,cACA,kBAAkB,gBAAgB;AAAA,cAClC,cAAc,gBAAgB;AAAA,cAC9B,OAAO;AAAA,cACP,YAAY,cAAc;AAAA,cAC1B,mBAAmB,CAAC;AAAA,cACpB;AAAA;AAAA,UACF;AAAA,UACA,4CAAC,2CAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;AAEA,YAAY,cAAc;AAC1B,MAAM,0BAAsB,kCAAS,WAAW;AAChD,oBAAoB,YAAY;",
6
- "names": []
4
+ "sourcesContent": ["import { describe } from '@elliemae/ds-props-helpers';\nimport React from 'react';\nimport { useAppPicker } from './config/useAppPicker.js';\nimport { DSAppPickerName } from './constants/index.js';\nimport { DSAppPickerContext, type DSAppPickerCTX } from './DSAppPickerCTX.js';\nimport { AppPickerContent } from './parts/AppPickerFloatingContext/AppPickerContent.js';\nimport type { DSAppPickerT } from './react-desc-prop-types.js';\nimport { DSAppPickerPropTypesSchema } from './react-desc-prop-types.js';\n\nconst DSAppPicker: React.ComponentType<DSAppPickerT.Props> = (props) => {\n const appPickerConfig = useAppPicker(props);\n const ctx: DSAppPickerCTX = React.useMemo(() => ({ ...appPickerConfig }), [appPickerConfig]);\n\n return (\n <DSAppPickerContext.Provider value={ctx}>\n <AppPickerContent />\n </DSAppPickerContext.Provider>\n );\n};\n\nDSAppPicker.displayName = DSAppPickerName;\nconst AppPickerWithSchema = describe(DSAppPicker);\nAppPickerWithSchema.propTypes = DSAppPickerPropTypesSchema;\n\nexport { AppPickerWithSchema, DSAppPicker };\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADejB;AAfN,8BAAyB;AACzB,mBAAkB;AAClB,0BAA6B;AAC7B,uBAAgC;AAChC,4BAAwD;AACxD,8BAAiC;AAEjC,mCAA2C;AAE3C,MAAM,cAAuD,CAAC,UAAU;AACtE,QAAM,sBAAkB,kCAAa,KAAK;AAC1C,QAAM,MAAsB,aAAAA,QAAM,QAAQ,OAAO,EAAE,GAAG,gBAAgB,IAAI,CAAC,eAAe,CAAC;AAE3F,SACE,4CAAC,yCAAmB,UAAnB,EAA4B,OAAO,KAClC,sDAAC,4CAAiB,GACpB;AAEJ;AAEA,YAAY,cAAc;AAC1B,MAAM,0BAAsB,kCAAS,WAAW;AAChD,oBAAoB,YAAY;",
6
+ "names": ["React"]
7
7
  }
@@ -33,26 +33,6 @@ __export(DSAppPickerCTX_exports, {
33
33
  module.exports = __toCommonJS(DSAppPickerCTX_exports);
34
34
  var React = __toESM(require("react"));
35
35
  var import_react = require("react");
36
- const defaultFocusContext = {
37
- focusRegion: "",
38
- firstFocusableRef: { current: null },
39
- lastFocusableRef: { current: null },
40
- registerChip: () => {
41
- },
42
- trackFocusChip: () => {
43
- },
44
- trackFocusRegionReset: () => {
45
- },
46
- trackFocusTrigger: () => {
47
- },
48
- trackFocusPanel: () => {
49
- },
50
- trackFocusSelectedItem: () => {
51
- },
52
- trackFocusFirstItem: () => {
53
- },
54
- trackFocusItemAtIndex: () => {
55
- }
56
- };
57
- const DSAppPickerContext = (0, import_react.createContext)(defaultFocusContext);
36
+ const defaultContext = {};
37
+ const DSAppPickerContext = (0, import_react.createContext)(defaultContext);
58
38
  //# sourceMappingURL=DSAppPickerCTX.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/DSAppPickerCTX.ts", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import React, { createContext } from 'react';\nimport type { useFocusTracker } from './config/useFocusTracker.js';\n\nexport type AppPickerFocusCTX = ReturnType<typeof useFocusTracker>;\n\nconst defaultFocusContext: AppPickerFocusCTX = {\n focusRegion: '',\n firstFocusableRef: { current: null } as React.MutableRefObject<HTMLElement | null>,\n lastFocusableRef: { current: null } as React.MutableRefObject<HTMLElement | null>,\n registerChip: () => {},\n trackFocusChip: () => {},\n trackFocusRegionReset: () => {},\n trackFocusTrigger: () => {},\n trackFocusPanel: () => {},\n trackFocusSelectedItem: () => {},\n trackFocusFirstItem: () => {},\n trackFocusItemAtIndex: () => {},\n};\n\n/** Focus tracker context for chip-level focus management inside DSAppPicker. */\nexport const DSAppPickerContext = createContext<AppPickerFocusCTX>(defaultFocusContext);\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAqC;AAKrC,MAAM,sBAAyC;AAAA,EAC7C,aAAa;AAAA,EACb,mBAAmB,EAAE,SAAS,KAAK;AAAA,EACnC,kBAAkB,EAAE,SAAS,KAAK;AAAA,EAClC,cAAc,MAAM;AAAA,EAAC;AAAA,EACrB,gBAAgB,MAAM;AAAA,EAAC;AAAA,EACvB,uBAAuB,MAAM;AAAA,EAAC;AAAA,EAC9B,mBAAmB,MAAM;AAAA,EAAC;AAAA,EAC1B,iBAAiB,MAAM;AAAA,EAAC;AAAA,EACxB,wBAAwB,MAAM;AAAA,EAAC;AAAA,EAC/B,qBAAqB,MAAM;AAAA,EAAC;AAAA,EAC5B,uBAAuB,MAAM;AAAA,EAAC;AAChC;AAGO,MAAM,yBAAqB,4BAAiC,mBAAmB;",
4
+ "sourcesContent": ["import { createContext } from 'react';\nimport type { useAppPicker } from './config/useAppPicker.js';\n\nexport interface DSAppPickerCTX extends ReturnType<typeof useAppPicker> {}\n\nconst defaultContext = {} as DSAppPickerCTX;\n\n/** Single source of truth for DSAppPicker's parts \u2014 props, owner-props config, floating-context\n * render state, and focus tracker. Replaces per-part prop drilling. */\nexport const DSAppPickerContext = createContext<DSAppPickerCTX>(defaultContext);\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAA8B;AAK9B,MAAM,iBAAiB,CAAC;AAIjB,MAAM,yBAAqB,4BAA8B,cAAc;",
6
6
  "names": []
7
7
  }
@@ -32,24 +32,38 @@ __export(useAppPicker_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(useAppPicker_exports);
34
34
  var React = __toESM(require("react"));
35
- var import_react = __toESM(require("react"));
36
35
  var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
36
+ var import_react = __toESM(require("react"));
37
37
  var import_react_desc_prop_types = require("../react-desc-prop-types.js");
38
+ var import_useFocusTracker = require("./useFocusTracker.js");
38
39
  var import_useValidateProps = require("./useValidateProps.js");
39
40
  const useAppPicker = (props) => {
40
41
  const propsWithDefault = (0, import_ds_props_helpers.useMemoMergePropsWithDefault)(props, import_react_desc_prop_types.defaultProps);
41
42
  (0, import_useValidateProps.useValidateProps)(propsWithDefault, import_react_desc_prop_types.DSAppPickerPropTypesSchema);
42
43
  const ownerPropsConfig = (0, import_ds_props_helpers.useOwnerProps)(propsWithDefault, propsWithDefault);
43
- const globalAttributes = (0, import_ds_props_helpers.getGlobalAttributes)(props);
44
- const xstyledProps = (0, import_ds_props_helpers.getXstyledProps)(props);
44
+ const globalAttributes = (0, import_ds_props_helpers.useGetGlobalAttributes)(props);
45
+ const xstyledProps = (0, import_ds_props_helpers.useGetXstyledProps)(props);
46
+ const wasOpenedByKeyboardRef = (0, import_react.useRef)(false);
47
+ const { isOpen, apps, customApps } = propsWithDefault;
48
+ const [internalIsOpen, setInternalIsOpen] = (0, import_react.useState)(false);
49
+ const resolvedIsOpen = typeof isOpen === "boolean" ? isOpen : internalIsOpen;
50
+ const mountedOpenAutofocusPendingRef = (0, import_react.useRef)(resolvedIsOpen);
51
+ const allApps = (0, import_react.useMemo)(() => [...apps, ...customApps], [apps, customApps]);
52
+ const useFocusTrackerConfig = (0, import_react.useMemo)(() => ({ allApps }), [allApps]);
53
+ const focusTrackers = (0, import_useFocusTracker.useFocusTracker)(useFocusTrackerConfig);
45
54
  return import_react.default.useMemo(
46
55
  () => ({
56
+ focusTrackers,
47
57
  propsWithDefault,
48
58
  ownerPropsConfig,
49
59
  globalAttributes,
50
- xstyledProps
60
+ xstyledProps,
61
+ wasOpenedByKeyboardRef,
62
+ mountedOpenAutofocusPendingRef,
63
+ resolvedIsOpen,
64
+ setInternalIsOpen
51
65
  }),
52
- [propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps]
66
+ [focusTrackers, propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps, resolvedIsOpen]
53
67
  );
54
68
  };
55
69
  //# sourceMappingURL=useAppPicker.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/config/useAppPicker.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useOwnerProps,\n getGlobalAttributes,\n getXstyledProps,\n} from '@elliemae/ds-props-helpers';\nimport { type DSAppPickerT, defaultProps, DSAppPickerPropTypesSchema } from '../react-desc-prop-types.js';\nimport { useValidateProps } from './useValidateProps.js';\n\nexport const useAppPicker = (props: DSAppPickerT.Props) => {\n // =============================================================================\n // MERGE WITH DEFAULT AND VALIDATE PROPS\n // =============================================================================\n const propsWithDefault = useMemoMergePropsWithDefault<DSAppPickerT.InternalProps>(props, defaultProps);\n useValidateProps(propsWithDefault, DSAppPickerPropTypesSchema);\n // =============================================================================\n // GLOBAL ATTRIBUTES & XSTYLED PROPS\n // =============================================================================\n // Use propsWithDefault (stable, deep-comparison memoized) instead of { ...props }\n // to prevent getOwnerPropsArguments from creating a new object reference every render.\n const ownerPropsConfig = useOwnerProps(propsWithDefault, propsWithDefault);\n\n const globalAttributes = getGlobalAttributes<DSAppPickerT.Props>(props);\n const xstyledProps = getXstyledProps<DSAppPickerT.Props>(props);\n\n return React.useMemo(\n () => ({\n propsWithDefault,\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n }),\n [propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkB;AAClB,8BAKO;AACP,mCAA4E;AAC5E,8BAAiC;AAE1B,MAAM,eAAe,CAAC,UAA8B;AAIzD,QAAM,uBAAmB,sDAAyD,OAAO,yCAAY;AACrG,gDAAiB,kBAAkB,uDAA0B;AAM7D,QAAM,uBAAmB,uCAAc,kBAAkB,gBAAgB;AAEzE,QAAM,uBAAmB,6CAAwC,KAAK;AACtE,QAAM,mBAAe,yCAAoC,KAAK;AAE9D,SAAO,aAAAA,QAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,kBAAkB,kBAAkB,kBAAkB,YAAY;AAAA,EACrE;AACF;",
4
+ "sourcesContent": ["import {\n useGetGlobalAttributes,\n useGetXstyledProps,\n useMemoMergePropsWithDefault,\n useOwnerProps,\n} from '@elliemae/ds-props-helpers';\nimport React, { useMemo, useRef, useState } from 'react';\nimport { type DSAppPickerT, defaultProps, DSAppPickerPropTypesSchema } from '../react-desc-prop-types.js';\nimport { useFocusTracker } from './useFocusTracker.js';\nimport { useValidateProps } from './useValidateProps.js';\n\nexport const useAppPicker = (props: DSAppPickerT.Props) => {\n // =============================================================================\n // MERGE WITH DEFAULT AND VALIDATE PROPS\n // =============================================================================\n const propsWithDefault = useMemoMergePropsWithDefault<DSAppPickerT.InternalProps>(props, defaultProps);\n useValidateProps(propsWithDefault, DSAppPickerPropTypesSchema);\n // =============================================================================\n // GLOBAL ATTRIBUTES & XSTYLED PROPS\n // =============================================================================\n // Use propsWithDefault (stable, deep-comparison memoized) instead of { ...props }\n // to prevent getOwnerPropsArguments from creating a new object reference every render.\n const ownerPropsConfig = useOwnerProps(propsWithDefault, propsWithDefault);\n\n const globalAttributes = useGetGlobalAttributes<DSAppPickerT.Props>(props);\n const xstyledProps = useGetXstyledProps<DSAppPickerT.Props>(props);\n // =============================================================================\n // Specific component state and logics\n // =============================================================================\n const wasOpenedByKeyboardRef = useRef(false);\n\n // \"Is the panel open\" is top-level component state. `isOpen` (controlled) takes precedence over\n // the internal state when provided. resolvedIsOpen feeds useFloatingContext's\n // externallyControlledIsOpen; initial-focus-on-open is driven off useFloatingContext's onOpen\n // (which fires on that transition), so the focus tracker itself stays a pure region tracker with\n // no open-state awareness.\n const { isOpen, apps, customApps } = propsWithDefault;\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const resolvedIsOpen = typeof isOpen === 'boolean' ? isOpen : internalIsOpen;\n\n // Was DSAppPicker rendered already-open at mount (declarative `isOpen`, before any user\n // interaction)? Such an open is not a transition, so useAppPickerFloatingContext's onOpen seed\n // never fires for it \u2014 AppPanel's useMountedOpenAutofocusNuance consumes this to seed that one\n // case. Captured once; the nuance flips it false after consuming so a later controlled reopen\n // (a real transition, handled by onOpen) doesn't re-trigger it.\n const mountedOpenAutofocusPendingRef = useRef(resolvedIsOpen);\n\n const allApps = useMemo(() => [...apps, ...customApps], [apps, customApps]);\n const useFocusTrackerConfig = useMemo(() => ({ allApps }), [allApps]);\n const focusTrackers = useFocusTracker(useFocusTrackerConfig);\n\n return React.useMemo(\n () => ({\n focusTrackers,\n propsWithDefault,\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n wasOpenedByKeyboardRef,\n mountedOpenAutofocusPendingRef,\n resolvedIsOpen,\n setInternalIsOpen,\n }),\n [focusTrackers, propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps, resolvedIsOpen],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,8BAKO;AACP,mBAAiD;AACjD,mCAA4E;AAC5E,6BAAgC;AAChC,8BAAiC;AAE1B,MAAM,eAAe,CAAC,UAA8B;AAIzD,QAAM,uBAAmB,sDAAyD,OAAO,yCAAY;AACrG,gDAAiB,kBAAkB,uDAA0B;AAM7D,QAAM,uBAAmB,uCAAc,kBAAkB,gBAAgB;AAEzE,QAAM,uBAAmB,gDAA2C,KAAK;AACzE,QAAM,mBAAe,4CAAuC,KAAK;AAIjE,QAAM,6BAAyB,qBAAO,KAAK;AAO3C,QAAM,EAAE,QAAQ,MAAM,WAAW,IAAI;AACrC,QAAM,CAAC,gBAAgB,iBAAiB,QAAI,uBAAS,KAAK;AAC1D,QAAM,iBAAiB,OAAO,WAAW,YAAY,SAAS;AAO9D,QAAM,qCAAiC,qBAAO,cAAc;AAE5D,QAAM,cAAU,sBAAQ,MAAM,CAAC,GAAG,MAAM,GAAG,UAAU,GAAG,CAAC,MAAM,UAAU,CAAC;AAC1E,QAAM,4BAAwB,sBAAQ,OAAO,EAAE,QAAQ,IAAI,CAAC,OAAO,CAAC;AACpE,QAAM,oBAAgB,wCAAgB,qBAAqB;AAE3D,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,CAAC,eAAe,kBAAkB,kBAAkB,kBAAkB,cAAc,cAAc;AAAA,EACpG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -28,25 +28,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var useFocusTracker_exports = {};
30
30
  __export(useFocusTracker_exports, {
31
- getChipRegionId: () => getChipRegionId,
32
31
  useFocusTracker: () => useFocusTracker
33
32
  });
34
33
  module.exports = __toCommonJS(useFocusTracker_exports);
35
34
  var React = __toESM(require("react"));
36
35
  var import_react = require("react");
37
36
  var import_constants = require("../constants/index.js");
38
- const CHIP_REGION_PREFIX = "chip-";
39
- const getChipRegionId = (chipId) => `${CHIP_REGION_PREFIX}${chipId}`;
40
- const useFocusTracker = () => {
37
+ var import_getChipId = require("../util/getChipId.js");
38
+ var import_getChipRegionId = require("../util/getChipRegionId.js");
39
+ const useFocusTracker = (config) => {
40
+ const { allApps } = config;
41
+ const firstFocusableIdx = (0, import_react.useMemo)(() => allApps.findIndex((app) => !app.disabled), [allApps]);
42
+ const lastFocusableIdx = (0, import_react.useMemo)(() => allApps.reduce((acc, app, i) => !app.disabled ? i : acc, -1), [allApps]);
41
43
  const [focusRegion, setFocusRegion] = (0, import_react.useState)(import_constants.APP_PICKER_REGION_FOCUSES.RESET);
42
- const chipIdRegistry = (0, import_react.useRef)(/* @__PURE__ */ new Map());
43
44
  const firstFocusableRef = (0, import_react.useRef)(null);
44
45
  const lastFocusableRef = (0, import_react.useRef)(null);
45
- const registerChip = (0, import_react.useCallback)((app, chipId) => {
46
- chipIdRegistry.current.set(app, chipId);
47
- }, []);
48
46
  const trackFocusChip = (0, import_react.useCallback)((chipId) => {
49
- setFocusRegion(getChipRegionId(chipId));
47
+ setFocusRegion((0, import_getChipRegionId.getChipRegionId)(chipId));
50
48
  }, []);
51
49
  const trackFocusRegionReset = (0, import_react.useCallback)(() => {
52
50
  setFocusRegion(import_constants.APP_PICKER_REGION_FOCUSES.RESET);
@@ -57,38 +55,30 @@ const useFocusTracker = () => {
57
55
  const trackFocusPanel = (0, import_react.useCallback)(() => {
58
56
  setFocusRegion(import_constants.APP_PICKER_REGION_FOCUSES.PANEL);
59
57
  }, []);
60
- const trackFocusSelectedItem = (0, import_react.useCallback)((apps, customApps) => {
61
- const all = [...apps, ...customApps];
62
- const selected = all.find((app) => app.selected);
63
- const target = selected ?? all.find((app) => !app.disabled);
64
- if (target) {
65
- const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;
66
- setFocusRegion(getChipRegionId(chipId));
67
- }
68
- }, []);
69
- const trackFocusFirstItem = (0, import_react.useCallback)((apps, customApps) => {
70
- const first = [...apps, ...customApps].find((app) => !app.disabled);
71
- if (first) {
72
- const chipId = chipIdRegistry.current.get(first) ?? first.id ?? first.label;
73
- setFocusRegion(getChipRegionId(chipId));
58
+ const trackFocusSelectedItem = (0, import_react.useCallback)(() => {
59
+ const selectedIdx = allApps.findIndex((app) => app.selected);
60
+ const index = selectedIdx !== -1 ? selectedIdx : allApps.findIndex((app) => !app.disabled);
61
+ if (index !== -1) setFocusRegion((0, import_getChipRegionId.getChipRegionId)((0, import_getChipId.getChipId)(allApps[index], index)));
62
+ }, [allApps]);
63
+ const trackFocusFirstItem = (0, import_react.useCallback)(() => {
64
+ if (firstFocusableIdx !== -1) {
65
+ setFocusRegion((0, import_getChipRegionId.getChipRegionId)((0, import_getChipId.getChipId)(allApps[firstFocusableIdx], firstFocusableIdx)));
74
66
  }
75
- }, []);
67
+ }, [firstFocusableIdx, allApps]);
76
68
  const trackFocusItemAtIndex = (0, import_react.useCallback)(
77
- (apps, customApps, index) => {
78
- const target = [...apps, ...customApps][index];
79
- if (target) {
80
- const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;
81
- setFocusRegion(getChipRegionId(chipId));
82
- }
69
+ (index) => {
70
+ const target = allApps[index];
71
+ if (target) setFocusRegion((0, import_getChipRegionId.getChipRegionId)((0, import_getChipId.getChipId)(target, index)));
83
72
  },
84
- []
73
+ [allApps]
85
74
  );
86
75
  return (0, import_react.useMemo)(
87
76
  () => ({
77
+ firstFocusableIdx,
78
+ lastFocusableIdx,
88
79
  focusRegion,
89
80
  firstFocusableRef,
90
81
  lastFocusableRef,
91
- registerChip,
92
82
  trackFocusChip,
93
83
  trackFocusRegionReset,
94
84
  trackFocusTrigger,
@@ -98,10 +88,9 @@ const useFocusTracker = () => {
98
88
  trackFocusItemAtIndex
99
89
  }),
100
90
  [
91
+ firstFocusableIdx,
92
+ lastFocusableIdx,
101
93
  focusRegion,
102
- firstFocusableRef,
103
- lastFocusableRef,
104
- registerChip,
105
94
  trackFocusChip,
106
95
  trackFocusRegionReset,
107
96
  trackFocusTrigger,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/config/useFocusTracker.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { APP_PICKER_REGION_FOCUSES } from '../constants/index.js';\nimport type { DSAppPickerT } from '../react-desc-prop-types.js';\n\nconst CHIP_REGION_PREFIX = 'chip-';\n\nexport const getChipRegionId = (chipId: string): string => `${CHIP_REGION_PREFIX}${chipId}`;\n\nexport const useFocusTracker = () => {\n const [focusRegion, setFocusRegion] = useState<string>(APP_PICKER_REGION_FOCUSES.RESET);\n\n // Registry mapping each AppItem instance \u2192 its stable chipId (id ?? `${label}-${uid}`).\n // Populated by AppPickerItem on mount so trackFocusSelectedItem / trackFocusFirstItem\n // resolve the uid-qualified chipId instead of the bare label.\n const chipIdRegistry = useRef(new Map<DSAppPickerT.AppItem, string>());\n\n // DOM refs for the first and last focusable chips \u2014 set by AppPickerItem on mount.\n // Used by useFocusTrap in AppPanel so the focus trap needs no DOM query.\n const firstFocusableRef = useRef<HTMLElement | null>(null);\n const lastFocusableRef = useRef<HTMLElement | null>(null);\n\n const registerChip = useCallback((app: DSAppPickerT.AppItem, chipId: string) => {\n chipIdRegistry.current.set(app, chipId);\n }, []);\n\n const trackFocusChip = useCallback((chipId: string) => {\n setFocusRegion(getChipRegionId(chipId));\n }, []);\n\n const trackFocusRegionReset = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.RESET);\n }, []);\n\n const trackFocusTrigger = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.TRIGGER);\n }, []);\n\n const trackFocusPanel = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.PANEL);\n }, []);\n\n const trackFocusSelectedItem = useCallback((apps: DSAppPickerT.AppItem[], customApps: DSAppPickerT.AppItem[]) => {\n const all = [...apps, ...customApps];\n const selected = all.find((app) => app.selected);\n const target = selected ?? all.find((app) => !app.disabled);\n if (target) {\n const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;\n setFocusRegion(getChipRegionId(chipId));\n }\n }, []);\n\n const trackFocusFirstItem = useCallback((apps: DSAppPickerT.AppItem[], customApps: DSAppPickerT.AppItem[]) => {\n const first = [...apps, ...customApps].find((app) => !app.disabled);\n if (first) {\n const chipId = chipIdRegistry.current.get(first) ?? first.id ?? first.label;\n setFocusRegion(getChipRegionId(chipId));\n }\n }, []);\n\n const trackFocusItemAtIndex = useCallback(\n (apps: DSAppPickerT.AppItem[], customApps: DSAppPickerT.AppItem[], index: number) => {\n const target = [...apps, ...customApps][index];\n if (target) {\n const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;\n setFocusRegion(getChipRegionId(chipId));\n }\n },\n [],\n );\n\n return useMemo(\n () => ({\n focusRegion,\n firstFocusableRef,\n lastFocusableRef,\n registerChip,\n trackFocusChip,\n trackFocusRegionReset,\n trackFocusTrigger,\n trackFocusPanel,\n trackFocusSelectedItem,\n trackFocusFirstItem,\n trackFocusItemAtIndex,\n }),\n [\n focusRegion,\n firstFocusableRef,\n lastFocusableRef,\n registerChip,\n trackFocusChip,\n trackFocusRegionReset,\n trackFocusTrigger,\n trackFocusPanel,\n trackFocusSelectedItem,\n trackFocusFirstItem,\n trackFocusItemAtIndex,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAuD;AACvD,uBAA0C;AAG1C,MAAM,qBAAqB;AAEpB,MAAM,kBAAkB,CAAC,WAA2B,GAAG,kBAAkB,GAAG,MAAM;AAElF,MAAM,kBAAkB,MAAM;AACnC,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAiB,2CAA0B,KAAK;AAKtF,QAAM,qBAAiB,qBAAO,oBAAI,IAAkC,CAAC;AAIrE,QAAM,wBAAoB,qBAA2B,IAAI;AACzD,QAAM,uBAAmB,qBAA2B,IAAI;AAExD,QAAM,mBAAe,0BAAY,CAAC,KAA2B,WAAmB;AAC9E,mBAAe,QAAQ,IAAI,KAAK,MAAM;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAiB,0BAAY,CAAC,WAAmB;AACrD,mBAAe,gBAAgB,MAAM,CAAC;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,4BAAwB,0BAAY,MAAM;AAC9C,mBAAe,2CAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAoB,0BAAY,MAAM;AAC1C,mBAAe,2CAA0B,OAAO;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAkB,0BAAY,MAAM;AACxC,mBAAe,2CAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,6BAAyB,0BAAY,CAAC,MAA8B,eAAuC;AAC/G,UAAM,MAAM,CAAC,GAAG,MAAM,GAAG,UAAU;AACnC,UAAM,WAAW,IAAI,KAAK,CAAC,QAAQ,IAAI,QAAQ;AAC/C,UAAM,SAAS,YAAY,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ;AAC1D,QAAI,QAAQ;AACV,YAAM,SAAS,eAAe,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,OAAO;AACzE,qBAAe,gBAAgB,MAAM,CAAC;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,0BAAsB,0BAAY,CAAC,MAA8B,eAAuC;AAC5G,UAAM,QAAQ,CAAC,GAAG,MAAM,GAAG,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ;AAClE,QAAI,OAAO;AACT,YAAM,SAAS,eAAe,QAAQ,IAAI,KAAK,KAAK,MAAM,MAAM,MAAM;AACtE,qBAAe,gBAAgB,MAAM,CAAC;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,4BAAwB;AAAA,IAC5B,CAAC,MAA8B,YAAoC,UAAkB;AACnF,YAAM,SAAS,CAAC,GAAG,MAAM,GAAG,UAAU,EAAE,KAAK;AAC7C,UAAI,QAAQ;AACV,cAAM,SAAS,eAAe,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,OAAO;AACzE,uBAAe,gBAAgB,MAAM,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;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,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { APP_PICKER_REGION_FOCUSES } from '../constants/index.js';\nimport type { DSAppPickerT } from '../react-desc-prop-types.js';\nimport { getChipId } from '../util/getChipId.js';\nimport { getChipRegionId } from '../util/getChipRegionId.js';\n\ntype FocusTrackerConfigT = {\n allApps: DSAppPickerT.AppItem[];\n};\n\nexport const useFocusTracker = (config: FocusTrackerConfigT) => {\n const { allApps } = config;\n\n // Flat indices of the first/last non-disabled item, used to mark the focus-trap edges.\n // AppSection passes isFirstFocusable/isLastFocusable to AppPickerItem, which sets\n // firstFocusableRef/lastFocusableRef when its innerRef fires.\n const firstFocusableIdx = useMemo(() => allApps.findIndex((app) => !app.disabled), [allApps]);\n const lastFocusableIdx = useMemo(() => allApps.reduce((acc, app, i) => (!app.disabled ? i : acc), -1), [allApps]);\n\n const [focusRegion, setFocusRegion] = useState<string>(APP_PICKER_REGION_FOCUSES.RESET);\n\n // DOM refs for the first and last focusable chips \u2014 set by AppPickerItem's innerRef.\n // Used by useFocusTrap in AppPanel so the focus trap needs no DOM query.\n const firstFocusableRef = useRef<HTMLElement | null>(null);\n const lastFocusableRef = useRef<HTMLElement | null>(null);\n\n const trackFocusChip = useCallback((chipId: string) => {\n setFocusRegion(getChipRegionId(chipId));\n }, []);\n\n const trackFocusRegionReset = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.RESET);\n }, []);\n\n const trackFocusTrigger = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.TRIGGER);\n }, []);\n\n const trackFocusPanel = useCallback(() => {\n setFocusRegion(APP_PICKER_REGION_FOCUSES.PANEL);\n }, []);\n\n const trackFocusSelectedItem = useCallback(() => {\n const selectedIdx = allApps.findIndex((app) => app.selected);\n const index = selectedIdx !== -1 ? selectedIdx : allApps.findIndex((app) => !app.disabled);\n if (index !== -1) setFocusRegion(getChipRegionId(getChipId(allApps[index], index)));\n }, [allApps]);\n\n const trackFocusFirstItem = useCallback(() => {\n if (firstFocusableIdx !== -1) {\n setFocusRegion(getChipRegionId(getChipId(allApps[firstFocusableIdx], firstFocusableIdx)));\n }\n }, [firstFocusableIdx, allApps]);\n\n const trackFocusItemAtIndex = useCallback(\n (index: number) => {\n const target = allApps[index];\n if (target) setFocusRegion(getChipRegionId(getChipId(target, index)));\n },\n [allApps],\n );\n\n return useMemo(\n () => ({\n firstFocusableIdx,\n lastFocusableIdx,\n focusRegion,\n firstFocusableRef,\n lastFocusableRef,\n trackFocusChip,\n trackFocusRegionReset,\n trackFocusTrigger,\n trackFocusPanel,\n trackFocusSelectedItem,\n trackFocusFirstItem,\n trackFocusItemAtIndex,\n }),\n [\n firstFocusableIdx,\n lastFocusableIdx,\n focusRegion,\n trackFocusChip,\n trackFocusRegionReset,\n trackFocusTrigger,\n trackFocusPanel,\n trackFocusSelectedItem,\n trackFocusFirstItem,\n trackFocusItemAtIndex,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAuD;AACvD,uBAA0C;AAE1C,uBAA0B;AAC1B,6BAAgC;AAMzB,MAAM,kBAAkB,CAAC,WAAgC;AAC9D,QAAM,EAAE,QAAQ,IAAI;AAKpB,QAAM,wBAAoB,sBAAQ,MAAM,QAAQ,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,OAAO,CAAC;AAC5F,QAAM,uBAAmB,sBAAQ,MAAM,QAAQ,OAAO,CAAC,KAAK,KAAK,MAAO,CAAC,IAAI,WAAW,IAAI,KAAM,EAAE,GAAG,CAAC,OAAO,CAAC;AAEhH,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAiB,2CAA0B,KAAK;AAItF,QAAM,wBAAoB,qBAA2B,IAAI;AACzD,QAAM,uBAAmB,qBAA2B,IAAI;AAExD,QAAM,qBAAiB,0BAAY,CAAC,WAAmB;AACrD,uBAAe,wCAAgB,MAAM,CAAC;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,4BAAwB,0BAAY,MAAM;AAC9C,mBAAe,2CAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAoB,0BAAY,MAAM;AAC1C,mBAAe,2CAA0B,OAAO;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAkB,0BAAY,MAAM;AACxC,mBAAe,2CAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,6BAAyB,0BAAY,MAAM;AAC/C,UAAM,cAAc,QAAQ,UAAU,CAAC,QAAQ,IAAI,QAAQ;AAC3D,UAAM,QAAQ,gBAAgB,KAAK,cAAc,QAAQ,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ;AACzF,QAAI,UAAU,GAAI,oBAAe,4CAAgB,4BAAU,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EACpF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,0BAAsB,0BAAY,MAAM;AAC5C,QAAI,sBAAsB,IAAI;AAC5B,yBAAe,4CAAgB,4BAAU,QAAQ,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;AAAA,IAC1F;AAAA,EACF,GAAG,CAAC,mBAAmB,OAAO,CAAC;AAE/B,QAAM,4BAAwB;AAAA,IAC5B,CAAC,UAAkB;AACjB,YAAM,SAAS,QAAQ,KAAK;AAC5B,UAAI,OAAQ,oBAAe,4CAAgB,4BAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,IACtE;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,aAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var constants_exports = {};
30
30
  __export(constants_exports, {
31
31
  APP_PICKER_REGION_FOCUSES: () => APP_PICKER_REGION_FOCUSES,
32
+ CHIP_REGION_PREFIX: () => CHIP_REGION_PREFIX,
32
33
  DSAppPickerDataTestIds: () => DSAppPickerDataTestIds,
33
34
  DSAppPickerName: () => DSAppPickerName,
34
35
  DSAppPickerSlots: () => DSAppPickerSlots
@@ -42,6 +43,7 @@ const APP_PICKER_REGION_FOCUSES = {
42
43
  TRIGGER: "trigger",
43
44
  PANEL: "panel"
44
45
  };
46
+ const CHIP_REGION_PREFIX = "chip-";
45
47
  const DSAppPickerSlots = {
46
48
  ROOT: "root",
47
49
  ITEM: "item",
@@ -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": ["import { slotObjectToDataTestIds } from '@elliemae/ds-system';\n\n// DEV-001: triple-p \"DSApppicker\" is the legacy public name. Renaming would break consumers.\n// See KNOWN_INTENTIONAL_DEVIATIONS.md.\nexport const DSAppPickerName = 'DSApppicker';\n\n// we are naming this with the ${component_name}_region_focuses convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const APP_PICKER_REGION_FOCUSES = {\n RESET: '',\n TRIGGER: 'trigger',\n PANEL: 'panel',\n} as const;\n\n// we are naming this with the ${component_name}_slots convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const DSAppPickerSlots = {\n ROOT: 'root',\n ITEM: 'item',\n TITLE: 'title',\n SEPARATOR: 'separator',\n ROW: 'row',\n CHIP: 'chip',\n BUTTON: 'button',\n FLOATING_WRAPPER: 'floating-wrapper',\n} as const;\n\n// Layer 2 legacy data-testid overrides:\n// CHIP and BUTTON predate the slot naming scheme; existing QA selectors must keep matching.\n// See project_compatibility.md (legacy data-testid 3-layer override pattern).\nexport const DSAppPickerDataTestIds = {\n ...(slotObjectToDataTestIds(DSAppPickerName, DSAppPickerSlots) as Record<keyof typeof DSAppPickerSlots, string>),\n CHIP: 'app-picker__chip',\n BUTTON: 'app-picker__button',\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAwC;AAIjC,MAAM,kBAAkB;AAGxB,MAAM,4BAA4B;AAAA,EACvC,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AACT;AAGO,MAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,kBAAkB;AACpB;AAKO,MAAM,yBAAyB;AAAA,EACpC,OAAI,0CAAwB,iBAAiB,gBAAgB;AAAA,EAC7D,MAAM;AAAA,EACN,QAAQ;AACV;",
4
+ "sourcesContent": ["import { slotObjectToDataTestIds } from '@elliemae/ds-system';\n\n// DEV-001: triple-p \"DSApppicker\" is the legacy public name. Renaming would break consumers.\n// See KNOWN_INTENTIONAL_DEVIATIONS.md.\nexport const DSAppPickerName = 'DSApppicker';\n\n// we are naming this with the ${component_name}_region_focuses convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const APP_PICKER_REGION_FOCUSES = {\n RESET: '',\n TRIGGER: 'trigger',\n PANEL: 'panel',\n} as const;\n\n// Prefix for the per-chip focus-region identifiers (see getChipRegionId in src/util).\nexport const CHIP_REGION_PREFIX = 'chip-';\n\n// we are naming this with the ${component_name}_slots convention to namespace & avoid errors on duplicate exports variables in aggregators\nexport const DSAppPickerSlots = {\n ROOT: 'root',\n ITEM: 'item',\n TITLE: 'title',\n SEPARATOR: 'separator',\n ROW: 'row',\n CHIP: 'chip',\n BUTTON: 'button',\n FLOATING_WRAPPER: 'floating-wrapper',\n} as const;\n\n// Layer 2 legacy data-testid overrides:\n// CHIP and BUTTON predate the slot naming scheme; existing QA selectors must keep matching.\n// See project_compatibility.md (legacy data-testid 3-layer override pattern).\nexport const DSAppPickerDataTestIds = {\n ...(slotObjectToDataTestIds(DSAppPickerName, DSAppPickerSlots) as Record<keyof typeof DSAppPickerSlots, string>),\n CHIP: 'app-picker__chip',\n BUTTON: 'app-picker__button',\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAwC;AAIjC,MAAM,kBAAkB;AAGxB,MAAM,4BAA4B;AAAA,EACvC,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AACT;AAGO,MAAM,qBAAqB;AAG3B,MAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,kBAAkB;AACpB;AAKO,MAAM,yBAAyB;AAAA,EACpC,OAAI,0CAAwB,iBAAiB,gBAAgB;AAAA,EAC7D,MAAM;AAAA,EACN,QAAQ;AACV;",
6
6
  "names": []
7
7
  }
@@ -33,37 +33,69 @@ __export(AppPanel_exports, {
33
33
  module.exports = __toCommonJS(AppPanel_exports);
34
34
  var React = __toESM(require("react"));
35
35
  var import_jsx_runtime = require("react/jsx-runtime");
36
- var import_react = require("react");
37
36
  var import_ds_hooks_focus_trap = require("@elliemae/ds-hooks-focus-trap");
38
- var import_style = require("./style.js");
37
+ var import_react = __toESM(require("react"));
39
38
  var import_constants = require("../constants/index.js");
40
- var import_AppSection = require("./AppSection.js");
41
39
  var import_DSAppPickerCTX = require("../DSAppPickerCTX.js");
42
- const AppPanelBase = (props) => {
43
- const { close, triggerRef, wasOpenedByKeyboardRef, triggerIsInternal, ownerPropsConfig, globalAttributes, xstyledProps } = props;
44
- const { apps, customApps, sectionTitle, customSectionTitle, onKeyDown } = props;
45
- const {
46
- focusRegion,
47
- firstFocusableRef,
48
- lastFocusableRef,
49
- trackFocusPanel,
50
- trackFocusFirstItem
51
- } = (0, import_react.useContext)(import_DSAppPickerCTX.DSAppPickerContext);
52
- const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;
53
- const allItems = (0, import_react.useMemo)(() => [...apps, ...customApps], [apps, customApps]);
54
- const firstFocusableIdx = (0, import_react.useMemo)(() => allItems.findIndex((app) => !app.disabled), [allItems]);
55
- const lastFocusableIdx = (0, import_react.useMemo)(
56
- () => allItems.reduce((acc, app, i) => !app.disabled ? i : acc, -1),
57
- [allItems]
58
- );
40
+ var import_AppSection = require("./AppSection.js");
41
+ var import_style = require("./style.js");
42
+ const wrapperGridLayout = {
43
+ cols: ["repeat(3, 92px)"],
44
+ // Row tracks are intentionally auto-sized:
45
+ // - title row picks up its own typography height
46
+ // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)
47
+ // - separator row picks up its own 1px height + margin
48
+ rows: ["auto"]
49
+ };
50
+ const useExecOnceAfterFirstRender = (callback) => {
51
+ const hasExecutedRef = import_react.default.useRef(false);
52
+ const executeInitialFocusRef = import_react.default.useRef(callback);
53
+ executeInitialFocusRef.current = callback;
59
54
  (0, import_react.useEffect)(() => {
60
- if (wasOpenedByKeyboardRef?.current && triggerIsInternal) return;
61
- if (triggerIsInternal) {
62
- trackFocusPanel();
63
- } else {
64
- trackFocusFirstItem(apps, customApps);
55
+ if (!hasExecutedRef.current) {
56
+ executeInitialFocusRef.current();
57
+ hasExecutedRef.current = true;
65
58
  }
66
59
  }, []);
60
+ };
61
+ const useMountedOpenAutofocusNuance = ({
62
+ pendingRef,
63
+ triggerIsInternal,
64
+ trackFocusPanel,
65
+ trackFocusFirstItem
66
+ }) => {
67
+ useExecOnceAfterFirstRender(() => {
68
+ if (!pendingRef.current) return;
69
+ pendingRef.current = false;
70
+ if (triggerIsInternal) trackFocusPanel();
71
+ else trackFocusFirstItem();
72
+ });
73
+ };
74
+ const AppPanelBase = () => {
75
+ const {
76
+ propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle, renderTrigger, onKeyDown },
77
+ ownerPropsConfig,
78
+ globalAttributes,
79
+ xstyledProps,
80
+ mountedOpenAutofocusPendingRef,
81
+ focusTrackers: {
82
+ focusRegion,
83
+ firstFocusableRef,
84
+ lastFocusableRef,
85
+ trackFocusPanel,
86
+ trackFocusFirstItem,
87
+ firstFocusableIdx,
88
+ lastFocusableIdx
89
+ }
90
+ } = (0, import_react.useContext)(import_DSAppPickerCTX.DSAppPickerContext);
91
+ const triggerIsInternal = !renderTrigger;
92
+ const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;
93
+ useMountedOpenAutofocusNuance({
94
+ pendingRef: mountedOpenAutofocusPendingRef,
95
+ triggerIsInternal,
96
+ trackFocusPanel,
97
+ trackFocusFirstItem
98
+ });
67
99
  const isWrapperFocused = focusRegion === import_constants.APP_PICKER_REGION_FOCUSES.PANEL;
68
100
  const handleWrapperRef = (0, import_react.useCallback)(
69
101
  (node) => {
@@ -74,27 +106,12 @@ const AppPanelBase = (props) => {
74
106
  const handleAppClick = (0, import_react.useCallback)((e, app) => {
75
107
  if (app.onClick) app.onClick(e, app);
76
108
  }, []);
77
- const handleOnKeyDownWrapper = (0, import_react.useCallback)(
78
- (e) => {
79
- if (onKeyDown) onKeyDown(e);
80
- if (!onKeyDown && e.key === "Escape") {
81
- triggerRef?.current?.focus();
82
- close();
83
- }
84
- },
85
- [onKeyDown, triggerRef, close]
86
- );
87
109
  const handleOnKeyDown = (0, import_ds_hooks_focus_trap.useFocusTrap)({
88
110
  firstElementRef: firstFocusableRef,
89
111
  lastElementRef: lastFocusableRef,
90
- onKeyDown: handleOnKeyDownWrapper
112
+ onKeyDown
91
113
  });
92
114
  const totalAppsLength = (0, import_react.useMemo)(() => apps.length + customApps.length, [apps.length, customApps.length]);
93
- const layout = (0, import_react.useMemo)(() => {
94
- const cols = ["repeat(3, 92px)"];
95
- const rows = ["auto"];
96
- return { rows, cols };
97
- }, []);
98
115
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
99
116
  import_style.StyledWrapper,
100
117
  {
@@ -102,8 +119,8 @@ const AppPanelBase = (props) => {
102
119
  role: "listbox",
103
120
  innerRef: handleWrapperRef,
104
121
  "data-testid": import_constants.DSAppPickerDataTestIds.ROOT,
105
- cols: layout.cols,
106
- rows: layout.rows,
122
+ cols: wrapperGridLayout.cols,
123
+ rows: wrapperGridLayout.rows,
107
124
  tabIndex: -1,
108
125
  "aria-label": `Application picker, ${sectionTitle} (${apps.length} apps)${customApps.length > 0 ? `, ${customSectionTitle} (${customApps.length} apps)` : ""}`,
109
126
  ...ownerPropsConfig,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/parts/AppPanel.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import React, { useCallback, useRef, useMemo, useEffect, useContext, memo } from 'react';\nimport { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport { StyledWrapper, StyledSeparator, StyledListItemFullRow } from './style.js';\nimport type { DSAppPickerT } from '../react-desc-prop-types.js';\nimport { DSAppPickerDataTestIds, APP_PICKER_REGION_FOCUSES } from '../constants/index.js';\nimport type { useAppPicker } from '../config/useAppPicker.js';\nimport { AppSection } from './AppSection.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\n\nconst AppPanelBase = (\n props: DSAppPickerT.InternalProps &\n Pick<ReturnType<typeof useAppPicker>, 'ownerPropsConfig' | 'globalAttributes' | 'xstyledProps'> & {\n close: () => void;\n wasOpenedByKeyboardRef: React.MutableRefObject<boolean>;\n triggerIsInternal: boolean;\n triggerRef: React.RefObject<HTMLButtonElement>;\n },\n) => {\n const { close, triggerRef, wasOpenedByKeyboardRef, triggerIsInternal, ownerPropsConfig, globalAttributes, xstyledProps } = props;\n const { apps, customApps, sectionTitle, customSectionTitle, onKeyDown } = props;\n\n const {\n focusRegion,\n firstFocusableRef,\n lastFocusableRef,\n trackFocusPanel,\n trackFocusFirstItem,\n } = useContext(DSAppPickerContext);\n\n // Global attributes are spread onto the ul because there is no shared wrapper that contains\n // both the floating panel and the trigger. `wrap`, `onClick`, and `onKeyDown` are filtered out\n // because they collide with the public component API (which uses these for different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Focus trap edges \u2014 populated by AppPickerItem ref callbacks, no DOM query.\n // ---------------------------------------------------------------------------\n\n // Compute which flat indices are first/last non-disabled in the full item list.\n // AppSection passes isFirstFocusable/isLastFocusable to AppPickerItem, which sets\n // firstFocusableRef/lastFocusableRef in the tracker when its innerRef fires.\n const allItems = useMemo(() => [...apps, ...customApps], [apps, customApps]);\n const firstFocusableIdx = useMemo(() => allItems.findIndex((app) => !app.disabled), [allItems]);\n const lastFocusableIdx = useMemo(\n () => allItems.reduce((acc, app, i) => (!app.disabled ? i : acc), -1),\n [allItems],\n );\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open \u2014 all paths go through the tracker.\n // ---------------------------------------------------------------------------\n // Children's effects run before parent effects, so AppPickerItem chip registration\n // (registerChip) is complete by the time this effect fires. Keyboard + internal trigger\n // is handled by useAppPickerBehavior's effect; this effect handles the other two paths.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- runs once on panel mount\n useEffect(() => {\n if (wasOpenedByKeyboardRef?.current && triggerIsInternal) return;\n if (triggerIsInternal) {\n trackFocusPanel();\n } else {\n trackFocusFirstItem(apps, customApps);\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Panel wrapper \u2014 tracker-driven focus for the mouse-open announcement path.\n // handleWrapperRef gets a new reference when isWrapperFocused changes \u2192 React\n // re-invokes the callback with the DOM node \u2192 node.focus() fires.\n // ---------------------------------------------------------------------------\n const isWrapperFocused = focusRegion === APP_PICKER_REGION_FOCUSES.PANEL;\n\n const handleWrapperRef = useCallback(\n (node: HTMLElement | null) => {\n if (node && isWrapperFocused) node.focus();\n },\n [isWrapperFocused],\n );\n\n // ---------------------------------------------------------------------------\n\n const handleAppClick = useCallback((e: React.MouseEvent, app: DSAppPickerT.AppItem) => {\n if (app.onClick) app.onClick(e, app);\n }, []);\n\n const handleOnKeyDownWrapper: React.KeyboardEventHandler = useCallback(\n (e) => {\n if (onKeyDown) onKeyDown(e);\n if (!onKeyDown && e.key === 'Escape') {\n triggerRef?.current?.focus();\n close();\n }\n },\n [onKeyDown, triggerRef, close],\n );\n\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown: handleOnKeyDownWrapper,\n });\n\n const totalAppsLength = useMemo(() => apps.length + customApps.length, [apps.length, customApps.length]);\n\n const layout = useMemo(() => {\n const cols = ['repeat(3, 92px)'];\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n const rows: string[] = ['auto'];\n return { rows, cols };\n }, []);\n\n return (\n <StyledWrapper\n forwardedAs=\"ul\"\n role=\"listbox\"\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={layout.cols}\n rows={layout.rows}\n tabIndex={-1}\n aria-label={`Application picker, ${sectionTitle} (${apps.length} apps)${\n customApps.length > 0 ? `, ${customSectionTitle} (${customApps.length} apps)` : ''\n }`}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection\n items={apps}\n title={sectionTitle}\n positionOffset={0}\n totalCount={totalAppsLength}\n ownerProps={ownerPropsConfig}\n onItemClick={handleAppClick}\n firstFocusableIdx={firstFocusableIdx}\n lastFocusableIdx={lastFocusableIdx}\n />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow\n data-testid={DSAppPickerDataTestIds.ROW}\n aria-hidden\n role=\"group\"\n {...ownerPropsConfig}\n >\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} role=\"presentation\" {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection\n items={customApps}\n title={customSectionTitle}\n positionOffset={apps.length}\n totalCount={totalAppsLength}\n ownerProps={ownerPropsConfig}\n onItemClick={handleAppClick}\n keyPrefix=\"custom-\"\n firstFocusableIdx={firstFocusableIdx}\n lastFocusableIdx={lastFocusableIdx}\n />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["import { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport React, { memo, useCallback, useContext, useEffect, useMemo } from 'react';\nimport { APP_PICKER_REGION_FOCUSES, DSAppPickerDataTestIds } from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport type { DSAppPickerT } from '../react-desc-prop-types.js';\nimport { AppSection } from './AppSection.js';\nimport { StyledListItemFullRow, StyledSeparator, StyledWrapper } from './style.js';\n\nconst wrapperGridLayout = {\n cols: ['repeat(3, 92px)'],\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n rows: ['auto'],\n};\n\nconst useExecOnceAfterFirstRender = (callback: () => void) => {\n const hasExecutedRef = React.useRef(false);\n const executeInitialFocusRef = React.useRef(callback);\n executeInitialFocusRef.current = callback;\n useEffect(() => {\n if (!hasExecutedRef.current) {\n executeInitialFocusRef.current();\n hasExecutedRef.current = true;\n }\n }, []);\n};\n\ntype MountedOpenAutofocusNuanceConfig = {\n pendingRef: React.MutableRefObject<boolean>;\n triggerIsInternal: boolean;\n trackFocusPanel: () => void;\n trackFocusFirstItem: () => void;\n};\n\n/**\n * NUANCE \u2014 the single case that initial-focus-on-open (useAppPickerFloatingContext's onOpen) cannot\n * cover: DSAppPicker rendered ALREADY open (declarative `isOpen` at mount, no user interaction).\n * That open is not a transition, so `onOpen` never fires for it. This mount-time hook seeds the same\n * initial focus a user-driven open would (panel wrapper for the internal trigger, first item for an\n * external renderTrigger). `pendingRef` is true only when the component started open and is flipped\n * false on first consume, so a later controlled reopen \u2014 a real transition handled by `onOpen` \u2014\n * does not double-seed. Every user-driven open (click/keyboard) is a transition handled by `onOpen`,\n * NOT here.\n *\n * REMOVABILITY: if the team decides declarative-open should not autofocus, delete this hook and its\n * call, and flip the \"rendered already-open \u2026 focuses the panel wrapper\" assertion in\n * app-picker.keyboard.test.js. Nothing else depends on it.\n */\nconst useMountedOpenAutofocusNuance = ({\n pendingRef,\n triggerIsInternal,\n trackFocusPanel,\n trackFocusFirstItem,\n}: MountedOpenAutofocusNuanceConfig) => {\n useExecOnceAfterFirstRender(() => {\n if (!pendingRef.current) return;\n pendingRef.current = false;\n if (triggerIsInternal) trackFocusPanel();\n else trackFocusFirstItem();\n });\n};\n\nconst AppPanelBase = () => {\n const {\n propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle, renderTrigger, onKeyDown },\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n mountedOpenAutofocusPendingRef,\n focusTrackers: {\n focusRegion,\n firstFocusableRef,\n lastFocusableRef,\n trackFocusPanel,\n trackFocusFirstItem,\n firstFocusableIdx,\n lastFocusableIdx,\n },\n } = useContext(DSAppPickerContext);\n const triggerIsInternal = !renderTrigger;\n\n // Global attributes are spread onto the ul because there is no shared wrapper that contains\n // both the floating panel and the trigger. `wrap`, `onClick`, and `onKeyDown` are filtered out\n // because they collide with the public component API (which uses these for different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open.\n // ---------------------------------------------------------------------------\n // User-driven opens (click/keyboard) are open transitions, seeded by\n // useAppPickerFloatingContext's onOpen. The one case that isn't a transition \u2014 being rendered\n // already-open (declarative `isOpen` at mount) \u2014 is covered here, scoped to exactly that.\n useMountedOpenAutofocusNuance({\n pendingRef: mountedOpenAutofocusPendingRef,\n triggerIsInternal,\n trackFocusPanel,\n trackFocusFirstItem,\n });\n\n // ---------------------------------------------------------------------------\n // Panel wrapper \u2014 tracker-driven focus for the mouse-open announcement path.\n // handleWrapperRef gets a new reference when isWrapperFocused changes \u2192 React\n // re-invokes the callback with the DOM node \u2192 node.focus() fires.\n // ---------------------------------------------------------------------------\n const isWrapperFocused = focusRegion === APP_PICKER_REGION_FOCUSES.PANEL;\n\n const handleWrapperRef = useCallback(\n (node: HTMLElement | null) => {\n if (node && isWrapperFocused) node.focus();\n },\n [isWrapperFocused],\n );\n\n // ---------------------------------------------------------------------------\n\n const handleAppClick = useCallback((e: React.MouseEvent, app: DSAppPickerT.AppItem) => {\n if (app.onClick) app.onClick(e, app);\n }, []);\n\n // Default Escape-close/refocus is handled declaratively by useFloatingContext\n // (see useAppPickerFloatingContext's closeOnEscape/onEscape wiring) whenever there is no consumer\n // onKeyDown \u2014 a consumer-provided onKeyDown takes over keydown handling entirely.\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown,\n });\n\n const totalAppsLength = useMemo(() => apps.length + customApps.length, [apps.length, customApps.length]);\n\n return (\n <StyledWrapper\n forwardedAs=\"ul\"\n role=\"listbox\"\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={wrapperGridLayout.cols}\n rows={wrapperGridLayout.rows}\n tabIndex={-1}\n aria-label={`Application picker, ${sectionTitle} (${apps.length} apps)${\n customApps.length > 0 ? `, ${customSectionTitle} (${customApps.length} apps)` : ''\n }`}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection\n items={apps}\n title={sectionTitle}\n positionOffset={0}\n totalCount={totalAppsLength}\n ownerProps={ownerPropsConfig}\n onItemClick={handleAppClick}\n firstFocusableIdx={firstFocusableIdx}\n lastFocusableIdx={lastFocusableIdx}\n />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow\n data-testid={DSAppPickerDataTestIds.ROW}\n aria-hidden\n role=\"group\"\n {...ownerPropsConfig}\n >\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} role=\"presentation\" {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection\n items={customApps}\n title={customSectionTitle}\n positionOffset={apps.length}\n totalCount={totalAppsLength}\n ownerProps={ownerPropsConfig}\n onItemClick={handleAppClick}\n keyPrefix=\"custom-\"\n firstFocusableIdx={firstFocusableIdx}\n lastFocusableIdx={lastFocusableIdx}\n />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": "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",
6
+ "names": ["React"]
7
7
  }