@elliemae/ds-app-picker 3.70.0-next.52 → 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
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var getChipId_exports = {};
30
+ __export(getChipId_exports, {
31
+ getChipId: () => getChipId
32
+ });
33
+ module.exports = __toCommonJS(getChipId_exports);
34
+ var React = __toESM(require("react"));
35
+ const getChipId = (app, flatIndex) => app.id ?? `${app.label}-${flatIndex}`;
36
+ //# sourceMappingURL=getChipId.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/util/getChipId.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["import type { DSAppPickerT } from '../react-desc-prop-types.js';\n\n// Chip identity, assigned top-down from data the parent already holds: the app's own `id`, or a\n// deterministic `${label}-${flatIndex}` fallback for id-less apps (the flat index disambiguates\n// duplicate labels). Both the parent (the focus tracker's track* handlers) and the child\n// (AppPickerItem, via the `chipId` prop threaded through AppSection) derive identity through THIS\n// single function, so the parent can compute the exact region string a chip will match without the\n// chip generating an id and reporting it back up. That determinism removes the child\u2192parent\n// dependency entirely: focus can be addressed by identity alone, with no registry to keep in sync\n// and no wait for the child to mount and register.\n//\n// Kept as a standalone leaf util (depends only on a type) so both the hook and the parts can import\n// it without routing through the hook module \u2014 avoids any import cycle risk.\nexport const getChipId = (app: DSAppPickerT.AppItem, flatIndex: number): string =>\n app.id ?? `${app.label}-${flatIndex}`;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADahB,MAAM,YAAY,CAAC,KAA2B,cACnD,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,SAAS;",
6
+ "names": []
7
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var getChipRegionId_exports = {};
30
+ __export(getChipRegionId_exports, {
31
+ getChipRegionId: () => getChipRegionId
32
+ });
33
+ module.exports = __toCommonJS(getChipRegionId_exports);
34
+ var React = __toESM(require("react"));
35
+ var import_constants = require("../constants/index.js");
36
+ const getChipRegionId = (chipId) => `${import_constants.CHIP_REGION_PREFIX}${chipId}`;
37
+ //# sourceMappingURL=getChipRegionId.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/util/getChipRegionId.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["import { CHIP_REGION_PREFIX } from '../constants/index.js';\n\n// Maps a chipId (see getChipId) to its focus-region identifier. Standalone leaf util \u2014 depends only\n// on the constants module \u2014 so the hook and the parts can share it without importing through the\n// hook, keeping the dependency graph acyclic.\nexport const getChipRegionId = (chipId: string): string => `${CHIP_REGION_PREFIX}${chipId}`;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,uBAAmC;AAK5B,MAAM,kBAAkB,CAAC,WAA2B,GAAG,mCAAkB,GAAG,MAAM;",
6
+ "names": []
7
+ }
@@ -1,74 +1,16 @@
1
1
  import * as React from "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { jsx } from "react/jsx-runtime";
3
3
  import { describe } from "@elliemae/ds-props-helpers";
4
- import { PopoverArrow } from "@elliemae/ds-floating-context";
5
- import { AppPanel } from "./parts/AppPanel.js";
6
- import { DSAppPickerPropTypesSchema } from "./react-desc-prop-types.js";
7
- import { DSAppPickerName } from "./constants/index.js";
4
+ import React2 from "react";
8
5
  import { useAppPicker } from "./config/useAppPicker.js";
9
- import { useAppPickerBehavior } from "./config/useAppPickerBehavior.js";
6
+ import { DSAppPickerName } from "./constants/index.js";
10
7
  import { DSAppPickerContext } from "./DSAppPickerCTX.js";
