@elliemae/ds-floating-context 3.70.0-next.53 → 3.70.0-next.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/DSFloatingContext.js +83 -33
- package/dist/cjs/DSFloatingContext.js.map +2 -2
- package/dist/cjs/hooks/useFloatingClickOutside.js +8 -8
- package/dist/cjs/hooks/useFloatingClickOutside.js.map +2 -2
- package/dist/cjs/hooks/useFloatingResizeObserver.js +8 -4
- package/dist/cjs/hooks/useFloatingResizeObserver.js.map +2 -2
- package/dist/cjs/hooks/useResolvedReference.js +2 -2
- package/dist/cjs/hooks/useResolvedReference.js.map +2 -2
- package/dist/cjs/hooks/{useFloatingEscape.js → useSyntheticEventFromControlledState.js} +19 -40
- package/dist/cjs/hooks/useSyntheticEventFromControlledState.js.map +7 -0
- package/dist/cjs/parts/FloatingWrapper/react-desc-prop-types.js +1 -1
- package/dist/cjs/parts/FloatingWrapper/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/parts/PopoverArrow.js.map +2 -2
- package/dist/cjs/react-desc-prop-types.js +8 -4
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/useComputedPositionStyles.js +24 -8
- package/dist/cjs/useComputedPositionStyles.js.map +2 -2
- package/dist/cjs/utils/computePosition.js +14 -7
- package/dist/cjs/utils/computePosition.js.map +2 -2
- package/dist/esm/DSFloatingContext.js +84 -34
- package/dist/esm/DSFloatingContext.js.map +2 -2
- package/dist/esm/hooks/useFloatingClickOutside.js +8 -8
- package/dist/esm/hooks/useFloatingClickOutside.js.map +2 -2
- package/dist/esm/hooks/useFloatingResizeObserver.js +8 -4
- package/dist/esm/hooks/useFloatingResizeObserver.js.map +2 -2
- package/dist/esm/hooks/useResolvedReference.js +2 -2
- package/dist/esm/hooks/useResolvedReference.js.map +2 -2
- package/dist/esm/hooks/useSyntheticEventFromControlledState.js +23 -0
- package/dist/esm/hooks/useSyntheticEventFromControlledState.js.map +7 -0
- package/dist/esm/parts/FloatingWrapper/react-desc-prop-types.js +1 -1
- package/dist/esm/parts/FloatingWrapper/react-desc-prop-types.js.map +2 -2
- package/dist/esm/parts/PopoverArrow.js.map +2 -2
- package/dist/esm/react-desc-prop-types.js +8 -4
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/esm/useComputedPositionStyles.js +24 -8
- package/dist/esm/useComputedPositionStyles.js.map +2 -2
- package/dist/esm/utils/computePosition.js +14 -7
- package/dist/esm/utils/computePosition.js.map +2 -2
- package/dist/types/DSFloatingContext.d.ts +46 -6
- package/dist/types/hooks/useFloatingClickOutside.d.ts +5 -5
- package/dist/types/hooks/useFloatingResizeObserver.d.ts +3 -3
- package/dist/types/hooks/useResolvedReference.d.ts +1 -1
- package/dist/types/hooks/useSyntheticEventFromControlledState.d.ts +32 -0
- package/dist/types/react-desc-prop-types.d.ts +39 -4
- package/dist/types/useComputedPositionStyles.d.ts +3 -3
- package/dist/types/utils/computePosition.d.ts +2 -2
- package/package.json +6 -6
- package/dist/cjs/hooks/useFloatingEscape.js.map +0 -7
- package/dist/esm/hooks/useFloatingEscape.js +0 -44
- package/dist/esm/hooks/useFloatingEscape.js.map +0 -7
- package/dist/types/hooks/useFloatingEscape.d.ts +0 -19
|
@@ -42,8 +42,9 @@ var import_positionObserver = require("./utils/positionObserver.js");
|
|
|
42
42
|
var import_useLatestRef = require("./hooks/useLatestRef.js");
|
|
43
43
|
var import_useResolvedReference = require("./hooks/useResolvedReference.js");
|
|
44
44
|
var import_useFloatingClickOutside = require("./hooks/useFloatingClickOutside.js");
|
|
45
|
-
var import_useFloatingEscape = require("./hooks/useFloatingEscape.js");
|
|
46
45
|
var import_useFloatingResizeObserver = require("./hooks/useFloatingResizeObserver.js");
|
|
46
|
+
var import_useSyntheticEventFromControlledState = require("./hooks/useSyntheticEventFromControlledState.js");
|
|
47
|
+
const isKeyboardEvent = (event) => !!event?.key;
|
|
47
48
|
const useFloatingContext = (props = {}) => {
|
|
48
49
|
const { onClickOutside, onEscape, onOpen, onClose, externalReferenceElement, ...stableProps } = props;
|
|
49
50
|
const propsWithDefault = (0, import_ds_props_helpers.useMemoMergePropsWithDefault)(
|
|
@@ -63,6 +64,9 @@ const useFloatingContext = (props = {}) => {
|
|
|
63
64
|
closeOnEscape,
|
|
64
65
|
returnFocusToReference
|
|
65
66
|
} = propsWithDefault;
|
|
67
|
+
const isControlled = externallyControlledIsOpen !== void 0;
|
|
68
|
+
const [floatingWrapperNode, setFloatingWrapperNode] = import_react.default.useState(null);
|
|
69
|
+
const triggerElementReferenceRef = import_react.default.useRef(null);
|
|
66
70
|
const onClickOutsideRef = (0, import_useLatestRef.useLatestRef)(onClickOutside);
|
|
67
71
|
const onEscapeRef = (0, import_useLatestRef.useLatestRef)(onEscape);
|
|
68
72
|
const onOpenRef = (0, import_useLatestRef.useLatestRef)(onOpen);
|
|
@@ -72,60 +76,106 @@ const useFloatingContext = (props = {}) => {
|
|
|
72
76
|
() => externallyControlledIsOpen !== void 0 ? externallyControlledIsOpen : internalIsOpen,
|
|
73
77
|
[externallyControlledIsOpen, internalIsOpen]
|
|
74
78
|
);
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const isControlledRef = (0, import_useLatestRef.useLatestRef)(isControlled);
|
|
80
|
+
const closeOnEscapeRef = (0, import_useLatestRef.useLatestRef)(closeOnEscape);
|
|
81
|
+
const returnFocusToReferenceRef = (0, import_useLatestRef.useLatestRef)(returnFocusToReference);
|
|
82
|
+
const floatingWrapperNodeRef = (0, import_useLatestRef.useLatestRef)(floatingWrapperNode);
|
|
83
|
+
const isOpenRef = (0, import_useLatestRef.useLatestRef)(isOpen);
|
|
84
|
+
const handleOpen = import_react.default.useCallback(
|
|
85
|
+
(event) => {
|
|
86
|
+
setInternalIsOpen(true);
|
|
87
|
+
onOpenRef.current?.({ reason: "interaction", event, isControlled: isControlledRef.current });
|
|
88
|
+
},
|
|
89
|
+
[onOpenRef, isControlledRef]
|
|
90
|
+
);
|
|
91
|
+
const isFocusWithinFloatingScope = (0, import_react.useCallback)(() => {
|
|
92
|
+
const active = document.activeElement;
|
|
93
|
+
if (!active) return false;
|
|
94
|
+
if (floatingWrapperNodeRef.current?.contains(active)) return true;
|
|
95
|
+
const reference = triggerElementReferenceRef.current;
|
|
96
|
+
return reference === active || !!reference?.contains(active);
|
|
97
|
+
}, [floatingWrapperNodeRef]);
|
|
98
|
+
const handleClose = import_react.default.useCallback(
|
|
99
|
+
(event) => {
|
|
100
|
+
const wasOpen = isOpenRef.current;
|
|
101
|
+
setInternalIsOpen(false);
|
|
102
|
+
const isScopedEscapeClose = wasOpen && closeOnEscapeRef.current && isKeyboardEvent(event) && event.key === "Escape" && isFocusWithinFloatingScope();
|
|
103
|
+
if (isScopedEscapeClose) {
|
|
104
|
+
onEscapeRef.current?.(event);
|
|
105
|
+
if (returnFocusToReferenceRef.current && triggerElementReferenceRef.current instanceof HTMLElement) {
|
|
106
|
+
triggerElementReferenceRef.current.focus();
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
onCloseRef.current?.({ reason: "interaction", event, isControlled: isControlledRef.current });
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
[
|
|
113
|
+
isOpenRef,
|
|
114
|
+
closeOnEscapeRef,
|
|
115
|
+
isFocusWithinFloatingScope,
|
|
116
|
+
returnFocusToReferenceRef,
|
|
117
|
+
onCloseRef,
|
|
118
|
+
onEscapeRef,
|
|
119
|
+
isControlledRef
|
|
120
|
+
]
|
|
121
|
+
);
|
|
122
|
+
const shouldFocusReferenceOnEscape = (0, import_react.useCallback)(
|
|
123
|
+
() => closeOnEscapeRef.current && returnFocusToReferenceRef.current && isFocusWithinFloatingScope(),
|
|
124
|
+
[closeOnEscapeRef, returnFocusToReferenceRef, isFocusWithinFloatingScope]
|
|
125
|
+
);
|
|
126
|
+
const tooltipHelpersConfig = (0, import_react.useMemo)(
|
|
127
|
+
() => ({ onOpen: handleOpen, onClose: handleClose, focusReferenceOnEscape: shouldFocusReferenceOnEscape }),
|
|
128
|
+
[handleOpen, handleClose, shouldFocusReferenceOnEscape]
|
|
129
|
+
);
|
|
130
|
+
const tooltipHelpers = (0, import_ds_hooks_headless_tooltip.useHeadlessTooltip)(tooltipHelpersConfig);
|
|
84
131
|
const {
|
|
85
132
|
setReferenceElement: setInternalReferenceElement,
|
|
86
133
|
referenceElement: internalReferenceElement,
|
|
87
134
|
hideTooltip,
|
|
88
135
|
showTooltip
|
|
89
136
|
} = tooltipHelpers;
|
|
90
|
-
const {
|
|
137
|
+
const { triggerElementReference, setReferenceElement } = (0, import_useResolvedReference.useResolvedReference)({
|
|
91
138
|
externalReferenceElement,
|
|
92
139
|
internalReferenceElement,
|
|
93
140
|
setInternalReferenceElement
|
|
94
141
|
});
|
|
95
|
-
|
|
142
|
+
triggerElementReferenceRef.current = triggerElementReference;
|
|
96
143
|
const { arrowStyles, floatingStyles, hasComputedOnce, updateStyles, debouncedUpdateStyles, mutableUpdateStyles } = (0, import_useComputedPositionStyles.useComputedPositionStyles)({
|
|
97
|
-
|
|
98
|
-
|
|
144
|
+
triggerElementReference,
|
|
145
|
+
floatingWrapperNode,
|
|
99
146
|
placement,
|
|
100
147
|
placementOrderPreference,
|
|
101
148
|
customOffset,
|
|
102
149
|
withoutPortal,
|
|
103
|
-
|
|
150
|
+
isClose: !isOpen,
|
|
104
151
|
debounceMs: 150
|
|
105
152
|
});
|
|
106
153
|
const floatingResizeOberverConfig = (0, import_react.useMemo)(
|
|
107
|
-
() => ({
|
|
108
|
-
[isOpen,
|
|
154
|
+
() => ({ isOpen, floatingWrapperNode, onResize: () => mutableUpdateStyles.current() }),
|
|
155
|
+
[isOpen, floatingWrapperNode, mutableUpdateStyles]
|
|
109
156
|
);
|
|
110
157
|
(0, import_useFloatingResizeObserver.useFloatingResizeObserver)(floatingResizeOberverConfig);
|
|
111
158
|
const onObservedMovement = import_react.default.useCallback(() => {
|
|
112
159
|
if (!isOpen) return;
|
|
113
160
|
debouncedUpdateStyles();
|
|
114
161
|
}, [isOpen, debouncedUpdateStyles]);
|
|
115
|
-
(0, import_positionObserver.usePositionObserver)(
|
|
162
|
+
(0, import_positionObserver.usePositionObserver)(triggerElementReference, onObservedMovement);
|
|
116
163
|
(0, import_useFloatingClickOutside.useFloatingClickOutside)({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
164
|
+
isOpen,
|
|
165
|
+
floatingWrapperNode,
|
|
166
|
+
triggerElementReference,
|
|
167
|
+
onClickOutsideRef
|
|
121
168
|
});
|
|
122
|
-
(0,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
169
|
+
const handleControlledOpen = (0, import_react.useCallback)(() => {
|
|
170
|
+
onOpenRef.current?.({ reason: "controlled-flip", isControlled: true });
|
|
171
|
+
}, [onOpenRef]);
|
|
172
|
+
const handleControlledClose = (0, import_react.useCallback)(() => {
|
|
173
|
+
onCloseRef.current?.({ reason: "controlled-flip", isControlled: true });
|
|
174
|
+
}, [onCloseRef]);
|
|
175
|
+
(0, import_useSyntheticEventFromControlledState.useSyntheticEventFromControlledState)({
|
|
176
|
+
controlledValue: externallyControlledIsOpen,
|
|
177
|
+
onEnter: handleControlledOpen,
|
|
178
|
+
onExit: handleControlledClose
|
|
129
179
|
});
|
|
130
180
|
const computedFloatingStyles = (0, import_react.useMemo)(() => {
|
|
131
181
|
const isInteractive = isOpen && hasComputedOnce;
|
|
@@ -138,11 +188,11 @@ const useFloatingContext = (props = {}) => {
|
|
|
138
188
|
const refs = (0, import_react.useMemo)(
|
|
139
189
|
() => ({
|
|
140
190
|
setReference: setReferenceElement,
|
|
141
|
-
setFloating,
|
|
142
|
-
floating,
|
|
143
|
-
reference:
|
|
191
|
+
setFloating: setFloatingWrapperNode,
|
|
192
|
+
floating: floatingWrapperNode,
|
|
193
|
+
reference: triggerElementReference
|
|
144
194
|
}),
|
|
145
|
-
[setReferenceElement,
|
|
195
|
+
[setReferenceElement, floatingWrapperNode, triggerElementReference]
|
|
146
196
|
);
|
|
147
197
|
const handlers = (0, import_react.useMemo)(
|
|
148
198
|
() => ({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/DSFloatingContext.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable max-statements */\nimport React, { useMemo } from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip } from '@elliemae/ds-hooks-headless-tooltip';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\nimport { useComputedPositionStyles } from './useComputedPositionStyles.js';\nimport { usePositionObserver } from './utils/positionObserver.js';\nimport { useLatestRef } from './hooks/useLatestRef.js';\nimport { useResolvedReference } from './hooks/useResolvedReference.js';\nimport { useFloatingClickOutside } from './hooks/useFloatingClickOutside.js';\nimport { useFloatingEscape } from './hooks/useFloatingEscape.js';\nimport { useFloatingResizeObserver } from './hooks/useFloatingResizeObserver.js';\n\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n // Extract unstable callback refs BEFORE useMemoMergePropsWithDefault.\n // useMemoMergePropsWithDefault compares with fast-deep-equal which compares functions by\n // reference; an inline callback from the consumer would invalidate propsWithDefault on every\n // render, which in turn would invalidate the destructured `customOffset` array and re-trigger\n // the position-computation useLayoutEffect on every render \u2192 infinite loop.\n const { onClickOutside, onEscape, onOpen, onClose, externalReferenceElement, ...stableProps } = props;\n\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(\n stableProps,\n defaultProps,\n );\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n externallyControlledIsOpen,\n closeOnEscape,\n returnFocusToReference,\n } = propsWithDefault;\n\n // Latest-refs for consumer callbacks (see useLatestRef docs).\n const onClickOutsideRef = useLatestRef(onClickOutside);\n const onEscapeRef = useLatestRef(onEscape);\n const onOpenRef = useLatestRef(onOpen);\n const onCloseRef = useLatestRef(onClose);\n\n // Open/close state \u2014 externally controlled when `externallyControlledIsOpen` is provided.\n const [internalIsOpen, setInternalIsOpen] = React.useState(false);\n const isOpen = useMemo(\n () => (externallyControlledIsOpen !== undefined ? externallyControlledIsOpen : internalIsOpen),\n [externallyControlledIsOpen, internalIsOpen],\n );\n\n const handleOpen = React.useCallback(() => {\n setInternalIsOpen(true);\n onOpenRef.current?.();\n }, [onOpenRef]);\n\n const handleClose = React.useCallback(() => {\n setInternalIsOpen(false);\n onCloseRef.current?.();\n }, [onCloseRef]);\n\n // Headless tooltip exposes show/hide helpers + manages its own internal state.\n const tooltipHelpers = useHeadlessTooltip({ onOpen: handleOpen, onClose: handleClose });\n const {\n setReferenceElement: setInternalReferenceElement,\n referenceElement: internalReferenceElement,\n hideTooltip,\n showTooltip,\n } = tooltipHelpers;\n\n // Reference element resolution: external takes precedence over internal.\n const { referenceElement, setReferenceElement } = useResolvedReference({\n externalReferenceElement,\n internalReferenceElement,\n setInternalReferenceElement,\n });\n\n // Anchor and floating refs\n const [floating, setFloating] = React.useState<HTMLElement | null>(null);\n\n // Compute position (skip when closed)\n const { arrowStyles, floatingStyles, hasComputedOnce, updateStyles, debouncedUpdateStyles, mutableUpdateStyles } =\n useComputedPositionStyles({\n reference: referenceElement,\n floating,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n preventComputing: !isOpen,\n debounceMs: 150,\n });\n\n const floatingResizeOberverConfig = useMemo(\n () => ({ enabled: isOpen, floating, onResize: () => mutableUpdateStyles.current() }),\n [isOpen, floating, mutableUpdateStyles],\n );\n\n // Re-compute position when the floating element's size changes (e.g. async content).\n useFloatingResizeObserver(floatingResizeOberverConfig);\n\n // Re-compute position when the reference element moves in the viewport.\n const onObservedMovement = React.useCallback(() => {\n if (!isOpen) return;\n debouncedUpdateStyles();\n }, [isOpen, debouncedUpdateStyles]);\n usePositionObserver(referenceElement, onObservedMovement);\n\n // Click-outside dismissal (opt-in via `onClickOutside`).\n useFloatingClickOutside({\n enabled: isOpen,\n floating,\n reference: referenceElement,\n callbackRef: onClickOutsideRef,\n });\n\n // Escape dismissal (opt-in via `closeOnEscape`).\n useFloatingEscape({\n enabled: isOpen && closeOnEscape,\n floating,\n reference: referenceElement,\n onEscapeRef,\n handleClose,\n returnFocusToReference,\n });\n\n // Expose visibility via opacity (NOT visibility:hidden \u2014 that blocks programmatic focus,\n // breaking autoFocus on first-open before the position-computation effect can run).\n // When `externalReferenceElement` is provided, computation runs on the first useLayoutEffect\n // (reference is known synchronously), so the popper becomes interactive in the same commit.\n const computedFloatingStyles = useMemo<React.CSSProperties>(() => {\n const isInteractive = isOpen && hasComputedOnce;\n return {\n ...floatingStyles,\n opacity: isInteractive ? 1 : 0,\n pointerEvents: isInteractive ? 'auto' : 'none',\n };\n }, [floatingStyles, hasComputedOnce, isOpen]);\n\n const refs = useMemo(\n () => ({\n setReference: setReferenceElement,\n setFloating,\n floating,\n reference: referenceElement,\n }),\n [setReferenceElement, floating, referenceElement],\n );\n\n const handlers = useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles: computedFloatingStyles,\n handlers,\n isOpen,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n mutableUpdateStyles,\n forceUpdatePosition: updateStyles,\n }),\n [\n refs,\n computedFloatingStyles,\n handlers,\n isOpen,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n mutableUpdateStyles,\n updateStyles,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
4
|
+
"sourcesContent": ["/* eslint-disable max-lines */\n/* eslint-disable max-statements */\nimport React, { useCallback, useMemo } from 'react';\nimport {\n useMemoMergePropsWithDefault,\n useValidateTypescriptPropTypes,\n describe,\n type ValidationMap,\n} from '@elliemae/ds-props-helpers';\nimport { useHeadlessTooltip, type UseHeadlessTooltipConfig } from '@elliemae/ds-hooks-headless-tooltip';\nimport type { DSHookFloatingContextT } from './react-desc-prop-types.js';\nimport { defaultProps, DSFloatingContextPropTypes } from './react-desc-prop-types.js';\nimport { useComputedPositionStyles } from './useComputedPositionStyles.js';\nimport { usePositionObserver } from './utils/positionObserver.js';\nimport { useLatestRef } from './hooks/useLatestRef.js';\nimport { useResolvedReference } from './hooks/useResolvedReference.js';\nimport { useFloatingClickOutside } from './hooks/useFloatingClickOutside.js';\nimport { useFloatingResizeObserver } from './hooks/useFloatingResizeObserver.js';\nimport { useSyntheticEventFromControlledState } from './hooks/useSyntheticEventFromControlledState.js';\n\nconst isKeyboardEvent = (\n event: React.FocusEvent | React.MouseEvent | KeyboardEvent | undefined,\n): event is KeyboardEvent => !!(event as KeyboardEvent)?.key;\n\n/**\n * useFloatingContext \u2014 headless positioning + open/close lifecycle for a floating surface\n * (popover / tooltip / dialog-like panel). Returns positioning styles + refs, imperative show/hide\n * helpers, interaction handlers to spread on a trigger, and a discriminated open/close notification.\n *\n * COUPLING: this hook is the shared substrate under ds-app-picker, ds-tooltip and others; its\n * open/close/escape/reason contract is relied on across packages. The consumer that leans hardest on\n * the exact semantics below is ds-app-picker\n * (layout/ds-app-picker/src/parts/AppPickerFloatingContext/useAppPickerFloatingContext.ts). Treat\n * changes to these semantics as cross-package.\n *\n * OPEN STATE \u2014 controlled vs uncontrolled\n * - Uncontrolled: `externallyControlledIsOpen` undefined \u2192 open state lives here (in the underlying\n * ds-hooks-headless-tooltip) and is driven by the focus/hover handlers + the show/hide helpers.\n * - Controlled: `externallyControlledIsOpen` is a boolean \u2192 the consumer owns visibility and the\n * internal open state is inert. `isControlled` is surfaced on every OpenChange payload.\n *\n * NOTIFICATION \u2014 one onOpen/onClose pair, two reasons (see OpenChange in react-desc-prop-types)\n * - 'interaction': fired synchronously in the event catch phase by this hook's own interaction\n * handling \u2014 focus/hover/blur/mouseleave, an imperative show/hide, or a NON-scoped Escape falling\n * through to onClose \u2014 carrying the DOM event when there is one. Fires for controlled contexts too\n * (the pre-flip signal a controlled consumer may act on).\n * - 'controlled-flip': fired from a post-commit effect (useSyntheticEventFromControlledState) when\n * `externallyControlledIsOpen` transitions. No event. NEVER fires on mount \u2014 a surface rendered\n * already-open gets no onOpen and must seed any initial focus itself.\n *\n * ESCAPE \u2014 one listener, not two\n * Escape dismissal rides ds-hooks-headless-tooltip's single always-on document keydown listener (it\n * calls hideTooltip on ANY Escape, even when this context never opened). handleClose is the one place\n * that interprets it:\n * - SCOPED Escape (was open + closeOnEscape + key 'Escape' + focus within the panel/reference)\n * \u2192 routes to `onEscape` (NOT onClose); if returnFocusToReference, focuses the reference.\n * - anything else, including a non-scoped Escape \u2192 `onClose` with reason 'interaction'.\n * returnFocusToReference is a SCOPED-ESCAPE-ONLY affordance; no other close path moves focus.\n *\n * FRAGILITY: closeOnEscape is honored independently of who owns open state. A CONTROLLED consumer that\n * leaves closeOnEscape on but does not itself close on Escape will have focus returned to the reference\n * on a scoped Escape while the consumer-owned open state has not changed \u2014 focus can leave a panel that\n * stays open. Controlled consumers should own Escape (ds-app-picker uses `closeOnEscape: !onKeyDown`).\n */\nconst useFloatingContext = (props: DSHookFloatingContextT.Props = {}) => {\n // Extract unstable callback refs BEFORE useMemoMergePropsWithDefault.\n // useMemoMergePropsWithDefault compares with fast-deep-equal which compares functions by\n // reference; an inline callback from the consumer would invalidate propsWithDefault on every\n // render, which in turn would invalidate the destructured `customOffset` array and re-trigger\n // the position-computation useLayoutEffect on every render \u2192 infinite loop.\n const { onClickOutside, onEscape, onOpen, onClose, externalReferenceElement, ...stableProps } = props;\n\n const propsWithDefault = useMemoMergePropsWithDefault<DSHookFloatingContextT.InternalProps>(\n stableProps,\n defaultProps,\n );\n useValidateTypescriptPropTypes(propsWithDefault, DSFloatingContextPropTypes, 'FloatingContext');\n\n const {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n placement,\n customOffset,\n placementOrderPreference,\n externallyControlledIsOpen,\n closeOnEscape,\n returnFocusToReference,\n } = propsWithDefault;\n // Whether the consumer owns the open state. Surfaced on the OpenChange payload so a handler can\n // branch without re-reading props.\n const isControlled = externallyControlledIsOpen !== undefined;\n // Anchor and floating refs\n const [floatingWrapperNode, setFloatingWrapperNode] = React.useState<HTMLElement | null>(null);\n\n // Resolved below (after useResolvedReference) into a stable ref rather than referenced directly,\n // because isFocusWithinFloatingScope / the escape-handling below need to read it from a config\n // object built BEFORE useResolvedReference (and the useHeadlessTooltip call it depends on) runs.\n // A ref sidesteps that ordering constraint; the value it holds is always current by the time\n // anything actually reads it (Escape handling only ever happens after mount, never during this\n // synchronous render pass).\n const triggerElementReferenceRef = React.useRef<Element | null>(null);\n\n // Latest-refs for consumer callbacks (see useLatestRef docs).\n const onClickOutsideRef = useLatestRef(onClickOutside);\n const onEscapeRef = useLatestRef(onEscape);\n const onOpenRef = useLatestRef(onOpen);\n const onCloseRef = useLatestRef(onClose);\n\n // Open/close state \u2014 externally controlled when `externallyControlledIsOpen` is provided.\n const [internalIsOpen, setInternalIsOpen] = React.useState(false);\n const isOpen = useMemo(\n () => (externallyControlledIsOpen !== undefined ? externallyControlledIsOpen : internalIsOpen),\n [externallyControlledIsOpen, internalIsOpen],\n );\n\n // Latest-refs for the reactive VALUES that handleOpen/handleClose read. These handlers are wired\n // into ds-hooks-headless-tooltip's always-on document keydown listener; if a handler's identity\n // changed whenever one of these values changed (isOpen flips on every open/close,\n // floatingWrapperNode on every mount/unmount), that listener would detach + re-attach on every\n // transition. Reading through refs keeps the handlers identity-stable so the listener attaches\n // once. Handlers only ever run post-commit, so the ref always holds the current value when read \u2014\n // same rationale as the consumer-callback refs above.\n const isControlledRef = useLatestRef(isControlled);\n const closeOnEscapeRef = useLatestRef(closeOnEscape);\n const returnFocusToReferenceRef = useLatestRef(returnFocusToReference);\n const floatingWrapperNodeRef = useLatestRef(floatingWrapperNode);\n const isOpenRef = useLatestRef(isOpen);\n\n const handleOpen = React.useCallback<Required<UseHeadlessTooltipConfig>['onOpen']>(\n (event) => {\n setInternalIsOpen(true);\n onOpenRef.current?.({ reason: 'interaction', event, isControlled: isControlledRef.current });\n },\n [onOpenRef, isControlledRef],\n );\n\n // \"In scope\" = the active element is inside the floating (popover) content, or is/inside the\n // reference (trigger) element. Used to decide whether an Escape is this floating context's concern.\n const isFocusWithinFloatingScope = useCallback((): boolean => {\n const active = document.activeElement;\n if (!active) return false;\n if (floatingWrapperNodeRef.current?.contains(active)) return true;\n const reference = triggerElementReferenceRef.current;\n return reference === active || !!reference?.contains(active);\n }, [floatingWrapperNodeRef]);\n\n const handleClose = React.useCallback<Required<UseHeadlessTooltipConfig>['onClose']>(\n (event) => {\n // Read before flipping state: a global Escape press can arrive while this context is\n // already closed (the underlying listener is always-on, see ds-hooks-headless-tooltip), and\n // onEscape must not fire for that \u2014 only a close that was actually transitioning from open.\n const wasOpen = isOpenRef.current;\n setInternalIsOpen(false);\n\n // Escape routing: when the context was open, `closeOnEscape` is set, the event is a keyboard\n // Escape, AND focus was within scope, we route to the dedicated `onEscape` callback (instead\n // of `onClose`) and, if asked, return focus to the reference. Every other close \u2014 including a\n // non-opted-in Escape \u2014 goes through `onClose` with `reason: 'interaction'`. Whether that\n // interaction is meaningful to a controlled consumer is THEIR call: they discriminate on the\n // OpenChange `reason` (interaction vs controlled-flip). We do not decide that for them here.\n // All reactive values are read through refs (see the latest-ref block above) so this handler's\n // identity stays stable and the always-on keydown listener is not re-attached per transition.\n const isScopedEscapeClose =\n wasOpen &&\n closeOnEscapeRef.current &&\n isKeyboardEvent(event) &&\n event.key === 'Escape' &&\n isFocusWithinFloatingScope();\n\n if (isScopedEscapeClose) {\n onEscapeRef.current?.(event);\n // Focus the resolved reference directly rather than relying solely on\n // ds-hooks-headless-tooltip's own focusReferenceOnEscape: that mechanism focuses the\n // hook's *internal* reference element, which stays null whenever this context is\n // configured with `externalReferenceElement` (useResolvedReference makes\n // refs.setReference a no-op in that mode \u2014 see its docstring). triggerElementReferenceRef\n // is always the correctly-resolved element (internal or external), so focusing it here\n // works for both.\n if (returnFocusToReferenceRef.current && triggerElementReferenceRef.current instanceof HTMLElement) {\n triggerElementReferenceRef.current.focus();\n }\n } else {\n onCloseRef.current?.({ reason: 'interaction', event, isControlled: isControlledRef.current });\n }\n },\n [\n isOpenRef,\n closeOnEscapeRef,\n isFocusWithinFloatingScope,\n returnFocusToReferenceRef,\n onCloseRef,\n onEscapeRef,\n isControlledRef,\n ],\n );\n\n // Passed as a thunk (not a pre-computed boolean) into useHeadlessTooltip's config: this config\n // object is built before useResolvedReference runs, so a boolean computed here would be evaluated\n // one render behind the reference element it depends on. Deferring the check to actual\n // Escape-handling time (inside ds-hooks-headless-tooltip) avoids that staleness.\n // Only drives ds-hooks-headless-tooltip's *internal*-reference focus path (see handleClose above\n // for why the externally-resolved reference is focused directly instead).\n const shouldFocusReferenceOnEscape = useCallback(\n () => closeOnEscapeRef.current && returnFocusToReferenceRef.current && isFocusWithinFloatingScope(),\n [closeOnEscapeRef, returnFocusToReferenceRef, isFocusWithinFloatingScope],\n );\n const tooltipHelpersConfig: UseHeadlessTooltipConfig = useMemo(\n () => ({ onOpen: handleOpen, onClose: handleClose, focusReferenceOnEscape: shouldFocusReferenceOnEscape }),\n [handleOpen, handleClose, shouldFocusReferenceOnEscape],\n );\n // Headless tooltip exposes show/hide helpers + manages its own internal state.\n const tooltipHelpers = useHeadlessTooltip(tooltipHelpersConfig);\n const {\n setReferenceElement: setInternalReferenceElement,\n referenceElement: internalReferenceElement,\n hideTooltip,\n showTooltip,\n } = tooltipHelpers;\n\n // Reference element resolution: external takes precedence over internal.\n const { triggerElementReference, setReferenceElement } = useResolvedReference({\n externalReferenceElement,\n internalReferenceElement,\n setInternalReferenceElement,\n });\n // Keep the ref declared above in sync \u2014 see its declaration comment for why this can't just be\n // read directly from isFocusWithinFloatingScope/handleClose without going through a ref first.\n triggerElementReferenceRef.current = triggerElementReference;\n\n // Compute position (skip when closed)\n const { arrowStyles, floatingStyles, hasComputedOnce, updateStyles, debouncedUpdateStyles, mutableUpdateStyles } =\n useComputedPositionStyles({\n triggerElementReference,\n floatingWrapperNode,\n placement,\n placementOrderPreference,\n customOffset,\n withoutPortal,\n isClose: !isOpen,\n debounceMs: 150,\n });\n\n const floatingResizeOberverConfig = useMemo(\n () => ({ isOpen, floatingWrapperNode, onResize: () => mutableUpdateStyles.current() }),\n [isOpen, floatingWrapperNode, mutableUpdateStyles],\n );\n\n // Re-compute position when the floating element's size changes (e.g. async content).\n useFloatingResizeObserver(floatingResizeOberverConfig);\n\n // Re-compute position when the reference element moves in the viewport.\n const onObservedMovement = React.useCallback(() => {\n if (!isOpen) return;\n debouncedUpdateStyles();\n }, [isOpen, debouncedUpdateStyles]);\n usePositionObserver(triggerElementReference, onObservedMovement);\n\n // Click-outside dismissal (opt-in via `onClickOutside`).\n useFloatingClickOutside({\n isOpen,\n floatingWrapperNode,\n triggerElementReference,\n onClickOutsideRef,\n });\n\n // Route controlled-flip transitions through the SAME onOpen/onClose callbacks, tagged\n // `reason: 'controlled-flip'`. The interaction handlers above emit `reason: 'interaction'` in the\n // event catch phase; these cover the transitions driven by the consumer flipping\n // `externallyControlledIsOpen`, which have no interaction to hang off \u2014 the sanctioned \"sync with\n // external system\" effect (see the hook). One callback, one contract; `reason` discriminates.\n const handleControlledOpen = useCallback(() => {\n onOpenRef.current?.({ reason: 'controlled-flip', isControlled: true });\n }, [onOpenRef]);\n const handleControlledClose = useCallback(() => {\n onCloseRef.current?.({ reason: 'controlled-flip', isControlled: true });\n }, [onCloseRef]);\n useSyntheticEventFromControlledState({\n controlledValue: externallyControlledIsOpen,\n onEnter: handleControlledOpen,\n onExit: handleControlledClose,\n });\n\n // Expose visibility via opacity (NOT visibility:hidden \u2014 that blocks programmatic focus,\n // breaking autoFocus on first-open before the position-computation effect can run).\n // When `externalReferenceElement` is provided, computation runs on the first useLayoutEffect\n // (reference is known synchronously), so the popper becomes interactive in the same commit.\n const computedFloatingStyles = useMemo<React.CSSProperties>(() => {\n const isInteractive = isOpen && hasComputedOnce;\n return {\n ...floatingStyles,\n opacity: isInteractive ? 1 : 0,\n pointerEvents: isInteractive ? 'auto' : 'none',\n };\n }, [floatingStyles, hasComputedOnce, isOpen]);\n\n const refs = useMemo(\n () => ({\n setReference: setReferenceElement,\n setFloating: setFloatingWrapperNode,\n floating: floatingWrapperNode,\n reference: triggerElementReference,\n }),\n [setReferenceElement, floatingWrapperNode, triggerElementReference],\n );\n\n const handlers = useMemo(\n () => ({\n onMouseEnter: tooltipHelpers.onMouseEnter,\n onMouseLeave: tooltipHelpers.onMouseLeave,\n onFocus: tooltipHelpers.onFocus,\n onBlur: tooltipHelpers.onBlur,\n }),\n [tooltipHelpers.onBlur, tooltipHelpers.onFocus, tooltipHelpers.onMouseEnter, tooltipHelpers.onMouseLeave],\n );\n\n return useMemo(\n () => ({\n refs,\n floatingStyles: computedFloatingStyles,\n handlers,\n isOpen,\n arrowStyles,\n hideTooltip,\n showTooltip,\n context: {\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n },\n mutableUpdateStyles,\n forceUpdatePosition: updateStyles,\n }),\n [\n refs,\n computedFloatingStyles,\n handlers,\n isOpen,\n arrowStyles,\n hideTooltip,\n showTooltip,\n withoutPortal,\n withoutAnimation,\n portalDOMContainer,\n animationDuration,\n mutableUpdateStyles,\n updateStyles,\n ],\n );\n};\n\nuseFloatingContext.displayName = 'FloatingContext';\nconst UseFloatingContextWithSchema = describe(useFloatingContext);\nUseFloatingContextWithSchema.propTypes =\n DSFloatingContextPropTypes as unknown as ValidationMap<DSHookFloatingContextT.Props>;\n\nexport { useFloatingContext, UseFloatingContextWithSchema };\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
|
@@ -34,19 +34,19 @@ module.exports = __toCommonJS(useFloatingClickOutside_exports);
|
|
|
34
34
|
var React = __toESM(require("react"));
|
|
35
35
|
var import_react = require("react");
|
|
36
36
|
const useFloatingClickOutside = ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
isOpen,
|
|
38
|
+
floatingWrapperNode,
|
|
39
|
+
triggerElementReference,
|
|
40
|
+
onClickOutsideRef
|
|
41
41
|
}) => {
|
|
42
42
|
(0, import_react.useEffect)(() => {
|
|
43
|
-
if (!
|
|
43
|
+
if (!isOpen || !floatingWrapperNode || !triggerElementReference) return void 0;
|
|
44
44
|
const listener = (event) => {
|
|
45
|
-
const cb =
|
|
45
|
+
const cb = onClickOutsideRef.current;
|
|
46
46
|
if (!cb) return;
|
|
47
47
|
const target = event.target;
|
|
48
48
|
if (!target) return;
|
|
49
|
-
if (
|
|
49
|
+
if (floatingWrapperNode.contains(target) || triggerElementReference.contains(target)) return;
|
|
50
50
|
cb(event);
|
|
51
51
|
};
|
|
52
52
|
document.addEventListener("mousedown", listener, true);
|
|
@@ -55,6 +55,6 @@ const useFloatingClickOutside = ({
|
|
|
55
55
|
document.removeEventListener("mousedown", listener, true);
|
|
56
56
|
document.removeEventListener("touchstart", listener, true);
|
|
57
57
|
};
|
|
58
|
-
}, [
|
|
58
|
+
}, [floatingWrapperNode, triggerElementReference, onClickOutsideRef, isOpen]);
|
|
59
59
|
};
|
|
60
60
|
//# sourceMappingURL=useFloatingClickOutside.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/useFloatingClickOutside.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useEffect, type MutableRefObject } from 'react';\n\ninterface UseFloatingClickOutsideParams {\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAiD;AAoB1C,MAAM,0BAA0B,CAAC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAqC;AACnC,8BAAU,MAAM;AACd,QAAI,CAAC,
|
|
4
|
+
"sourcesContent": ["import { useEffect, type MutableRefObject } from 'react';\n\ninterface UseFloatingClickOutsideParams {\n isOpen: boolean;\n floatingWrapperNode: HTMLElement | null;\n triggerElementReference: Element | null;\n /**\n * Latest-ref of the click-outside callback. Passed as a ref (rather than a value)\n * so consumers can pass inline functions without re-attaching listeners on every render.\n * Use `useLatestRef(onClickOutside)` to construct it.\n */\n onClickOutsideRef: MutableRefObject<((event: MouseEvent | TouchEvent) => void) | undefined>;\n}\n\n/**\n * Attaches mousedown/touchstart listeners on the document that fire when the click target\n * is outside BOTH the floating element and the reference element.\n *\n * Only active when `enabled === true` and both elements exist.\n */\nexport const useFloatingClickOutside = ({\n isOpen,\n floatingWrapperNode,\n triggerElementReference,\n onClickOutsideRef,\n}: UseFloatingClickOutsideParams) => {\n useEffect(() => {\n if (!isOpen || !floatingWrapperNode || !triggerElementReference) return undefined;\n\n const listener = (event: MouseEvent | TouchEvent) => {\n const cb = onClickOutsideRef.current;\n if (!cb) return;\n const target = event.target as Node | null;\n if (!target) return;\n if (floatingWrapperNode.contains(target) || triggerElementReference.contains(target)) return;\n cb(event);\n };\n\n document.addEventListener('mousedown', listener, true);\n document.addEventListener('touchstart', listener, true);\n return () => {\n document.removeEventListener('mousedown', listener, true);\n document.removeEventListener('touchstart', listener, true);\n };\n }, [floatingWrapperNode, triggerElementReference, onClickOutsideRef, isOpen]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAiD;AAoB1C,MAAM,0BAA0B,CAAC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAqC;AACnC,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC,wBAAyB,QAAO;AAExE,UAAM,WAAW,CAAC,UAAmC;AACnD,YAAM,KAAK,kBAAkB;AAC7B,UAAI,CAAC,GAAI;AACT,YAAM,SAAS,MAAM;AACrB,UAAI,CAAC,OAAQ;AACb,UAAI,oBAAoB,SAAS,MAAM,KAAK,wBAAwB,SAAS,MAAM,EAAG;AACtF,SAAG,KAAK;AAAA,IACV;AAEA,aAAS,iBAAiB,aAAa,UAAU,IAAI;AACrD,aAAS,iBAAiB,cAAc,UAAU,IAAI;AACtD,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,UAAU,IAAI;AACxD,eAAS,oBAAoB,cAAc,UAAU,IAAI;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,qBAAqB,yBAAyB,mBAAmB,MAAM,CAAC;AAC9E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -33,16 +33,20 @@ __export(useFloatingResizeObserver_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(useFloatingResizeObserver_exports);
|
|
34
34
|
var React = __toESM(require("react"));
|
|
35
35
|
var import_react = require("react");
|
|
36
|
-
const useFloatingResizeObserver = ({
|
|
36
|
+
const useFloatingResizeObserver = ({
|
|
37
|
+
isOpen,
|
|
38
|
+
floatingWrapperNode,
|
|
39
|
+
onResize
|
|
40
|
+
}) => {
|
|
37
41
|
const onResizeRef = (0, import_react.useRef)(onResize);
|
|
38
42
|
onResizeRef.current = onResize;
|
|
39
43
|
(0, import_react.useEffect)(() => {
|
|
40
|
-
if (!
|
|
44
|
+
if (!isOpen || !floatingWrapperNode) return void 0;
|
|
41
45
|
const observer = new ResizeObserver(() => {
|
|
42
46
|
onResizeRef.current();
|
|
43
47
|
});
|
|
44
|
-
observer.observe(
|
|
48
|
+
observer.observe(floatingWrapperNode);
|
|
45
49
|
return () => observer.disconnect();
|
|
46
|
-
}, [
|
|
50
|
+
}, [isOpen, floatingWrapperNode]);
|
|
47
51
|
};
|
|
48
52
|
//# sourceMappingURL=useFloatingResizeObserver.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/useFloatingResizeObserver.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useEffect, useRef } from 'react';\n\ninterface UseFloatingResizeObserverParams {\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkC;AAY3B,MAAM,4BAA4B,CAAC,
|
|
4
|
+
"sourcesContent": ["import { useEffect, useRef } from 'react';\n\ninterface UseFloatingResizeObserverParams {\n isOpen: boolean;\n floatingWrapperNode: HTMLElement | null;\n onResize: () => void;\n}\n\n/**\n * Observes the floating element's size and calls `onResize` when its bounding box changes.\n * Used to re-run position computation when the floating content reflows (e.g. async-loaded data).\n */\nexport const useFloatingResizeObserver = ({\n isOpen,\n floatingWrapperNode,\n onResize,\n}: UseFloatingResizeObserverParams) => {\n // Latest-ref so an inline `onResize` does not invalidate the effect on every render.\n // ResizeObserver fires an initial callback on `observe()`, so re-subscribing every render\n // would call `onResize` \u2192 setState \u2192 re-render \u2192 re-subscribe \u2192 infinite loop.\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n\n useEffect(() => {\n if (!isOpen || !floatingWrapperNode) return undefined;\n\n const observer = new ResizeObserver(() => {\n onResizeRef.current();\n });\n observer.observe(floatingWrapperNode);\n\n return () => observer.disconnect();\n }, [isOpen, floatingWrapperNode]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkC;AAY3B,MAAM,4BAA4B,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,MAAuC;AAIrC,QAAM,kBAAc,qBAAO,QAAQ;AACnC,cAAY,UAAU;AAEtB,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,oBAAqB,QAAO;AAE5C,UAAM,WAAW,IAAI,eAAe,MAAM;AACxC,kBAAY,QAAQ;AAAA,IACtB,CAAC;AACD,aAAS,QAAQ,mBAAmB;AAEpC,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,QAAQ,mBAAmB,CAAC;AAClC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -39,7 +39,7 @@ const useResolvedReference = ({
|
|
|
39
39
|
setInternalReferenceElement
|
|
40
40
|
}) => {
|
|
41
41
|
const hasExternalReference = externalReferenceElement !== void 0;
|
|
42
|
-
const
|
|
42
|
+
const triggerElementReference = hasExternalReference ? externalReferenceElement : internalReferenceElement;
|
|
43
43
|
const setReferenceElement = (0, import_react.useCallback)(
|
|
44
44
|
(el) => {
|
|
45
45
|
if (hasExternalReference) return;
|
|
@@ -47,6 +47,6 @@ const useResolvedReference = ({
|
|
|
47
47
|
},
|
|
48
48
|
[hasExternalReference, setInternalReferenceElement]
|
|
49
49
|
);
|
|
50
|
-
return {
|
|
50
|
+
return { triggerElementReference, setReferenceElement };
|
|
51
51
|
};
|
|
52
52
|
//# sourceMappingURL=useResolvedReference.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/hooks/useResolvedReference.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useCallback } from 'react';\n\ninterface UseResolvedReferenceParams {\n externalReferenceElement: Element | null | undefined;\n internalReferenceElement: Element | null;\n setInternalReferenceElement: (el: Element | null) => void;\n}\n\n/**\n * Resolves the active reference element for the floating context.\n *\n * - When `externalReferenceElement` is provided (anything other than `undefined`, including `null`),\n * it is used as the source of truth. `setReference` becomes a no-op so consumers that mistakenly\n * call `refs.setReference()` don't desynchronize the two sources.\n * - Otherwise the internally-managed state is used, populated by the consumer via `refs.setReference()`\n * (typically as a callback ref: `innerRef={refs.setReference}`).\n */\nexport const useResolvedReference = ({\n externalReferenceElement,\n internalReferenceElement,\n setInternalReferenceElement,\n}: UseResolvedReferenceParams) => {\n const hasExternalReference = externalReferenceElement !== undefined;\n const
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAA4B;AAiBrB,MAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,MAAkC;AAChC,QAAM,uBAAuB,6BAA6B;AAC1D,QAAM,
|
|
4
|
+
"sourcesContent": ["import { useCallback } from 'react';\n\ninterface UseResolvedReferenceParams {\n externalReferenceElement: Element | null | undefined;\n internalReferenceElement: Element | null;\n setInternalReferenceElement: (el: Element | null) => void;\n}\n\n/**\n * Resolves the active reference element for the floating context.\n *\n * - When `externalReferenceElement` is provided (anything other than `undefined`, including `null`),\n * it is used as the source of truth. `setReference` becomes a no-op so consumers that mistakenly\n * call `refs.setReference()` don't desynchronize the two sources.\n * - Otherwise the internally-managed state is used, populated by the consumer via `refs.setReference()`\n * (typically as a callback ref: `innerRef={refs.setReference}`).\n */\nexport const useResolvedReference = ({\n externalReferenceElement,\n internalReferenceElement,\n setInternalReferenceElement,\n}: UseResolvedReferenceParams) => {\n const hasExternalReference = externalReferenceElement !== undefined;\n const triggerElementReference = hasExternalReference ? externalReferenceElement : internalReferenceElement;\n\n const setReferenceElement = useCallback(\n (el: Element | null) => {\n if (hasExternalReference) return;\n setInternalReferenceElement(el);\n },\n [hasExternalReference, setInternalReferenceElement],\n );\n\n return { triggerElementReference, setReferenceElement };\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAA4B;AAiBrB,MAAM,uBAAuB,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,MAAkC;AAChC,QAAM,uBAAuB,6BAA6B;AAC1D,QAAM,0BAA0B,uBAAuB,2BAA2B;AAElF,QAAM,0BAAsB;AAAA,IAC1B,CAAC,OAAuB;AACtB,UAAI,qBAAsB;AAC1B,kCAA4B,EAAE;AAAA,IAChC;AAAA,IACA,CAAC,sBAAsB,2BAA2B;AAAA,EACpD;AAEA,SAAO,EAAE,yBAAyB,oBAAoB;AACxD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -26,49 +26,28 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
31
|
-
|
|
29
|
+
var useSyntheticEventFromControlledState_exports = {};
|
|
30
|
+
__export(useSyntheticEventFromControlledState_exports, {
|
|
31
|
+
useSyntheticEventFromControlledState: () => useSyntheticEventFromControlledState
|
|
32
32
|
});
|
|
33
|
-
module.exports = __toCommonJS(
|
|
33
|
+
module.exports = __toCommonJS(useSyntheticEventFromControlledState_exports);
|
|
34
34
|
var React = __toESM(require("react"));
|
|
35
35
|
var import_react = require("react");
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
handleClose,
|
|
42
|
-
returnFocusToReference
|
|
36
|
+
var import_useLatestRef = require("./useLatestRef.js");
|
|
37
|
+
const useSyntheticEventFromControlledState = ({
|
|
38
|
+
controlledValue,
|
|
39
|
+
onEnter,
|
|
40
|
+
onExit
|
|
43
41
|
}) => {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (floating && floating.contains(active)) return true;
|
|
48
|
-
if (!reference) return false;
|
|
49
|
-
return reference === active || reference.contains(active);
|
|
50
|
-
},
|
|
51
|
-
[floating, reference]
|
|
52
|
-
);
|
|
42
|
+
const onEnterRef = (0, import_useLatestRef.useLatestRef)(onEnter);
|
|
43
|
+
const onExitRef = (0, import_useLatestRef.useLatestRef)(onExit);
|
|
44
|
+
const previousValueRef = (0, import_react.useRef)(controlledValue);
|
|
53
45
|
(0, import_react.useEffect)(() => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
cb(event);
|
|
61
|
-
} else {
|
|
62
|
-
handleClose();
|
|
63
|
-
}
|
|
64
|
-
if (returnFocusToReference && reference instanceof HTMLElement) {
|
|
65
|
-
reference.focus();
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
document.addEventListener("keydown", listener, true);
|
|
69
|
-
return () => {
|
|
70
|
-
document.removeEventListener("keydown", listener, true);
|
|
71
|
-
};
|
|
72
|
-
}, [enabled, handleClose, isFocusWithinFloatingScope, onEscapeRef, reference, returnFocusToReference]);
|
|
46
|
+
const previousValue = previousValueRef.current;
|
|
47
|
+
previousValueRef.current = controlledValue;
|
|
48
|
+
if (previousValue === controlledValue) return;
|
|
49
|
+
if (controlledValue === true) onEnterRef.current?.();
|
|
50
|
+
else if (controlledValue === false) onExitRef.current?.();
|
|
51
|
+
}, [controlledValue, onEnterRef, onExitRef]);
|
|
73
52
|
};
|
|
74
|
-
//# sourceMappingURL=
|
|
53
|
+
//# sourceMappingURL=useSyntheticEventFromControlledState.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/hooks/useSyntheticEventFromControlledState.ts", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
+
"sourcesContent": ["import { useEffect, useRef } from 'react';\nimport { useLatestRef } from './useLatestRef.js';\n\ninterface UseSyntheticEventFromControlledStateParams {\n /**\n * The externally-controlled value whose transitions are turned into events. `undefined` means\n * the value is not being controlled (uncontrolled usage) \u2014 no events are synthesized in that case.\n */\n controlledValue: boolean | undefined;\n /** Fired when `controlledValue` transitions to `true`. Passed inline is fine (latest-ref'd). */\n onEnter?: () => void;\n /** Fired when `controlledValue` transitions to `false`. Passed inline is fine (latest-ref'd). */\n onExit?: () => void;\n}\n\n/**\n * Synthesizes semantic enter/exit events from transitions of an **externally-controlled** value.\n *\n * Why this is a hook (and an effect), not something a caller should hand-roll: when a value is\n * controlled by the consumer, its changes originate *outside* this component \u2014 there is no\n * interaction handler in here to hang a notification on. Reacting to that change and emitting an\n * event is the *sanctioned* `useEffect` use: **synchronizing with an external system**, where the\n * external system is the consumer that owns the controlled state. This is categorically different\n * from the `useEffect` misuse (deriving/coordinating internal state), and it is the reason the\n * emitted callback is a genuine \"for whatever reason the owner changed it\" event rather than a\n * per-interaction one.\n *\n * Guarantees:\n * - Never fires on mount \u2014 only on real transitions after the initial value.\n * - Never fires while uncontrolled (`undefined`); only on explicit `false \u2194 true` edges.\n * - The prev-value bookkeeping is a ref (not state) *on purpose*: it is read/written only inside\n * the effect (post-commit), never during render, so it carries none of the render-purity hazards\n * that would make a ref wrong for an in-render transition guard.\n */\nexport const useSyntheticEventFromControlledState = ({\n controlledValue,\n onEnter,\n onExit,\n}: UseSyntheticEventFromControlledStateParams) => {\n const onEnterRef = useLatestRef(onEnter);\n const onExitRef = useLatestRef(onExit);\n const previousValueRef = useRef(controlledValue);\n\n useEffect(() => {\n const previousValue = previousValueRef.current;\n previousValueRef.current = controlledValue;\n if (previousValue === controlledValue) return;\n if (controlledValue === true) onEnterRef.current?.();\n else if (controlledValue === false) onExitRef.current?.();\n }, [controlledValue, onEnterRef, onExitRef]);\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkC;AAClC,0BAA6B;AAiCtB,MAAM,uCAAuC,CAAC;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AACF,MAAkD;AAChD,QAAM,iBAAa,kCAAa,OAAO;AACvC,QAAM,gBAAY,kCAAa,MAAM;AACrC,QAAM,uBAAmB,qBAAO,eAAe;AAE/C,8BAAU,MAAM;AACd,UAAM,gBAAgB,iBAAiB;AACvC,qBAAiB,UAAU;AAC3B,QAAI,kBAAkB,gBAAiB;AACvC,QAAI,oBAAoB,KAAM,YAAW,UAAU;AAAA,aAC1C,oBAAoB,MAAO,WAAU,UAAU;AAAA,EAC1D,GAAG,CAAC,iBAAiB,YAAY,SAAS,CAAC;AAC7C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -53,7 +53,7 @@ const DSFloatingWrapperPropTypes = {
|
|
|
53
53
|
isOpen: import_ds_props_helpers.PropTypes.bool.description("Whether the floating wrapper is open").isRequired,
|
|
54
54
|
floatingStyles: import_ds_props_helpers.PropTypes.object.description("Style for the floating wrapper").isRequired,
|
|
55
55
|
context: import_ds_props_helpers.PropTypes.shape({
|
|
56
|
-
portalDOMContainer: import_ds_props_helpers.PropTypes.
|
|
56
|
+
portalDOMContainer: import_ds_props_helpers.PropTypes.object.description("The DOM element where the tooltip will be rendered.").defaultValue('the first "main" landmark available in the document or the body if no "main" is found'),
|
|
57
57
|
withoutPortal: import_ds_props_helpers.PropTypes.bool.description("Whether to render the floating wrapper without a portal"),
|
|
58
58
|
animationDuration: import_ds_props_helpers.PropTypes.number.description("Duration of the animation"),
|
|
59
59
|
withoutAnimation: import_ds_props_helpers.PropTypes.bool.description("Whether to render the floating wrapper without animation")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parts/FloatingWrapper/react-desc-prop-types.ts", "../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\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 { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAKO;AAEP,uBAA8D;
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-empty-interface */\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 { DSFloatingWrapperName, DSFloatingWrapperSlots } from '../../constants/index.js';\n\nexport declare namespace DSFloatingWrapperT {\n export interface RequiredProps {\n children: TypescriptHelpersT.ReactChildrenComplete;\n innerRef: TypescriptHelpersT.AnyRef<HTMLDivElement>;\n isOpen: boolean;\n floatingStyles: React.CSSProperties;\n }\n\n export interface DefaultProps {\n context: {\n portalDOMContainer?: HTMLElement;\n withoutPortal: boolean;\n animationDuration: number;\n withoutAnimation: boolean;\n };\n customOffset: [number, number];\n }\n\n export interface OptionalProps extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSFloatingWrapperName,\n typeof DSFloatingWrapperSlots\n > {\n onAnimationEnd?: React.AnimationEventHandler<HTMLDivElement>;\n onAnimationStartTriggered?: () => void;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n RequiredProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLElement>,\n keyof DefaultProps | keyof OptionalProps | keyof RequiredProps | keyof XstyledProps\n >,\n XstyledProps {}\n}\n\nexport const defaultProps: Partial<DSFloatingWrapperT.DefaultProps> = {\n context: {\n withoutPortal: false,\n animationDuration: 300,\n withoutAnimation: false,\n },\n customOffset: [0, 12],\n};\n\nexport const DSFloatingWrapperPropTypes: DSPropTypesSchema<DSFloatingWrapperT.InternalProps> = {\n ...getPropsPerSlotPropTypes(DSFloatingWrapperName, DSFloatingWrapperSlots),\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n children: PropTypes.node.description('Content of the floating wrapper').isRequired,\n innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).description('Ref for the floating wrapper')\n .isRequired,\n isOpen: PropTypes.bool.description('Whether the floating wrapper is open').isRequired,\n floatingStyles: PropTypes.object.description('Style for the floating wrapper').isRequired,\n context: PropTypes.shape({\n portalDOMContainer: PropTypes.object\n .description('The DOM element where the tooltip will be rendered.')\n .defaultValue('the first \"main\" landmark available in the document or the body if no \"main\" is found'),\n withoutPortal: PropTypes.bool.description('Whether to render the floating wrapper without a portal'),\n animationDuration: PropTypes.number.description('Duration of the animation'),\n withoutAnimation: PropTypes.bool.description('Whether to render the floating wrapper without animation'),\n }).description('Context for the floating wrapper'),\n onAnimationStartTriggered: PropTypes.func.description(\n 'Callback invoked when the component trigger the animation start. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n onAnimationEnd: PropTypes.func.description(\n 'Callback when the animation ends. Required to properly position nested floating context without visual artefacts in case animations are used.',\n ),\n customOffset: PropTypes.arrayOf(PropTypes.number).description('Custom offset for the floating wrapper'),\n};\n\nexport const DSFloatingWrapperPropTypesSchema =\n DSFloatingWrapperPropTypes as unknown as ValidationMap<DSFloatingWrapperT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADEvB,8BAKO;AAEP,uBAA8D;AAmDvD,MAAM,eAAyD;AAAA,EACpE,SAAS;AAAA,IACP,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AAAA,EACA,cAAc,CAAC,GAAG,EAAE;AACtB;AAEO,MAAM,6BAAkF;AAAA,EAC7F,OAAG,kDAAyB,wCAAuB,uCAAsB;AAAA,EACzE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,UAAU,kCAAU,KAAK,YAAY,iCAAiC,EAAE;AAAA,EACxE,UAAU,kCAAU,UAAU,CAAC,kCAAU,QAAQ,kCAAU,IAAI,CAAC,EAAE,YAAY,8BAA8B,EACzG;AAAA,EACH,QAAQ,kCAAU,KAAK,YAAY,sCAAsC,EAAE;AAAA,EAC3E,gBAAgB,kCAAU,OAAO,YAAY,gCAAgC,EAAE;AAAA,EAC/E,SAAS,kCAAU,MAAM;AAAA,IACvB,oBAAoB,kCAAU,OAC3B,YAAY,qDAAqD,EACjE,aAAa,uFAAuF;AAAA,IACvG,eAAe,kCAAU,KAAK,YAAY,yDAAyD;AAAA,IACnG,mBAAmB,kCAAU,OAAO,YAAY,2BAA2B;AAAA,IAC3E,kBAAkB,kCAAU,KAAK,YAAY,0DAA0D;AAAA,EACzG,CAAC,EAAE,YAAY,kCAAkC;AAAA,EACjD,2BAA2B,kCAAU,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EACA,gBAAgB,kCAAU,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,cAAc,kCAAU,QAAQ,kCAAU,MAAM,EAAE,YAAY,wCAAwC;AACxG;AAEO,MAAM,mCACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/parts/PopoverArrow.tsx", "../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import React from 'react';\nimport { useOwnerProps, useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport { styled } from '@elliemae/ds-system';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperSlots, DSFloatingWrapperName } from '../constants/index.js';\nexport interface PopoverArrowT
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
4
|
+
"sourcesContent": ["import React from 'react';\nimport { useOwnerProps, useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport { styled } from '@elliemae/ds-system';\nimport type { TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { DSFloatingWrapperSlots, DSFloatingWrapperName } from '../constants/index.js';\nexport interface PopoverArrowT extends TypescriptHelpersT.PropsForGlobalOnSlots<\n typeof DSFloatingWrapperName,\n typeof DSFloatingWrapperSlots\n> {\n placement: string;\n style: React.CSSProperties;\n arrowElementRef?: React.Dispatch<React.SetStateAction<HTMLDivElement | null>>;\n}\nconst arrowWidth = 18;\nconst OFFSET_FIX_SHADOW_DEFECT = 0.25;\n\nconst arrowDimensionBase13 = arrowWidth / 13;\nconst OFFSET_FIX_SHADOW_DEFECT_BASE13 = OFFSET_FIX_SHADOW_DEFECT / 13;\nconst arrowDimensionBase16 = arrowWidth / 16;\nconst OFFSET_FIX_SHADOW_DEFECT_BASE16 = OFFSET_FIX_SHADOW_DEFECT / 16;\n\nconst arrowPlacementBase13 = arrowDimensionBase13 - OFFSET_FIX_SHADOW_DEFECT_BASE13;\nconst arrowPlacementBase16 = arrowDimensionBase16 - OFFSET_FIX_SHADOW_DEFECT_BASE16;\n\nconst isTopOrBottom = (placement: string) => placement.startsWith('top') || placement.startsWith('bottom');\n\nconst isLeftOrRight = (placement: string) => placement.startsWith('left') || placement.startsWith('right');\n\nconst StyledArrow = styled('div', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW,\n})<{ 'data-placement': string }>`\n line-height: 0;\n position: absolute;\n width: ${arrowDimensionBase16}rem;\n height: ${arrowDimensionBase16}rem;\n pointer-events: none;\n background-color: transparent;\n & .stroke {\n fill: rgb(105, 116, 137);\n fill-opacity: 0.4;\n }\n & .fill {\n fill: rgb(255, 255, 255);\n }\n\n &[data-placement^='top'] {\n svg {\n transform: rotateZ(180deg);\n }\n bottom: -${arrowPlacementBase16}rem;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='right'] {\n svg {\n transform: rotateZ(-90deg);\n }\n left: -${arrowPlacementBase16}rem;\n }\n &[data-placement^='bottom'] {\n top: -${arrowPlacementBase16}rem;\n left: ${(props) => {\n if (props['data-placement'].endsWith('start')) return `25%`;\n if (props['data-placement'].endsWith('end')) return `75%`;\n return '';\n }};\n }\n &[data-placement^='left'] {\n svg {\n transform: rotateZ(90deg);\n }\n right: -${arrowPlacementBase16}rem;\n }\n margin-left: ${(props) => (isTopOrBottom(props['data-placement']) ? `-${arrowDimensionBase16 / 2}rem` : '0')};\n margin-top: ${(props) => (isLeftOrRight(props['data-placement']) ? `-${arrowDimensionBase16 / 2}rem` : '0')};\n\n @media (min-width: ${({ theme }) => theme.breakpoints.small}) {\n width: ${arrowDimensionBase13}rem;\n height: ${arrowDimensionBase13}rem;\n\n &[data-placement^='top'] {\n bottom: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='bottom'] {\n top: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='left'] {\n right: -${arrowPlacementBase13}rem;\n }\n\n &[data-placement^='right'] {\n left: -${arrowPlacementBase13}rem;\n }\n\n margin-left: ${(props) => (isTopOrBottom(props['data-placement']) ? `-${arrowDimensionBase13 / 2}rem` : '0')};\n\n margin-top: ${(props) => (isLeftOrRight(props['data-placement']) ? `-${arrowDimensionBase13 / 2}rem` : '0')};\n }\n`;\n\nconst StylePathShadow = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_SHADOW,\n})``;\n\nconst StylePathFill = styled('path', {\n name: DSFloatingWrapperName,\n slot: DSFloatingWrapperSlots.ARROW_FILL,\n})``;\n\nexport const PopoverArrow = ({ placement, style, arrowElementRef, ...rest }: PopoverArrowT): React.ReactElement => {\n const ownerProps = useOwnerProps(rest);\n const globalAttributes = useGetGlobalAttributes(rest);\n const xstyledProps = useGetXstyledProps(rest);\n return (\n <StyledArrow\n key=\"popper-arrow\"\n data-placement={placement}\n style={style}\n innerRef={arrowElementRef}\n data-testid=\"ds-tooltip-arrow\"\n aria-hidden=\"true\"\n {...ownerProps}\n {...globalAttributes}\n {...xstyledProps}\n >\n <svg viewBox=\"0 0 30 30\">\n <StylePathShadow\n {...ownerProps}\n className=\"stroke\"\n d=\"M23.7,27.1L17,19.9C16.5,19.3,15.8,19,15,19s-1.6,0.3-2.1,0.9l-6.6,7.2C5.3,28.1,3.4,29,2,29h26\n C26.7,29,24.6,28.1,23.7,27.1z\"\n />\n <StylePathFill\n {...ownerProps}\n className=\"fill\"\n d=\"M23,27.8c1.1,1.2,3.4,2.2,5,2.2h2H0h2c1.7,0,3.9-1,5-2.2l6.6-7.2c0.7-0.8,2-0.8,2.7,0L23,27.8L23,27.8z\"\n />\n </svg>\n </StyledArrow>\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -46,7 +46,7 @@ const defaultProps = {
|
|
|
46
46
|
const DSFloatingContextPropTypes = {
|
|
47
47
|
withoutPortal: import_ds_props_helpers.PropTypes.bool.description("If true, the tooltip will not be rendered inside a portal.").defaultValue(false),
|
|
48
48
|
withoutAnimation: import_ds_props_helpers.PropTypes.bool.description("If true, the tooltip will not have an animation.").defaultValue(false),
|
|
49
|
-
portalDOMContainer: import_ds_props_helpers.PropTypes.
|
|
49
|
+
portalDOMContainer: import_ds_props_helpers.PropTypes.object.description("The DOM element where the tooltip will be rendered.").defaultValue('the first "main" landmark available in the document or the body if no "main" is found'),
|
|
50
50
|
animationDuration: import_ds_props_helpers.PropTypes.number.description("The duration of the animation in milliseconds.").defaultValue(300),
|
|
51
51
|
placement: import_ds_props_helpers.PropTypes.oneOf([
|
|
52
52
|
"top-start",
|
|
@@ -77,12 +77,16 @@ const DSFloatingContextPropTypes = {
|
|
|
77
77
|
import_ds_props_helpers.PropTypes.tuple([import_ds_props_helpers.PropTypes.oneOf(["left"])]),
|
|
78
78
|
import_ds_props_helpers.PropTypes.tuple([import_ds_props_helpers.PropTypes.oneOf(["left-start"])])
|
|
79
79
|
]).description("The order of the placement preference."),
|
|
80
|
-
onOpen: import_ds_props_helpers.PropTypes.func.description(
|
|
81
|
-
|
|
80
|
+
onOpen: import_ds_props_helpers.PropTypes.func.description(
|
|
81
|
+
"Called on every open transition (interaction or controlled-flip); receives arguments with a `reason`."
|
|
82
|
+
),
|
|
83
|
+
onClose: import_ds_props_helpers.PropTypes.func.description(
|
|
84
|
+
"Called on every close transition (interaction or controlled-flip); receives arguments with a `reason`."
|
|
85
|
+
),
|
|
82
86
|
externallyControlledIsOpen: import_ds_props_helpers.PropTypes.bool.description(
|
|
83
87
|
"If true, the context open/close state will be controlled externally."
|
|
84
88
|
),
|
|
85
|
-
externalReferenceElement: import_ds_props_helpers.PropTypes.
|
|
89
|
+
externalReferenceElement: import_ds_props_helpers.PropTypes.object.description(
|
|
86
90
|
"Pre-resolved reference element. When provided, used as the source of truth for positioning, avoiding the need for a follow-up refs.setReference() effect and the visibility:hidden race on open."
|
|
87
91
|
),
|
|
88
92
|
onClickOutside: import_ds_props_helpers.PropTypes.func.description(
|