@elliemae/ds-app-picker 3.70.0-next.3 → 3.70.0-next.31

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 (94) hide show
  1. package/dist/cjs/DSAppPicker.js +59 -132
  2. package/dist/cjs/DSAppPicker.js.map +3 -3
  3. package/dist/cjs/{utils.js → DSAppPickerCTX.js} +26 -23
  4. package/dist/cjs/DSAppPickerCTX.js.map +7 -0
  5. package/dist/cjs/config/useAppPicker.js +3 -3
  6. package/dist/cjs/config/useAppPicker.js.map +3 -3
  7. package/dist/cjs/config/useAppPickerBehavior.js +156 -0
  8. package/dist/cjs/config/useAppPickerBehavior.js.map +7 -0
  9. package/dist/cjs/config/useFocusTracker.js +115 -0
  10. package/dist/cjs/config/useFocusTracker.js.map +7 -0
  11. package/dist/cjs/config/useValidateProps.js +45 -0
  12. package/dist/cjs/config/useValidateProps.js.map +7 -0
  13. package/dist/cjs/constants/index.js +8 -1
  14. package/dist/cjs/constants/index.js.map +2 -2
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/parts/AppPanel.js +159 -0
  17. package/dist/cjs/parts/AppPanel.js.map +7 -0
  18. package/dist/cjs/parts/AppPickerItem.js +102 -0
  19. package/dist/cjs/parts/AppPickerItem.js.map +7 -0
  20. package/dist/cjs/parts/AppSection.js +68 -0
  21. package/dist/cjs/parts/AppSection.js.map +7 -0
  22. package/dist/cjs/parts/Trigger.js +62 -0
  23. package/dist/cjs/parts/Trigger.js.map +7 -0
  24. package/dist/cjs/{styles.js → parts/style.js} +21 -9
  25. package/dist/cjs/parts/style.js.map +7 -0
  26. package/dist/cjs/react-desc-prop-types.js +6 -7
  27. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  28. package/dist/cjs/typescript-testing/typescript-app-picker-valid.js +5 -0
  29. package/dist/cjs/typescript-testing/typescript-app-picker-valid.js.map +2 -2
  30. package/dist/esm/DSAppPicker.js +62 -135
  31. package/dist/esm/DSAppPicker.js.map +2 -2
  32. package/dist/esm/DSAppPickerCTX.js +28 -0
  33. package/dist/esm/DSAppPickerCTX.js.map +7 -0
  34. package/dist/esm/config/useAppPicker.js +4 -5
  35. package/dist/esm/config/useAppPicker.js.map +3 -3
  36. package/dist/esm/config/useAppPickerBehavior.js +126 -0
  37. package/dist/esm/config/useAppPickerBehavior.js.map +7 -0
  38. package/dist/esm/config/useFocusTracker.js +85 -0
  39. package/dist/esm/config/useFocusTracker.js.map +7 -0
  40. package/dist/esm/config/useValidateProps.js +15 -0
  41. package/dist/esm/config/useValidateProps.js.map +7 -0
  42. package/dist/esm/constants/index.js +8 -1
  43. package/dist/esm/constants/index.js.map +2 -2
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/parts/AppPanel.js +129 -0
  46. package/dist/esm/parts/AppPanel.js.map +7 -0
  47. package/dist/esm/parts/AppPickerItem.js +72 -0
  48. package/dist/esm/parts/AppPickerItem.js.map +7 -0
  49. package/dist/esm/parts/AppSection.js +38 -0
  50. package/dist/esm/parts/AppSection.js.map +7 -0
  51. package/dist/esm/parts/Trigger.js +32 -0
  52. package/dist/esm/parts/Trigger.js.map +7 -0
  53. package/dist/esm/{styles.js → parts/style.js} +18 -6
  54. package/dist/esm/parts/style.js.map +7 -0
  55. package/dist/esm/react-desc-prop-types.js +12 -8
  56. package/dist/esm/react-desc-prop-types.js.map +2 -2
  57. package/dist/esm/typescript-testing/typescript-app-picker-valid.js +5 -0
  58. package/dist/esm/typescript-testing/typescript-app-picker-valid.js.map +2 -2
  59. package/dist/types/DSAppPicker.d.ts +0 -1
  60. package/dist/types/DSAppPickerCTX.d.ts +17 -0
  61. package/dist/types/config/useAppPicker.d.ts +5 -5
  62. package/dist/types/config/useAppPickerBehavior.d.ts +39 -0
  63. package/dist/types/config/useFocusTracker.d.ts +15 -0
  64. package/dist/types/config/useValidateProps.d.ts +3 -0
  65. package/dist/types/constants/index.d.ts +14 -7
  66. package/dist/types/parts/AppPanel.d.ts +9 -0
  67. package/dist/types/parts/AppPickerItem.d.ts +14 -0
  68. package/dist/types/parts/AppSection.d.ts +17 -0
  69. package/dist/types/parts/Trigger.d.ts +15 -0
  70. package/dist/types/{styles.d.ts → parts/style.d.ts} +3 -4
  71. package/dist/types/react-desc-prop-types.d.ts +21 -8
  72. package/dist/types/tests/app-picker.get-owner-props-arguments-18354.test.d.ts +1 -0
  73. package/dist/types/tests/app-picker.proptype-schema.test.d.ts +1 -0
  74. package/dist/types/tests/app-picker.pui-18354.test.d.ts +1 -0
  75. package/dist/types/tests/playwright/DSAppPicker.slot-contracts-dynamic.test.playwright.d.ts +1 -0
  76. package/dist/types/tests/playwright/DSAppPickerSlotContractRenderer.d.ts +1 -0
  77. package/package.json +16 -14
  78. package/dist/cjs/AppPickerImpl.js +0 -204
  79. package/dist/cjs/AppPickerImpl.js.map +0 -7
  80. package/dist/cjs/hooks/useKeepTrackButtons.js +0 -69
  81. package/dist/cjs/hooks/useKeepTrackButtons.js.map +0 -7
  82. package/dist/cjs/styles.js.map +0 -7
  83. package/dist/cjs/utils.js.map +0 -7
  84. package/dist/esm/AppPickerImpl.js +0 -174
  85. package/dist/esm/AppPickerImpl.js.map +0 -7
  86. package/dist/esm/hooks/useKeepTrackButtons.js +0 -39
  87. package/dist/esm/hooks/useKeepTrackButtons.js.map +0 -7
  88. package/dist/esm/styles.js.map +0 -7
  89. package/dist/esm/utils.js +0 -25
  90. package/dist/esm/utils.js.map +0 -7
  91. package/dist/types/AppPickerImpl.d.ts +0 -11
  92. package/dist/types/hooks/useKeepTrackButtons.d.ts +0 -13
  93. package/dist/types/utils.d.ts +0 -14
  94. /package/dist/types/tests/{app-picker.get-owner-props.test.d.ts → app-picker.api.test.d.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useAppPicker.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useOwnerProps,\n useValidateTypescriptPropTypes,\n getGlobalAttributes,\n getXstyledProps,\n} from '@elliemae/ds-props-helpers';\nimport { type DSAppPickerT, defaultProps, DSAppPickerPropTypes } from '../react-desc-prop-types.js';\nimport { DSAppPickerName } from '../constants/index.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 useValidateTypescriptPropTypes(propsWithDefault, DSAppPickerPropTypes, DSAppPickerName);\n // =============================================================================\n // GLOBAL ATTRIBUTES & XSTYLED PROPS\n // =============================================================================\n const ownerPropsConfig = useOwnerProps(propsWithDefault, { ...props });\n\n const globalAttributes = getGlobalAttributes<DSAppPickerT.Props>(props);\n const xstyledProps = getXstyledProps<DSAppPickerT.Props>(props);\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,EACA;AAAA,OACK;AACP,SAA4B,cAAc,4BAA4B;AACtE,SAAS,uBAAuB;AAEzB,MAAM,eAAe,CAAC,UAA8B;AAIzD,QAAM,mBAAmB,6BAAyD,OAAO,YAAY;AACrG,iCAA+B,kBAAkB,sBAAsB,eAAe;AAItF,QAAM,mBAAmB,cAAc,kBAAkB,EAAE,GAAG,MAAM,CAAC;AAErE,QAAM,mBAAmB,oBAAwC,KAAK;AACtE,QAAM,eAAe,gBAAoC,KAAK;AAC9D,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;",
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;",
6
6
  "names": ["React"]
