@elliemae/ds-app-picker 3.70.0-next.62 → 3.70.0-next.69

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.
@@ -41,5 +41,23 @@ const useValidateProps = (props, propTypes) => {
41
41
  `[${import_constants.DSAppPickerName}] At least one of "apps" or "customApps" must contain items. Providing both as empty arrays renders an empty picker.`
42
42
  );
43
43
  }
44
+ const suppliedAppIds = [...props.apps, ...props.customApps].map((app) => app.id).filter((id) => id !== void 0);
45
+ const seen = /* @__PURE__ */ new Set();
46
+ const duplicates = /* @__PURE__ */ new Set();
47
+ for (const id of suppliedAppIds) {
48
+ if (seen.has(id)) duplicates.add(id);
49
+ else seen.add(id);
50
+ }
51
+ const duplicatedAppIds = [...duplicates];
52
+ if (duplicatedAppIds.length) {
53
+ throw new Error(
54
+ `[${import_constants.DSAppPickerName}] Every app "id" must be unique across "apps" and "customApps" \u2014 each one is rendered as that chip's DOM id, and duplicates produce an invalid document. Duplicated: ${duplicatedAppIds.map((id) => `"${id}"`).join(", ")}.`
55
+ );
56
+ }
57
+ if (props.id !== void 0 && suppliedAppIds.includes(props.id)) {
58
+ throw new Error(
59
+ `[${import_constants.DSAppPickerName}] The app "id" "${props.id}" collides with the "id" given to the component, which is rendered on the root element. Every other id is suffixed away from it \u2014 see getIdForAppPickerTrigger / getIdForAppPickerSectionTitle / getIdForAppPickerCustomSectionTitle \u2014 but this one is not ours to move.`
60
+ );
61
+ }
44
62
  };
45
63
  //# sourceMappingURL=useValidateProps.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/config/useValidateProps.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["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", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,8BAA+C;AAG/C,uBAAgC;AAEzB,MAAM,mBAAmB,CAAC,OAAmC,cAA4C;AAC9G,8DAA+B,OAAO,WAAW,gCAAe;AAEhE,MAAI,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,WAAW,QAAQ;AAClD,UAAM,IAAI;AAAA,MACR,IAAI,gCAAe;AAAA,IAErB;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["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 /*\n * An app's `id` is rendered verbatim as the chip's DOM id \u2014 it is the consumer's own value, deliberately\n * left un-namespaced so they can address their chips by the identity they already know. `apps` and\n * `customApps` are two independent arrays, so nothing about the shape of the API stops the same value\n * appearing twice, and a duplicate DOM id is a broken document: `getElementById`, `document.querySelector`\n * and every `aria-*` reference silently resolve to the first match only.\n *\n * We do not fix that by rewriting their ids \u2014 that would take away the surface the field exists to\n * provide. We make it impossible to ship instead. Uniqueness stays the consumer's responsibility; this\n * turns \"silently wrong in production\" into \"cannot render\", which is the only version of that\n * responsibility that actually holds.\n *\n * Scoped to ids the consumer supplied: id-less apps are legal (AppSection falls back to a positional key\n * and getChipId to a label-index identity), and no chip id is emitted for them at all.\n */\n const suppliedAppIds = [...props.apps, ...props.customApps]\n .map((app) => app.id)\n .filter((id): id is string => id !== undefined);\n\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of suppliedAppIds) {\n if (seen.has(id)) duplicates.add(id);\n else seen.add(id);\n }\n const duplicatedAppIds = [...duplicates];\n if (duplicatedAppIds.length) {\n throw new Error(\n `[${DSAppPickerName}] Every app \"id\" must be unique across \"apps\" and \"customApps\" \u2014 each one is ` +\n `rendered as that chip's DOM id, and duplicates produce an invalid document. ` +\n `Duplicated: ${duplicatedAppIds.map((id) => `\"${id}\"`).join(', ')}.`,\n );\n }\n\n /*\n * Same defect, one level up: the consumer's `id` lands unmodified on the ROOT (see util/instanceIds), so\n * an app carrying that same value collides with it. Every id this component generates for itself is\n * suffixed through that module and therefore cannot participate \u2014 this is the one remaining pair where\n * two consumer-supplied values meet.\n */\n if (props.id !== undefined && suppliedAppIds.includes(props.id)) {\n throw new Error(\n `[${DSAppPickerName}] The app \"id\" \"${props.id}\" collides with the \"id\" given to the component, ` +\n `which is rendered on the root element. Every other id is suffixed away from it \u2014 see ` +\n `getIdForAppPickerTrigger / getIdForAppPickerSectionTitle / getIdForAppPickerCustomSectionTitle \u2014 but this one is not ours to move.`,\n );\n }\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,8BAA+C;AAG/C,uBAAgC;AAEzB,MAAM,mBAAmB,CAAC,OAAmC,cAA4C;AAC9G,8DAA+B,OAAO,WAAW,gCAAe;AAEhE,MAAI,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,WAAW,QAAQ;AAClD,UAAM,IAAI;AAAA,MACR,IAAI,gCAAe;AAAA,IAErB;AAAA,EACF;AAiBA,QAAM,iBAAiB,CAAC,GAAG,MAAM,MAAM,GAAG,MAAM,UAAU,EACvD,IAAI,CAAC,QAAQ,IAAI,EAAE,EACnB,OAAO,CAAC,OAAqB,OAAO,MAAS;AAEhD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,MAAM,gBAAgB;AAC/B,QAAI,KAAK,IAAI,EAAE,EAAG,YAAW,IAAI,EAAE;AAAA,QAC9B,MAAK,IAAI,EAAE;AAAA,EAClB;AACA,QAAM,mBAAmB,CAAC,GAAG,UAAU;AACvC,MAAI,iBAAiB,QAAQ;AAC3B,UAAM,IAAI;AAAA,MACR,IAAI,gCAAe,6KAEF,iBAAiB,IAAI,CAAC,OAAO,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,IACrE;AAAA,EACF;AAQA,MAAI,MAAM,OAAO,UAAa,eAAe,SAAS,MAAM,EAAE,GAAG;AAC/D,UAAM,IAAI;AAAA,MACR,IAAI,gCAAe,mBAAmB,MAAM,EAAE;AAAA,IAGhD;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/dist/cjs/index.js CHANGED
@@ -33,11 +33,16 @@ __export(index_exports, {
33
33
  DSAppPickerDataTestIds: () => import_constants.DSAppPickerDataTestIds,
34
34
  DSAppPickerName: () => import_constants.DSAppPickerName,
35
35
  DSAppPickerSlots: () => import_constants.DSAppPickerSlots,
36
- getDSAppPickerContractProps: () => import_getDSAppPickerContractProps.getDSAppPickerContractProps
36
+ getDSAppPickerContractProps: () => import_getDSAppPickerContractProps.getDSAppPickerContractProps,
37
+ getIdForAppPickerCustomSectionTitle: () => import_instanceIds.getIdForAppPickerCustomSectionTitle,
38
+ getIdForAppPickerRoot: () => import_instanceIds.getIdForAppPickerRoot,
39
+ getIdForAppPickerSectionTitle: () => import_instanceIds.getIdForAppPickerSectionTitle,
40
+ getIdForAppPickerTrigger: () => import_instanceIds.getIdForAppPickerTrigger
37
41
  });
38
42
  module.exports = __toCommonJS(index_exports);
39
43
  var React = __toESM(require("react"));
40
44
  var import_DSAppPicker = require("./DSAppPicker.js");
41
45
  var import_constants = require("./constants/index.js");
42
46
  var import_getDSAppPickerContractProps = require("./util/getDSAppPickerContractProps.js");