11
- import { StyledAppPickerFloating } from "./parts/style.js";
12
- import { Trigger } from "./parts/Trigger.js";
8
+ import { AppPickerContent } from "./parts/AppPickerFloatingContext/AppPickerContent.js";
9
+ import { DSAppPickerPropTypesSchema } from "./react-desc-prop-types.js";
13
10
  const DSAppPicker = (props) => {
14
11
  const appPickerConfig = useAppPicker(props);
15
- const {
16
- Icon,
17
- renderTrigger,
18
- resolvedIsOpen,
19
- floatingStyles,
20
- arrowStyles,
21
- floatingContext,
22
- ownerPropsConfig,
23
- defaultTriggerRef,
24
- triggerRef,
25
- wasOpenedByKeyboardRef,
26
- handleClose,
27
- handleTriggerRef,
28
- handleTriggerClick,
29
- floatingInnerRef,
30
- focusTracker
31
- } = useAppPickerBehavior(appPickerConfig);
32
- return /* @__PURE__ */ jsxs(DSAppPickerContext.Provider, { value: focusTracker, children: [
33
- /* @__PURE__ */ jsx(
34
- Trigger,
35
- {
36
- Icon,
37
- isOpen: resolvedIsOpen,
38
- setRef: handleTriggerRef,
39
- ownerProps: ownerPropsConfig,
40
- onClick: handleTriggerClick,
41
- renderTrigger
42
- }
43
- ),
44
- /* @__PURE__ */ jsxs(
45
- StyledAppPickerFloating,
46
- {
47
- innerRef: floatingInnerRef,
48
- isOpen: resolvedIsOpen,
49
- floatingStyles,
50
- context: floatingContext,
51
- getOwnerProps: ownerPropsConfig.getOwnerProps,
52
- getOwnerPropsArguments: ownerPropsConfig.getOwnerPropsArguments,
53
- children: [
54
- /* @__PURE__ */ jsx(
55
- AppPanel,
56
- {
57
- ...appPickerConfig.propsWithDefault,
58
- ownerPropsConfig,
59
- globalAttributes: appPickerConfig.globalAttributes,
60
- xstyledProps: appPickerConfig.xstyledProps,
61
- close: handleClose,
62
- triggerRef: triggerRef || defaultTriggerRef,
63
- triggerIsInternal: !renderTrigger,
64
- wasOpenedByKeyboardRef
65
- }
66
- ),
67
- /* @__PURE__ */ jsx(PopoverArrow, { ...arrowStyles })
68
- ]
69
- }
70
- )
71
- ] });
12
+ const ctx = React2.useMemo(() => ({ ...appPickerConfig }), [appPickerConfig]);
13
+ return /* @__PURE__ */ jsx(DSAppPickerContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(AppPickerContent, {}) });
72
14
  };
73
15
  DSAppPicker.displayName = DSAppPickerName;
74
16
  const AppPickerWithSchema = describe(DSAppPicker);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSAppPicker.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACmCjB,cAQA,YARA;AAlCN,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AAEzB,SAAS,kCAAkC;AAC3C,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,eAAe;AAExB,MAAM,cAAuD,CAAC,UAAU;AACtE,QAAM,kBAAkB,aAAa,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,IAAI,qBAAqB,eAAe;AAExC,SACE,qBAAC,mBAAmB,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,oBAAC,gBAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;AAEA,YAAY,cAAc;AAC1B,MAAM,sBAAsB,SAAS,WAAW;AAChD,oBAAoB,YAAY;",
6
- "names": []
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACejB;AAfN,SAAS,gBAAgB;AACzB,OAAOA,YAAW;AAClB,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,0BAA+C;AACxD,SAAS,wBAAwB;AAEjC,SAAS,kCAAkC;AAE3C,MAAM,cAAuD,CAAC,UAAU;AACtE,QAAM,kBAAkB,aAAa,KAAK;AAC1C,QAAM,MAAsBA,OAAM,QAAQ,OAAO,EAAE,GAAG,gBAAgB,IAAI,CAAC,eAAe,CAAC;AAE3F,SACE,oBAAC,mBAAmB,UAAnB,EAA4B,OAAO,KAClC,8BAAC,oBAAiB,GACpB;AAEJ;AAEA,YAAY,cAAc;AAC1B,MAAM,sBAAsB,SAAS,WAAW;AAChD,oBAAoB,YAAY;",
6
+ "names": ["React"]
7
7
  }