7
7
  }
@@ -0,0 +1,126 @@
1
+ import * as React from "react";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
+ import { useFloatingContext } from "@elliemae/ds-floating-context";
4
+ import { useFocusTracker } from "./useFocusTracker.js";
5
+ const useAppPickerBehavior = (appPickerConfig) => {
6
+ const { propsWithDefault, ownerPropsConfig } = appPickerConfig;
7
+ const {
8
+ apps,
9
+ customApps,
10
+ icon: Icon,
11
+ renderTrigger,
12
+ isOpen,
13
+ onClose,
14
+ actionRef,
15
+ onClick,
16
+ onClickOutside,
17
+ triggerRef
18
+ } = propsWithDefault;
19
+ const focusTracker = useFocusTracker();
20
+ const { trackFocusSelectedItem, trackFocusItemAtIndex, trackFocusPanel } = focusTracker;
21
+ const [open, setOpen] = useState(false);
22
+ const defaultTriggerRef = useRef(null);
23
+ const wasOpenedByKeyboardRef = useRef(false);
24
+ const appsRef = useRef(apps);
25
+ appsRef.current = apps;
26
+ const customAppsRef = useRef(customApps);
27
+ customAppsRef.current = customApps;
28
+ const resolvedIsOpen = typeof isOpen === "boolean" ? isOpen : open;
29
+ const handleClose = useCallback(() => {
30
+ setOpen(false);
31
+ onClose?.();
32
+ }, [onClose]);
33
+ const handleClickOutside = useCallback(
34
+ (e) => {
35
+ setOpen(false);
36
+ onClose?.();
37
+ onClickOutside?.(e);
38
+ },
39
+ [onClose, onClickOutside]
40
+ );
41
+ const {
42
+ refs: floatingRefs,
43
+ floatingStyles,
44
+ arrowStyles,
45
+ context: floatingContext
46
+ } = useFloatingContext({
47
+ placement: "bottom",
48
+ // Arrow tip is ~6.1px above the panel top (arrowPlacementBase16 ≈ 17.5px, tip at 11.4px from box top).
49
+ // 4px spec gap → 4 + 6.1 ≈ 10px offset.
50
+ customOffset: [0, 10],
51
+ externallyControlledIsOpen: resolvedIsOpen,
52
+ withoutAnimation: true,
53
+ onClickOutside: handleClickOutside
54
+ });
55
+ const handleTriggerRef = useCallback(
56
+ (node) => {
57
+ defaultTriggerRef.current = node;
58
+ floatingRefs.setReference(node);
59
+ if (triggerRef) {
60
+ triggerRef.current = node;
61
+ }
62
+ },
63
+ [floatingRefs, triggerRef]
64
+ );
65
+ const handleActionRef = useCallback(
66
+ (node) => {
67
+ if (node && actionRef?.current) {
68
+ actionRef.current.focusToIndex = (index) => {
69
+ trackFocusItemAtIndex(appsRef.current, customAppsRef.current, index);
70
+ };
71
+ actionRef.current.focusWrapper = () => {
72
+ trackFocusPanel();
73
+ };
74
+ actionRef.current.focusSelectedOrFirstAvailable = () => {
75
+ trackFocusSelectedItem(appsRef.current, customAppsRef.current);
76
+ };
77
+ }
78
+ },
79
+ [actionRef, trackFocusItemAtIndex, trackFocusPanel, trackFocusSelectedItem]
80
+ );
81
+ const floatingInnerRef = useCallback(
82
+ (node) => {
83
+ floatingRefs.setFloating(node);
84
+ handleActionRef(node);
85
+ },
86
+ [floatingRefs.setFloating, handleActionRef]
87
+ );
88
+ useEffect(() => {
89
+ if (resolvedIsOpen && wasOpenedByKeyboardRef.current) {
90
+ trackFocusSelectedItem(apps, customApps);
91
+ }
92
+ }, [resolvedIsOpen, trackFocusSelectedItem, apps, customApps]);
93
+ const handleTriggerClick = useCallback(
94
+ (e) => {
95
+ wasOpenedByKeyboardRef.current = e.detail === 0;
96
+ onClick?.(e);
97
+ setOpen((prev) => !prev);
98
+ },
99
+ [onClick]
100
+ );
101
+ return {
102
+ // For rendering
103
+ Icon,
104
+ renderTrigger,
105
+ resolvedIsOpen,
106
+ floatingStyles,
107
+ arrowStyles,
108
+ floatingContext,
109
+ ownerPropsConfig,
110
+ // Refs
111
+ defaultTriggerRef,
112
+ triggerRef,
113
+ wasOpenedByKeyboardRef,
114
+ // Handlers
115
+ handleClose,
116
+ handleTriggerRef,
117
+ handleTriggerClick,
118
+ floatingInnerRef,
119
+ // Context value
120
+ focusTracker
121
+ };
122
+ };
123
+ export {
124
+ useAppPickerBehavior
125
+ };
126
+ //# sourceMappingURL=useAppPickerBehavior.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useAppPickerBehavior.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-statements */\nimport type React from 'react';\nimport { useState, useRef, useCallback, useEffect } from 'react';\nimport { useFloatingContext } from '@elliemae/ds-floating-context';\nimport { useFocusTracker } from './useFocusTracker.js';\nimport type { useAppPicker } from './useAppPicker.js';\n\nexport const useAppPickerBehavior = (appPickerConfig: ReturnType<typeof useAppPicker>) => {\n const { propsWithDefault, ownerPropsConfig } = appPickerConfig;\n const {\n apps,\n customApps,\n icon: Icon,\n renderTrigger,\n isOpen,\n onClose,\n actionRef,\n onClick,\n onClickOutside,\n triggerRef,\n } = propsWithDefault;\n\n const focusTracker = useFocusTracker();\n const { trackFocusSelectedItem, trackFocusItemAtIndex, trackFocusPanel } = focusTracker;\n\n const [open, setOpen] = useState(false);\n const defaultTriggerRef = useRef<HTMLButtonElement>(null);\n const wasOpenedByKeyboardRef = useRef(false);\n\n // Stable refs for actionRef methods \u2014 closed over by the callback below so they are\n // always current without causing the ref callback to regenerate on every data change.\n const appsRef = useRef(apps);\n appsRef.current = apps;\n const customAppsRef = useRef(customApps);\n customAppsRef.current = customApps;\n\n const resolvedIsOpen = typeof isOpen === 'boolean' ? isOpen : open;\n\n const handleClose = useCallback(() => {\n setOpen(false);\n onClose?.();\n }, [onClose]);\n\n const handleClickOutside = useCallback(\n (e: MouseEvent | TouchEvent) => {\n setOpen(false);\n onClose?.();\n onClickOutside?.(e as MouseEvent);\n },\n [onClose, onClickOutside],\n );\n\n const {\n refs: floatingRefs,\n floatingStyles,\n arrowStyles,\n context: floatingContext,\n } = useFloatingContext({\n placement: 'bottom',\n // Arrow tip is ~6.1px above the panel top (arrowPlacementBase16 \u2248 17.5px, tip at 11.4px from box top).\n // 4px spec gap \u2192 4 + 6.1 \u2248 10px offset.\n customOffset: [0, 10],\n externallyControlledIsOpen: resolvedIsOpen,\n withoutAnimation: true,\n onClickOutside: handleClickOutside,\n });\n\n const handleTriggerRef = useCallback<React.RefCallback<HTMLButtonElement>>(\n (node) => {\n (defaultTriggerRef as React.MutableRefObject<HTMLButtonElement | null>).current = node;\n floatingRefs.setReference(node);\n if (triggerRef) {\n (triggerRef as React.MutableRefObject<HTMLButtonElement | null>).current = node;\n }\n },\n [floatingRefs, triggerRef],\n );\n\n // Ref callback on StyledAppPickerFloating: fires on mount with the panel node, populating\n // actionRef methods. All focus operations go through the tracker \u2014 no DOM queries.\n const handleActionRef = useCallback<React.RefCallback<HTMLDivElement>>(\n (node) => {\n if (node && actionRef?.current) {\n actionRef.current.focusToIndex = (index: number) => {\n trackFocusItemAtIndex(appsRef.current, customAppsRef.current, index);\n };\n actionRef.current.focusWrapper = () => {\n trackFocusPanel();\n };\n actionRef.current.focusSelectedOrFirstAvailable = () => {\n trackFocusSelectedItem(appsRef.current, customAppsRef.current);\n };\n }\n },\n [actionRef, trackFocusItemAtIndex, trackFocusPanel, trackFocusSelectedItem],\n );\n\n const floatingInnerRef = useCallback<React.RefCallback<HTMLDivElement>>(\n (node) => {\n (floatingRefs.setFloating as React.RefCallback<HTMLDivElement>)(node);\n handleActionRef(node);\n },\n [floatingRefs.setFloating, handleActionRef],\n );\n\n // When panel opens via keyboard, seed the focus tracker so the correct chip gets focus\n // via its innerRef callback. Non-keyboard paths are handled by AppPanel on mount.\n useEffect(() => {\n if (resolvedIsOpen && wasOpenedByKeyboardRef.current) {\n trackFocusSelectedItem(apps, customApps);\n }\n }, [resolvedIsOpen, trackFocusSelectedItem, apps, customApps]);\n\n const handleTriggerClick = useCallback(\n (e: React.MouseEvent | React.KeyboardEvent) => {\n wasOpenedByKeyboardRef.current = (e as React.MouseEvent).detail === 0;\n onClick?.(e);\n setOpen((prev) => !prev);\n },\n [onClick],\n );\n\n return {\n // For rendering\n Icon,\n renderTrigger,\n resolvedIsOpen,\n floatingStyles,\n arrowStyles,\n floatingContext,\n ownerPropsConfig,\n // Refs\n defaultTriggerRef,\n triggerRef,\n wasOpenedByKeyboardRef,\n // Handlers\n handleClose,\n handleTriggerRef,\n handleTriggerClick,\n floatingInnerRef,\n // Context value\n focusTracker,\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,85 @@
1
+ import * as React from "react";
2
+ import { useCallback, useMemo, useRef, useState } from "react";
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 = () => {
7
+ const [focusRegion, setFocusRegion] = useState(APP_PICKER_REGION_FOCUSES.RESET);
8
+ const chipIdRegistry = useRef(/* @__PURE__ */ new Map());
9
+ const firstFocusableRef = useRef(null);
10
+ const lastFocusableRef = useRef(null);
11
+ const registerChip = useCallback((app, chipId) => {
12
+ chipIdRegistry.current.set(app, chipId);
13
+ }, []);
14
+ const trackFocusChip = useCallback((chipId) => {
15
+ setFocusRegion(getChipRegionId(chipId));
16
+ }, []);
17
+ const trackFocusRegionReset = useCallback(() => {
18
+ setFocusRegion(APP_PICKER_REGION_FOCUSES.RESET);
19
+ }, []);
20
+ const trackFocusTrigger = useCallback(() => {
21
+ setFocusRegion(APP_PICKER_REGION_FOCUSES.TRIGGER);
22
+ }, []);
23
+ const trackFocusPanel = useCallback(() => {
24
+ setFocusRegion(APP_PICKER_REGION_FOCUSES.PANEL);
25
+ }, []);
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));
40
+ }
41
+ }, []);
42
+ 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
+ }
49
+ },
50
+ []
51
+ );
52
+ return useMemo(
53
+ () => ({
54
+ focusRegion,
55
+ firstFocusableRef,
56
+ lastFocusableRef,
57
+ registerChip,
58
+ trackFocusChip,
59
+ trackFocusRegionReset,
60
+ trackFocusTrigger,
61
+ trackFocusPanel,
62
+ trackFocusSelectedItem,
63
+ trackFocusFirstItem,
64
+ trackFocusItemAtIndex
65
+ }),
66
+ [
67
+ focusRegion,
68
+ firstFocusableRef,
69
+ lastFocusableRef,
70
+ registerChip,
71
+ trackFocusChip,
72
+ trackFocusRegionReset,
73
+ trackFocusTrigger,
74
+ trackFocusPanel,
75
+ trackFocusSelectedItem,
76
+ trackFocusFirstItem,
77
+ trackFocusItemAtIndex
78
+ ]
79
+ );
80
+ };
81
+ export {
82
+ getChipRegionId,
83
+ useFocusTracker
84
+ };
85
+ //# sourceMappingURL=useFocusTracker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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;",
6
+ "names": []
7
+ }
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import { useValidateTypescriptPropTypes } from "@elliemae/ds-props-helpers";
3
+ import { DSAppPickerName } from "../constants/index.js";
4
+ const useValidateProps = (props, propTypes) => {
5
+ useValidateTypescriptPropTypes(props, propTypes, DSAppPickerName);
6
+ if (!props.apps.length && !props.customApps.length) {
7
+ throw new Error(
8
+ `[${DSAppPickerName}] At least one of "apps" or "customApps" must contain items. Providing both as empty arrays renders an empty picker.`
9
+ );
10
+ }
11
+ };
12
+ export {
13
+ useValidateProps
14
+ };
15
+ //# sourceMappingURL=useValidateProps.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useValidateProps.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';\nimport type { ValidationMap } from '@elliemae/ds-props-helpers';\nimport { type DSAppPickerT } from '../react-desc-prop-types.js';\nimport { DSAppPickerName } from '../constants/index.js';\n\nexport const useValidateProps = (props: DSAppPickerT.InternalProps, propTypes: ValidationMap<unknown>): void => {\n useValidateTypescriptPropTypes(props, propTypes, DSAppPickerName);\n\n if (!props.apps.length && !props.customApps.length) {\n throw new Error(\n `[${DSAppPickerName}] At least one of \"apps\" or \"customApps\" must contain items. ` +\n `Providing both as empty arrays renders an empty picker.`,\n );\n }\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,sCAAsC;AAG/C,SAAS,uBAAuB;AAEzB,MAAM,mBAAmB,CAAC,OAAmC,cAA4C;AAC9G,iCAA+B,OAAO,WAAW,eAAe;AAEhE,MAAI,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,WAAW,QAAQ;AAClD,UAAM,IAAI;AAAA,MACR,IAAI,eAAe;AAAA,IAErB;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -1,6 +1,11 @@
1
1
  import * as React from "react";
