@elliemae/ds-floating-context 3.70.0-next.7 → 3.70.0-next.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/cjs/DSFloatingContext.js +58 -27
  2. package/dist/cjs/DSFloatingContext.js.map +2 -2
  3. package/dist/cjs/hooks/useFloatingClickOutside.js +60 -0
  4. package/dist/cjs/hooks/useFloatingClickOutside.js.map +7 -0
  5. package/dist/cjs/hooks/useFloatingEscape.js +74 -0
  6. package/dist/cjs/hooks/useFloatingEscape.js.map +7 -0
  7. package/dist/cjs/hooks/useFloatingResizeObserver.js +46 -0
  8. package/dist/cjs/hooks/useFloatingResizeObserver.js.map +7 -0
  9. package/dist/cjs/hooks/useLatestRef.js +41 -0
  10. package/dist/cjs/hooks/useLatestRef.js.map +7 -0
  11. package/dist/cjs/hooks/useResolvedReference.js +52 -0
  12. package/dist/cjs/hooks/useResolvedReference.js.map +7 -0
  13. package/dist/cjs/react-desc-prop-types.js +13 -2
  14. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  15. package/dist/cjs/typescript-testing/typescript-floating-context-valid.js +5 -1
  16. package/dist/cjs/typescript-testing/typescript-floating-context-valid.js.map +2 -2
  17. package/dist/cjs/useComputedPositionStyles.js +4 -2
  18. package/dist/cjs/useComputedPositionStyles.js.map +2 -2
  19. package/dist/esm/DSFloatingContext.js +59 -28
  20. package/dist/esm/DSFloatingContext.js.map +2 -2
  21. package/dist/esm/hooks/useFloatingClickOutside.js +30 -0
  22. package/dist/esm/hooks/useFloatingClickOutside.js.map +7 -0
  23. package/dist/esm/hooks/useFloatingEscape.js +44 -0
  24. package/dist/esm/hooks/useFloatingEscape.js.map +7 -0
  25. package/dist/esm/hooks/useFloatingResizeObserver.js +16 -0
  26. package/dist/esm/hooks/useFloatingResizeObserver.js.map +7 -0
  27. package/dist/esm/hooks/useLatestRef.js +11 -0
  28. package/dist/esm/hooks/useLatestRef.js.map +7 -0
  29. package/dist/esm/hooks/useResolvedReference.js +22 -0
  30. package/dist/esm/hooks/useResolvedReference.js.map +7 -0
  31. package/dist/esm/react-desc-prop-types.js +13 -2
  32. package/dist/esm/react-desc-prop-types.js.map +2 -2
  33. package/dist/esm/typescript-testing/typescript-floating-context-valid.js +5 -1
  34. package/dist/esm/typescript-testing/typescript-floating-context-valid.js.map +2 -2
  35. package/dist/esm/useComputedPositionStyles.js +4 -2
  36. package/dist/esm/useComputedPositionStyles.js.map +2 -2
  37. package/dist/types/DSFloatingContext.d.ts +1 -1
  38. package/dist/types/hooks/useFloatingClickOutside.d.ts +20 -0
  39. package/dist/types/hooks/useFloatingEscape.d.ts +19 -0
  40. package/dist/types/hooks/useFloatingResizeObserver.d.ts +11 -0
  41. package/dist/types/hooks/useLatestRef.d.ts +7 -0
  42. package/dist/types/hooks/useResolvedReference.d.ts +19 -0
  43. package/dist/types/react-desc-prop-types.d.ts +19 -0
  44. package/package.json +6 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/useComputedPositionStyles.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-statements */\nimport { useLayoutEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport { debounce } from 'lodash-es';\nimport { type CSSProperties } from 'styled-components';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\n\ntype UseComputedPositionStylesT = {\n /** Prevent computing when closed (optimization + avoids unnecessary frames) */\n preventComputing?: boolean;\n reference: Element | null;\n floating: HTMLElement | null;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n /** Debounce ms for scroll/resize/observer events */\n debounceMs?: number;\n};\n\nexport const useComputedPositionStyles = (config: UseComputedPositionStylesT) => {\n const {\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n preventComputing = false,\n debounceMs = 150,\n } = config;\n\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({ style: { left: 0 }, placement: 'top' });\n\n // Important: do not initialize top/left to (0,0); keep hidden until the first computation\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n visibility: 'hidden',\n willChange: 'transform',\n });\n\n const [hasComputedOnce, setHasComputedOnce] = useState(false);\n\n const canCompute = reference !== null && floating !== null && !preventComputing;\n\n const updateStyles = useCallback(() => {\n if (!canCompute) return;\n\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n // Do not touch visibility here; it is managed outside depending on open/hasComputedOnce\n setFloatingStyles((prev) => ({\n position: 'absolute',\n zIndex: 3000,\n ...prev,\n ...coordsStyle,\n }));\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n setHasComputedOnce(true);\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n // Store latest update function in a ref to keep debounced stable\n const mutableUpdateStyles = useRef(updateStyles);\n mutableUpdateStyles.current = updateStyles;\n\n const debouncedUpdateStyles = useMemo(() => {\n const d = debounce(() => {\n mutableUpdateStyles.current();\n }, debounceMs);\n return d;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debounceMs]);\n\n // Clean up debounce on unmount\n useLayoutEffect(\n () => () => {\n debouncedUpdateStyles.cancel();\n },\n [debouncedUpdateStyles],\n );\n\n // Recalculate BEFORE paint when dependencies change\n useLayoutEffect(() => {\n if (canCompute) {\n mutableUpdateStyles.current();\n }\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n const forceUpdatePosition = useCallback(() => {\n mutableUpdateStyles.current();\n }, []);\n\n // Do not reset coordinates when closing; just hide\n const resetVisibilityOnly = useCallback(() => {\n setFloatingStyles((prev) => ({\n ...prev,\n visibility: 'hidden',\n }));\n }, []);\n\n return useMemo(\n () => ({\n arrowStyles,\n floatingStyles,\n hasComputedOnce,\n updateStyles: forceUpdatePosition,\n debouncedUpdateStyles,\n mutableUpdateStyles,\n resetVisibilityOnly,\n }),\n [arrowStyles, floatingStyles, hasComputedOnce, forceUpdatePosition, debouncedUpdateStyles, resetVisibilityOnly],\n );\n};\n"],
5
- "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,iBAAiB,SAAS,QAAQ,UAAU,mBAAmB;AACxE,SAAS,gBAAgB;AAEzB,SAAS,uBAAuB;AAiBzB,MAAM,4BAA4B,CAAC,WAAuC;AAC/E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB,aAAa;AAAA,EACf,IAAI;AAEJ,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AAGtG,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,EACd,CAAC;AAED,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAE5D,QAAM,aAAa,cAAc,QAAQ,aAAa,QAAQ,CAAC;AAE/D,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,WAAY;AAEjB,UAAM,EAAE,aAAa,gBAAgB,YAAY,IAAI,gBAAgB;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,sBAAkB,CAAC,UAAU;AAAA,MAC3B,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE;AACF,mBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAChE,uBAAmB,IAAI;AAAA,EACzB,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAGtG,QAAM,sBAAsB,OAAO,YAAY;AAC/C,sBAAoB,UAAU;AAE9B,QAAM,wBAAwB,QAAQ,MAAM;AAC1C,UAAM,IAAI,SAAS,MAAM;AACvB,0BAAoB,QAAQ;AAAA,IAC9B,GAAG,UAAU;AACb,WAAO;AAAA,EAET,GAAG,CAAC,UAAU,CAAC;AAGf;AAAA,IACE,MAAM,MAAM;AACV,4BAAsB,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,qBAAqB;AAAA,EACxB;AAGA,kBAAgB,MAAM;AACpB,QAAI,YAAY;AACd,0BAAoB,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAEtG,QAAM,sBAAsB,YAAY,MAAM;AAC5C,wBAAoB,QAAQ;AAAA,EAC9B,GAAG,CAAC,CAAC;AAGL,QAAM,sBAAsB,YAAY,MAAM;AAC5C,sBAAkB,CAAC,UAAU;AAAA,MAC3B,GAAG;AAAA,MACH,YAAY;AAAA,IACd,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,aAAa,gBAAgB,iBAAiB,qBAAqB,uBAAuB,mBAAmB;AAAA,EAChH;AACF;",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable max-statements */\nimport { useLayoutEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport { debounce } from 'lodash-es';\nimport { type CSSProperties } from 'styled-components';\nimport { computePosition } from './utils/computePosition.js';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport type { PopoverArrowT } from './parts/PopoverArrow.js';\n\ntype UseComputedPositionStylesT = {\n /** Prevent computing when closed (optimization + avoids unnecessary frames) */\n preventComputing?: boolean;\n reference: Element | null;\n floating: HTMLElement | null;\n placement: DSHookFloatingContextT.PopperPlacementsT;\n placementOrderPreference?: DSHookFloatingContextT.PopperPlacementsT[];\n customOffset: [number, number];\n withoutPortal: boolean;\n /** Debounce ms for scroll/resize/observer events */\n debounceMs?: number;\n};\n\nexport const useComputedPositionStyles = (config: UseComputedPositionStylesT) => {\n const {\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n preventComputing = false,\n debounceMs = 150,\n } = config;\n\n const [arrowStyles, setArrowStyles] = useState<PopoverArrowT>({ style: { left: 0 }, placement: 'top' });\n\n // Initial state: invisible (opacity:0) but FOCUSABLE.\n // We intentionally use opacity instead of visibility:hidden \u2014 `visibility:hidden` blocks\n // programmatic focus on descendants (including React's `autoFocus` attribute on inputs),\n // which causes a race on first-open: the floating content's autoFocus fires before the\n // position-computation useLayoutEffect can flip visibility to `visible`, so the focus\n // silently no-ops. Opacity:0 keeps the element invisible while letting `.focus()` work.\n // pointer-events:none prevents accidental clicks on the still-unpositioned (0,0) area.\n const [floatingStyles, setFloatingStyles] = useState<CSSProperties>({\n position: 'absolute',\n zIndex: 3000,\n opacity: 0,\n pointerEvents: 'none',\n willChange: 'transform',\n });\n\n const [hasComputedOnce, setHasComputedOnce] = useState(false);\n\n const canCompute = reference !== null && floating !== null && !preventComputing;\n\n const updateStyles = useCallback(() => {\n if (!canCompute) return;\n\n const { coordsStyle, finalPlacement, coordsArrow } = computePosition({\n reference,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n });\n\n // Do not touch visibility here; it is managed outside depending on open/hasComputedOnce\n setFloatingStyles((prev) => ({\n position: 'absolute',\n zIndex: 3000,\n ...prev,\n ...coordsStyle,\n }));\n setArrowStyles({ style: coordsArrow, placement: finalPlacement });\n setHasComputedOnce(true);\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n // Store latest update function in a ref to keep debounced stable\n const mutableUpdateStyles = useRef(updateStyles);\n mutableUpdateStyles.current = updateStyles;\n\n const debouncedUpdateStyles = useMemo(() => {\n const d = debounce(() => {\n mutableUpdateStyles.current();\n }, debounceMs);\n return d;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debounceMs]);\n\n // Clean up debounce on unmount\n useLayoutEffect(\n () => () => {\n debouncedUpdateStyles.cancel();\n },\n [debouncedUpdateStyles],\n );\n\n // Recalculate BEFORE paint when dependencies change\n useLayoutEffect(() => {\n if (canCompute) {\n mutableUpdateStyles.current();\n }\n }, [canCompute, reference, floating, placement, placementOrderPreference, customOffset, withoutPortal]);\n\n const forceUpdatePosition = useCallback(() => {\n mutableUpdateStyles.current();\n }, []);\n\n // Do not reset coordinates when closing; just hide via opacity (keeps element focusable\n // if anything inside needs to remain focusable during animations).\n const resetVisibilityOnly = useCallback(() => {\n setFloatingStyles((prev) => ({\n ...prev,\n opacity: 0,\n pointerEvents: 'none',\n }));\n }, []);\n\n return useMemo(\n () => ({\n arrowStyles,\n floatingStyles,\n hasComputedOnce,\n updateStyles: forceUpdatePosition,\n debouncedUpdateStyles,\n mutableUpdateStyles,\n resetVisibilityOnly,\n }),\n [arrowStyles, floatingStyles, hasComputedOnce, forceUpdatePosition, debouncedUpdateStyles, resetVisibilityOnly],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,iBAAiB,SAAS,QAAQ,UAAU,mBAAmB;AACxE,SAAS,gBAAgB;AAEzB,SAAS,uBAAuB;AAiBzB,MAAM,4BAA4B,CAAC,WAAuC;AAC/E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB,aAAa;AAAA,EACf,IAAI;AAEJ,QAAM,CAAC,aAAa,cAAc,IAAI,SAAwB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,MAAM,CAAC;AAStG,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB;AAAA,IAClE,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,EACd,CAAC;AAED,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAE5D,QAAM,aAAa,cAAc,QAAQ,aAAa,QAAQ,CAAC;AAE/D,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,WAAY;AAEjB,UAAM,EAAE,aAAa,gBAAgB,YAAY,IAAI,gBAAgB;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,sBAAkB,CAAC,UAAU;AAAA,MAC3B,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE;AACF,mBAAe,EAAE,OAAO,aAAa,WAAW,eAAe,CAAC;AAChE,uBAAmB,IAAI;AAAA,EACzB,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAGtG,QAAM,sBAAsB,OAAO,YAAY;AAC/C,sBAAoB,UAAU;AAE9B,QAAM,wBAAwB,QAAQ,MAAM;AAC1C,UAAM,IAAI,SAAS,MAAM;AACvB,0BAAoB,QAAQ;AAAA,IAC9B,GAAG,UAAU;AACb,WAAO;AAAA,EAET,GAAG,CAAC,UAAU,CAAC;AAGf;AAAA,IACE,MAAM,MAAM;AACV,4BAAsB,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,qBAAqB;AAAA,EACxB;AAGA,kBAAgB,MAAM;AACpB,QAAI,YAAY;AACd,0BAAoB,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,YAAY,WAAW,UAAU,WAAW,0BAA0B,cAAc,aAAa,CAAC;AAEtG,QAAM,sBAAsB,YAAY,MAAM;AAC5C,wBAAoB,QAAQ;AAAA,EAC9B,GAAG,CAAC,CAAC;AAIL,QAAM,sBAAsB,YAAY,MAAM;AAC5C,sBAAkB,CAAC,UAAU;AAAA,MAC3B,GAAG;AAAA,MACH,SAAS;AAAA,MACT,eAAe;AAAA,IACjB,EAAE;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,aAAa,gBAAgB,iBAAiB,qBAAqB,uBAAuB,mBAAmB;AAAA,EAChH;AACF;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@ import type { DSHookFloatingContextT } from './react-desc-prop-types.js';
3
3
  declare const useFloatingContext: {
4
4
  (props?: DSHookFloatingContextT.Props): {
5
5
  refs: {
6
- setReference: React.Dispatch<React.SetStateAction<Element | null>>;
6
+ setReference: (el: Element | null) => void;
7
7
  setFloating: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
8
8
  floating: HTMLElement | null;
9
9
  reference: Element | null;
@@ -0,0 +1,20 @@
1
+ import { type MutableRefObject } from 'react';
2
+ interface UseFloatingClickOutsideParams {
3
+ enabled: boolean;
4
+ floating: HTMLElement | null;
5
+ reference: Element | null;
6
+ /**
7
+ * Latest-ref of the click-outside callback. Passed as a ref (rather than a value)
8
+ * so consumers can pass inline functions without re-attaching listeners on every render.
9
+ * Use `useLatestRef(onClickOutside)` to construct it.
10
+ */
11
+ callbackRef: MutableRefObject<((event: MouseEvent | TouchEvent) => void) | undefined>;
12
+ }
13
+ /**
14
+ * Attaches mousedown/touchstart listeners on the document that fire when the click target
15
+ * is outside BOTH the floating element and the reference element.
16
+ *
17
+ * Only active when `enabled === true` and both elements exist.
18
+ */
19
+ export declare const useFloatingClickOutside: ({ enabled, floating, reference, callbackRef, }: UseFloatingClickOutsideParams) => void;
20
+ export {};
@@ -0,0 +1,19 @@
1
+ import { type MutableRefObject } from 'react';
2
+ interface UseFloatingEscapeParams {
3
+ enabled: boolean;
4
+ floating: HTMLElement | null;
5
+ reference: Element | null;
6
+ /** Latest-ref of the consumer's onEscape callback. Construct with `useLatestRef(onEscape)`. */
7
+ onEscapeRef: MutableRefObject<((event: KeyboardEvent) => void) | undefined>;
8
+ /** Fallback close handler invoked when no `onEscape` is provided. */
9
+ handleClose: () => void;
10
+ /** When true, calls `reference.focus()` after the escape close. */
11
+ returnFocusToReference: boolean;
12
+ }
13
+ /**
14
+ * Listens for `Escape` on the document and dismisses the floating element when focus is
15
+ * within the floating element or on the reference element. Outside that scope the event is
16
+ * ignored — we don't hijack Escape for unrelated UI on the page.
17
+ */
18
+ export declare const useFloatingEscape: ({ enabled, floating, reference, onEscapeRef, handleClose, returnFocusToReference, }: UseFloatingEscapeParams) => void;
19
+ export {};
@@ -0,0 +1,11 @@
1
+ interface UseFloatingResizeObserverParams {
2
+ enabled: boolean;
3
+ floating: HTMLElement | null;
4
+ onResize: () => void;
5
+ }
6
+ /**
7
+ * Observes the floating element's size and calls `onResize` when its bounding box changes.
8
+ * Used to re-run position computation when the floating content reflows (e.g. async-loaded data).
9
+ */
10
+ export declare const useFloatingResizeObserver: ({ enabled, floating, onResize }: UseFloatingResizeObserverParams) => void;
11
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Latest-ref pattern: keeps the value in a ref that's updated on every render.
3
+ * Use this when an effect/listener needs to read the latest value of a prop or callback
4
+ * without including it in the effect's dependency array — avoids re-attaching listeners
5
+ * (and infinite loops via deep-equal comparators) when consumers pass inline callbacks.
6
+ */
7
+ export declare const useLatestRef: <T>(value: T) => import("react").MutableRefObject<T>;
@@ -0,0 +1,19 @@
1
+ interface UseResolvedReferenceParams {
2
+ externalReferenceElement: Element | null | undefined;
3
+ internalReferenceElement: Element | null;
4
+ setInternalReferenceElement: (el: Element | null) => void;
5
+ }
6
+ /**
7
+ * Resolves the active reference element for the floating context.
8
+ *
9
+ * - When `externalReferenceElement` is provided (anything other than `undefined`, including `null`),
10
+ * it is used as the source of truth. `setReference` becomes a no-op so consumers that mistakenly
11
+ * call `refs.setReference()` don't desynchronize the two sources.
12
+ * - Otherwise the internally-managed state is used, populated by the consumer via `refs.setReference()`
13
+ * (typically as a callback ref: `innerRef={refs.setReference}`).
14
+ */
15
+ export declare const useResolvedReference: ({ externalReferenceElement, internalReferenceElement, setInternalReferenceElement, }: UseResolvedReferenceParams) => {
16
+ referenceElement: Element | null;
17
+ setReferenceElement: (el: Element | null) => void;
18
+ };
19
+ export {};
@@ -7,12 +7,31 @@ export declare namespace DSHookFloatingContextT {
7
7
  animationDuration: number;
8
8
  placement: PopperPlacementsT;
9
9
  customOffset: [number, number];
10
+ closeOnEscape: boolean;
11
+ returnFocusToReference: boolean;
10
12
  }
11
13
  interface OptionalProps {
12
14
  placementOrderPreference?: PopperPlacementsT[];
13
15
  onOpen?: () => void;
14
16
  onClose?: () => void;
15
17
  externallyControlledIsOpen?: boolean;
18
+ /**
19
+ * Pre-resolved reference element. When provided, the hook uses this as the
20
+ * source of truth for positioning and ignores its internal reference state.
21
+ * Eliminates the need for a follow-up `refs.setReference(...)` effect and
22
+ * removes the visibility:hidden race that breaks programmatic focus on open.
23
+ */
24
+ externalReferenceElement?: Element | null;
25
+ /**
26
+ * Called when the user clicks/taps outside both the floating element and
27
+ * the reference element while the floating is open.
28
+ */
29
+ onClickOutside?: (event: MouseEvent | TouchEvent) => void;
30
+ /**
31
+ * Called when Escape is pressed while focus is within the floating element.
32
+ * Only fires when `closeOnEscape` is true.
33
+ */
34
+ onEscape?: (event: KeyboardEvent) => void;
16
35
  }
17
36
  interface Props extends Partial<DefaultProps>, OptionalProps {
18
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-floating-context",
3
- "version": "3.70.0-next.7",
3
+ "version": "3.70.0-next.9",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Popper Hook",
6
6
  "files": [
@@ -36,14 +36,14 @@
36
36
  "indent": 4
37
37
  },
38
38
  "dependencies": {
39
- "@elliemae/ds-hooks-headless-tooltip": "3.70.0-next.7",
40
- "@elliemae/ds-props-helpers": "3.70.0-next.7",
41
- "@elliemae/ds-system": "3.70.0-next.7",
42
- "@elliemae/ds-typescript-helpers": "3.70.0-next.7"
39
+ "@elliemae/ds-hooks-headless-tooltip": "3.70.0-next.9",
40
+ "@elliemae/ds-system": "3.70.0-next.9",
41
+ "@elliemae/ds-props-helpers": "3.70.0-next.9",
42
+ "@elliemae/ds-typescript-helpers": "3.70.0-next.9"
43
43
  },
44
44
  "devDependencies": {
45
45
  "jest": "^30.0.0",
46
- "@elliemae/ds-monorepo-devops": "3.70.0-next.7"
46
+ "@elliemae/ds-monorepo-devops": "3.70.0-next.9"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "lodash-es": "^4.17.21",