@@ -1,27 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { createContext } from "react";
3
- const defaultFocusContext = {
4
- focusRegion: "",
5
- firstFocusableRef: { current: null },
6
- lastFocusableRef: { current: null },
7
- registerChip: () => {
8
- },
9
- trackFocusChip: () => {
10
- },
11
- trackFocusRegionReset: () => {
12
- },
13
- trackFocusTrigger: () => {
14
- },
15
- trackFocusPanel: () => {
16
- },
17
- trackFocusSelectedItem: () => {
18
- },
19
- trackFocusFirstItem: () => {
20
- },
21
- trackFocusItemAtIndex: () => {
22
- }
23
- };
24
- const DSAppPickerContext = createContext(defaultFocusContext);
3
+ const defaultContext = {};
4
+ const DSAppPickerContext = createContext(defaultContext);
25
5
  export {
26
6
  DSAppPickerContext
27
7
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSAppPickerCTX.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAgB,qBAAqB;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,qBAAqB,cAAiC,mBAAmB;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,qBAAqB;AAK9B,MAAM,iBAAiB,CAAC;AAIjB,MAAM,qBAAqB,cAA8B,cAAc;",
6
6
  "names": []
7
7
  }
@@ -1,27 +1,41 @@
1
1
  import * as React from "react";
2
- import React2 from "react";
3
2
  import {
3
+ useGetGlobalAttributes,
4
+ useGetXstyledProps,
4
5
  useMemoMergePropsWithDefault,
5
- useOwnerProps,
6
- getGlobalAttributes,
7
- getXstyledProps
6
+ useOwnerProps
8
7
  } from "@elliemae/ds-props-helpers";
8
+ import React2, { useMemo, useRef, useState } from "react";
9
9
  import { defaultProps, DSAppPickerPropTypesSchema } from "../react-desc-prop-types.js";
10
+ import { useFocusTracker } from "./useFocusTracker.js";
10
11
  import { useValidateProps } from "./useValidateProps.js";
11
12
  const useAppPicker = (props) => {
12
13
  const propsWithDefault = useMemoMergePropsWithDefault(props, defaultProps);
13
14
  useValidateProps(propsWithDefault, DSAppPickerPropTypesSchema);
14
15
  const ownerPropsConfig = useOwnerProps(propsWithDefault, propsWithDefault);
15
- const globalAttributes = getGlobalAttributes(props);
16
- const xstyledProps = getXstyledProps(props);
16
+ const globalAttributes = useGetGlobalAttributes(props);
17
+ const xstyledProps = useGetXstyledProps(props);
18
+ const wasOpenedByKeyboardRef = useRef(false);
19
+ const { isOpen, apps, customApps } = propsWithDefault;
20
+ const [internalIsOpen, setInternalIsOpen] = useState(false);
21
+ const resolvedIsOpen = typeof isOpen === "boolean" ? isOpen : internalIsOpen;
22
+ const mountedOpenAutofocusPendingRef = useRef(resolvedIsOpen);
23
+ const allApps = useMemo(() => [...apps, ...customApps], [apps, customApps]);
24
+ const useFocusTrackerConfig = useMemo(() => ({ allApps }), [allApps]);
25
+ const focusTrackers = useFocusTracker(useFocusTrackerConfig);
17
26
  return React2.useMemo(
18
27
  () => ({
28
+ focusTrackers,
19
29
  propsWithDefault,
20
30
  ownerPropsConfig,
21
31
  globalAttributes,
22
- xstyledProps
32
+ xstyledProps,
33
+ wasOpenedByKeyboardRef,
34
+ mountedOpenAutofocusPendingRef,
35
+ resolvedIsOpen,
36
+ setInternalIsOpen
23
37
  }),
24
- [propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps]
38
+ [focusTrackers, propsWithDefault, ownerPropsConfig, globalAttributes, xstyledProps, resolvedIsOpen]
25
39
  );
26
40
  };