2
2
  import { slotObjectToDataTestIds } from "@elliemae/ds-system";
3
3
  const DSAppPickerName = "DSApppicker";
4
+ const APP_PICKER_REGION_FOCUSES = {
5
+ RESET: "",
6
+ TRIGGER: "trigger",
7
+ PANEL: "panel"
8
+ };
4
9
  const DSAppPickerSlots = {
5
10
  ROOT: "root",
6
11
  ITEM: "item",
@@ -8,7 +13,8 @@ const DSAppPickerSlots = {
8
13
  SEPARATOR: "separator",
9
14
  ROW: "row",
10
15
  CHIP: "chip",
11
- BUTTON: "button"
16
+ BUTTON: "button",
17
+ FLOATING_WRAPPER: "floating-wrapper"
12
18
  };
13
19
  const DSAppPickerDataTestIds = {
14
20
  ...slotObjectToDataTestIds(DSAppPickerName, DSAppPickerSlots),
@@ -16,6 +22,7 @@ const DSAppPickerDataTestIds = {
16
22
  BUTTON: "app-picker__button"
17
23
  };
18
24
  export {
25
+ APP_PICKER_REGION_FOCUSES,
19
26
  DSAppPickerDataTestIds,
20
27
  DSAppPickerName,
21
28
  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\nexport const DSAppPickerName = 'DSApppicker';\n\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};\n\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;AAEjC,MAAM,kBAAkB;AAExB,MAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AACV;AAEO,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// 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;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/index.tsx"],
3
+ "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/index.ts"],
4
4
  "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export { DSAppPicker, AppPickerWithSchema } from './DSAppPicker.js';\nexport { DSAppPickerName, DSAppPickerSlots, DSAppPickerDataTestIds } from './constants/index.js';\nexport type { DSAppPickerT } from './react-desc-prop-types.js';\n"],