47
+ var import_instanceIds = require("./util/instanceIds.js");
43
48
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["export { DSAppPicker, AppPickerWithSchema } from './DSAppPicker.js';\nexport { DSAppPickerName, DSAppPickerSlots, DSAppPickerDataTestIds } from './constants/index.js';\nexport { getDSAppPickerContractProps } from './util/getDSAppPickerContractProps.js';\nexport type { DSAppPickerT } from './react-desc-prop-types.js';\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,yBAAiD;AACjD,uBAA0E;AAC1E,yCAA4C;",
4
+ "sourcesContent": ["export { DSAppPicker, AppPickerWithSchema } from './DSAppPicker.js';\nexport { DSAppPickerName, DSAppPickerSlots, DSAppPickerDataTestIds } from './constants/index.js';\nexport { getDSAppPickerContractProps } from './util/getDSAppPickerContractProps.js';\nexport {\n getIdForAppPickerRoot,\n getIdForAppPickerTrigger,\n getIdForAppPickerSectionTitle,\n getIdForAppPickerCustomSectionTitle,\n} from './util/instanceIds.js';\nexport type { DSAppPickerT } from './react-desc-prop-types.js';\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,yBAAiD;AACjD,uBAA0E;AAC1E,yCAA4C;AAC5C,yBAKO;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/parts/AppPanel.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { Grid } from '@elliemae/ds-grid';\nimport { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport { styled } from '@elliemae/ds-system';\nimport React, { memo, useCallback, useContext, useEffect } from 'react';\nimport {\n APP_PICKER_REGION_FOCUSES,\n DSAppPickerDataTestIds,\n DSAppPickerName,\n DSAppPickerSlots,\n} from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { AppSection } from './AppSection.js';\nimport { StyledListItemFullRow } from './shared-styles.js';\n\nconst StyledWrapper = styled(Grid, { name: DSAppPickerName, slot: DSAppPickerSlots.ROOT })`\n background-color: ${({ theme }) => theme.colors.neutral['000']};\n min-width: 308px;\n min-height: 110px;\n max-height: 449px;\n width: 308px;\n overflow-y: auto;\n overflow-x: hidden;\n /* Baseline 2024: reserve scrollbar gutter so the layout doesn't shift between overflow/no-overflow.\n Replaces a JS isOverflow detection effect that toggled right padding. */\n scrollbar-gutter: stable;\n margin: 0;\n padding: 0 0 8px 16px;\n &:focus {\n outline: none;\n }\n`;\n\nconst StyledSeparator = styled('hr', { name: DSAppPickerName, slot: DSAppPickerSlots.SEPARATOR })`\n border-top: 1px solid ${({ theme }) => theme.colors.neutral[300]};\n border-bottom: none;\n width: 100%;\n margin: 8px 0 0 0;\n`;\n\nconst wrapperGridLayout = {\n cols: ['repeat(3, 92px)'],\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n rows: ['auto'],\n};\n\nconst useExecOnceAfterFirstRender = (callback: () => void) => {\n const hasExecutedRef = React.useRef(false);\n const executeInitialFocusRef = React.useRef(callback);\n executeInitialFocusRef.current = callback;\n useEffect(() => {\n if (!hasExecutedRef.current) {\n executeInitialFocusRef.current();\n hasExecutedRef.current = true;\n }\n }, []);\n};\n\ntype MountedOpenAutofocusNuanceConfig = {\n pendingRef: React.MutableRefObject<boolean>;\n trackFocusPanel: () => void;\n};\n\n/**\n * NUANCE \u2014 the single case that initial-focus-on-open (useAppPickerFloatingContext's onOpen) cannot\n * cover: DSAppPicker rendered ALREADY open (declarative `isOpen` at mount, no user interaction).\n * That open is not a transition, so `onOpen` never fires for it. This mount-time hook seeds the panel\n * wrapper, which is what a pointer open seeds too: there was no gesture at all here, so the\n * keyboard-only \"land on the selected app\" rule does not apply, and the panel is the target that gets\n * the dialog announced. `pendingRef` is true only when the component started open and is flipped\n * false on first consume, so a later controlled reopen \u2014 a real transition handled by `onOpen` \u2014\n * does not double-seed. Every user-driven open (click/keyboard) is a transition handled by `onOpen`,\n * NOT here.\n *\n * REMOVABILITY: if the team decides declarative-open should not autofocus, delete this hook and its\n * call, and flip the \"rendered already-open \u2026 focuses the panel wrapper\" assertions in\n * DSAppPicker.keyboard.test.js. Nothing else depends on it.\n */\nconst useMountedOpenAutofocusNuance = ({ pendingRef, trackFocusPanel }: MountedOpenAutofocusNuanceConfig) => {\n useExecOnceAfterFirstRender(() => {\n if (!pendingRef.current) return;\n pendingRef.current = false;\n trackFocusPanel();\n });\n};\n\nconst AppPanelBase = () => {\n const {\n propsWithDefault: { customApps, onKeyDown },\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n mountedOpenAutofocusPendingRef,\n focusTrackers: { focusRegion, firstFocusableRef, lastFocusableRef, trackFocusPanel },\n } = useContext(DSAppPickerContext);\n\n // Global attributes are spread onto the panel root because there is no shared wrapper that\n // contains both the floating panel and the trigger. `wrap`, `onClick`, and `onKeyDown` are\n // filtered out because they collide with the public component API (which uses these for\n // different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open.\n // ---------------------------------------------------------------------------\n // User-driven opens (click/keyboard) are open transitions, seeded by\n // useAppPickerFloatingContext's onOpen. The one case that isn't a transition \u2014 being rendered\n // already-open (declarative `isOpen` at mount) \u2014 is covered here, scoped to exactly that.\n useMountedOpenAutofocusNuance({\n pendingRef: mountedOpenAutofocusPendingRef,\n trackFocusPanel,\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 // Default Escape-close/refocus is handled declaratively by useFloatingContext\n // (see useAppPickerFloatingContext's closeOnEscape/onEscape wiring) whenever there is no consumer\n // onKeyDown \u2014 a consumer-provided onKeyDown takes over keydown handling entirely.\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown,\n });\n\n // The panel root carries NO aria-label: it is a roleless element (generic role does not support\n // an accessible name, so any label here is dropped by assistive tech). The component's accessible\n // name lives on the dialog \u2014 see AppPickerContent's role=\"dialog\" + aria-labelledby.\n return (\n <StyledWrapper\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={wrapperGridLayout.cols}\n rows={wrapperGridLayout.rows}\n // when opening the dialog via mouse, the focus is programmatically assigned here via handleWrapperRef, -1 allows .focus() to work\n tabIndex={-1}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection isCustomApps />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD0JjB;AA1JN,qBAAqB;AACrB,iCAA6B;AAC7B,uBAAuB;AACvB,mBAAgE;AAChE,uBAKO;AACP,4BAAmC;AACnC,wBAA2B;AAC3B,2BAAsC;AAEtC,MAAM,oBAAgB,yBAAO,qBAAM,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,KAAK,CAAC;AAAA,sBACnE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBhE,MAAM,sBAAkB,yBAAO,MAAM,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,UAAU,CAAC;AAAA,0BACtE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAMlE,MAAM,oBAAoB;AAAA,EACxB,MAAM,CAAC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAM,CAAC,MAAM;AACf;AAEA,MAAM,8BAA8B,CAAC,aAAyB;AAC5D,QAAM,iBAAiB,aAAAA,QAAM,OAAO,KAAK;AACzC,QAAM,yBAAyB,aAAAA,QAAM,OAAO,QAAQ;AACpD,yBAAuB,UAAU;AACjC,8BAAU,MAAM;AACd,QAAI,CAAC,eAAe,SAAS;AAC3B,6BAAuB,QAAQ;AAC/B,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AACP;AAsBA,MAAM,gCAAgC,CAAC,EAAE,YAAY,gBAAgB,MAAwC;AAC3G,8BAA4B,MAAM;AAChC,QAAI,CAAC,WAAW,QAAS;AACzB,eAAW,UAAU;AACrB,oBAAgB;AAAA,EAClB,CAAC;AACH;AAEA,MAAM,eAAe,MAAM;AACzB,QAAM;AAAA,IACJ,kBAAkB,EAAE,YAAY,UAAU;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,EAAE,aAAa,mBAAmB,kBAAkB,gBAAgB;AAAA,EACrF,QAAI,yBAAW,wCAAkB;AAMjC,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,GAAG,qBAAqB,IAAI;AAQ/E,gCAA8B;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAOD,QAAM,mBAAmB,gBAAgB,2CAA0B;AAEnE,QAAM,uBAAmB;AAAA,IACvB,CAAC,SAA6B;AAC5B,UAAI,QAAQ,iBAAkB,MAAK,MAAM;AAAA,IAC3C;AAAA,IACA,CAAC,gBAAgB;AAAA,EACnB;AAKA,QAAM,sBAAkB,yCAAa;AAAA,IACnC,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF,CAAC;AAKD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,eAAa,wCAAuB;AAAA,MACpC,MAAM,kBAAkB;AAAA,MACxB,MAAM,kBAAkB;AAAA,MAExB,UAAU;AAAA,MACT,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACJ,WAAW;AAAA,MAEX;AAAA,oDAAC,gCAAW;AAAA,QACX,WAAW,SAAS,KACnB,4EACE;AAAA,sDAAC,8CAAsB,eAAa,wCAAuB,KAAM,GAAG,kBAClE,sDAAC,mBAAgB,eAAa,wCAAuB,WAAY,GAAG,kBAAkB,GACxF;AAAA,UACA,4CAAC,gCAAW,cAAY,MAAC;AAAA,WAC3B;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEO,MAAM,eAAW,mBAAK,YAAY;AACzC,SAAS,cAAc;",
4
+ "sourcesContent": ["import { Grid } from '@elliemae/ds-grid';\nimport { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport { styled } from '@elliemae/ds-system';\nimport React, { memo, useCallback, useContext, useEffect } from 'react';\nimport {\n APP_PICKER_REGION_FOCUSES,\n DSAppPickerDataTestIds,\n DSAppPickerName,\n DSAppPickerSlots,\n} from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { AppSection } from './AppSection.js';\nimport { StyledListItemFullRow } from './shared-styles.js';\n\nconst StyledWrapper = styled(Grid, { name: DSAppPickerName, slot: DSAppPickerSlots.ROOT })`\n background-color: ${({ theme }) => theme.colors.neutral['000']};\n min-width: 308px;\n min-height: 110px;\n max-height: 449px;\n width: 308px;\n overflow-y: auto;\n overflow-x: hidden;\n /* Baseline 2024: reserve scrollbar gutter so the layout doesn't shift between overflow/no-overflow.\n Replaces a JS isOverflow detection effect that toggled right padding. */\n scrollbar-gutter: stable;\n margin: 0;\n padding: 0 0 8px 16px;\n &:focus {\n outline: none;\n }\n`;\n\nconst StyledSeparator = styled('hr', { name: DSAppPickerName, slot: DSAppPickerSlots.SEPARATOR })`\n border-top: 1px solid ${({ theme }) => theme.colors.neutral[300]};\n border-bottom: none;\n width: 100%;\n margin: 8px 0 0 0;\n`;\n\nconst wrapperGridLayout = {\n cols: ['repeat(3, 92px)'],\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n rows: ['auto'],\n};\n\nconst useExecOnceAfterFirstRender = (callback: () => void) => {\n const hasExecutedRef = React.useRef(false);\n const executeInitialFocusRef = React.useRef(callback);\n executeInitialFocusRef.current = callback;\n useEffect(() => {\n if (!hasExecutedRef.current) {\n executeInitialFocusRef.current();\n hasExecutedRef.current = true;\n }\n }, []);\n};\n\ntype MountedOpenAutofocusNuanceConfig = {\n pendingRef: React.MutableRefObject<boolean>;\n trackFocusPanel: () => void;\n};\n\n/**\n * NUANCE \u2014 the single case that initial-focus-on-open (useAppPickerFloatingContext's onOpen) cannot\n * cover: DSAppPicker rendered ALREADY open (declarative `isOpen` at mount, no user interaction).\n * That open is not a transition, so `onOpen` never fires for it. This mount-time hook seeds the panel\n * wrapper, which is what a pointer open seeds too: there was no gesture at all here, so the\n * keyboard-only \"land on the selected app\" rule does not apply, and the panel is the target that gets\n * the dialog announced. `pendingRef` is true only when the component started open and is flipped\n * false on first consume, so a later controlled reopen \u2014 a real transition handled by `onOpen` \u2014\n * does not double-seed. Every user-driven open (click/keyboard) is a transition handled by `onOpen`,\n * NOT here.\n *\n * REMOVABILITY: if the team decides declarative-open should not autofocus, delete this hook and its\n * call, and flip the \"rendered already-open \u2026 focuses the panel wrapper\" assertions in\n * DSAppPicker.keyboard.test.js. Nothing else depends on it.\n */\nconst useMountedOpenAutofocusNuance = ({ pendingRef, trackFocusPanel }: MountedOpenAutofocusNuanceConfig) => {\n useExecOnceAfterFirstRender(() => {\n if (!pendingRef.current) return;\n pendingRef.current = false;\n trackFocusPanel();\n });\n};\n\nconst AppPanelBase = () => {\n const {\n propsWithDefault: { customApps, onKeyDown },\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n mountedOpenAutofocusPendingRef,\n focusTrackers: { focusRegion, firstFocusableRef, lastFocusableRef, trackFocusPanel },\n } = useContext(DSAppPickerContext);\n\n // Global attributes are spread here, on the panel root, which is this component's root for the purpose\n // of the Dimsum convention that global attributes land on the styled root (see project_slots.md \u2014 it is\n // gate 2 of `data-dimsum-parent-slot`, and a component spreading them on an inner control is treated as\n // a defect, not a variant).\n //\n // There is no element containing both the trigger and the floating panel, so \"root\" has to be chosen\n // rather than read off the tree. The panel is the right choice, and not merely the larger one: the\n // floating context, the sections and the chips are what this component actually is, while the trigger is\n // the replaceable part \u2014 `TriggerComponent` already lets a consumer supply their own, and the direction\n // ds-menu-button points at (a behavioural layer wrapping arbitrary children, with the menu as its own\n // part) would make it fully app-owned. The panel stays the root through that change; a trigger-rooted\n // choice would not survive it.\n //\n // `wrap`, `onClick`, and `onKeyDown` are filtered out because they collide with the public component API\n // (which uses these for different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open.\n // ---------------------------------------------------------------------------\n // User-driven opens (click/keyboard) are open transitions, seeded by\n // useAppPickerFloatingContext's onOpen. The one case that isn't a transition \u2014 being rendered\n // already-open (declarative `isOpen` at mount) \u2014 is covered here, scoped to exactly that.\n useMountedOpenAutofocusNuance({\n pendingRef: mountedOpenAutofocusPendingRef,\n trackFocusPanel,\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 // Default Escape-close/refocus is handled declaratively by useFloatingContext\n // (see useAppPickerFloatingContext's closeOnEscape/onEscape wiring) whenever there is no consumer\n // onKeyDown \u2014 a consumer-provided onKeyDown takes over keydown handling entirely.\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown,\n });\n\n // The panel root carries NO aria-label: it is a roleless element (generic role does not support\n // an accessible name, so any label here is dropped by assistive tech). The component's accessible\n // name lives on the dialog \u2014 see AppPickerContent's role=\"dialog\" + aria-labelledby.\n return (\n <StyledWrapper\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={wrapperGridLayout.cols}\n rows={wrapperGridLayout.rows}\n // when opening the dialog via mouse, the focus is programmatically assigned here via handleWrapperRef, -1 allows .focus() to work\n tabIndex={-1}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection isCustomApps />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADqKjB;AArKN,qBAAqB;AACrB,iCAA6B;AAC7B,uBAAuB;AACvB,mBAAgE;AAChE,uBAKO;AACP,4BAAmC;AACnC,wBAA2B;AAC3B,2BAAsC;AAEtC,MAAM,oBAAgB,yBAAO,qBAAM,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,KAAK,CAAC;AAAA,sBACnE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBhE,MAAM,sBAAkB,yBAAO,MAAM,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,UAAU,CAAC;AAAA,0BACtE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAMlE,MAAM,oBAAoB;AAAA,EACxB,MAAM,CAAC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAM,CAAC,MAAM;AACf;AAEA,MAAM,8BAA8B,CAAC,aAAyB;AAC5D,QAAM,iBAAiB,aAAAA,QAAM,OAAO,KAAK;AACzC,QAAM,yBAAyB,aAAAA,QAAM,OAAO,QAAQ;AACpD,yBAAuB,UAAU;AACjC,8BAAU,MAAM;AACd,QAAI,CAAC,eAAe,SAAS;AAC3B,6BAAuB,QAAQ;AAC/B,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AACP;AAsBA,MAAM,gCAAgC,CAAC,EAAE,YAAY,gBAAgB,MAAwC;AAC3G,8BAA4B,MAAM;AAChC,QAAI,CAAC,WAAW,QAAS;AACzB,eAAW,UAAU;AACrB,oBAAgB;AAAA,EAClB,CAAC;AACH;AAEA,MAAM,eAAe,MAAM;AACzB,QAAM;AAAA,IACJ,kBAAkB,EAAE,YAAY,UAAU;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,EAAE,aAAa,mBAAmB,kBAAkB,gBAAgB;AAAA,EACrF,QAAI,yBAAW,wCAAkB;AAiBjC,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,GAAG,qBAAqB,IAAI;AAQ/E,gCAA8B;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAOD,QAAM,mBAAmB,gBAAgB,2CAA0B;AAEnE,QAAM,uBAAmB;AAAA,IACvB,CAAC,SAA6B;AAC5B,UAAI,QAAQ,iBAAkB,MAAK,MAAM;AAAA,IAC3C;AAAA,IACA,CAAC,gBAAgB;AAAA,EACnB;AAKA,QAAM,sBAAkB,yCAAa;AAAA,IACnC,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF,CAAC;AAKD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,eAAa,wCAAuB;AAAA,MACpC,MAAM,kBAAkB;AAAA,MACxB,MAAM,kBAAkB;AAAA,MAExB,UAAU;AAAA,MACT,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACJ,WAAW;AAAA,MAEX;AAAA,oDAAC,gCAAW;AAAA,QACX,WAAW,SAAS,KACnB,4EACE;AAAA,sDAAC,8CAAsB,eAAa,wCAAuB,KAAM,GAAG,kBAClE,sDAAC,mBAAgB,eAAa,wCAAuB,WAAY,GAAG,kBAAkB,GACxF;AAAA,UACA,4CAAC,gCAAW,cAAY,MAAC;AAAA,WAC3B;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEO,MAAM,eAAW,mBAAK,YAAY;AACzC,SAAS,cAAc;",
6
6
  "names": ["React"]
7
7
  }
@@ -38,6 +38,7 @@ var import_ds_system = require("@elliemae/ds-system");
38
38
  var import_react = require("react");
39
39
  var import_constants = require("../../constants/index.js");
40
40
  var import_DSAppPickerCTX = require("../../DSAppPickerCTX.js");
41
+ var import_instanceIds = require("../../util/instanceIds.js");
41
42
  var import_AppPanel = require("../AppPanel.js");
42
43
  var import_Trigger = require("../Trigger.js");
43
44
  var import_useAppPickerFloatingContext = require("./useAppPickerFloatingContext.js");
@@ -70,7 +71,7 @@ const AppPickerContent = () => {
70
71
  resolvedIsOpen,
71
72
  setInternalIsOpen
72
73
  });
73
- const dialogLabelId = `${instanceUid}-dialog-trigger-btn`;
74
+ const dialogLabelId = (0, import_instanceIds.getIdForAppPickerTrigger)(instanceUid);
74
75
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
75
76
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
76
77
  import_Trigger.Trigger,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/parts/AppPickerFloatingContext/AppPickerContent.tsx", "../../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { FloatingWrapper, PopoverArrow } from '@elliemae/ds-floating-context';\nimport { styled } from '@elliemae/ds-system';\nimport React, { useContext } from 'react';\nimport { DSAppPickerName, DSAppPickerSlots } from '../../constants/index.js';\nimport { DSAppPickerContext } from '../../DSAppPickerCTX.js';\nimport type { DSAppPickerT } from '../../react-desc-prop-types.js';\nimport { AppPanel } from '../AppPanel.js';\nimport { Trigger } from '../Trigger.js';\nimport { useAppPickerFloatingContext } from './useAppPickerFloatingContext.js';\n\nconst StyledAppPickerFloating = styled(FloatingWrapper, {\n name: DSAppPickerName,\n slot: DSAppPickerSlots.FLOATING_WRAPPER,\n})``;\n\nexport const AppPickerContent: React.ComponentType<DSAppPickerT.Props> = () => {\n const {\n ownerPropsConfig,\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n instanceUid,\n } = useContext(DSAppPickerContext);\n const {\n floatingStyles,\n arrowStyles,\n floatingContext,\n floatingInnerRef,\n handleTriggerRef,\n handleTriggerClick,\n handleTriggerKeyDown,\n } = useAppPickerFloatingContext({\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n });\n\n const dialogLabelId = `${instanceUid}-dialog-trigger-btn`;\n\n return (\n <>\n <Trigger\n handleTriggerRef={handleTriggerRef}\n handleTriggerClick={handleTriggerClick}\n handleTriggerKeyDown={handleTriggerKeyDown}\n dialogLabelId={dialogLabelId}\n />\n <StyledAppPickerFloating\n innerRef={floatingInnerRef}\n isOpen={resolvedIsOpen}\n floatingStyles={floatingStyles}\n context={floatingContext}\n getOwnerProps={ownerPropsConfig.getOwnerProps}\n getOwnerPropsArguments={ownerPropsConfig.getOwnerPropsArguments}\n role=\"dialog\"\n aria-labelledby={dialogLabelId}\n >\n <AppPanel />\n <PopoverArrow {...arrowStyles} />\n </StyledAppPickerFloating>\n </>\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD4CnB;AA5CJ,iCAA8C;AAC9C,uBAAuB;AACvB,mBAAkC;AAClC,uBAAkD;AAClD,4BAAmC;AAEnC,sBAAyB;AACzB,qBAAwB;AACxB,yCAA4C;AAE5C,MAAM,8BAA0B,yBAAO,4CAAiB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,kCAAiB;AACzB,CAAC;AAEM,MAAM,mBAA4D,MAAM;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,yBAAW,wCAAkB;AACjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,gEAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB,GAAG,WAAW;AAEpC,SACE,4EACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;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,QACzC,MAAK;AAAA,QACL,mBAAiB;AAAA,QAEjB;AAAA,sDAAC,4BAAS;AAAA,UACV,4CAAC,2CAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;",
4
+ "sourcesContent": ["import { FloatingWrapper, PopoverArrow } from '@elliemae/ds-floating-context';\nimport { styled } from '@elliemae/ds-system';\nimport React, { useContext } from 'react';\nimport { DSAppPickerName, DSAppPickerSlots } from '../../constants/index.js';\nimport { DSAppPickerContext } from '../../DSAppPickerCTX.js';\nimport type { DSAppPickerT } from '../../react-desc-prop-types.js';\nimport { getIdForAppPickerTrigger } from '../../util/instanceIds.js';\nimport { AppPanel } from '../AppPanel.js';\nimport { Trigger } from '../Trigger.js';\nimport { useAppPickerFloatingContext } from './useAppPickerFloatingContext.js';\n\nconst StyledAppPickerFloating = styled(FloatingWrapper, {\n name: DSAppPickerName,\n slot: DSAppPickerSlots.FLOATING_WRAPPER,\n})``;\n\nexport const AppPickerContent: React.ComponentType<DSAppPickerT.Props> = () => {\n const {\n ownerPropsConfig,\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n instanceUid,\n } = useContext(DSAppPickerContext);\n const {\n floatingStyles,\n arrowStyles,\n floatingContext,\n floatingInnerRef,\n handleTriggerRef,\n handleTriggerClick,\n handleTriggerKeyDown,\n } = useAppPickerFloatingContext({\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n });\n\n // Suffix owned by util/instanceIds \u2014 never composed inline, so consumers and this call site cannot\n // drift apart. `getIdForAppPickerTrigger` is the exported counterpart.\n const dialogLabelId = getIdForAppPickerTrigger(instanceUid);\n\n return (\n <>\n <Trigger\n handleTriggerRef={handleTriggerRef}\n handleTriggerClick={handleTriggerClick}\n handleTriggerKeyDown={handleTriggerKeyDown}\n dialogLabelId={dialogLabelId}\n />\n <StyledAppPickerFloating\n innerRef={floatingInnerRef}\n isOpen={resolvedIsOpen}\n floatingStyles={floatingStyles}\n context={floatingContext}\n getOwnerProps={ownerPropsConfig.getOwnerProps}\n getOwnerPropsArguments={ownerPropsConfig.getOwnerPropsArguments}\n role=\"dialog\"\n aria-labelledby={dialogLabelId}\n >\n <AppPanel />\n <PopoverArrow {...arrowStyles} />\n </StyledAppPickerFloating>\n </>\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD+CnB;AA/CJ,iCAA8C;AAC9C,uBAAuB;AACvB,mBAAkC;AAClC,uBAAkD;AAClD,4BAAmC;AAEnC,yBAAyC;AACzC,sBAAyB;AACzB,qBAAwB;AACxB,yCAA4C;AAE5C,MAAM,8BAA0B,yBAAO,4CAAiB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,kCAAiB;AACzB,CAAC;AAEM,MAAM,mBAA4D,MAAM;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,yBAAW,wCAAkB;AACjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,gEAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAID,QAAM,oBAAgB,6CAAyB,WAAW;AAE1D,SACE,4EACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;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,QACzC,MAAK;AAAA,QACL,mBAAiB;AAAA,QAEjB;AAAA,sDAAC,4BAAS;AAAA,UACV,4CAAC,2CAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -39,6 +39,7 @@ var import_react = require("react");
39
39
  var import_constants = require("../constants/index.js");
40
40
  var import_DSAppPickerCTX = require("../DSAppPickerCTX.js");
41
41
  var import_getChipId = require("../util/getChipId.js");
42
+ var import_instanceIds = require("../util/instanceIds.js");
42
43
  var import_AppPickerItem = require("./AppPickerItem.js");
43
44
  var import_shared_styles = require("./shared-styles.js");
44
45
  const StyledTitle = (0, import_ds_system.styled)(import_ds_typography.DSTypography, { name: import_constants.DSAppPickerName, slot: import_constants.DSAppPickerSlots.TITLE })`
@@ -58,7 +59,7 @@ const AppSection = ({ isCustomApps = false }) => {
58
59
  ownerPropsConfig
59
60
  } = (0, import_react.useContext)(import_DSAppPickerCTX.DSAppPickerContext);
60
61
  const items = isCustomApps ? customApps : apps;
61
- const titleId = isCustomApps ? `${instanceUid}-custom-section-title` : `${instanceUid}-section-title`;
62
+ const titleId = isCustomApps ? (0, import_instanceIds.getIdForAppPickerCustomSectionTitle)(instanceUid) : (0, import_instanceIds.getIdForAppPickerSectionTitle)(instanceUid);
62
63
  const title = isCustomApps ? customSectionTitle : sectionTitle;
63
64
  const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);
64
65
  const initialPositionOffset = isCustomApps ? apps.length : 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/parts/AppSection.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["import { styled } from '@elliemae/ds-system';\nimport { DSTypography } from '@elliemae/ds-typography';\nimport React, { useContext } from 'react';\nimport { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { getChipId } from '../util/getChipId.js';\nimport { AppPickerItem } from './AppPickerItem.js';\nimport { StyledListItemFullRow, StyledSection } from './shared-styles.js';\n\nconst StyledTitle = styled(DSTypography, { name: DSAppPickerName, slot: DSAppPickerSlots.TITLE })`\n color: ${({ theme }) => theme.colors.neutral[700]};\n font-size: ${({ theme }) => theme.fontSizes.value[400]};\n font-weight: ${({ theme }) => theme.fontWeights.semibold};\n margin: 12px 0 8px 0;\n line-height: 1.385;\n text-transform: uppercase;\n text-align: center;\n`;\n\ninterface AppSectionProps {\n isCustomApps?: boolean;\n}\n\nexport const AppSection: React.FC<AppSectionProps> = ({ isCustomApps = false }) => {\n const {\n propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle },\n instanceUid,\n focusTrackers: { firstFocusableIdx, lastFocusableIdx },\n ownerPropsConfig,\n } = useContext(DSAppPickerContext);\n\n const items = isCustomApps ? customApps : apps;\n const titleId = isCustomApps ? `${instanceUid}-custom-section-title` : `${instanceUid}-section-title`;\n const title = isCustomApps ? customSectionTitle : sectionTitle;\n\n const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);\n const initialPositionOffset = isCustomApps ? apps.length : 0;\n return (\n <StyledSection\n data-testid={DSAppPickerDataTestIds.GROUP}\n role=\"group\"\n aria-labelledby={titleId}\n {...ownerPropsConfig}\n >\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledTitle data-testid={DSAppPickerDataTestIds.TITLE} id={titleId} variant=\"h3-strong\" {...ownerPropsConfig}>\n {title}\n </StyledTitle>\n </StyledListItemFullRow>\n {items.map((app, index) => {\n const flatIndex = initialPositionOffset + index;\n const positionAnnouncement = `${flatIndex + 1} of ${totalCount}`;\n return (\n <AppPickerItem\n key={app.id ?? `${app.label}-${isCustomApps ? 'custom' : 'main'}-${index}`}\n positionAnnouncement={positionAnnouncement}\n app={app}\n chipId={getChipId(app, flatIndex)}\n isFirstFocusable={flatIndex === firstFocusableIdx}\n isLastFocusable={flatIndex === lastFocusableIdx}\n />\n );\n })}\n </StyledSection>\n );\n};\n\nAppSection.displayName = 'DSAppPicker.AppSection';\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADsCnB;AAtCJ,uBAAuB;AACvB,2BAA6B;AAC7B,mBAAkC;AAClC,uBAA0E;AAC1E,4BAAmC;AACnC,uBAA0B;AAC1B,2BAA8B;AAC9B,2BAAqD;AAErD,MAAM,kBAAc,yBAAO,mCAAc,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,MAAM,CAAC;AAAA,WACrF,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,eACpC,CAAC,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,GAAG,CAAC;AAAA,iBACvC,CAAC,EAAE,MAAM,MAAM,MAAM,YAAY,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAWnD,MAAM,aAAwC,CAAC,EAAE,eAAe,MAAM,MAAM;AACjF,QAAM;AAAA,IACJ,kBAAkB,EAAE,MAAM,YAAY,cAAc,mBAAmB;AAAA,IACvE;AAAA,IACA,eAAe,EAAE,mBAAmB,iBAAiB;AAAA,IACrD;AAAA,EACF,QAAI,yBAAW,wCAAkB;AAEjC,QAAM,QAAQ,eAAe,aAAa;AAC1C,QAAM,UAAU,eAAe,GAAG,WAAW,0BAA0B,GAAG,WAAW;AACrF,QAAM,QAAQ,eAAe,qBAAqB;AAElD,QAAM,cAAc,MAAM,UAAU,MAAM,YAAY,UAAU;AAChE,QAAM,wBAAwB,eAAe,KAAK,SAAS;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa,wCAAuB;AAAA,MACpC,MAAK;AAAA,MACL,mBAAiB;AAAA,MAChB,GAAG;AAAA,MAEJ;AAAA,oDAAC,8CAAsB,eAAa,wCAAuB,KAAM,GAAG,kBAClE,sDAAC,eAAY,eAAa,wCAAuB,OAAO,IAAI,SAAS,SAAQ,aAAa,GAAG,kBAC1F,iBACH,GACF;AAAA,QACC,MAAM,IAAI,CAAC,KAAK,UAAU;AACzB,gBAAM,YAAY,wBAAwB;AAC1C,gBAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,UAAU;AAC9D,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA,YAAQ,4BAAU,KAAK,SAAS;AAAA,cAChC,kBAAkB,cAAc;AAAA,cAChC,iBAAiB,cAAc;AAAA;AAAA,YAL1B,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,eAAe,WAAW,MAAM,IAAI,KAAK;AAAA,UAM1E;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,WAAW,cAAc;",
4
+ "sourcesContent": ["import { styled } from '@elliemae/ds-system';\nimport { DSTypography } from '@elliemae/ds-typography';\nimport React, { useContext } from 'react';\nimport { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { getChipId } from '../util/getChipId.js';\nimport { getIdForAppPickerCustomSectionTitle, getIdForAppPickerSectionTitle } from '../util/instanceIds.js';\nimport { AppPickerItem } from './AppPickerItem.js';\nimport { StyledListItemFullRow, StyledSection } from './shared-styles.js';\n\nconst StyledTitle = styled(DSTypography, { name: DSAppPickerName, slot: DSAppPickerSlots.TITLE })`\n color: ${({ theme }) => theme.colors.neutral[700]};\n font-size: ${({ theme }) => theme.fontSizes.value[400]};\n font-weight: ${({ theme }) => theme.fontWeights.semibold};\n margin: 12px 0 8px 0;\n line-height: 1.385;\n text-transform: uppercase;\n text-align: center;\n`;\n\ninterface AppSectionProps {\n isCustomApps?: boolean;\n}\n\nexport const AppSection: React.FC<AppSectionProps> = ({ isCustomApps = false }) => {\n const {\n propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle },\n instanceUid,\n focusTrackers: { firstFocusableIdx, lastFocusableIdx },\n ownerPropsConfig,\n } = useContext(DSAppPickerContext);\n\n const items = isCustomApps ? customApps : apps;\n // Suffixes owned by util/instanceIds \u2014 see that module for why they are never composed inline.\n const titleId = isCustomApps\n ? getIdForAppPickerCustomSectionTitle(instanceUid)\n : getIdForAppPickerSectionTitle(instanceUid);\n const title = isCustomApps ? customSectionTitle : sectionTitle;\n\n const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);\n const initialPositionOffset = isCustomApps ? apps.length : 0;\n return (\n <StyledSection\n data-testid={DSAppPickerDataTestIds.GROUP}\n role=\"group\"\n aria-labelledby={titleId}\n {...ownerPropsConfig}\n >\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledTitle data-testid={DSAppPickerDataTestIds.TITLE} id={titleId} variant=\"h3-strong\" {...ownerPropsConfig}>\n {title}\n </StyledTitle>\n </StyledListItemFullRow>\n {items.map((app, index) => {\n const flatIndex = initialPositionOffset + index;\n const positionAnnouncement = `${flatIndex + 1} of ${totalCount}`;\n return (\n <AppPickerItem\n key={app.id ?? `${app.label}-${isCustomApps ? 'custom' : 'main'}-${index}`}\n positionAnnouncement={positionAnnouncement}\n app={app}\n chipId={getChipId(app, flatIndex)}\n isFirstFocusable={flatIndex === firstFocusableIdx}\n isLastFocusable={flatIndex === lastFocusableIdx}\n />\n );\n })}\n </StyledSection>\n );\n};\n\nAppSection.displayName = 'DSAppPicker.AppSection';\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD0CnB;AA1CJ,uBAAuB;AACvB,2BAA6B;AAC7B,mBAAkC;AAClC,uBAA0E;AAC1E,4BAAmC;AACnC,uBAA0B;AAC1B,yBAAmF;AACnF,2BAA8B;AAC9B,2BAAqD;AAErD,MAAM,kBAAc,yBAAO,mCAAc,EAAE,MAAM,kCAAiB,MAAM,kCAAiB,MAAM,CAAC;AAAA,WACrF,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,eACpC,CAAC,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,GAAG,CAAC;AAAA,iBACvC,CAAC,EAAE,MAAM,MAAM,MAAM,YAAY,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAWnD,MAAM,aAAwC,CAAC,EAAE,eAAe,MAAM,MAAM;AACjF,QAAM;AAAA,IACJ,kBAAkB,EAAE,MAAM,YAAY,cAAc,mBAAmB;AAAA,IACvE;AAAA,IACA,eAAe,EAAE,mBAAmB,iBAAiB;AAAA,IACrD;AAAA,EACF,QAAI,yBAAW,wCAAkB;AAEjC,QAAM,QAAQ,eAAe,aAAa;AAE1C,QAAM,UAAU,mBACZ,wDAAoC,WAAW,QAC/C,kDAA8B,WAAW;AAC7C,QAAM,QAAQ,eAAe,qBAAqB;AAElD,QAAM,cAAc,MAAM,UAAU,MAAM,YAAY,UAAU;AAChE,QAAM,wBAAwB,eAAe,KAAK,SAAS;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa,wCAAuB;AAAA,MACpC,MAAK;AAAA,MACL,mBAAiB;AAAA,MAChB,GAAG;AAAA,MAEJ;AAAA,oDAAC,8CAAsB,eAAa,wCAAuB,KAAM,GAAG,kBAClE,sDAAC,eAAY,eAAa,wCAAuB,OAAO,IAAI,SAAS,SAAQ,aAAa,GAAG,kBAC1F,iBACH,GACF;AAAA,QACC,MAAM,IAAI,CAAC,KAAK,UAAU;AACzB,gBAAM,YAAY,wBAAwB;AAC1C,gBAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,UAAU;AAC9D,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA,YAAQ,4BAAU,KAAK,SAAS;AAAA,cAChC,kBAAkB,cAAc;AAAA,cAChC,iBAAiB,cAAc;AAAA;AAAA,YAL1B,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,eAAe,WAAW,MAAM,IAAI,KAAK;AAAA,UAM1E;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,WAAW,cAAc;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/react-desc-prop-types.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\nimport React from 'react';\nimport { MenuPicker } from '@elliemae/ds-icons';\nimport type { SvgIconT } from '@elliemae/ds-icons';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSAppPickerName, DSAppPickerSlots } from './constants/index.js';\n\nexport declare namespace DSAppPickerT {\n export interface AppItem {\n label: string;\n icon: React.ComponentType<{ className: string; size: string }>;\n onClick?: (e: React.MouseEvent, item: AppItem) => void | null;\n disabled?: boolean;\n applyAriaDisabled?: boolean;\n id?: string;\n selected?: boolean;\n wrapText?: boolean;\n }\n\n export type ActionRef = React.MutableRefObject<{\n focusToIndex?: (index: number) => void;\n focusSelectedOrFirstAvailable?: () => void;\n focusWrapper: () => void;\n }>;\n\n /**\n * Why the panel opened. `trigger` carries the activating event and fires synchronously in the\n * trigger's click handler (AppPicker owns the open). `controlled` fires when the consumer flips\n * the `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type OpenChange =\n { reason: 'trigger'; event: React.MouseEvent | React.KeyboardEvent } | { reason: 'controlled' };\n\n /**\n * Why the panel closed. The event-carrying reasons fire synchronously from the handler that owns\n * the close (AppPicker in uncontrolled mode): `escape` (a scoped Escape), `click-outside`, and\n * `trigger-toggle` (the trigger clicked while open). `controlled` fires when the consumer flips the\n * `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type CloseChange =\n | { reason: 'escape'; event: KeyboardEvent }\n | { reason: 'click-outside'; event: MouseEvent | TouchEvent }\n | { reason: 'trigger-toggle'; event: React.MouseEvent | React.KeyboardEvent }\n | { reason: 'controlled' };\n\n export interface RequiredProps {}\n\n export type SlotFunctionArguments = {\n dsApppickerRoot: () => object;\n dsApppickerGroup: () => object;\n dsApppickerItem: () => object;\n dsApppickerTitle: () => object;\n dsApppickerSeparator: () => object;\n dsApppickerRow: () => object;\n dsApppickerChip: () => object;\n dsApppickerButton: () => object;\n dsApppickerFloatingWrapper: () => object;\n };\n\n export interface DefaultProps {\n apps: AppItem[];\n customApps: AppItem[];\n sectionTitle: string;\n customSectionTitle: string;\n icon: React.ComponentType<SvgIconT.Props>;\n /**\n * Opt in to arrow-key opening on the trigger: ArrowDown opens and focuses the selected application\n * (the first available one when nothing is selected), ArrowUp opens and focuses the selected\n * application (the last available one when nothing is selected).\n *\n * The picker owns this flow end to end \u2014 a consumer does not wire a key handler, drive `isOpen`, or\n * reach through `actionRef` to place the focus. Defaults to `false`, so it is purely additive: a\n * picker that does not opt in behaves exactly as before, with the arrow keys doing nothing on the\n * trigger.\n *\n * Independent of `actionRef`, which stays the imperative handle for a consumer to move focus from\n * their own business logic at any time.\n */\n openAndFocusOnArrowKeys: boolean;\n }\n\n interface RenderTriggerProp {\n ref: React.RefCallback<HTMLButtonElement>;\n [key: string]: unknown;\n }\n\n /**\n * Props handed to a `TriggerComponent`. This is the only trigger API that participates in the\n * dialog's accessible-name wiring: `id` is the element the panel's `aria-labelledby` points at,\n * so a TriggerComponent that drops it leaves the dialog unnamed.\n *\n * `innerRef`, not `ref`, deliberately: under React 18 a `ref` passed through JSX is consumed by\n * the fiber and never reaches a plain function component's props unless it is wrapped in\n * `forwardRef`. `innerRef` is the established Dimsum convention (see `ds-system`'s styled\n * components) and keeps `forwardRef` optional for the consumer \u2014 which is the same ergonomic\n * concern that produced DEV-002, solved here without the plain-function call.\n */\n export interface TriggerComponentProps {\n innerRef: React.RefCallback<HTMLButtonElement>;\n id: string;\n onClick: (e: React.MouseEvent | React.KeyboardEvent) => void;\n /**\n * Attach to the trigger element alongside `onClick`. It is what implements\n * `openAndFocusOnArrowKeys`, and it is a keydown handler in its own right \u2014 never route a keydown\n * through `onClick` to get the same effect: `onClick` infers keyboard activation from the click's\n * `detail`, which is a property of clicks, not of key presses.\n *\n * Harmless to attach when `openAndFocusOnArrowKeys` is false \u2014 it ignores every key in that case.\n *\n * The keys it acts on are ArrowDown and ArrowUp. A trigger that drives its own `isOpen` \u2014 which makes\n * the picker's internal flip inert \u2014 has to open on those same two keys itself.\n */\n onKeyDown: (e: React.KeyboardEvent) => void;\n 'aria-haspopup': 'dialog';\n }\n\n /**\n * How the pending open was triggered, which is the only input to where initial focus lands:\n * `pointer` \u2192 the panel \u00B7 `keyboard-first` \u2192 the selection, else the first available item \u00B7\n * `keyboard-last` \u2192 the selection, else the last available item.\n */\n export type OpenIntent = 'pointer' | 'keyboard-first' | 'keyboard-last';\n\n export interface OptionalProps extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSAppPickerName,\n typeof DSAppPickerSlots\n > {\n onOpen?: (info: OpenChange) => void;\n onClose?: (info: CloseChange) => void;\n onClick?: (e: React.MouseEvent | React.KeyboardEvent) => void;\n onClickOutside?: (e: MouseEvent | React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n actionRef?: ActionRef;\n /**\n * @deprecated v4.x \u2014 use `TriggerComponent`. `renderTrigger` receives only `ref` and cannot be\n * given the id the dialog's `aria-labelledby` points at, so the panel is left without an\n * accessible name. See DEV-002 in KNOWN_INTENTIONAL_DEVIATIONS.md.\n */\n renderTrigger?: (props: RenderTriggerProp) => React.ReactElement | null;\n /**\n * Custom trigger, rendered as a real React element so it owns its own fiber. Takes precedence\n * over `renderTrigger` when both are supplied.\n */\n TriggerComponent?: React.ComponentType<TriggerComponentProps>;\n isOpen?: boolean;\n triggerRef?: React.RefObject<HTMLButtonElement>;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n}\n\nexport const defaultProps: DSAppPickerT.DefaultProps = {\n apps: [],\n customApps: [],\n sectionTitle: 'APPLICATIONS',\n customSectionTitle: 'CUSTOM APPLICATIONS',\n icon: () => <MenuPicker color={['brand-primary', '700']} size=\"m\" />,\n openAndFocusOnArrowKeys: false,\n};\n\n// =============================================================================\n// PropTypes\n// =============================================================================\n\nexport const DSAppPickerPropTypes: DSPropTypesSchema<DSAppPickerT.Props> = {\n ...getPropsPerSlotPropTypes(DSAppPickerName, DSAppPickerSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n apps: PropTypes.array\n .description(\n 'Main items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n customApps: PropTypes.array\n .description(\n 'Custom items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n sectionTitle: PropTypes.string.description('main section title').defaultValue('APPLICATIONS'),\n customSectionTitle: PropTypes.string.description('custom section title').defaultValue('CUSTOM APPLICATIONS'),\n icon: PropTypes.func.description('trigger button s icon').defaultValue(MenuPicker),\n openAndFocusOnArrowKeys: PropTypes.bool\n .description(\n 'Opt in to arrow-key opening on the trigger. ArrowDown opens and focuses the selected application, ' +\n 'falling back to the first available one; ArrowUp opens and focuses the selected application, falling ' +\n 'back to the last available one. The picker owns the whole flow \u2014 no key handler, no isOpen wiring and ' +\n 'no actionRef needed. Independent of actionRef, which remains the imperative handle for moving focus ' +\n 'from your own logic.',\n )\n .defaultValue(false),\n renderTrigger: PropTypes.func\n .description(\n 'Custom trigger, called as a plain function with { ref }. Superseded by TriggerComponent: this ' +\n \"render-prop cannot receive the id that the panel's aria-labelledby points at, so the dialog \" +\n 'is left without an accessible name. TriggerComponent takes precedence when both are supplied.',\n )\n .deprecated({\n version: '4.x',\n message: 'Use \"TriggerComponent\" instead \u2014 it receives the id required for the dialog accessible name.',\n }),\n TriggerComponent: PropTypes.func.description(\n 'Custom trigger rendered as a React element. Receives { innerRef, id, onClick, aria-haspopup }; ' +\n 'the id must be applied to the focusable trigger element for the panel to have an accessible name. ' +\n 'Takes precedence over the deprecated renderTrigger when both are supplied.',\n ),\n actionRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref containing a focusToIndex method. This method allows you to focus any App inside the AppPicker.',\n ),\n isOpen: PropTypes.bool.description('Wether the AppPicker should be open or not.'),\n onOpen: PropTypes.func.description(\n 'Callback when the AppPicker opens; receives { reason: \"trigger\" | \"controlled\", event? }.',\n ),\n onClose: PropTypes.func.description(\n 'Callback when the AppPicker closes; receives { reason: \"escape\" | \"click-outside\" | \"trigger-toggle\" | \"controlled\", event? }.',\n ),\n onKeyDown: PropTypes.func.description('OnKeyDown handler callback.'),\n onClick: PropTypes.func.description('Custom onClick for Trigger component.'),\n onClickOutside: PropTypes.func.description('Callback event when the user clicks outside the App Picker.'),\n triggerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref to the trigger button.',\n ),\n};\n\nexport const DSAppPickerPropTypesSchema = DSAppPickerPropTypes as unknown as ValidationMap<DSAppPickerT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADiLT;AA/Kd,sBAA2B;AAG3B,8BAKO;AAEP,uBAAkD;AAgK3C,MAAM,eAA0C;AAAA,EACrD,MAAM,CAAC;AAAA,EACP,YAAY,CAAC;AAAA,EACb,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,MAAM,MAAM,4CAAC,8BAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,MAAK,KAAI;AAAA,EAClE,yBAAyB;AAC3B;AAMO,MAAM,uBAA8D;AAAA,EACzE,OAAG,kDAAyB,kCAAiB,iCAAgB;AAAA,EAC7D,GAAG;AAAA,EACH,GAAG;AAAA,EACH,MAAM,kCAAU,MACb;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,YAAY,kCAAU,MACnB;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,cAAc,kCAAU,OAAO,YAAY,oBAAoB,EAAE,aAAa,cAAc;AAAA,EAC5F,oBAAoB,kCAAU,OAAO,YAAY,sBAAsB,EAAE,aAAa,qBAAqB;AAAA,EAC3G,MAAM,kCAAU,KAAK,YAAY,uBAAuB,EAAE,aAAa,0BAAU;AAAA,EACjF,yBAAyB,kCAAU,KAChC;AAAA,IACC;AAAA,EAKF,EACC,aAAa,KAAK;AAAA,EACrB,eAAe,kCAAU,KACtB;AAAA,IACC;AAAA,EAGF,EACC,WAAW;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAAA,EACH,kBAAkB,kCAAU,KAAK;AAAA,IAC/B;AAAA,EAGF;AAAA,EACA,WAAW,kCAAU,UAAU,CAAC,kCAAU,MAAM,kCAAU,MAAM,EAAE,SAAS,kCAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC5F;AAAA,EACF;AAAA,EACA,QAAQ,kCAAU,KAAK,YAAY,6CAA6C;AAAA,EAChF,QAAQ,kCAAU,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EACA,SAAS,kCAAU,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,WAAW,kCAAU,KAAK,YAAY,6BAA6B;AAAA,EACnE,SAAS,kCAAU,KAAK,YAAY,uCAAuC;AAAA,EAC3E,gBAAgB,kCAAU,KAAK,YAAY,6DAA6D;AAAA,EACxG,YAAY,kCAAU,UAAU,CAAC,kCAAU,MAAM,kCAAU,MAAM,EAAE,SAAS,kCAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC7F;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B;",
4
+ "sourcesContent": ["import React from 'react';\nimport { MenuPicker } from '@elliemae/ds-icons';\nimport type { SvgIconT } from '@elliemae/ds-icons';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSAppPickerName, DSAppPickerSlots } from './constants/index.js';\n\nexport declare namespace DSAppPickerT {\n export interface AppItem {\n label: string;\n icon: React.ComponentType<{ className: string; size: string }>;\n onClick?: (e: React.MouseEvent, item: AppItem) => void | null;\n disabled?: boolean;\n applyAriaDisabled?: boolean;\n id?: string;\n selected?: boolean;\n wrapText?: boolean;\n }\n\n export type ActionRef = React.MutableRefObject<{\n focusToIndex?: (index: number) => void;\n focusSelectedOrFirstAvailable?: () => void;\n focusWrapper: () => void;\n }>;\n\n /**\n * Why the panel opened. `trigger` carries the activating event and fires synchronously in the\n * trigger's click handler (AppPicker owns the open). `controlled` fires when the consumer flips\n * the `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type OpenChange =\n { reason: 'trigger'; event: React.MouseEvent | React.KeyboardEvent } | { reason: 'controlled' };\n\n /**\n * Why the panel closed. The event-carrying reasons fire synchronously from the handler that owns\n * the close (AppPicker in uncontrolled mode): `escape` (a scoped Escape), `click-outside`, and\n * `trigger-toggle` (the trigger clicked while open). `controlled` fires when the consumer flips the\n * `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type CloseChange =\n | { reason: 'escape'; event: KeyboardEvent }\n | { reason: 'click-outside'; event: MouseEvent | TouchEvent }\n | { reason: 'trigger-toggle'; event: React.MouseEvent | React.KeyboardEvent }\n | { reason: 'controlled' };\n\n export interface RequiredProps {}\n\n export type SlotFunctionArguments = {\n dsApppickerRoot: () => object;\n dsApppickerGroup: () => object;\n dsApppickerItem: () => object;\n dsApppickerTitle: () => object;\n dsApppickerSeparator: () => object;\n dsApppickerRow: () => object;\n dsApppickerChip: () => object;\n dsApppickerButton: () => object;\n dsApppickerFloatingWrapper: () => object;\n };\n\n export interface DefaultProps {\n apps: AppItem[];\n customApps: AppItem[];\n sectionTitle: string;\n customSectionTitle: string;\n icon: React.ComponentType<SvgIconT.Props>;\n /**\n * Opt in to arrow-key opening on the trigger: ArrowDown opens and focuses the selected application\n * (the first available one when nothing is selected), ArrowUp opens and focuses the selected\n * application (the last available one when nothing is selected).\n *\n * The picker owns this flow end to end \u2014 a consumer does not wire a key handler, drive `isOpen`, or\n * reach through `actionRef` to place the focus. Defaults to `false`, so it is purely additive: a\n * picker that does not opt in behaves exactly as before, with the arrow keys doing nothing on the\n * trigger.\n *\n * Independent of `actionRef`, which stays the imperative handle for a consumer to move focus from\n * their own business logic at any time.\n */\n openAndFocusOnArrowKeys: boolean;\n }\n\n interface RenderTriggerProp {\n ref: React.RefCallback<HTMLButtonElement>;\n [key: string]: unknown;\n }\n\n /**\n * Props handed to a `TriggerComponent`. This is the only trigger API that participates in the\n * dialog's accessible-name wiring: `id` is the element the panel's `aria-labelledby` points at,\n * so a TriggerComponent that drops it leaves the dialog unnamed.\n *\n * `innerRef`, not `ref`, deliberately: under React 18 a `ref` passed through JSX is consumed by\n * the fiber and never reaches a plain function component's props unless it is wrapped in\n * `forwardRef`. `innerRef` is the established Dimsum convention (see `ds-system`'s styled\n * components) and keeps `forwardRef` optional for the consumer \u2014 which is the same ergonomic\n * concern that produced DEV-002, solved here without the plain-function call.\n */\n export interface TriggerComponentProps {\n innerRef: React.RefCallback<HTMLButtonElement>;\n id: string;\n onClick: (e: React.MouseEvent | React.KeyboardEvent) => void;\n /**\n * Attach to the trigger element alongside `onClick`. It is what implements\n * `openAndFocusOnArrowKeys`, and it is a keydown handler in its own right \u2014 never route a keydown\n * through `onClick` to get the same effect: `onClick` infers keyboard activation from the click's\n * `detail`, which is a property of clicks, not of key presses.\n *\n * Harmless to attach when `openAndFocusOnArrowKeys` is false \u2014 it ignores every key in that case.\n *\n * The keys it acts on are ArrowDown and ArrowUp. A trigger that drives its own `isOpen` \u2014 which makes\n * the picker's internal flip inert \u2014 has to open on those same two keys itself.\n */\n onKeyDown: (e: React.KeyboardEvent) => void;\n 'aria-haspopup': 'dialog';\n }\n\n /**\n * How the pending open was triggered, which is the only input to where initial focus lands:\n * `pointer` \u2192 the panel \u00B7 `keyboard-first` \u2192 the selection, else the first available item \u00B7\n * `keyboard-last` \u2192 the selection, else the last available item.\n */\n export type OpenIntent = 'pointer' | 'keyboard-first' | 'keyboard-last';\n\n export interface OptionalProps extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSAppPickerName,\n typeof DSAppPickerSlots\n > {\n onOpen?: (info: OpenChange) => void;\n onClose?: (info: CloseChange) => void;\n onClick?: (e: React.MouseEvent | React.KeyboardEvent) => void;\n onClickOutside?: (e: MouseEvent | React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n actionRef?: ActionRef;\n /**\n * @deprecated v4.x \u2014 use `TriggerComponent`. `renderTrigger` receives only `ref` and cannot be\n * given the id the dialog's `aria-labelledby` points at, so the panel is left without an\n * accessible name. See DEV-002 in KNOWN_INTENTIONAL_DEVIATIONS.md.\n */\n renderTrigger?: (props: RenderTriggerProp) => React.ReactElement | null;\n /**\n * Custom trigger, rendered as a real React element so it owns its own fiber. Takes precedence\n * over `renderTrigger` when both are supplied.\n */\n TriggerComponent?: React.ComponentType<TriggerComponentProps>;\n isOpen?: boolean;\n triggerRef?: React.RefObject<HTMLButtonElement>;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n}\n\nexport const defaultProps: DSAppPickerT.DefaultProps = {\n apps: [],\n customApps: [],\n sectionTitle: 'APPLICATIONS',\n customSectionTitle: 'CUSTOM APPLICATIONS',\n icon: () => <MenuPicker color={['brand-primary', '700']} size=\"m\" />,\n openAndFocusOnArrowKeys: false,\n};\n\n// =============================================================================\n// PropTypes\n// =============================================================================\n\nexport const DSAppPickerPropTypes: DSPropTypesSchema<DSAppPickerT.Props> = {\n ...getPropsPerSlotPropTypes(DSAppPickerName, DSAppPickerSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n apps: PropTypes.array\n .description(\n 'Main items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n customApps: PropTypes.array\n .description(\n 'Custom items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n sectionTitle: PropTypes.string.description('main section title').defaultValue('APPLICATIONS'),\n customSectionTitle: PropTypes.string.description('custom section title').defaultValue('CUSTOM APPLICATIONS'),\n icon: PropTypes.func.description('trigger button s icon').defaultValue(MenuPicker),\n openAndFocusOnArrowKeys: PropTypes.bool\n .description(\n 'Opt in to arrow-key opening on the trigger. ArrowDown opens and focuses the selected application, ' +\n 'falling back to the first available one; ArrowUp opens and focuses the selected application, falling ' +\n 'back to the last available one. The picker owns the whole flow \u2014 no key handler, no isOpen wiring and ' +\n 'no actionRef needed. Independent of actionRef, which remains the imperative handle for moving focus ' +\n 'from your own logic.',\n )\n .defaultValue(false),\n renderTrigger: PropTypes.func\n .description(\n 'Custom trigger, called as a plain function with { ref }. Superseded by TriggerComponent: this ' +\n \"render-prop cannot receive the id that the panel's aria-labelledby points at, so the dialog \" +\n 'is left without an accessible name. TriggerComponent takes precedence when both are supplied.',\n )\n .deprecated({\n version: '4.x',\n message: 'Use \"TriggerComponent\" instead \u2014 it receives the id required for the dialog accessible name.',\n }),\n TriggerComponent: PropTypes.func.description(\n 'Custom trigger rendered as a React element. Receives { innerRef, id, onClick, aria-haspopup }; ' +\n 'the id must be applied to the focusable trigger element for the panel to have an accessible name. ' +\n 'Takes precedence over the deprecated renderTrigger when both are supplied.',\n ),\n actionRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref containing a focusToIndex method. This method allows you to focus any App inside the AppPicker.',\n ),\n isOpen: PropTypes.bool.description('Wether the AppPicker should be open or not.'),\n onOpen: PropTypes.func.description(\n 'Callback when the AppPicker opens; receives { reason: \"trigger\" | \"controlled\", event? }.',\n ),\n onClose: PropTypes.func.description(\n 'Callback when the AppPicker closes; receives { reason: \"escape\" | \"click-outside\" | \"trigger-toggle\" | \"controlled\", event? }.',\n ),\n onKeyDown: PropTypes.func.description('OnKeyDown handler callback.'),\n onClick: PropTypes.func.description('Custom onClick for Trigger component.'),\n onClickOutside: PropTypes.func.description('Callback event when the user clicks outside the App Picker.'),\n triggerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref to the trigger button.',\n ),\n};\n\nexport const DSAppPickerPropTypesSchema = DSAppPickerPropTypes as unknown as ValidationMap<DSAppPickerT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADgLT;AA/Kd,sBAA2B;AAG3B,8BAKO;AAEP,uBAAkD;AAgK3C,MAAM,eAA0C;AAAA,EACrD,MAAM,CAAC;AAAA,EACP,YAAY,CAAC;AAAA,EACb,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,MAAM,MAAM,4CAAC,8BAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,MAAK,KAAI;AAAA,EAClE,yBAAyB;AAC3B;AAMO,MAAM,uBAA8D;AAAA,EACzE,OAAG,kDAAyB,kCAAiB,iCAAgB;AAAA,EAC7D,GAAG;AAAA,EACH,GAAG;AAAA,EACH,MAAM,kCAAU,MACb;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,YAAY,kCAAU,MACnB;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,cAAc,kCAAU,OAAO,YAAY,oBAAoB,EAAE,aAAa,cAAc;AAAA,EAC5F,oBAAoB,kCAAU,OAAO,YAAY,sBAAsB,EAAE,aAAa,qBAAqB;AAAA,EAC3G,MAAM,kCAAU,KAAK,YAAY,uBAAuB,EAAE,aAAa,0BAAU;AAAA,EACjF,yBAAyB,kCAAU,KAChC;AAAA,IACC;AAAA,EAKF,EACC,aAAa,KAAK;AAAA,EACrB,eAAe,kCAAU,KACtB;AAAA,IACC;AAAA,EAGF,EACC,WAAW;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAAA,EACH,kBAAkB,kCAAU,KAAK;AAAA,IAC/B;AAAA,EAGF;AAAA,EACA,WAAW,kCAAU,UAAU,CAAC,kCAAU,MAAM,kCAAU,MAAM,EAAE,SAAS,kCAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC5F;AAAA,EACF;AAAA,EACA,QAAQ,kCAAU,KAAK,YAAY,6CAA6C;AAAA,EAChF,QAAQ,kCAAU,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EACA,SAAS,kCAAU,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,WAAW,kCAAU,KAAK,YAAY,6BAA6B;AAAA,EACnE,SAAS,kCAAU,KAAK,YAAY,uCAAuC;AAAA,EAC3E,gBAAgB,kCAAU,KAAK,YAAY,6DAA6D;AAAA,EACxG,YAAY,kCAAU,UAAU,CAAC,kCAAU,MAAM,kCAAU,MAAM,EAAE,SAAS,kCAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC7F;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,42 @@
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 instanceIds_exports = {};
30
+ __export(instanceIds_exports, {
31
+ getIdForAppPickerCustomSectionTitle: () => getIdForAppPickerCustomSectionTitle,
32
+ getIdForAppPickerRoot: () => getIdForAppPickerRoot,
33
+ getIdForAppPickerSectionTitle: () => getIdForAppPickerSectionTitle,
34
+ getIdForAppPickerTrigger: () => getIdForAppPickerTrigger
35
+ });
36
+ module.exports = __toCommonJS(instanceIds_exports);
37
+ var React = __toESM(require("react"));
38
+ const getIdForAppPickerRoot = (id) => id;
39
+ const getIdForAppPickerTrigger = (id) => `${id}-dialog-trigger-btn`;
40
+ const getIdForAppPickerSectionTitle = (id) => `${id}-section-title`;
41
+ const getIdForAppPickerCustomSectionTitle = (id) => `${id}-custom-section-title`;
42
+ //# sourceMappingURL=instanceIds.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/util/instanceIds.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
4
+ "sourcesContent": ["/*\n * The single place that owns every id suffix DSAppPicker appends.\n *\n * The component receives one `id` and has to put several distinct ids into the DOM. The id the consumer\n * gave lands, unmodified, on the ROOT \u2014 that one is theirs. Every other element gets that same value\n * with a suffix, which is what keeps a picker's ids from colliding with each other, with a second picker\n * on the page, or with the consumer's own markup.\n *\n * A suffix is only useful to a consumer if they can compute it, and it is only safe for us to change if\n * they never wrote it down. So the rule this module encodes is: EVERY suffix we invent gets an exported\n * helper here, and nothing anywhere else \u2014 inside the package or outside it \u2014 composes one by hand. A\n * consumer who needs the trigger writes `getIdForAppPickerTrigger(myId)`; if we rename the suffix\n * tomorrow, their call site keeps working and the rename is not a breaking change. A hardcoded\n * `${myId}-dialog-trigger-btn` in consumer code turns that same rename into one.\n *\n * `getIdForAppPickerRoot` appends nothing today and is exported anyway, for the same reason: it makes\n * \"your id lands on the root\" a call instead of a convention, so the day the root does need a suffix, the\n * consumers who used it are already correct.\n *\n * The names carry `AppPicker` even though the module does not need the disambiguation internally. These\n * are package-level named exports, and the next component to need the same treatment will want the same\n * four names \u2014 a consumer importing both should never have to alias one of them at the import site.\n *\n * Suffix values are frozen published surface \u2014 change them only under the breaking-change protocol, even\n * though this module is what makes such a change survivable.\n */\n\n/** The element the consumer's own `id` lands on, unchanged. */\nexport const getIdForAppPickerRoot = (id: string): string => id;\n\n/**\n * The trigger button. This is the id the panel's `aria-labelledby` points at, so it is also the answer to\n * \"what names the dialog\" \u2014 see `TriggerComponent` in the Custom Triggers documentation.\n */\nexport const getIdForAppPickerTrigger = (id: string): string => `${id}-dialog-trigger-btn`;\n\n/** The `sectionTitle` heading, which labels the `apps` group. */\nexport const getIdForAppPickerSectionTitle = (id: string): string => `${id}-section-title`;\n\n/** The `customSectionTitle` heading, which labels the `customApps` group. */\nexport const getIdForAppPickerCustomSectionTitle = (id: string): string => `${id}-custom-section-title`;\n", "import * as React from 'react';\nexport { React };\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;AD4BhB,MAAM,wBAAwB,CAAC,OAAuB;AAMtD,MAAM,2BAA2B,CAAC,OAAuB,GAAG,EAAE;AAG9D,MAAM,gCAAgC,CAAC,OAAuB,GAAG,EAAE;AAGnE,MAAM,sCAAsC,CAAC,OAAuB,GAAG,EAAE;",
6
+ "names": []
7
+ }
@@ -8,6 +8,24 @@ const useValidateProps = (props, propTypes) => {
8
8
  `[${DSAppPickerName}] At least one of "apps" or "customApps" must contain items. Providing both as empty arrays renders an empty picker.`
9
9
  );
10
10
  }
11
+ const suppliedAppIds = [...props.apps, ...props.customApps].map((app) => app.id).filter((id) => id !== void 0);
12
+ const seen = /* @__PURE__ */ new Set();
13
+ const duplicates = /* @__PURE__ */ new Set();
14
+ for (const id of suppliedAppIds) {
15
+ if (seen.has(id)) duplicates.add(id);
16
+ else seen.add(id);
17
+ }
18
+ const duplicatedAppIds = [...duplicates];
19
+ if (duplicatedAppIds.length) {
20
+ throw new Error(
21
+ `[${DSAppPickerName}] Every app "id" must be unique across "apps" and "customApps" \u2014 each one is rendered as that chip's DOM id, and duplicates produce an invalid document. Duplicated: ${duplicatedAppIds.map((id) => `"${id}"`).join(", ")}.`
22
+ );
23
+ }
24
+ if (props.id !== void 0 && suppliedAppIds.includes(props.id)) {
25
+ throw new Error(
26
+ `[${DSAppPickerName}] The app "id" "${props.id}" collides with the "id" given to the component, which is rendered on the root element. Every other id is suffixed away from it \u2014 see getIdForAppPickerTrigger / getIdForAppPickerSectionTitle / getIdForAppPickerCustomSectionTitle \u2014 but this one is not ours to move.`
27
+ );
28
+ }
11
29
  };
12
30
  export {
13
31
  useValidateProps
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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;",
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 /*\n * An app's `id` is rendered verbatim as the chip's DOM id \u2014 it is the consumer's own value, deliberately\n * left un-namespaced so they can address their chips by the identity they already know. `apps` and\n * `customApps` are two independent arrays, so nothing about the shape of the API stops the same value\n * appearing twice, and a duplicate DOM id is a broken document: `getElementById`, `document.querySelector`\n * and every `aria-*` reference silently resolve to the first match only.\n *\n * We do not fix that by rewriting their ids \u2014 that would take away the surface the field exists to\n * provide. We make it impossible to ship instead. Uniqueness stays the consumer's responsibility; this\n * turns \"silently wrong in production\" into \"cannot render\", which is the only version of that\n * responsibility that actually holds.\n *\n * Scoped to ids the consumer supplied: id-less apps are legal (AppSection falls back to a positional key\n * and getChipId to a label-index identity), and no chip id is emitted for them at all.\n */\n const suppliedAppIds = [...props.apps, ...props.customApps]\n .map((app) => app.id)\n .filter((id): id is string => id !== undefined);\n\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of suppliedAppIds) {\n if (seen.has(id)) duplicates.add(id);\n else seen.add(id);\n }\n const duplicatedAppIds = [...duplicates];\n if (duplicatedAppIds.length) {\n throw new Error(\n `[${DSAppPickerName}] Every app \"id\" must be unique across \"apps\" and \"customApps\" \u2014 each one is ` +\n `rendered as that chip's DOM id, and duplicates produce an invalid document. ` +\n `Duplicated: ${duplicatedAppIds.map((id) => `\"${id}\"`).join(', ')}.`,\n );\n }\n\n /*\n * Same defect, one level up: the consumer's `id` lands unmodified on the ROOT (see util/instanceIds), so\n * an app carrying that same value collides with it. Every id this component generates for itself is\n * suffixed through that module and therefore cannot participate \u2014 this is the one remaining pair where\n * two consumer-supplied values meet.\n */\n if (props.id !== undefined && suppliedAppIds.includes(props.id)) {\n throw new Error(\n `[${DSAppPickerName}] The app \"id\" \"${props.id}\" collides with the \"id\" given to the component, ` +\n `which is rendered on the root element. Every other id is suffixed away from it \u2014 see ` +\n `getIdForAppPickerTrigger / getIdForAppPickerSectionTitle / getIdForAppPickerCustomSectionTitle \u2014 but this one is not ours to move.`,\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;AAiBA,QAAM,iBAAiB,CAAC,GAAG,MAAM,MAAM,GAAG,MAAM,UAAU,EACvD,IAAI,CAAC,QAAQ,IAAI,EAAE,EACnB,OAAO,CAAC,OAAqB,OAAO,MAAS;AAEhD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,MAAM,gBAAgB;AAC/B,QAAI,KAAK,IAAI,EAAE,EAAG,YAAW,IAAI,EAAE;AAAA,QAC9B,MAAK,IAAI,EAAE;AAAA,EAClB;AACA,QAAM,mBAAmB,CAAC,GAAG,UAAU;AACvC,MAAI,iBAAiB,QAAQ;AAC3B,UAAM,IAAI;AAAA,MACR,IAAI,eAAe,6KAEF,iBAAiB,IAAI,CAAC,OAAO,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,IACrE;AAAA,EACF;AAQA,MAAI,MAAM,OAAO,UAAa,eAAe,SAAS,MAAM,EAAE,GAAG;AAC/D,UAAM,IAAI;AAAA,MACR,IAAI,eAAe,mBAAmB,MAAM,EAAE;AAAA,IAGhD;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/dist/esm/index.js CHANGED
@@ -2,12 +2,22 @@ import * as React from "react";
2
2
  import { DSAppPicker, AppPickerWithSchema } from "./DSAppPicker.js";
3
3
  import { DSAppPickerName, DSAppPickerSlots, DSAppPickerDataTestIds } from "./constants/index.js";
4
4
  import { getDSAppPickerContractProps } from "./util/getDSAppPickerContractProps.js";
5
+ import {
6
+ getIdForAppPickerRoot,
7
+ getIdForAppPickerTrigger,
8
+ getIdForAppPickerSectionTitle,
9
+ getIdForAppPickerCustomSectionTitle
10
+ } from "./util/instanceIds.js";
5
11
  export {
6
12
  AppPickerWithSchema,
7
13
  DSAppPicker,
8
14
  DSAppPickerDataTestIds,
9
15
  DSAppPickerName,
10
16
  DSAppPickerSlots,
11
- getDSAppPickerContractProps
17
+ getDSAppPickerContractProps,
18
+ getIdForAppPickerCustomSectionTitle,
19
+ getIdForAppPickerRoot,
20
+ getIdForAppPickerSectionTitle,
21
+ getIdForAppPickerTrigger
12
22
  };
13
23
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/index.ts"],
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 { getDSAppPickerContractProps } from './util/getDSAppPickerContractProps.js';\nexport type { DSAppPickerT } from './react-desc-prop-types.js';\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,2BAA2B;AACjD,SAAS,iBAAiB,kBAAkB,8BAA8B;AAC1E,SAAS,mCAAmC;",
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 { getDSAppPickerContractProps } from './util/getDSAppPickerContractProps.js';\nexport {\n getIdForAppPickerRoot,\n getIdForAppPickerTrigger,\n getIdForAppPickerSectionTitle,\n getIdForAppPickerCustomSectionTitle,\n} from './util/instanceIds.js';\nexport type { DSAppPickerT } from './react-desc-prop-types.js';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,aAAa,2BAA2B;AACjD,SAAS,iBAAiB,kBAAkB,8BAA8B;AAC1E,SAAS,mCAAmC;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/AppPanel.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { Grid } from '@elliemae/ds-grid';\nimport { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport { styled } from '@elliemae/ds-system';\nimport React, { memo, useCallback, useContext, useEffect } from 'react';\nimport {\n APP_PICKER_REGION_FOCUSES,\n DSAppPickerDataTestIds,\n DSAppPickerName,\n DSAppPickerSlots,\n} from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { AppSection } from './AppSection.js';\nimport { StyledListItemFullRow } from './shared-styles.js';\n\nconst StyledWrapper = styled(Grid, { name: DSAppPickerName, slot: DSAppPickerSlots.ROOT })`\n background-color: ${({ theme }) => theme.colors.neutral['000']};\n min-width: 308px;\n min-height: 110px;\n max-height: 449px;\n width: 308px;\n overflow-y: auto;\n overflow-x: hidden;\n /* Baseline 2024: reserve scrollbar gutter so the layout doesn't shift between overflow/no-overflow.\n Replaces a JS isOverflow detection effect that toggled right padding. */\n scrollbar-gutter: stable;\n margin: 0;\n padding: 0 0 8px 16px;\n &:focus {\n outline: none;\n }\n`;\n\nconst StyledSeparator = styled('hr', { name: DSAppPickerName, slot: DSAppPickerSlots.SEPARATOR })`\n border-top: 1px solid ${({ theme }) => theme.colors.neutral[300]};\n border-bottom: none;\n width: 100%;\n margin: 8px 0 0 0;\n`;\n\nconst wrapperGridLayout = {\n cols: ['repeat(3, 92px)'],\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n rows: ['auto'],\n};\n\nconst useExecOnceAfterFirstRender = (callback: () => void) => {\n const hasExecutedRef = React.useRef(false);\n const executeInitialFocusRef = React.useRef(callback);\n executeInitialFocusRef.current = callback;\n useEffect(() => {\n if (!hasExecutedRef.current) {\n executeInitialFocusRef.current();\n hasExecutedRef.current = true;\n }\n }, []);\n};\n\ntype MountedOpenAutofocusNuanceConfig = {\n pendingRef: React.MutableRefObject<boolean>;\n trackFocusPanel: () => void;\n};\n\n/**\n * NUANCE \u2014 the single case that initial-focus-on-open (useAppPickerFloatingContext's onOpen) cannot\n * cover: DSAppPicker rendered ALREADY open (declarative `isOpen` at mount, no user interaction).\n * That open is not a transition, so `onOpen` never fires for it. This mount-time hook seeds the panel\n * wrapper, which is what a pointer open seeds too: there was no gesture at all here, so the\n * keyboard-only \"land on the selected app\" rule does not apply, and the panel is the target that gets\n * the dialog announced. `pendingRef` is true only when the component started open and is flipped\n * false on first consume, so a later controlled reopen \u2014 a real transition handled by `onOpen` \u2014\n * does not double-seed. Every user-driven open (click/keyboard) is a transition handled by `onOpen`,\n * NOT here.\n *\n * REMOVABILITY: if the team decides declarative-open should not autofocus, delete this hook and its\n * call, and flip the \"rendered already-open \u2026 focuses the panel wrapper\" assertions in\n * DSAppPicker.keyboard.test.js. Nothing else depends on it.\n */\nconst useMountedOpenAutofocusNuance = ({ pendingRef, trackFocusPanel }: MountedOpenAutofocusNuanceConfig) => {\n useExecOnceAfterFirstRender(() => {\n if (!pendingRef.current) return;\n pendingRef.current = false;\n trackFocusPanel();\n });\n};\n\nconst AppPanelBase = () => {\n const {\n propsWithDefault: { customApps, onKeyDown },\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n mountedOpenAutofocusPendingRef,\n focusTrackers: { focusRegion, firstFocusableRef, lastFocusableRef, trackFocusPanel },\n } = useContext(DSAppPickerContext);\n\n // Global attributes are spread onto the panel root because there is no shared wrapper that\n // contains both the floating panel and the trigger. `wrap`, `onClick`, and `onKeyDown` are\n // filtered out because they collide with the public component API (which uses these for\n // different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open.\n // ---------------------------------------------------------------------------\n // User-driven opens (click/keyboard) are open transitions, seeded by\n // useAppPickerFloatingContext's onOpen. The one case that isn't a transition \u2014 being rendered\n // already-open (declarative `isOpen` at mount) \u2014 is covered here, scoped to exactly that.\n useMountedOpenAutofocusNuance({\n pendingRef: mountedOpenAutofocusPendingRef,\n trackFocusPanel,\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 // Default Escape-close/refocus is handled declaratively by useFloatingContext\n // (see useAppPickerFloatingContext's closeOnEscape/onEscape wiring) whenever there is no consumer\n // onKeyDown \u2014 a consumer-provided onKeyDown takes over keydown handling entirely.\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown,\n });\n\n // The panel root carries NO aria-label: it is a roleless element (generic role does not support\n // an accessible name, so any label here is dropped by assistive tech). The component's accessible\n // name lives on the dialog \u2014 see AppPickerContent's role=\"dialog\" + aria-labelledby.\n return (\n <StyledWrapper\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={wrapperGridLayout.cols}\n rows={wrapperGridLayout.rows}\n // when opening the dialog via mouse, the focus is programmatically assigned here via handleWrapperRef, -1 allows .focus() to work\n tabIndex={-1}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection isCustomApps />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC0JjB,SAEE,UAFF,KAEE,YAFF;AA1JN,SAAS,YAAY;AACrB,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,OAAOA,UAAS,MAAM,aAAa,YAAY,iBAAiB;AAChE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,6BAA6B;AAEtC,MAAM,gBAAgB,OAAO,MAAM,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,KAAK,CAAC;AAAA,sBACnE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBhE,MAAM,kBAAkB,OAAO,MAAM,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,UAAU,CAAC;AAAA,0BACtE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAMlE,MAAM,oBAAoB;AAAA,EACxB,MAAM,CAAC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAM,CAAC,MAAM;AACf;AAEA,MAAM,8BAA8B,CAAC,aAAyB;AAC5D,QAAM,iBAAiBA,OAAM,OAAO,KAAK;AACzC,QAAM,yBAAyBA,OAAM,OAAO,QAAQ;AACpD,yBAAuB,UAAU;AACjC,YAAU,MAAM;AACd,QAAI,CAAC,eAAe,SAAS;AAC3B,6BAAuB,QAAQ;AAC/B,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AACP;AAsBA,MAAM,gCAAgC,CAAC,EAAE,YAAY,gBAAgB,MAAwC;AAC3G,8BAA4B,MAAM;AAChC,QAAI,CAAC,WAAW,QAAS;AACzB,eAAW,UAAU;AACrB,oBAAgB;AAAA,EAClB,CAAC;AACH;AAEA,MAAM,eAAe,MAAM;AACzB,QAAM;AAAA,IACJ,kBAAkB,EAAE,YAAY,UAAU;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,EAAE,aAAa,mBAAmB,kBAAkB,gBAAgB;AAAA,EACrF,IAAI,WAAW,kBAAkB;AAMjC,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,GAAG,qBAAqB,IAAI;AAQ/E,gCAA8B;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAOD,QAAM,mBAAmB,gBAAgB,0BAA0B;AAEnE,QAAM,mBAAmB;AAAA,IACvB,CAAC,SAA6B;AAC5B,UAAI,QAAQ,iBAAkB,MAAK,MAAM;AAAA,IAC3C;AAAA,IACA,CAAC,gBAAgB;AAAA,EACnB;AAKA,QAAM,kBAAkB,aAAa;AAAA,IACnC,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF,CAAC;AAKD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,eAAa,uBAAuB;AAAA,MACpC,MAAM,kBAAkB;AAAA,MACxB,MAAM,kBAAkB;AAAA,MAExB,UAAU;AAAA,MACT,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACJ,WAAW;AAAA,MAEX;AAAA,4BAAC,cAAW;AAAA,QACX,WAAW,SAAS,KACnB,iCACE;AAAA,8BAAC,yBAAsB,eAAa,uBAAuB,KAAM,GAAG,kBAClE,8BAAC,mBAAgB,eAAa,uBAAuB,WAAY,GAAG,kBAAkB,GACxF;AAAA,UACA,oBAAC,cAAW,cAAY,MAAC;AAAA,WAC3B;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEO,MAAM,WAAW,KAAK,YAAY;AACzC,SAAS,cAAc;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { Grid } from '@elliemae/ds-grid';\nimport { useFocusTrap } from '@elliemae/ds-hooks-focus-trap';\nimport { styled } from '@elliemae/ds-system';\nimport React, { memo, useCallback, useContext, useEffect } from 'react';\nimport {\n APP_PICKER_REGION_FOCUSES,\n DSAppPickerDataTestIds,\n DSAppPickerName,\n DSAppPickerSlots,\n} from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { AppSection } from './AppSection.js';\nimport { StyledListItemFullRow } from './shared-styles.js';\n\nconst StyledWrapper = styled(Grid, { name: DSAppPickerName, slot: DSAppPickerSlots.ROOT })`\n background-color: ${({ theme }) => theme.colors.neutral['000']};\n min-width: 308px;\n min-height: 110px;\n max-height: 449px;\n width: 308px;\n overflow-y: auto;\n overflow-x: hidden;\n /* Baseline 2024: reserve scrollbar gutter so the layout doesn't shift between overflow/no-overflow.\n Replaces a JS isOverflow detection effect that toggled right padding. */\n scrollbar-gutter: stable;\n margin: 0;\n padding: 0 0 8px 16px;\n &:focus {\n outline: none;\n }\n`;\n\nconst StyledSeparator = styled('hr', { name: DSAppPickerName, slot: DSAppPickerSlots.SEPARATOR })`\n border-top: 1px solid ${({ theme }) => theme.colors.neutral[300]};\n border-bottom: none;\n width: 100%;\n margin: 8px 0 0 0;\n`;\n\nconst wrapperGridLayout = {\n cols: ['repeat(3, 92px)'],\n // Row tracks are intentionally auto-sized:\n // - title row picks up its own typography height\n // - chip rows expand when `wrapText` causes a chip to wrap onto a second line (Reflow story)\n // - separator row picks up its own 1px height + margin\n rows: ['auto'],\n};\n\nconst useExecOnceAfterFirstRender = (callback: () => void) => {\n const hasExecutedRef = React.useRef(false);\n const executeInitialFocusRef = React.useRef(callback);\n executeInitialFocusRef.current = callback;\n useEffect(() => {\n if (!hasExecutedRef.current) {\n executeInitialFocusRef.current();\n hasExecutedRef.current = true;\n }\n }, []);\n};\n\ntype MountedOpenAutofocusNuanceConfig = {\n pendingRef: React.MutableRefObject<boolean>;\n trackFocusPanel: () => void;\n};\n\n/**\n * NUANCE \u2014 the single case that initial-focus-on-open (useAppPickerFloatingContext's onOpen) cannot\n * cover: DSAppPicker rendered ALREADY open (declarative `isOpen` at mount, no user interaction).\n * That open is not a transition, so `onOpen` never fires for it. This mount-time hook seeds the panel\n * wrapper, which is what a pointer open seeds too: there was no gesture at all here, so the\n * keyboard-only \"land on the selected app\" rule does not apply, and the panel is the target that gets\n * the dialog announced. `pendingRef` is true only when the component started open and is flipped\n * false on first consume, so a later controlled reopen \u2014 a real transition handled by `onOpen` \u2014\n * does not double-seed. Every user-driven open (click/keyboard) is a transition handled by `onOpen`,\n * NOT here.\n *\n * REMOVABILITY: if the team decides declarative-open should not autofocus, delete this hook and its\n * call, and flip the \"rendered already-open \u2026 focuses the panel wrapper\" assertions in\n * DSAppPicker.keyboard.test.js. Nothing else depends on it.\n */\nconst useMountedOpenAutofocusNuance = ({ pendingRef, trackFocusPanel }: MountedOpenAutofocusNuanceConfig) => {\n useExecOnceAfterFirstRender(() => {\n if (!pendingRef.current) return;\n pendingRef.current = false;\n trackFocusPanel();\n });\n};\n\nconst AppPanelBase = () => {\n const {\n propsWithDefault: { customApps, onKeyDown },\n ownerPropsConfig,\n globalAttributes,\n xstyledProps,\n mountedOpenAutofocusPendingRef,\n focusTrackers: { focusRegion, firstFocusableRef, lastFocusableRef, trackFocusPanel },\n } = useContext(DSAppPickerContext);\n\n // Global attributes are spread here, on the panel root, which is this component's root for the purpose\n // of the Dimsum convention that global attributes land on the styled root (see project_slots.md \u2014 it is\n // gate 2 of `data-dimsum-parent-slot`, and a component spreading them on an inner control is treated as\n // a defect, not a variant).\n //\n // There is no element containing both the trigger and the floating panel, so \"root\" has to be chosen\n // rather than read off the tree. The panel is the right choice, and not merely the larger one: the\n // floating context, the sections and the chips are what this component actually is, while the trigger is\n // the replaceable part \u2014 `TriggerComponent` already lets a consumer supply their own, and the direction\n // ds-menu-button points at (a behavioural layer wrapping arbitrary children, with the menu as its own\n // part) would make it fully app-owned. The panel stays the root through that change; a trigger-rooted\n // choice would not survive it.\n //\n // `wrap`, `onClick`, and `onKeyDown` are filtered out because they collide with the public component API\n // (which uses these for different semantics).\n const { wrap, onClick, onKeyDown: onKeyDownGlobal, ...safeGlobalAttributes } = globalAttributes;\n\n // ---------------------------------------------------------------------------\n // Initial focus on panel open.\n // ---------------------------------------------------------------------------\n // User-driven opens (click/keyboard) are open transitions, seeded by\n // useAppPickerFloatingContext's onOpen. The one case that isn't a transition \u2014 being rendered\n // already-open (declarative `isOpen` at mount) \u2014 is covered here, scoped to exactly that.\n useMountedOpenAutofocusNuance({\n pendingRef: mountedOpenAutofocusPendingRef,\n trackFocusPanel,\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 // Default Escape-close/refocus is handled declaratively by useFloatingContext\n // (see useAppPickerFloatingContext's closeOnEscape/onEscape wiring) whenever there is no consumer\n // onKeyDown \u2014 a consumer-provided onKeyDown takes over keydown handling entirely.\n const handleOnKeyDown = useFocusTrap({\n firstElementRef: firstFocusableRef,\n lastElementRef: lastFocusableRef,\n onKeyDown,\n });\n\n // The panel root carries NO aria-label: it is a roleless element (generic role does not support\n // an accessible name, so any label here is dropped by assistive tech). The component's accessible\n // name lives on the dialog \u2014 see AppPickerContent's role=\"dialog\" + aria-labelledby.\n return (\n <StyledWrapper\n innerRef={handleWrapperRef}\n data-testid={DSAppPickerDataTestIds.ROOT}\n cols={wrapperGridLayout.cols}\n rows={wrapperGridLayout.rows}\n // when opening the dialog via mouse, the focus is programmatically assigned here via handleWrapperRef, -1 allows .focus() to work\n tabIndex={-1}\n {...ownerPropsConfig}\n {...safeGlobalAttributes}\n {...xstyledProps}\n onKeyDown={handleOnKeyDown}\n >\n <AppSection />\n {customApps.length > 0 && (\n <>\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledSeparator data-testid={DSAppPickerDataTestIds.SEPARATOR} {...ownerPropsConfig} />\n </StyledListItemFullRow>\n <AppSection isCustomApps />\n </>\n )}\n </StyledWrapper>\n );\n};\n\nexport const AppPanel = memo(AppPanelBase);\nAppPanel.displayName = 'DSAppPicker.AppPanel';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACqKjB,SAEE,UAFF,KAEE,YAFF;AArKN,SAAS,YAAY;AACrB,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,OAAOA,UAAS,MAAM,aAAa,YAAY,iBAAiB;AAChE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,6BAA6B;AAEtC,MAAM,gBAAgB,OAAO,MAAM,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,KAAK,CAAC;AAAA,sBACnE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBhE,MAAM,kBAAkB,OAAO,MAAM,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,UAAU,CAAC;AAAA,0BACtE,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAMlE,MAAM,oBAAoB;AAAA,EACxB,MAAM,CAAC,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,MAAM,CAAC,MAAM;AACf;AAEA,MAAM,8BAA8B,CAAC,aAAyB;AAC5D,QAAM,iBAAiBA,OAAM,OAAO,KAAK;AACzC,QAAM,yBAAyBA,OAAM,OAAO,QAAQ;AACpD,yBAAuB,UAAU;AACjC,YAAU,MAAM;AACd,QAAI,CAAC,eAAe,SAAS;AAC3B,6BAAuB,QAAQ;AAC/B,qBAAe,UAAU;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,CAAC;AACP;AAsBA,MAAM,gCAAgC,CAAC,EAAE,YAAY,gBAAgB,MAAwC;AAC3G,8BAA4B,MAAM;AAChC,QAAI,CAAC,WAAW,QAAS;AACzB,eAAW,UAAU;AACrB,oBAAgB;AAAA,EAClB,CAAC;AACH;AAEA,MAAM,eAAe,MAAM;AACzB,QAAM;AAAA,IACJ,kBAAkB,EAAE,YAAY,UAAU;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,EAAE,aAAa,mBAAmB,kBAAkB,gBAAgB;AAAA,EACrF,IAAI,WAAW,kBAAkB;AAiBjC,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,GAAG,qBAAqB,IAAI;AAQ/E,gCAA8B;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,EACF,CAAC;AAOD,QAAM,mBAAmB,gBAAgB,0BAA0B;AAEnE,QAAM,mBAAmB;AAAA,IACvB,CAAC,SAA6B;AAC5B,UAAI,QAAQ,iBAAkB,MAAK,MAAM;AAAA,IAC3C;AAAA,IACA,CAAC,gBAAgB;AAAA,EACnB;AAKA,QAAM,kBAAkB,aAAa;AAAA,IACnC,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB;AAAA,EACF,CAAC;AAKD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU;AAAA,MACV,eAAa,uBAAuB;AAAA,MACpC,MAAM,kBAAkB;AAAA,MACxB,MAAM,kBAAkB;AAAA,MAExB,UAAU;AAAA,MACT,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACJ,WAAW;AAAA,MAEX;AAAA,4BAAC,cAAW;AAAA,QACX,WAAW,SAAS,KACnB,iCACE;AAAA,8BAAC,yBAAsB,eAAa,uBAAuB,KAAM,GAAG,kBAClE,8BAAC,mBAAgB,eAAa,uBAAuB,WAAY,GAAG,kBAAkB,GACxF;AAAA,UACA,oBAAC,cAAW,cAAY,MAAC;AAAA,WAC3B;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEO,MAAM,WAAW,KAAK,YAAY;AACzC,SAAS,cAAc;",
6
6
  "names": ["React"]
7
7
  }
@@ -5,6 +5,7 @@ import { styled } from "@elliemae/ds-system";
5
5
  import { useContext } from "react";
6
6
  import { DSAppPickerName, DSAppPickerSlots } from "../../constants/index.js";
7
7
  import { DSAppPickerContext } from "../../DSAppPickerCTX.js";
8
+ import { getIdForAppPickerTrigger } from "../../util/instanceIds.js";
8
9
  import { AppPanel } from "../AppPanel.js";
9
10
  import { Trigger } from "../Trigger.js";
10
11
  import { useAppPickerFloatingContext } from "./useAppPickerFloatingContext.js";
@@ -37,7 +38,7 @@ const AppPickerContent = () => {
37
38
  resolvedIsOpen,
38
39
  setInternalIsOpen
39
40
  });
40
- const dialogLabelId = `${instanceUid}-dialog-trigger-btn`;
41
+ const dialogLabelId = getIdForAppPickerTrigger(instanceUid);
41
42
  return /* @__PURE__ */ jsxs(Fragment, { children: [
42
43
  /* @__PURE__ */ jsx(
43
44
  Trigger,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../scripts/build/transpile/react-shim.js", "../../../../src/parts/AppPickerFloatingContext/AppPickerContent.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { FloatingWrapper, PopoverArrow } from '@elliemae/ds-floating-context';\nimport { styled } from '@elliemae/ds-system';\nimport React, { useContext } from 'react';\nimport { DSAppPickerName, DSAppPickerSlots } from '../../constants/index.js';\nimport { DSAppPickerContext } from '../../DSAppPickerCTX.js';\nimport type { DSAppPickerT } from '../../react-desc-prop-types.js';\nimport { AppPanel } from '../AppPanel.js';\nimport { Trigger } from '../Trigger.js';\nimport { useAppPickerFloatingContext } from './useAppPickerFloatingContext.js';\n\nconst StyledAppPickerFloating = styled(FloatingWrapper, {\n name: DSAppPickerName,\n slot: DSAppPickerSlots.FLOATING_WRAPPER,\n})``;\n\nexport const AppPickerContent: React.ComponentType<DSAppPickerT.Props> = () => {\n const {\n ownerPropsConfig,\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n instanceUid,\n } = useContext(DSAppPickerContext);\n const {\n floatingStyles,\n arrowStyles,\n floatingContext,\n floatingInnerRef,\n handleTriggerRef,\n handleTriggerClick,\n handleTriggerKeyDown,\n } = useAppPickerFloatingContext({\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n });\n\n const dialogLabelId = `${instanceUid}-dialog-trigger-btn`;\n\n return (\n <>\n <Trigger\n handleTriggerRef={handleTriggerRef}\n handleTriggerClick={handleTriggerClick}\n handleTriggerKeyDown={handleTriggerKeyDown}\n dialogLabelId={dialogLabelId}\n />\n <StyledAppPickerFloating\n innerRef={floatingInnerRef}\n isOpen={resolvedIsOpen}\n floatingStyles={floatingStyles}\n context={floatingContext}\n getOwnerProps={ownerPropsConfig.getOwnerProps}\n getOwnerPropsArguments={ownerPropsConfig.getOwnerPropsArguments}\n role=\"dialog\"\n aria-labelledby={dialogLabelId}\n >\n <AppPanel />\n <PopoverArrow {...arrowStyles} />\n </StyledAppPickerFloating>\n </>\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;AC4CnB,mBACE,KAMA,YAPF;AA5CJ,SAAS,iBAAiB,oBAAoB;AAC9C,SAAS,cAAc;AACvB,SAAgB,kBAAkB;AAClC,SAAS,iBAAiB,wBAAwB;AAClD,SAAS,0BAA0B;AAEnC,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,mCAAmC;AAE5C,MAAM,0BAA0B,OAAO,iBAAiB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,iBAAiB;AACzB,CAAC;AAEM,MAAM,mBAA4D,MAAM;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,kBAAkB;AACjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,4BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB,GAAG,WAAW;AAEpC,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;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,QACzC,MAAK;AAAA,QACL,mBAAiB;AAAA,QAEjB;AAAA,8BAAC,YAAS;AAAA,UACV,oBAAC,gBAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { FloatingWrapper, PopoverArrow } from '@elliemae/ds-floating-context';\nimport { styled } from '@elliemae/ds-system';\nimport React, { useContext } from 'react';\nimport { DSAppPickerName, DSAppPickerSlots } from '../../constants/index.js';\nimport { DSAppPickerContext } from '../../DSAppPickerCTX.js';\nimport type { DSAppPickerT } from '../../react-desc-prop-types.js';\nimport { getIdForAppPickerTrigger } from '../../util/instanceIds.js';\nimport { AppPanel } from '../AppPanel.js';\nimport { Trigger } from '../Trigger.js';\nimport { useAppPickerFloatingContext } from './useAppPickerFloatingContext.js';\n\nconst StyledAppPickerFloating = styled(FloatingWrapper, {\n name: DSAppPickerName,\n slot: DSAppPickerSlots.FLOATING_WRAPPER,\n})``;\n\nexport const AppPickerContent: React.ComponentType<DSAppPickerT.Props> = () => {\n const {\n ownerPropsConfig,\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n instanceUid,\n } = useContext(DSAppPickerContext);\n const {\n floatingStyles,\n arrowStyles,\n floatingContext,\n floatingInnerRef,\n handleTriggerRef,\n handleTriggerClick,\n handleTriggerKeyDown,\n } = useAppPickerFloatingContext({\n propsWithDefault,\n focusTrackers,\n openIntentRef,\n resolvedIsOpen,\n setInternalIsOpen,\n });\n\n // Suffix owned by util/instanceIds \u2014 never composed inline, so consumers and this call site cannot\n // drift apart. `getIdForAppPickerTrigger` is the exported counterpart.\n const dialogLabelId = getIdForAppPickerTrigger(instanceUid);\n\n return (\n <>\n <Trigger\n handleTriggerRef={handleTriggerRef}\n handleTriggerClick={handleTriggerClick}\n handleTriggerKeyDown={handleTriggerKeyDown}\n dialogLabelId={dialogLabelId}\n />\n <StyledAppPickerFloating\n innerRef={floatingInnerRef}\n isOpen={resolvedIsOpen}\n floatingStyles={floatingStyles}\n context={floatingContext}\n getOwnerProps={ownerPropsConfig.getOwnerProps}\n getOwnerPropsArguments={ownerPropsConfig.getOwnerPropsArguments}\n role=\"dialog\"\n aria-labelledby={dialogLabelId}\n >\n <AppPanel />\n <PopoverArrow {...arrowStyles} />\n </StyledAppPickerFloating>\n </>\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC+CnB,mBACE,KAMA,YAPF;AA/CJ,SAAS,iBAAiB,oBAAoB;AAC9C,SAAS,cAAc;AACvB,SAAgB,kBAAkB;AAClC,SAAS,iBAAiB,wBAAwB;AAClD,SAAS,0BAA0B;AAEnC,SAAS,gCAAgC;AACzC,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,mCAAmC;AAE5C,MAAM,0BAA0B,OAAO,iBAAiB;AAAA,EACtD,MAAM;AAAA,EACN,MAAM,iBAAiB;AACzB,CAAC;AAEM,MAAM,mBAA4D,MAAM;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,WAAW,kBAAkB;AACjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,4BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAID,QAAM,gBAAgB,yBAAyB,WAAW;AAE1D,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;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,QACzC,MAAK;AAAA,QACL,mBAAiB;AAAA,QAEjB;AAAA,8BAAC,YAAS;AAAA,UACV,oBAAC,gBAAc,GAAG,aAAa;AAAA;AAAA;AAAA,IACjC;AAAA,KACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,7 @@ import { useContext } from "react";
6
6
  import { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from "../constants/index.js";
7
7
  import { DSAppPickerContext } from "../DSAppPickerCTX.js";
8
8
  import { getChipId } from "../util/getChipId.js";
9
+ import { getIdForAppPickerCustomSectionTitle, getIdForAppPickerSectionTitle } from "../util/instanceIds.js";
9
10
  import { AppPickerItem } from "./AppPickerItem.js";
10
11
  import { StyledListItemFullRow, StyledSection } from "./shared-styles.js";
11
12
  const StyledTitle = styled(DSTypography, { name: DSAppPickerName, slot: DSAppPickerSlots.TITLE })`
@@ -25,7 +26,7 @@ const AppSection = ({ isCustomApps = false }) => {
25
26
  ownerPropsConfig
26
27
  } = useContext(DSAppPickerContext);
27
28
  const items = isCustomApps ? customApps : apps;
28
- const titleId = isCustomApps ? `${instanceUid}-custom-section-title` : `${instanceUid}-section-title`;
29
+ const titleId = isCustomApps ? getIdForAppPickerCustomSectionTitle(instanceUid) : getIdForAppPickerSectionTitle(instanceUid);
29
30
  const title = isCustomApps ? customSectionTitle : sectionTitle;
30
31
  const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);
31
32
  const initialPositionOffset = isCustomApps ? apps.length : 0;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/AppSection.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { styled } from '@elliemae/ds-system';\nimport { DSTypography } from '@elliemae/ds-typography';\nimport React, { useContext } from 'react';\nimport { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { getChipId } from '../util/getChipId.js';\nimport { AppPickerItem } from './AppPickerItem.js';\nimport { StyledListItemFullRow, StyledSection } from './shared-styles.js';\n\nconst StyledTitle = styled(DSTypography, { name: DSAppPickerName, slot: DSAppPickerSlots.TITLE })`\n color: ${({ theme }) => theme.colors.neutral[700]};\n font-size: ${({ theme }) => theme.fontSizes.value[400]};\n font-weight: ${({ theme }) => theme.fontWeights.semibold};\n margin: 12px 0 8px 0;\n line-height: 1.385;\n text-transform: uppercase;\n text-align: center;\n`;\n\ninterface AppSectionProps {\n isCustomApps?: boolean;\n}\n\nexport const AppSection: React.FC<AppSectionProps> = ({ isCustomApps = false }) => {\n const {\n propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle },\n instanceUid,\n focusTrackers: { firstFocusableIdx, lastFocusableIdx },\n ownerPropsConfig,\n } = useContext(DSAppPickerContext);\n\n const items = isCustomApps ? customApps : apps;\n const titleId = isCustomApps ? `${instanceUid}-custom-section-title` : `${instanceUid}-section-title`;\n const title = isCustomApps ? customSectionTitle : sectionTitle;\n\n const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);\n const initialPositionOffset = isCustomApps ? apps.length : 0;\n return (\n <StyledSection\n data-testid={DSAppPickerDataTestIds.GROUP}\n role=\"group\"\n aria-labelledby={titleId}\n {...ownerPropsConfig}\n >\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledTitle data-testid={DSAppPickerDataTestIds.TITLE} id={titleId} variant=\"h3-strong\" {...ownerPropsConfig}>\n {title}\n </StyledTitle>\n </StyledListItemFullRow>\n {items.map((app, index) => {\n const flatIndex = initialPositionOffset + index;\n const positionAnnouncement = `${flatIndex + 1} of ${totalCount}`;\n return (\n <AppPickerItem\n key={app.id ?? `${app.label}-${isCustomApps ? 'custom' : 'main'}-${index}`}\n positionAnnouncement={positionAnnouncement}\n app={app}\n chipId={getChipId(app, flatIndex)}\n isFirstFocusable={flatIndex === firstFocusableIdx}\n isLastFocusable={flatIndex === lastFocusableIdx}\n />\n );\n })}\n </StyledSection>\n );\n};\n\nAppSection.displayName = 'DSAppPicker.AppSection';\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACsCnB,SAOI,KAPJ;AAtCJ,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAC7B,SAAgB,kBAAkB;AAClC,SAAS,wBAAwB,iBAAiB,wBAAwB;AAC1E,SAAS,0BAA0B;AACnC,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB,qBAAqB;AAErD,MAAM,cAAc,OAAO,cAAc,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,CAAC;AAAA,WACrF,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,eACpC,CAAC,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,GAAG,CAAC;AAAA,iBACvC,CAAC,EAAE,MAAM,MAAM,MAAM,YAAY,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAWnD,MAAM,aAAwC,CAAC,EAAE,eAAe,MAAM,MAAM;AACjF,QAAM;AAAA,IACJ,kBAAkB,EAAE,MAAM,YAAY,cAAc,mBAAmB;AAAA,IACvE;AAAA,IACA,eAAe,EAAE,mBAAmB,iBAAiB;AAAA,IACrD;AAAA,EACF,IAAI,WAAW,kBAAkB;AAEjC,QAAM,QAAQ,eAAe,aAAa;AAC1C,QAAM,UAAU,eAAe,GAAG,WAAW,0BAA0B,GAAG,WAAW;AACrF,QAAM,QAAQ,eAAe,qBAAqB;AAElD,QAAM,cAAc,MAAM,UAAU,MAAM,YAAY,UAAU;AAChE,QAAM,wBAAwB,eAAe,KAAK,SAAS;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa,uBAAuB;AAAA,MACpC,MAAK;AAAA,MACL,mBAAiB;AAAA,MAChB,GAAG;AAAA,MAEJ;AAAA,4BAAC,yBAAsB,eAAa,uBAAuB,KAAM,GAAG,kBAClE,8BAAC,eAAY,eAAa,uBAAuB,OAAO,IAAI,SAAS,SAAQ,aAAa,GAAG,kBAC1F,iBACH,GACF;AAAA,QACC,MAAM,IAAI,CAAC,KAAK,UAAU;AACzB,gBAAM,YAAY,wBAAwB;AAC1C,gBAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,UAAU;AAC9D,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA,QAAQ,UAAU,KAAK,SAAS;AAAA,cAChC,kBAAkB,cAAc;AAAA,cAChC,iBAAiB,cAAc;AAAA;AAAA,YAL1B,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,eAAe,WAAW,MAAM,IAAI,KAAK;AAAA,UAM1E;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,WAAW,cAAc;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { styled } from '@elliemae/ds-system';\nimport { DSTypography } from '@elliemae/ds-typography';\nimport React, { useContext } from 'react';\nimport { DSAppPickerDataTestIds, DSAppPickerName, DSAppPickerSlots } from '../constants/index.js';\nimport { DSAppPickerContext } from '../DSAppPickerCTX.js';\nimport { getChipId } from '../util/getChipId.js';\nimport { getIdForAppPickerCustomSectionTitle, getIdForAppPickerSectionTitle } from '../util/instanceIds.js';\nimport { AppPickerItem } from './AppPickerItem.js';\nimport { StyledListItemFullRow, StyledSection } from './shared-styles.js';\n\nconst StyledTitle = styled(DSTypography, { name: DSAppPickerName, slot: DSAppPickerSlots.TITLE })`\n color: ${({ theme }) => theme.colors.neutral[700]};\n font-size: ${({ theme }) => theme.fontSizes.value[400]};\n font-weight: ${({ theme }) => theme.fontWeights.semibold};\n margin: 12px 0 8px 0;\n line-height: 1.385;\n text-transform: uppercase;\n text-align: center;\n`;\n\ninterface AppSectionProps {\n isCustomApps?: boolean;\n}\n\nexport const AppSection: React.FC<AppSectionProps> = ({ isCustomApps = false }) => {\n const {\n propsWithDefault: { apps, customApps, sectionTitle, customSectionTitle },\n instanceUid,\n focusTrackers: { firstFocusableIdx, lastFocusableIdx },\n ownerPropsConfig,\n } = useContext(DSAppPickerContext);\n\n const items = isCustomApps ? customApps : apps;\n // Suffixes owned by util/instanceIds \u2014 see that module for why they are never composed inline.\n const titleId = isCustomApps\n ? getIdForAppPickerCustomSectionTitle(instanceUid)\n : getIdForAppPickerSectionTitle(instanceUid);\n const title = isCustomApps ? customSectionTitle : sectionTitle;\n\n const totalCount = (apps?.length ?? 0) + (customApps?.length ?? 0);\n const initialPositionOffset = isCustomApps ? apps.length : 0;\n return (\n <StyledSection\n data-testid={DSAppPickerDataTestIds.GROUP}\n role=\"group\"\n aria-labelledby={titleId}\n {...ownerPropsConfig}\n >\n <StyledListItemFullRow data-testid={DSAppPickerDataTestIds.ROW} {...ownerPropsConfig}>\n <StyledTitle data-testid={DSAppPickerDataTestIds.TITLE} id={titleId} variant=\"h3-strong\" {...ownerPropsConfig}>\n {title}\n </StyledTitle>\n </StyledListItemFullRow>\n {items.map((app, index) => {\n const flatIndex = initialPositionOffset + index;\n const positionAnnouncement = `${flatIndex + 1} of ${totalCount}`;\n return (\n <AppPickerItem\n key={app.id ?? `${app.label}-${isCustomApps ? 'custom' : 'main'}-${index}`}\n positionAnnouncement={positionAnnouncement}\n app={app}\n chipId={getChipId(app, flatIndex)}\n isFirstFocusable={flatIndex === firstFocusableIdx}\n isLastFocusable={flatIndex === lastFocusableIdx}\n />\n );\n })}\n </StyledSection>\n );\n};\n\nAppSection.displayName = 'DSAppPicker.AppSection';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC0CnB,SAOI,KAPJ;AA1CJ,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAC7B,SAAgB,kBAAkB;AAClC,SAAS,wBAAwB,iBAAiB,wBAAwB;AAC1E,SAAS,0BAA0B;AACnC,SAAS,iBAAiB;AAC1B,SAAS,qCAAqC,qCAAqC;AACnF,SAAS,qBAAqB;AAC9B,SAAS,uBAAuB,qBAAqB;AAErD,MAAM,cAAc,OAAO,cAAc,EAAE,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,CAAC;AAAA,WACrF,CAAC,EAAE,MAAM,MAAM,MAAM,OAAO,QAAQ,GAAG,CAAC;AAAA,eACpC,CAAC,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,GAAG,CAAC;AAAA,iBACvC,CAAC,EAAE,MAAM,MAAM,MAAM,YAAY,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAWnD,MAAM,aAAwC,CAAC,EAAE,eAAe,MAAM,MAAM;AACjF,QAAM;AAAA,IACJ,kBAAkB,EAAE,MAAM,YAAY,cAAc,mBAAmB;AAAA,IACvE;AAAA,IACA,eAAe,EAAE,mBAAmB,iBAAiB;AAAA,IACrD;AAAA,EACF,IAAI,WAAW,kBAAkB;AAEjC,QAAM,QAAQ,eAAe,aAAa;AAE1C,QAAM,UAAU,eACZ,oCAAoC,WAAW,IAC/C,8BAA8B,WAAW;AAC7C,QAAM,QAAQ,eAAe,qBAAqB;AAElD,QAAM,cAAc,MAAM,UAAU,MAAM,YAAY,UAAU;AAChE,QAAM,wBAAwB,eAAe,KAAK,SAAS;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa,uBAAuB;AAAA,MACpC,MAAK;AAAA,MACL,mBAAiB;AAAA,MAChB,GAAG;AAAA,MAEJ;AAAA,4BAAC,yBAAsB,eAAa,uBAAuB,KAAM,GAAG,kBAClE,8BAAC,eAAY,eAAa,uBAAuB,OAAO,IAAI,SAAS,SAAQ,aAAa,GAAG,kBAC1F,iBACH,GACF;AAAA,QACC,MAAM,IAAI,CAAC,KAAK,UAAU;AACzB,gBAAM,YAAY,wBAAwB;AAC1C,gBAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,UAAU;AAC9D,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC;AAAA,cACA;AAAA,cACA,QAAQ,UAAU,KAAK,SAAS;AAAA,cAChC,kBAAkB,cAAc;AAAA,cAChC,iBAAiB,cAAc;AAAA;AAAA,YAL1B,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,eAAe,WAAW,MAAM,IAAI,KAAK;AAAA,UAM1E;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,WAAW,cAAc;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/react-desc-prop-types.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable @typescript-eslint/no-empty-interface */\nimport React from 'react';\nimport { MenuPicker } from '@elliemae/ds-icons';\nimport type { SvgIconT } from '@elliemae/ds-icons';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSAppPickerName, DSAppPickerSlots } from './constants/index.js';\n\nexport declare namespace DSAppPickerT {\n export interface AppItem {\n label: string;\n icon: React.ComponentType<{ className: string; size: string }>;\n onClick?: (e: React.MouseEvent, item: AppItem) => void | null;\n disabled?: boolean;\n applyAriaDisabled?: boolean;\n id?: string;\n selected?: boolean;\n wrapText?: boolean;\n }\n\n export type ActionRef = React.MutableRefObject<{\n focusToIndex?: (index: number) => void;\n focusSelectedOrFirstAvailable?: () => void;\n focusWrapper: () => void;\n }>;\n\n /**\n * Why the panel opened. `trigger` carries the activating event and fires synchronously in the\n * trigger's click handler (AppPicker owns the open). `controlled` fires when the consumer flips\n * the `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type OpenChange =\n { reason: 'trigger'; event: React.MouseEvent | React.KeyboardEvent } | { reason: 'controlled' };\n\n /**\n * Why the panel closed. The event-carrying reasons fire synchronously from the handler that owns\n * the close (AppPicker in uncontrolled mode): `escape` (a scoped Escape), `click-outside`, and\n * `trigger-toggle` (the trigger clicked while open). `controlled` fires when the consumer flips the\n * `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type CloseChange =\n | { reason: 'escape'; event: KeyboardEvent }\n | { reason: 'click-outside'; event: MouseEvent | TouchEvent }\n | { reason: 'trigger-toggle'; event: React.MouseEvent | React.KeyboardEvent }\n | { reason: 'controlled' };\n\n export interface RequiredProps {}\n\n export type SlotFunctionArguments = {\n dsApppickerRoot: () => object;\n dsApppickerGroup: () => object;\n dsApppickerItem: () => object;\n dsApppickerTitle: () => object;\n dsApppickerSeparator: () => object;\n dsApppickerRow: () => object;\n dsApppickerChip: () => object;\n dsApppickerButton: () => object;\n dsApppickerFloatingWrapper: () => object;\n };\n\n export interface DefaultProps {\n apps: AppItem[];\n customApps: AppItem[];\n sectionTitle: string;\n customSectionTitle: string;\n icon: React.ComponentType<SvgIconT.Props>;\n /**\n * Opt in to arrow-key opening on the trigger: ArrowDown opens and focuses the selected application\n * (the first available one when nothing is selected), ArrowUp opens and focuses the selected\n * application (the last available one when nothing is selected).\n *\n * The picker owns this flow end to end \u2014 a consumer does not wire a key handler, drive `isOpen`, or\n * reach through `actionRef` to place the focus. Defaults to `false`, so it is purely additive: a\n * picker that does not opt in behaves exactly as before, with the arrow keys doing nothing on the\n * trigger.\n *\n * Independent of `actionRef`, which stays the imperative handle for a consumer to move focus from\n * their own business logic at any time.\n */\n openAndFocusOnArrowKeys: boolean;\n }\n\n interface RenderTriggerProp {\n ref: React.RefCallback<HTMLButtonElement>;\n [key: string]: unknown;\n }\n\n /**\n * Props handed to a `TriggerComponent`. This is the only trigger API that participates in the\n * dialog's accessible-name wiring: `id` is the element the panel's `aria-labelledby` points at,\n * so a TriggerComponent that drops it leaves the dialog unnamed.\n *\n * `innerRef`, not `ref`, deliberately: under React 18 a `ref` passed through JSX is consumed by\n * the fiber and never reaches a plain function component's props unless it is wrapped in\n * `forwardRef`. `innerRef` is the established Dimsum convention (see `ds-system`'s styled\n * components) and keeps `forwardRef` optional for the consumer \u2014 which is the same ergonomic\n * concern that produced DEV-002, solved here without the plain-function call.\n */\n export interface TriggerComponentProps {\n innerRef: React.RefCallback<HTMLButtonElement>;\n id: string;\n onClick: (e: React.MouseEvent | React.KeyboardEvent) => void;\n /**\n * Attach to the trigger element alongside `onClick`. It is what implements\n * `openAndFocusOnArrowKeys`, and it is a keydown handler in its own right \u2014 never route a keydown\n * through `onClick` to get the same effect: `onClick` infers keyboard activation from the click's\n * `detail`, which is a property of clicks, not of key presses.\n *\n * Harmless to attach when `openAndFocusOnArrowKeys` is false \u2014 it ignores every key in that case.\n *\n * The keys it acts on are ArrowDown and ArrowUp. A trigger that drives its own `isOpen` \u2014 which makes\n * the picker's internal flip inert \u2014 has to open on those same two keys itself.\n */\n onKeyDown: (e: React.KeyboardEvent) => void;\n 'aria-haspopup': 'dialog';\n }\n\n /**\n * How the pending open was triggered, which is the only input to where initial focus lands:\n * `pointer` \u2192 the panel \u00B7 `keyboard-first` \u2192 the selection, else the first available item \u00B7\n * `keyboard-last` \u2192 the selection, else the last available item.\n */\n export type OpenIntent = 'pointer' | 'keyboard-first' | 'keyboard-last';\n\n export interface OptionalProps extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSAppPickerName,\n typeof DSAppPickerSlots\n > {\n onOpen?: (info: OpenChange) => void;\n onClose?: (info: CloseChange) => void;\n onClick?: (e: React.MouseEvent | React.KeyboardEvent) => void;\n onClickOutside?: (e: MouseEvent | React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n actionRef?: ActionRef;\n /**\n * @deprecated v4.x \u2014 use `TriggerComponent`. `renderTrigger` receives only `ref` and cannot be\n * given the id the dialog's `aria-labelledby` points at, so the panel is left without an\n * accessible name. See DEV-002 in KNOWN_INTENTIONAL_DEVIATIONS.md.\n */\n renderTrigger?: (props: RenderTriggerProp) => React.ReactElement | null;\n /**\n * Custom trigger, rendered as a real React element so it owns its own fiber. Takes precedence\n * over `renderTrigger` when both are supplied.\n */\n TriggerComponent?: React.ComponentType<TriggerComponentProps>;\n isOpen?: boolean;\n triggerRef?: React.RefObject<HTMLButtonElement>;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n}\n\nexport const defaultProps: DSAppPickerT.DefaultProps = {\n apps: [],\n customApps: [],\n sectionTitle: 'APPLICATIONS',\n customSectionTitle: 'CUSTOM APPLICATIONS',\n icon: () => <MenuPicker color={['brand-primary', '700']} size=\"m\" />,\n openAndFocusOnArrowKeys: false,\n};\n\n// =============================================================================\n// PropTypes\n// =============================================================================\n\nexport const DSAppPickerPropTypes: DSPropTypesSchema<DSAppPickerT.Props> = {\n ...getPropsPerSlotPropTypes(DSAppPickerName, DSAppPickerSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n apps: PropTypes.array\n .description(\n 'Main items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n customApps: PropTypes.array\n .description(\n 'Custom items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n sectionTitle: PropTypes.string.description('main section title').defaultValue('APPLICATIONS'),\n customSectionTitle: PropTypes.string.description('custom section title').defaultValue('CUSTOM APPLICATIONS'),\n icon: PropTypes.func.description('trigger button s icon').defaultValue(MenuPicker),\n openAndFocusOnArrowKeys: PropTypes.bool\n .description(\n 'Opt in to arrow-key opening on the trigger. ArrowDown opens and focuses the selected application, ' +\n 'falling back to the first available one; ArrowUp opens and focuses the selected application, falling ' +\n 'back to the last available one. The picker owns the whole flow \u2014 no key handler, no isOpen wiring and ' +\n 'no actionRef needed. Independent of actionRef, which remains the imperative handle for moving focus ' +\n 'from your own logic.',\n )\n .defaultValue(false),\n renderTrigger: PropTypes.func\n .description(\n 'Custom trigger, called as a plain function with { ref }. Superseded by TriggerComponent: this ' +\n \"render-prop cannot receive the id that the panel's aria-labelledby points at, so the dialog \" +\n 'is left without an accessible name. TriggerComponent takes precedence when both are supplied.',\n )\n .deprecated({\n version: '4.x',\n message: 'Use \"TriggerComponent\" instead \u2014 it receives the id required for the dialog accessible name.',\n }),\n TriggerComponent: PropTypes.func.description(\n 'Custom trigger rendered as a React element. Receives { innerRef, id, onClick, aria-haspopup }; ' +\n 'the id must be applied to the focusable trigger element for the panel to have an accessible name. ' +\n 'Takes precedence over the deprecated renderTrigger when both are supplied.',\n ),\n actionRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref containing a focusToIndex method. This method allows you to focus any App inside the AppPicker.',\n ),\n isOpen: PropTypes.bool.description('Wether the AppPicker should be open or not.'),\n onOpen: PropTypes.func.description(\n 'Callback when the AppPicker opens; receives { reason: \"trigger\" | \"controlled\", event? }.',\n ),\n onClose: PropTypes.func.description(\n 'Callback when the AppPicker closes; receives { reason: \"escape\" | \"click-outside\" | \"trigger-toggle\" | \"controlled\", event? }.',\n ),\n onKeyDown: PropTypes.func.description('OnKeyDown handler callback.'),\n onClick: PropTypes.func.description('Custom onClick for Trigger component.'),\n onClickOutside: PropTypes.func.description('Callback event when the user clicks outside the App Picker.'),\n triggerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref to the trigger button.',\n ),\n};\n\nexport const DSAppPickerPropTypesSchema = DSAppPickerPropTypes as unknown as ValidationMap<DSAppPickerT.Props>;\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACiLT;AA/Kd,SAAS,kBAAkB;AAG3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,iBAAiB,wBAAwB;AAgK3C,MAAM,eAA0C;AAAA,EACrD,MAAM,CAAC;AAAA,EACP,YAAY,CAAC;AAAA,EACb,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,MAAM,MAAM,oBAAC,cAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,MAAK,KAAI;AAAA,EAClE,yBAAyB;AAC3B;AAMO,MAAM,uBAA8D;AAAA,EACzE,GAAG,yBAAyB,iBAAiB,gBAAgB;AAAA,EAC7D,GAAG;AAAA,EACH,GAAG;AAAA,EACH,MAAM,UAAU,MACb;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,YAAY,UAAU,MACnB;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,cAAc,UAAU,OAAO,YAAY,oBAAoB,EAAE,aAAa,cAAc;AAAA,EAC5F,oBAAoB,UAAU,OAAO,YAAY,sBAAsB,EAAE,aAAa,qBAAqB;AAAA,EAC3G,MAAM,UAAU,KAAK,YAAY,uBAAuB,EAAE,aAAa,UAAU;AAAA,EACjF,yBAAyB,UAAU,KAChC;AAAA,IACC;AAAA,EAKF,EACC,aAAa,KAAK;AAAA,EACrB,eAAe,UAAU,KACtB;AAAA,IACC;AAAA,EAGF,EACC,WAAW;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAAA,EACH,kBAAkB,UAAU,KAAK;AAAA,IAC/B;AAAA,EAGF;AAAA,EACA,WAAW,UAAU,UAAU,CAAC,UAAU,MAAM,UAAU,MAAM,EAAE,SAAS,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC5F;AAAA,EACF;AAAA,EACA,QAAQ,UAAU,KAAK,YAAY,6CAA6C;AAAA,EAChF,QAAQ,UAAU,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EACA,SAAS,UAAU,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,WAAW,UAAU,KAAK,YAAY,6BAA6B;AAAA,EACnE,SAAS,UAAU,KAAK,YAAY,uCAAuC;AAAA,EAC3E,gBAAgB,UAAU,KAAK,YAAY,6DAA6D;AAAA,EACxG,YAAY,UAAU,UAAU,CAAC,UAAU,MAAM,UAAU,MAAM,EAAE,SAAS,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC7F;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { MenuPicker } from '@elliemae/ds-icons';\nimport type { SvgIconT } from '@elliemae/ds-icons';\nimport type { GlobalAttributesT, XstyledProps, DSPropTypesSchema, ValidationMap } from '@elliemae/ds-props-helpers';\nimport {\n PropTypes,\n getPropsPerSlotPropTypes,\n globalAttributesPropTypes,\n xstyledPropTypes,\n} from '@elliemae/ds-props-helpers';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSAppPickerName, DSAppPickerSlots } from './constants/index.js';\n\nexport declare namespace DSAppPickerT {\n export interface AppItem {\n label: string;\n icon: React.ComponentType<{ className: string; size: string }>;\n onClick?: (e: React.MouseEvent, item: AppItem) => void | null;\n disabled?: boolean;\n applyAriaDisabled?: boolean;\n id?: string;\n selected?: boolean;\n wrapText?: boolean;\n }\n\n export type ActionRef = React.MutableRefObject<{\n focusToIndex?: (index: number) => void;\n focusSelectedOrFirstAvailable?: () => void;\n focusWrapper: () => void;\n }>;\n\n /**\n * Why the panel opened. `trigger` carries the activating event and fires synchronously in the\n * trigger's click handler (AppPicker owns the open). `controlled` fires when the consumer flips\n * the `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type OpenChange =\n { reason: 'trigger'; event: React.MouseEvent | React.KeyboardEvent } | { reason: 'controlled' };\n\n /**\n * Why the panel closed. The event-carrying reasons fire synchronously from the handler that owns\n * the close (AppPicker in uncontrolled mode): `escape` (a scoped Escape), `click-outside`, and\n * `trigger-toggle` (the trigger clicked while open). `controlled` fires when the consumer flips the\n * `isOpen` prop themselves \u2014 no event, delivered when that flip takes effect.\n */\n export type CloseChange =\n | { reason: 'escape'; event: KeyboardEvent }\n | { reason: 'click-outside'; event: MouseEvent | TouchEvent }\n | { reason: 'trigger-toggle'; event: React.MouseEvent | React.KeyboardEvent }\n | { reason: 'controlled' };\n\n export interface RequiredProps {}\n\n export type SlotFunctionArguments = {\n dsApppickerRoot: () => object;\n dsApppickerGroup: () => object;\n dsApppickerItem: () => object;\n dsApppickerTitle: () => object;\n dsApppickerSeparator: () => object;\n dsApppickerRow: () => object;\n dsApppickerChip: () => object;\n dsApppickerButton: () => object;\n dsApppickerFloatingWrapper: () => object;\n };\n\n export interface DefaultProps {\n apps: AppItem[];\n customApps: AppItem[];\n sectionTitle: string;\n customSectionTitle: string;\n icon: React.ComponentType<SvgIconT.Props>;\n /**\n * Opt in to arrow-key opening on the trigger: ArrowDown opens and focuses the selected application\n * (the first available one when nothing is selected), ArrowUp opens and focuses the selected\n * application (the last available one when nothing is selected).\n *\n * The picker owns this flow end to end \u2014 a consumer does not wire a key handler, drive `isOpen`, or\n * reach through `actionRef` to place the focus. Defaults to `false`, so it is purely additive: a\n * picker that does not opt in behaves exactly as before, with the arrow keys doing nothing on the\n * trigger.\n *\n * Independent of `actionRef`, which stays the imperative handle for a consumer to move focus from\n * their own business logic at any time.\n */\n openAndFocusOnArrowKeys: boolean;\n }\n\n interface RenderTriggerProp {\n ref: React.RefCallback<HTMLButtonElement>;\n [key: string]: unknown;\n }\n\n /**\n * Props handed to a `TriggerComponent`. This is the only trigger API that participates in the\n * dialog's accessible-name wiring: `id` is the element the panel's `aria-labelledby` points at,\n * so a TriggerComponent that drops it leaves the dialog unnamed.\n *\n * `innerRef`, not `ref`, deliberately: under React 18 a `ref` passed through JSX is consumed by\n * the fiber and never reaches a plain function component's props unless it is wrapped in\n * `forwardRef`. `innerRef` is the established Dimsum convention (see `ds-system`'s styled\n * components) and keeps `forwardRef` optional for the consumer \u2014 which is the same ergonomic\n * concern that produced DEV-002, solved here without the plain-function call.\n */\n export interface TriggerComponentProps {\n innerRef: React.RefCallback<HTMLButtonElement>;\n id: string;\n onClick: (e: React.MouseEvent | React.KeyboardEvent) => void;\n /**\n * Attach to the trigger element alongside `onClick`. It is what implements\n * `openAndFocusOnArrowKeys`, and it is a keydown handler in its own right \u2014 never route a keydown\n * through `onClick` to get the same effect: `onClick` infers keyboard activation from the click's\n * `detail`, which is a property of clicks, not of key presses.\n *\n * Harmless to attach when `openAndFocusOnArrowKeys` is false \u2014 it ignores every key in that case.\n *\n * The keys it acts on are ArrowDown and ArrowUp. A trigger that drives its own `isOpen` \u2014 which makes\n * the picker's internal flip inert \u2014 has to open on those same two keys itself.\n */\n onKeyDown: (e: React.KeyboardEvent) => void;\n 'aria-haspopup': 'dialog';\n }\n\n /**\n * How the pending open was triggered, which is the only input to where initial focus lands:\n * `pointer` \u2192 the panel \u00B7 `keyboard-first` \u2192 the selection, else the first available item \u00B7\n * `keyboard-last` \u2192 the selection, else the last available item.\n */\n export type OpenIntent = 'pointer' | 'keyboard-first' | 'keyboard-last';\n\n export interface OptionalProps extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSAppPickerName,\n typeof DSAppPickerSlots\n > {\n onOpen?: (info: OpenChange) => void;\n onClose?: (info: CloseChange) => void;\n onClick?: (e: React.MouseEvent | React.KeyboardEvent) => void;\n onClickOutside?: (e: MouseEvent | React.MouseEvent) => void;\n onKeyDown?: (e: React.KeyboardEvent) => void;\n actionRef?: ActionRef;\n /**\n * @deprecated v4.x \u2014 use `TriggerComponent`. `renderTrigger` receives only `ref` and cannot be\n * given the id the dialog's `aria-labelledby` points at, so the panel is left without an\n * accessible name. See DEV-002 in KNOWN_INTENTIONAL_DEVIATIONS.md.\n */\n renderTrigger?: (props: RenderTriggerProp) => React.ReactElement | null;\n /**\n * Custom trigger, rendered as a real React element so it owns its own fiber. Takes precedence\n * over `renderTrigger` when both are supplied.\n */\n TriggerComponent?: React.ComponentType<TriggerComponentProps>;\n isOpen?: boolean;\n triggerRef?: React.RefObject<HTMLButtonElement>;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n OptionalProps,\n Omit<GlobalAttributesT<HTMLDivElement>, keyof DefaultProps | keyof OptionalProps | keyof XstyledProps>,\n XstyledProps,\n RequiredProps {}\n}\n\nexport const defaultProps: DSAppPickerT.DefaultProps = {\n apps: [],\n customApps: [],\n sectionTitle: 'APPLICATIONS',\n customSectionTitle: 'CUSTOM APPLICATIONS',\n icon: () => <MenuPicker color={['brand-primary', '700']} size=\"m\" />,\n openAndFocusOnArrowKeys: false,\n};\n\n// =============================================================================\n// PropTypes\n// =============================================================================\n\nexport const DSAppPickerPropTypes: DSPropTypesSchema<DSAppPickerT.Props> = {\n ...getPropsPerSlotPropTypes(DSAppPickerName, DSAppPickerSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n apps: PropTypes.array\n .description(\n 'Main items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n customApps: PropTypes.array\n .description(\n 'Custom items. Format: [{ label:string, icon:component, onClick:func, disabled:bool, selected:bool }]. ' +\n 'Conditionally required: at least one of \"apps\" or \"customApps\" must contain items \u2014 a picker with ' +\n 'nothing to pick has no purpose, so providing both empty throws.',\n )\n .defaultValue([]),\n sectionTitle: PropTypes.string.description('main section title').defaultValue('APPLICATIONS'),\n customSectionTitle: PropTypes.string.description('custom section title').defaultValue('CUSTOM APPLICATIONS'),\n icon: PropTypes.func.description('trigger button s icon').defaultValue(MenuPicker),\n openAndFocusOnArrowKeys: PropTypes.bool\n .description(\n 'Opt in to arrow-key opening on the trigger. ArrowDown opens and focuses the selected application, ' +\n 'falling back to the first available one; ArrowUp opens and focuses the selected application, falling ' +\n 'back to the last available one. The picker owns the whole flow \u2014 no key handler, no isOpen wiring and ' +\n 'no actionRef needed. Independent of actionRef, which remains the imperative handle for moving focus ' +\n 'from your own logic.',\n )\n .defaultValue(false),\n renderTrigger: PropTypes.func\n .description(\n 'Custom trigger, called as a plain function with { ref }. Superseded by TriggerComponent: this ' +\n \"render-prop cannot receive the id that the panel's aria-labelledby points at, so the dialog \" +\n 'is left without an accessible name. TriggerComponent takes precedence when both are supplied.',\n )\n .deprecated({\n version: '4.x',\n message: 'Use \"TriggerComponent\" instead \u2014 it receives the id required for the dialog accessible name.',\n }),\n TriggerComponent: PropTypes.func.description(\n 'Custom trigger rendered as a React element. Receives { innerRef, id, onClick, aria-haspopup }; ' +\n 'the id must be applied to the focusable trigger element for the panel to have an accessible name. ' +\n 'Takes precedence over the deprecated renderTrigger when both are supplied.',\n ),\n actionRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref containing a focusToIndex method. This method allows you to focus any App inside the AppPicker.',\n ),\n isOpen: PropTypes.bool.description('Wether the AppPicker should be open or not.'),\n onOpen: PropTypes.func.description(\n 'Callback when the AppPicker opens; receives { reason: \"trigger\" | \"controlled\", event? }.',\n ),\n onClose: PropTypes.func.description(\n 'Callback when the AppPicker closes; receives { reason: \"escape\" | \"click-outside\" | \"trigger-toggle\" | \"controlled\", event? }.',\n ),\n onKeyDown: PropTypes.func.description('OnKeyDown handler callback.'),\n onClick: PropTypes.func.description('Custom onClick for Trigger component.'),\n onClickOutside: PropTypes.func.description('Callback event when the user clicks outside the App Picker.'),\n triggerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]).description(\n 'Ref to the trigger button.',\n ),\n};\n\nexport const DSAppPickerPropTypesSchema = DSAppPickerPropTypes as unknown as ValidationMap<DSAppPickerT.Props>;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACgLT;AA/Kd,SAAS,kBAAkB;AAG3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,iBAAiB,wBAAwB;AAgK3C,MAAM,eAA0C;AAAA,EACrD,MAAM,CAAC;AAAA,EACP,YAAY,CAAC;AAAA,EACb,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,MAAM,MAAM,oBAAC,cAAW,OAAO,CAAC,iBAAiB,KAAK,GAAG,MAAK,KAAI;AAAA,EAClE,yBAAyB;AAC3B;AAMO,MAAM,uBAA8D;AAAA,EACzE,GAAG,yBAAyB,iBAAiB,gBAAgB;AAAA,EAC7D,GAAG;AAAA,EACH,GAAG;AAAA,EACH,MAAM,UAAU,MACb;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,YAAY,UAAU,MACnB;AAAA,IACC;AAAA,EAGF,EACC,aAAa,CAAC,CAAC;AAAA,EAClB,cAAc,UAAU,OAAO,YAAY,oBAAoB,EAAE,aAAa,cAAc;AAAA,EAC5F,oBAAoB,UAAU,OAAO,YAAY,sBAAsB,EAAE,aAAa,qBAAqB;AAAA,EAC3G,MAAM,UAAU,KAAK,YAAY,uBAAuB,EAAE,aAAa,UAAU;AAAA,EACjF,yBAAyB,UAAU,KAChC;AAAA,IACC;AAAA,EAKF,EACC,aAAa,KAAK;AAAA,EACrB,eAAe,UAAU,KACtB;AAAA,IACC;AAAA,EAGF,EACC,WAAW;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAAA,EACH,kBAAkB,UAAU,KAAK;AAAA,IAC/B;AAAA,EAGF;AAAA,EACA,WAAW,UAAU,UAAU,CAAC,UAAU,MAAM,UAAU,MAAM,EAAE,SAAS,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC5F;AAAA,EACF;AAAA,EACA,QAAQ,UAAU,KAAK,YAAY,6CAA6C;AAAA,EAChF,QAAQ,UAAU,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EACA,SAAS,UAAU,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,WAAW,UAAU,KAAK,YAAY,6BAA6B;AAAA,EACnE,SAAS,UAAU,KAAK,YAAY,uCAAuC;AAAA,EAC3E,gBAAgB,UAAU,KAAK,YAAY,6DAA6D;AAAA,EACxG,YAAY,UAAU,UAAU,CAAC,UAAU,MAAM,UAAU,MAAM,EAAE,SAAS,UAAU,IAAI,CAAC,CAAC,CAAC,EAAE;AAAA,IAC7F;AAAA,EACF;AACF;AAEO,MAAM,6BAA6B;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ const getIdForAppPickerRoot = (id) => id;
3
+ const getIdForAppPickerTrigger = (id) => `${id}-dialog-trigger-btn`;
4
+ const getIdForAppPickerSectionTitle = (id) => `${id}-section-title`;
5
+ const getIdForAppPickerCustomSectionTitle = (id) => `${id}-custom-section-title`;
6
+ export {
7
+ getIdForAppPickerCustomSectionTitle,
8
+ getIdForAppPickerRoot,
9
+ getIdForAppPickerSectionTitle,
10
+ getIdForAppPickerTrigger
11
+ };
12
+ //# sourceMappingURL=instanceIds.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/util/instanceIds.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/*\n * The single place that owns every id suffix DSAppPicker appends.\n *\n * The component receives one `id` and has to put several distinct ids into the DOM. The id the consumer\n * gave lands, unmodified, on the ROOT \u2014 that one is theirs. Every other element gets that same value\n * with a suffix, which is what keeps a picker's ids from colliding with each other, with a second picker\n * on the page, or with the consumer's own markup.\n *\n * A suffix is only useful to a consumer if they can compute it, and it is only safe for us to change if\n * they never wrote it down. So the rule this module encodes is: EVERY suffix we invent gets an exported\n * helper here, and nothing anywhere else \u2014 inside the package or outside it \u2014 composes one by hand. A\n * consumer who needs the trigger writes `getIdForAppPickerTrigger(myId)`; if we rename the suffix\n * tomorrow, their call site keeps working and the rename is not a breaking change. A hardcoded\n * `${myId}-dialog-trigger-btn` in consumer code turns that same rename into one.\n *\n * `getIdForAppPickerRoot` appends nothing today and is exported anyway, for the same reason: it makes\n * \"your id lands on the root\" a call instead of a convention, so the day the root does need a suffix, the\n * consumers who used it are already correct.\n *\n * The names carry `AppPicker` even though the module does not need the disambiguation internally. These\n * are package-level named exports, and the next component to need the same treatment will want the same\n * four names \u2014 a consumer importing both should never have to alias one of them at the import site.\n *\n * Suffix values are frozen published surface \u2014 change them only under the breaking-change protocol, even\n * though this module is what makes such a change survivable.\n */\n\n/** The element the consumer's own `id` lands on, unchanged. */\nexport const getIdForAppPickerRoot = (id: string): string => id;\n\n/**\n * The trigger button. This is the id the panel's `aria-labelledby` points at, so it is also the answer to\n * \"what names the dialog\" \u2014 see `TriggerComponent` in the Custom Triggers documentation.\n */\nexport const getIdForAppPickerTrigger = (id: string): string => `${id}-dialog-trigger-btn`;\n\n/** The `sectionTitle` heading, which labels the `apps` group. */\nexport const getIdForAppPickerSectionTitle = (id: string): string => `${id}-section-title`;\n\n/** The `customSectionTitle` heading, which labels the `customApps` group. */\nexport const getIdForAppPickerCustomSectionTitle = (id: string): string => `${id}-custom-section-title`;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC4BhB,MAAM,wBAAwB,CAAC,OAAuB;AAMtD,MAAM,2BAA2B,CAAC,OAAuB,GAAG,EAAE;AAG9D,MAAM,gCAAgC,CAAC,OAAuB,GAAG,EAAE;AAGnE,MAAM,sCAAsC,CAAC,OAAuB,GAAG,EAAE;",
6
+ "names": []
7
+ }
@@ -1,4 +1,5 @@
1
1
  export { DSAppPicker, AppPickerWithSchema } from './DSAppPicker.js';
2
2
  export { DSAppPickerName, DSAppPickerSlots, DSAppPickerDataTestIds } from './constants/index.js';
3
3
  export { getDSAppPickerContractProps } from './util/getDSAppPickerContractProps.js';
4
+ export { getIdForAppPickerRoot, getIdForAppPickerTrigger, getIdForAppPickerSectionTitle, getIdForAppPickerCustomSectionTitle, } from './util/instanceIds.js';
4
5
  export type { DSAppPickerT } from './react-desc-prop-types.js';
@@ -0,0 +1,11 @@
1
+ /** The element the consumer's own `id` lands on, unchanged. */
2
+ export declare const getIdForAppPickerRoot: (id: string) => string;
3
+ /**
4
+ * The trigger button. This is the id the panel's `aria-labelledby` points at, so it is also the answer to
5
+ * "what names the dialog" — see `TriggerComponent` in the Custom Triggers documentation.
6
+ */
7
+ export declare const getIdForAppPickerTrigger: (id: string) => string;
8
+ /** The `sectionTitle` heading, which labels the `apps` group. */
9
+ export declare const getIdForAppPickerSectionTitle: (id: string) => string;
10
+ /** The `customSectionTitle` heading, which labels the `customApps` group. */
11
+ export declare const getIdForAppPickerCustomSectionTitle: (id: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-app-picker",
3
- "version": "3.70.0-next.62",
3
+ "version": "3.70.0-next.69",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - App Picker",
6
6
  "files": [
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://git.elliemae.io/platform-ui/dimsum.git"
25
+ "url": "https://github.com/intcx/PLATFORM-UI.dimsum.git"
26
26
  },
27
27
  "engines": {
28
28
  "pnpm": ">=9",
@@ -37,24 +37,24 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "uid": "^2.0.2",
40
- "@elliemae/ds-button-v2": "3.70.0-next.62",
41
- "@elliemae/ds-chip": "3.70.0-next.62",
42
- "@elliemae/ds-hooks-focus-trap": "3.70.0-next.62",
43
- "@elliemae/ds-grid": "3.70.0-next.62",
44
- "@elliemae/ds-floating-context": "3.70.0-next.62",
45
- "@elliemae/ds-props-helpers": "3.70.0-next.62",
46
- "@elliemae/ds-system": "3.70.0-next.62",
47
- "@elliemae/ds-icons": "3.70.0-next.62",
48
- "@elliemae/ds-typography": "3.70.0-next.62"
40
+ "@elliemae/ds-button-v2": "3.70.0-next.69",
41
+ "@elliemae/ds-chip": "3.70.0-next.69",
42
+ "@elliemae/ds-floating-context": "3.70.0-next.69",
43
+ "@elliemae/ds-hooks-focus-trap": "3.70.0-next.69",
44
+ "@elliemae/ds-icons": "3.70.0-next.69",
45
+ "@elliemae/ds-grid": "3.70.0-next.69",
46
+ "@elliemae/ds-props-helpers": "3.70.0-next.69",
47
+ "@elliemae/ds-system": "3.70.0-next.69",
48
+ "@elliemae/ds-typography": "3.70.0-next.69"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@playwright/experimental-ct-react": "1.61.1",
52
52
  "jest": "^30.0.0",
53
53
  "jest-axe": "^11.0.0",
54
54
  "styled-components": "~5.3.11",
55
- "@elliemae/ds-monorepo-devops": "3.70.0-next.62",
56
- "@elliemae/ds-test-utils": "3.70.0-next.62",
57
- "@elliemae/ds-typescript-helpers": "3.70.0-next.62"
55
+ "@elliemae/ds-monorepo-devops": "3.70.0-next.69",
56
+ "@elliemae/ds-test-utils": "3.70.0-next.69",
57
+ "@elliemae/ds-typescript-helpers": "3.70.0-next.69"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "react": "^18.3.1",