27
41
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useAppPicker.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,YAAW;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA4B,cAAc,kCAAkC;AAC5E,SAAS,wBAAwB;AAE1B,MAAM,eAAe,CAAC,UAA8B;AAIzD,QAAM,mBAAmB,6BAAyD,OAAO,YAAY;AACrG,mBAAiB,kBAAkB,0BAA0B;AAM7D,QAAM,mBAAmB,cAAc,kBAAkB,gBAAgB;AAEzE,QAAM,mBAAmB,oBAAwC,KAAK;AACtE,QAAM,eAAe,gBAAoC,KAAK;AAE9D,SAAOA,OAAM;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 * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAOA,UAAS,SAAS,QAAQ,gBAAgB;AACjD,SAA4B,cAAc,kCAAkC;AAC5E,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AAE1B,MAAM,eAAe,CAAC,UAA8B;AAIzD,QAAM,mBAAmB,6BAAyD,OAAO,YAAY;AACrG,mBAAiB,kBAAkB,0BAA0B;AAM7D,QAAM,mBAAmB,cAAc,kBAAkB,gBAAgB;AAEzE,QAAM,mBAAmB,uBAA2C,KAAK;AACzE,QAAM,eAAe,mBAAuC,KAAK;AAIjE,QAAM,yBAAyB,OAAO,KAAK;AAO3C,QAAM,EAAE,QAAQ,MAAM,WAAW,IAAI;AACrC,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAC1D,QAAM,iBAAiB,OAAO,WAAW,YAAY,SAAS;AAO9D,QAAM,iCAAiC,OAAO,cAAc;AAE5D,QAAM,UAAU,QAAQ,MAAM,CAAC,GAAG,MAAM,GAAG,UAAU,GAAG,CAAC,MAAM,UAAU,CAAC;AAC1E,QAAM,wBAAwB,QAAQ,OAAO,EAAE,QAAQ,IAAI,CAAC,OAAO,CAAC;AACpE,QAAM,gBAAgB,gBAAgB,qBAAqB;AAE3D,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,eAAe,kBAAkB,kBAAkB,kBAAkB,cAAc,cAAc;AAAA,EACpG;AACF;",
6
6
  "names": ["React"]
7
7
  }
@@ -1,16 +1,15 @@
1
1
  import * as React from "react";
2
2
  import { useCallback, useMemo, useRef, useState } from "react";
3
3
  import { APP_PICKER_REGION_FOCUSES } from "../constants/index.js";