5
5
  "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,2BAA2B;AACjD,SAAS,iBAAiB,kBAAkB,8BAA8B;",
6
6
  "names": []
@@ -0,0 +1,129 @@
1
+ import * as React from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useMemo, useEffect, useContext, memo } from "react";
4
+ 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";
8
+ 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
+ );
26
+ useEffect(() => {
27
+ if (wasOpenedByKeyboardRef?.current && triggerIsInternal) return;
28
+ if (triggerIsInternal) {
29
+ trackFocusPanel();
30
+ } else {
31
+ trackFocusFirstItem(apps, customApps);
32
+ }
33
+ }, []);
34
+ const isWrapperFocused = focusRegion === APP_PICKER_REGION_FOCUSES.PANEL;
35
+ const handleWrapperRef = useCallback(
36
+ (node) => {
37
+ if (node && isWrapperFocused) node.focus();
38
+ },
39
+ [isWrapperFocused]
40
+ );
41
+ const handleAppClick = useCallback((e, app) => {
42
+ if (app.onClick) app.onClick(e, app);
43
+ }, []);
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
+ const handleOnKeyDown = useFocusTrap({
55
+ firstElementRef: firstFocusableRef,
56
+ lastElementRef: lastFocusableRef,
57
+ onKeyDown: handleOnKeyDownWrapper
58
+ });
59
+ 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
+ return /* @__PURE__ */ jsxs(
66
+ StyledWrapper,
67
+ {
68
+ forwardedAs: "ul",
69
+ role: "listbox",
70
+ innerRef: handleWrapperRef,
71
+ "data-testid": DSAppPickerDataTestIds.ROOT,
72
+ cols: layout.cols,
73
+ rows: layout.rows,
74
+ tabIndex: -1,
75
+ "aria-label": `Application picker, ${sectionTitle} (${apps.length} apps)${customApps.length > 0 ? `, ${customSectionTitle} (${customApps.length} apps)` : ""}`,
76
+ ...ownerPropsConfig,
77
+ ...safeGlobalAttributes,
78
+ ...xstyledProps,
79
+ onKeyDown: handleOnKeyDown,
80
+ children: [
81
+ /* @__PURE__ */ jsx(
82
+ AppSection,
83
+ {
84
+ items: apps,
85
+ title: sectionTitle,
86
+ positionOffset: 0,
87
+ totalCount: totalAppsLength,
88
+ ownerProps: ownerPropsConfig,
89
+ onItemClick: handleAppClick,
90
+ firstFocusableIdx,
91
+ lastFocusableIdx
92
+ }
93
+ ),
94
+ customApps.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
95
+ /* @__PURE__ */ jsx(
96
+ StyledListItemFullRow,
97
+ {
98
+ "data-testid": DSAppPickerDataTestIds.ROW,
99
+ "aria-hidden": true,
100
+ role: "group",
101
+ ...ownerPropsConfig,
102
+ children: /* @__PURE__ */ jsx(StyledSeparator, { "data-testid": DSAppPickerDataTestIds.SEPARATOR, role: "presentation", ...ownerPropsConfig })
103
+ }
104
+ ),
105
+ /* @__PURE__ */ jsx(
106
+ AppSection,
107
+ {
108
+ items: customApps,
109
+ title: customSectionTitle,
110
+ positionOffset: apps.length,
111
+ totalCount: totalAppsLength,
112
+ ownerProps: ownerPropsConfig,
113
+ onItemClick: handleAppClick,
114
+ keyPrefix: "custom-",
115
+ firstFocusableIdx,
116
+ lastFocusableIdx
117
+ }
118
+ )
119
+ ] })
120
+ ]
121
+ }
122
+ );
123
+ };
124
+ const AppPanel = memo(AppPanelBase);
125
+ AppPanel.displayName = "DSAppPicker.AppPanel";
126
+ export {
127
+ AppPanel
128
+ };
129
+ //# sourceMappingURL=AppPanel.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/AppPanel.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,72 @@
1
+ import * as React from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import React2, { useContext } from "react";
4
+ import { uid } from "uid";
5
+ import { styled } from "@elliemae/ds-system";
6
+ import { DSChip } from "@elliemae/ds-chip";
7
+ import { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from "../constants/index.js";
8
+ import { StyledListItem } from "./style.js";
9
+ import { DSAppPickerContext } from "../DSAppPickerCTX.js";
10
+ import { getChipRegionId } from "../config/useFocusTracker.js";
11
+ const StyledChip = styled(DSChip, { name: DSAppPickerName, slot: DSAppPickerSlots.CHIP })``;
12
+ const AppIcon = ({ icon: Icon }) => /* @__PURE__ */ jsx(Icon, { className: "app-picker__icon", size: "m" });
13
+ const AppPickerItem = React2.memo(
14
+ ({ app, positionLabel, ownerProps, onClick, isFirstFocusable, isLastFocusable }) => {
15
+ const { label, disabled, applyAriaDisabled, selected, icon, id, wrapText } = app;
16
+ const { focusRegion, firstFocusableRef, lastFocusableRef, registerChip, trackFocusChip, trackFocusRegionReset } = useContext(DSAppPickerContext);
17
+ const instanceUid = React2.useMemo(() => uid(5), []);
18
+ const chipId = id ?? `${label}-${instanceUid}`;
19
+ const isFocused = focusRegion === getChipRegionId(chipId);
20
+ React2.useEffect(() => {
21
+ registerChip(app, chipId);
22
+ }, [app, chipId, registerChip]);
23
+ const getOwnerPropsArguments = React2.useCallback(() => app, [app]);
24
+ const renderIcon = React2.useCallback(() => /* @__PURE__ */ jsx(AppIcon, { icon }), [icon]);
25
+ const handleClick = React2.useCallback((e) => onClick(e, app), [app, onClick]);
26
+ const handleFocus = React2.useCallback(() => trackFocusChip(chipId), [chipId, trackFocusChip]);
27
+ const handleChipRef = React2.useCallback(
28
+ (node) => {
29
+ if (isFirstFocusable) firstFocusableRef.current = node;
30
+ if (isLastFocusable) lastFocusableRef.current = node;
31
+ if (node && isFocused) node.focus();
32
+ },
33
+ [isFirstFocusable, isLastFocusable, isFocused, firstFocusableRef, lastFocusableRef]
34
+ );
35
+ return /* @__PURE__ */ jsx(
36
+ StyledListItem,
37
+ {
38
+ "data-testid": DSAppPickerDataTestIds.ITEM,
39
+ role: "presentation",
40
+ getOwnerProps: ownerProps.getOwnerProps,
41
+ getOwnerPropsArguments,
42
+ children: /* @__PURE__ */ jsx(
43
+ StyledChip,
44
+ {
45
+ onClick: handleClick,
46
+ "data-testid": DSAppPickerDataTestIds.CHIP,
47
+ disabled,
48
+ applyAriaDisabled,
49
+ selected,
50
+ "aria-selected": selected,
51
+ role: "option",
52
+ id,
53
+ "aria-label": `${label}. ${positionLabel}`,
54
+ icon: renderIcon,
55
+ label,
56
+ getOwnerProps: ownerProps.getOwnerProps,
57
+ getOwnerPropsArguments,
58
+ wrapText,
59
+ innerRef: handleChipRef,
60
+ onBlur: trackFocusRegionReset,
61
+ onFocus: handleFocus
62
+ }
63
+ )
64
+ }
65
+ );
66
+ }
67
+ );
68
+ AppPickerItem.displayName = "DSAppPicker.AppPickerItem";
69
+ export {
70
+ AppPickerItem
71
+ };
72
+ //# sourceMappingURL=AppPickerItem.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/AppPickerItem.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React, { useContext } from 'react';\nimport { uid } from 'uid';\nimport { styled } from '@elliemae/ds-system';\nimport { DSChip } from '@elliemae/ds-chip';\nimport type { DSAppPickerT } from '../react-desc-prop-types.js';\nimport { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from '../constants/index.js';\nimport { StyledListItem } from './style.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { getChipRegionId } from '../config/useFocusTracker.js';\n\nconst StyledChip = styled(DSChip, { name: DSAppPickerName, slot: DSAppPickerSlots.CHIP })``;\n\ninterface AppIconProps {\n icon: DSAppPickerT.AppItem['icon'];\n}\n\nconst AppIcon: React.FC<AppIconProps> = ({ icon: Icon }) => <Icon className=\"app-picker__icon\" size=\"m\" />;\n\ninterface AppPickerItemProps {\n app: DSAppPickerT.AppItem;\n positionLabel: string;\n ownerProps: { getOwnerProps: () => object };\n onClick: (e: React.MouseEvent, app: DSAppPickerT.AppItem) => void;\n isFirstFocusable: boolean;\n isLastFocusable: boolean;\n}\n\nexport const AppPickerItem: React.FC<AppPickerItemProps> = React.memo(\n ({ app, positionLabel, ownerProps, onClick, isFirstFocusable, isLastFocusable }) => {\n const { label, disabled, applyAriaDisabled, selected, icon, id, wrapText } = app;\n const { focusRegion, firstFocusableRef, lastFocusableRef, registerChip, trackFocusChip, trackFocusRegionReset } =\n useContext(DSAppPickerContext);\n\n const instanceUid = React.useMemo(() => uid(5), []);\n const chipId = id ?? `${label}-${instanceUid}`;\n const isFocused = focusRegion === getChipRegionId(chipId);\n\n React.useEffect(() => {\n registerChip(app, chipId);\n }, [app, chipId, registerChip]);\n\n const getOwnerPropsArguments = React.useCallback(() => app, [app]);\n const renderIcon = React.useCallback(() => <AppIcon icon={icon} />, [icon]);\n const handleClick = React.useCallback((e: React.MouseEvent) => onClick(e, app), [app, onClick]);\n const handleFocus = React.useCallback(() => trackFocusChip(chipId), [chipId, trackFocusChip]);\n\n // Single ref callback: registers focus-trap edges and drives tracker-seeded focus.\n // New reference when isFocused or edge membership changes \u2014 React re-invokes with the DOM node.\n const handleChipRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (isFirstFocusable) firstFocusableRef.current = node;\n if (isLastFocusable) lastFocusableRef.current = node;\n if (node && isFocused) node.focus();\n },\n [isFirstFocusable, isLastFocusable, isFocused, firstFocusableRef, lastFocusableRef],\n );\n\n return (\n <StyledListItem\n data-testid={DSAppPickerDataTestIds.ITEM}\n role=\"presentation\"\n getOwnerProps={ownerProps.getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n >\n <StyledChip\n onClick={handleClick}\n data-testid={DSAppPickerDataTestIds.CHIP}\n disabled={disabled}\n applyAriaDisabled={applyAriaDisabled}\n selected={selected}\n aria-selected={selected}\n role=\"option\"\n id={id}\n aria-label={`${label}. ${positionLabel}`}\n icon={renderIcon}\n label={label}\n getOwnerProps={ownerProps.getOwnerProps}\n getOwnerPropsArguments={getOwnerPropsArguments}\n wrapText={wrapText}\n innerRef={handleChipRef}\n onBlur={trackFocusRegionReset}\n onFocus={handleFocus}\n />\n </StyledListItem>\n );\n },\n);\n\nAppPickerItem.displayName = 'DSAppPicker.AppPickerItem';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACgBqC;AAhB5D,OAAOA,UAAS,kBAAkB;AAClC,SAAS,WAAW;AACpB,SAAS,cAAc;AACvB,SAAS,cAAc;AAEvB,SAAS,wBAAwB,iBAAiB,wBAAwB;AAC1E,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAEhC,MAAM,aAAa,OAAO,QAAQ,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,KAAK,CAAC;AAMxF,MAAM,UAAkC,CAAC,EAAE,MAAM,KAAK,MAAM,oBAAC,QAAK,WAAU,oBAAmB,MAAK,KAAI;AAWjG,MAAM,gBAA8CA,OAAM;AAAA,EAC/D,CAAC,EAAE,KAAK,eAAe,YAAY,SAAS,kBAAkB,gBAAgB,MAAM;AAClF,UAAM,EAAE,OAAO,UAAU,mBAAmB,UAAU,MAAM,IAAI,SAAS,IAAI;AAC7E,UAAM,EAAE,aAAa,mBAAmB,kBAAkB,cAAc,gBAAgB,sBAAsB,IAC5G,WAAW,kBAAkB;AAE/B,UAAM,cAAcA,OAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,UAAM,SAAS,MAAM,GAAG,KAAK,IAAI,WAAW;AAC5C,UAAM,YAAY,gBAAgB,gBAAgB,MAAM;AAExD,IAAAA,OAAM,UAAU,MAAM;AACpB,mBAAa,KAAK,MAAM;AAAA,IAC1B,GAAG,CAAC,KAAK,QAAQ,YAAY,CAAC;AAE9B,UAAM,yBAAyBA,OAAM,YAAY,MAAM,KAAK,CAAC,GAAG,CAAC;AACjE,UAAM,aAAaA,OAAM,YAAY,MAAM,oBAAC,WAAQ,MAAY,GAAI,CAAC,IAAI,CAAC;AAC1E,UAAM,cAAcA,OAAM,YAAY,CAAC,MAAwB,QAAQ,GAAG,GAAG,GAAG,CAAC,KAAK,OAAO,CAAC;AAC9F,UAAM,cAAcA,OAAM,YAAY,MAAM,eAAe,MAAM,GAAG,CAAC,QAAQ,cAAc,CAAC;AAI5F,UAAM,gBAAgBA,OAAM;AAAA,MAC1B,CAAC,SAA6B;AAC5B,YAAI,iBAAkB,mBAAkB,UAAU;AAClD,YAAI,gBAAiB,kBAAiB,UAAU;AAChD,YAAI,QAAQ,UAAW,MAAK,MAAM;AAAA,MACpC;AAAA,MACA,CAAC,kBAAkB,iBAAiB,WAAW,mBAAmB,gBAAgB;AAAA,IACpF;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,eAAa,uBAAuB;AAAA,QACpC,MAAK;AAAA,QACL,eAAe,WAAW;AAAA,QAC1B;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,eAAa,uBAAuB;AAAA,YACpC;AAAA,YACA;AAAA,YACA;AAAA,YACA,iBAAe;AAAA,YACf,MAAK;AAAA,YACL;AAAA,YACA,cAAY,GAAG,KAAK,KAAK,aAAa;AAAA,YACtC,MAAM;AAAA,YACN;AAAA,YACA,eAAe,WAAW;AAAA,YAC1B;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,SAAS;AAAA;AAAA,QACX;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,cAAc,cAAc;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { StyledListItemFullRow, StyledTitle } from "./style.js";
4
+ import { DSAppPickerDataTestIds } from "../constants/index.js";
5
+ import { AppPickerItem } from "./AppPickerItem.js";
6
+ const AppSection = ({
7
+ items,
8
+ title,
9
+ positionOffset,
10
+ totalCount,
11
+ ownerProps,
12
+ onItemClick,
13
+ keyPrefix = "",
14
+ firstFocusableIdx,
15
+ lastFocusableIdx
16
+ }) => /* @__PURE__ */ jsxs(Fragment, { children: [
17
+ /* @__PURE__ */ jsx(StyledListItemFullRow, { "data-testid": DSAppPickerDataTestIds.ROW, "aria-hidden": true, role: "group", ...ownerProps, children: /* @__PURE__ */ jsx(StyledTitle, { "data-testid": DSAppPickerDataTestIds.TITLE, role: "presentation", variant: "h3-strong", ...ownerProps, children: title }) }),
18
+ items.map((app, index) => {
19
+ const flatIndex = positionOffset + index;
20
+ return /* @__PURE__ */ jsx(
21
+ AppPickerItem,
22
+ {
23
+ app,
24
+ positionLabel: `${title} (${flatIndex + 1} of ${totalCount})`,
25
+ ownerProps,
26
+ onClick: onItemClick,
27
+ isFirstFocusable: flatIndex === firstFocusableIdx,
28
+ isLastFocusable: flatIndex === lastFocusableIdx
29
+ },
30
+ app.id ?? `${app.label}-${keyPrefix}${index}`
31
+ );
32
+ })
33
+ ] });
34
+ AppSection.displayName = "DSAppPicker.AppSection";
35
+ export {
36
+ AppSection
37
+ };
38
+ //# sourceMappingURL=AppSection.js.map