4
- const CHIP_REGION_PREFIX = "chip-";
5
- const getChipRegionId = (chipId) => `${CHIP_REGION_PREFIX}${chipId}`;
6
- const useFocusTracker = () => {
4
+ import { getChipId } from "../util/getChipId.js";
5
+ import { getChipRegionId } from "../util/getChipRegionId.js";
6
+ const useFocusTracker = (config) => {
7
+ const { allApps } = config;
8
+ const firstFocusableIdx = useMemo(() => allApps.findIndex((app) => !app.disabled), [allApps]);
9
+ const lastFocusableIdx = useMemo(() => allApps.reduce((acc, app, i) => !app.disabled ? i : acc, -1), [allApps]);
7
10
  const [focusRegion, setFocusRegion] = useState(APP_PICKER_REGION_FOCUSES.RESET);
8
- const chipIdRegistry = useRef(/* @__PURE__ */ new Map());
9
11
  const firstFocusableRef = useRef(null);
10
12
  const lastFocusableRef = useRef(null);
11
- const registerChip = useCallback((app, chipId) => {
12
- chipIdRegistry.current.set(app, chipId);
13
- }, []);
14
13
  const trackFocusChip = useCallback((chipId) => {
15
14
  setFocusRegion(getChipRegionId(chipId));
16
15
  }, []);
@@ -23,38 +22,30 @@ const useFocusTracker = () => {
23
22
  const trackFocusPanel = useCallback(() => {
24
23
  setFocusRegion(APP_PICKER_REGION_FOCUSES.PANEL);
25
24
  }, []);
26
- const trackFocusSelectedItem = useCallback((apps, customApps) => {
27
- const all = [...apps, ...customApps];
28
- const selected = all.find((app) => app.selected);
29
- const target = selected ?? all.find((app) => !app.disabled);
30
- if (target) {
31
- const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;
32
- setFocusRegion(getChipRegionId(chipId));
33
- }
34
- }, []);
35
- const trackFocusFirstItem = useCallback((apps, customApps) => {
36
- const first = [...apps, ...customApps].find((app) => !app.disabled);
37
- if (first) {
38
- const chipId = chipIdRegistry.current.get(first) ?? first.id ?? first.label;
39
- setFocusRegion(getChipRegionId(chipId));
25
+ const trackFocusSelectedItem = useCallback(() => {
26
+ const selectedIdx = allApps.findIndex((app) => app.selected);
27
+ const index = selectedIdx !== -1 ? selectedIdx : allApps.findIndex((app) => !app.disabled);
28
+ if (index !== -1) setFocusRegion(getChipRegionId(getChipId(allApps[index], index)));
29
+ }, [allApps]);
30
+ const trackFocusFirstItem = useCallback(() => {
31
+ if (firstFocusableIdx !== -1) {
32
+ setFocusRegion(getChipRegionId(getChipId(allApps[firstFocusableIdx], firstFocusableIdx)));
40
33
  }
41
- }, []);
34
+ }, [firstFocusableIdx, allApps]);
42
35
  const trackFocusItemAtIndex = useCallback(
43
- (apps, customApps, index) => {
44
- const target = [...apps, ...customApps][index];
45
- if (target) {
46
- const chipId = chipIdRegistry.current.get(target) ?? target.id ?? target.label;
47
- setFocusRegion(getChipRegionId(chipId));
48
- }
36
+ (index) => {
37
+ const target = allApps[index];
38
+ if (target) setFocusRegion(getChipRegionId(getChipId(target, index)));
49
39
  },
50
- []
40
+ [allApps]
51
41
  );
52
42
  return useMemo(
53
43
  () => ({
44
+ firstFocusableIdx,
45
+ lastFocusableIdx,
54
46
  focusRegion,
55
47
  firstFocusableRef,
56
48
  lastFocusableRef,
57
- registerChip,
58
49
  trackFocusChip,
59
50
  trackFocusRegionReset,
60
51
  trackFocusTrigger,
@@ -64,10 +55,9 @@ const useFocusTracker = () => {
64
55
  trackFocusItemAtIndex
65
56
  }),
66
57
  [
58
+ firstFocusableIdx,
59
+ lastFocusableIdx,
67
60
  focusRegion,
68
- firstFocusableRef,
69
- lastFocusableRef,
70
- registerChip,
71
61
  trackFocusChip,
72
62
  trackFocusRegionReset,
73
63
  trackFocusTrigger,
@@ -79,7 +69,6 @@ const useFocusTracker = () => {
79
69
  );
80
70
  };
81
71
  export {
82
- getChipRegionId,
83
72
  useFocusTracker
84
73
  };
85
74
  //# sourceMappingURL=useFocusTracker.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useFocusTracker.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,SAAS,QAAQ,gBAAgB;AACvD,SAAS,iCAAiC;AAG1C,MAAM,qBAAqB;AAEpB,MAAM,kBAAkB,CAAC,WAA2B,GAAG,kBAAkB,GAAG,MAAM;AAElF,MAAM,kBAAkB,MAAM;AACnC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAiB,0BAA0B,KAAK;AAKtF,QAAM,iBAAiB,OAAO,oBAAI,IAAkC,CAAC;AAIrE,QAAM,oBAAoB,OAA2B,IAAI;AACzD,QAAM,mBAAmB,OAA2B,IAAI;AAExD,QAAM,eAAe,YAAY,CAAC,KAA2B,WAAmB;AAC9E,mBAAe,QAAQ,IAAI,KAAK,MAAM;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,iBAAiB,YAAY,CAAC,WAAmB;AACrD,mBAAe,gBAAgB,MAAM,CAAC;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAwB,YAAY,MAAM;AAC9C,mBAAe,0BAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoB,YAAY,MAAM;AAC1C,mBAAe,0BAA0B,OAAO;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,YAAY,MAAM;AACxC,mBAAe,0BAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyB,YAAY,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,sBAAsB,YAAY,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,wBAAwB;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,SAAO;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 * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,SAAS,QAAQ,gBAAgB;AACvD,SAAS,iCAAiC;AAE1C,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAMzB,MAAM,kBAAkB,CAAC,WAAgC;AAC9D,QAAM,EAAE,QAAQ,IAAI;AAKpB,QAAM,oBAAoB,QAAQ,MAAM,QAAQ,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,OAAO,CAAC;AAC5F,QAAM,mBAAmB,QAAQ,MAAM,QAAQ,OAAO,CAAC,KAAK,KAAK,MAAO,CAAC,IAAI,WAAW,IAAI,KAAM,EAAE,GAAG,CAAC,OAAO,CAAC;AAEhH,QAAM,CAAC,aAAa,cAAc,IAAI,SAAiB,0BAA0B,KAAK;AAItF,QAAM,oBAAoB,OAA2B,IAAI;AACzD,QAAM,mBAAmB,OAA2B,IAAI;AAExD,QAAM,iBAAiB,YAAY,CAAC,WAAmB;AACrD,mBAAe,gBAAgB,MAAM,CAAC;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAwB,YAAY,MAAM;AAC9C,mBAAe,0BAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoB,YAAY,MAAM;AAC1C,mBAAe,0BAA0B,OAAO;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,YAAY,MAAM;AACxC,mBAAe,0BAA0B,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyB,YAAY,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,gBAAe,gBAAgB,UAAU,QAAQ,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,EACpF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,sBAAsB,YAAY,MAAM;AAC5C,QAAI,sBAAsB,IAAI;AAC5B,qBAAe,gBAAgB,UAAU,QAAQ,iBAAiB,GAAG,iBAAiB,CAAC,CAAC;AAAA,IAC1F;AAAA,EACF,GAAG,CAAC,mBAAmB,OAAO,CAAC;AAE/B,QAAM,wBAAwB;AAAA,IAC5B,CAAC,UAAkB;AACjB,YAAM,SAAS,QAAQ,KAAK;AAC5B,UAAI,OAAQ,gBAAe,gBAAgB,UAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,IACtE;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,SAAO;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
  }
@@ -6,6 +6,7 @@ const APP_PICKER_REGION_FOCUSES = {
6
6
  TRIGGER: "trigger",
7
7
  PANEL: "panel"
8
8
  };
9
+ const CHIP_REGION_PREFIX = "chip-";
9
10
  const DSAppPickerSlots = {
10
11
  ROOT: "root",
11
12
  ITEM: "item",
@@ -23,6 +24,7 @@ const DSAppPickerDataTestIds = {
23
24
  };
24
25
  export {
25
26
  APP_PICKER_REGION_FOCUSES,
27
+ CHIP_REGION_PREFIX,
26
28
  DSAppPickerDataTestIds,
27
29
  DSAppPickerName,
28
30
  DSAppPickerSlots
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/constants/index.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,+BAA+B;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,GAAI,wBAAwB,iBAAiB,gBAAgB;AAAA,EAC7D,MAAM;AAAA,EACN,QAAQ;AACV;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,+BAA+B;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,GAAI,wBAAwB,iBAAiB,gBAAgB;AAAA,EAC7D,MAAM;AAAA,EACN,QAAQ;AACV;",
6
6
  "names": []
7
7
  }
@@ -1,36 +1,68 @@
1
1
  import * as React from "react";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { useCallback, useMemo, useEffect, useContext, memo } from "react";
4
3
  import { useFocusTrap } from "@elliemae/ds-hooks-focus-trap";
5
- import { StyledWrapper, StyledSeparator, StyledListItemFullRow } from "./style.js";
6
- import { DSAppPickerDataTestIds, APP_PICKER_REGION_FOCUSES } from "../constants/index.js";
7
- import { AppSection } from "./AppSection.js";
4
+ import React2, { memo, useCallback, useContext, useEffect, useMemo } from "react";
5
+ import { APP_PICKER_REGION_FOCUSES, DSAppPickerDataTestIds } from "../constants/index.js";
8
6
  import { DSAppPickerContext } from "../DSAppPickerCTX.js";
9
- const AppPanelBase = (props) => {
10
- const { close, triggerRef, wasOpenedByKeyboardRef, triggerIsInternal, ownerPropsConfig, globalAttributes, xstyledProps } = props;
11
- const { apps, customApps, sectionTitle, customSectionTitle, onKeyDown } = props;
12
- const {
13
- focusRegion,
14
- firstFocusableRef,
15
- lastFocusableRef,
16
- trackFocusPanel,
17
- trackFocusFirstItem
18
- } = useContext(DSAppPickerContext);
19
- const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;
20
- const allItems = useMemo(() => [...apps, ...customApps], [apps, customApps]);
21
- const firstFocusableIdx = useMemo(() => allItems.findIndex((app) => !app.disabled), [allItems]);
22
- const lastFocusableIdx = useMemo(
23
- () => allItems.reduce((acc, app, i) => !app.disabled ? i : acc, -1),
24
- [allItems]
25
- );
7
+ import { AppSection } from "./AppSection.js";
8
+ import { StyledListItemFullRow, StyledSeparator, StyledWrapper } from "./style.js";
9
+ const wrapperGridLayout = {
10
+ cols: ["repeat(3, 92px)"],
11
+ // Row tracks are intentionally auto-sized:
12
+ // - title row picks up its own typography height
13
+ // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)
14
+ // - separator row picks up its own 1px height + margin
15
+ rows: ["auto"]
16
+ };
17
+ const useExecOnceAfterFirstRender = (callback) => {
18
+ const hasExecutedRef = React2.useRef(false);
19
+ const executeInitialFocusRef = React2.useRef(callback);
20
+ executeInitialFocusRef.current = callback;
26
21
  useEffect(() => {
27
- if (wasOpenedByKeyboardRef?.current && triggerIsInternal) return;
28
- if (triggerIsInternal) {
29
- trackFocusPanel();
30
- } else {
31
- trackFocusFirstItem(apps, customApps);
22
+ if (!hasExecutedRef.current) {
23
+ executeInitialFocusRef.current();
24
+ hasExecutedRef.current = true;
32
25
  }
33
26
  }, []);
27
+ };
28
+ const useMountedOpenAutofocusNuance = ({
29
+ pendingRef,
30
+ triggerIsInternal,
31
+ trackFocusPanel,
32
+ trackFocusFirstItem
33
+ }) => {
34
+ useExecOnceAfterFirstRender(() => {
35
+ if (!pendingRef.current) return;
36
+ pendingRef.current = false;
37
+ if (triggerIsInternal) trackFocusPanel();
38
+ else trackFocusFirstItem();
39
+ });
40
+ };
41
+ const AppPanelBase = () => {
42
+ const {
43
+ propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle, renderTrigger, onKeyDown },
44
+ ownerPropsConfig,
45
+ globalAttributes,
46
+ xstyledProps,
47
+ mountedOpenAutofocusPendingRef,
48
+ focusTrackers: {
49
+ focusRegion,
50
+ firstFocusableRef,
51
+ lastFocusableRef,
52
+ trackFocusPanel,
53
+ trackFocusFirstItem,
54
+ firstFocusableIdx,
55
+ lastFocusableIdx
56
+ }
57
+ } = useContext(DSAppPickerContext);
58
+ const triggerIsInternal = !renderTrigger;
59
+ const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;
60
+ useMountedOpenAutofocusNuance({
61
+ pendingRef: mountedOpenAutofocusPendingRef,
62
+ triggerIsInternal,
63
+ trackFocusPanel,
64
+ trackFocusFirstItem
65
+ });
34
66
  const isWrapperFocused = focusRegion === APP_PICKER_REGION_FOCUSES.PANEL;
35
67
  const handleWrapperRef = useCallback(
36
68
  (node) => {
@@ -41,27 +73,12 @@ const AppPanelBase = (props) => {
41
73
  const handleAppClick = useCallback((e, app) => {
42
74
  if (app.onClick) app.onClick(e, app);
43
75
  }, []);
44
- const handleOnKeyDownWrapper = useCallback(
45
- (e) => {
46
- if (onKeyDown) onKeyDown(e);
47
- if (!onKeyDown && e.key === "Escape") {
48
- triggerRef?.current?.focus();
49
- close();
50
- }
51
- },
52
- [onKeyDown, triggerRef, close]
53
- );
54
76
  const handleOnKeyDown = useFocusTrap({
55
77
  firstElementRef: firstFocusableRef,
56
78
  lastElementRef: lastFocusableRef,
57
- onKeyDown: handleOnKeyDownWrapper
79
+ onKeyDown
58
80
  });
59
81
  const totalAppsLength = useMemo(() => apps.length + customApps.length, [apps.length, customApps.length]);
60
- const layout = useMemo(() => {
61
- const cols = ["repeat(3, 92px)"];
62
- const rows = ["auto"];
63
- return { rows, cols };
64
- }, []);
65
82
  return /* @__PURE__ */ jsxs(
66
83
  StyledWrapper,
67
84
  {
@@ -69,8 +86,8 @@ const AppPanelBase = (props) => {
69
86
  role: "listbox",
70
87
  innerRef: handleWrapperRef,
71
88
  "data-testid": DSAppPickerDataTestIds.ROOT,
72
- cols: layout.cols,
73
- rows: layout.rows,
89
+ cols: wrapperGridLayout.cols,
90
+ rows: wrapperGridLayout.rows,
74
91
  tabIndex: -1,
75
92
  "aria-label": `Application picker, ${sectionTitle} (${apps.length} apps)${customApps.length > 0 ? `, ${customSectionTitle} (${customApps.length} apps)` : ""}`,
76
93
  ...ownerPropsConfig,