@elliemae/ds-hooks-headless-tooltip 3.70.0-next.9 → 3.70.0-rc.1
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/DSHooksHeadlessTooltip.js +68 -36
- package/dist/cjs/DSHooksHeadlessTooltip.js.map +2 -2
- package/dist/cjs/package.json +1 -4
- package/dist/esm/DSHooksHeadlessTooltip.js +68 -36
- package/dist/esm/DSHooksHeadlessTooltip.js.map +2 -2
- package/dist/esm/package.json +1 -4
- package/dist/types/DSHooksHeadlessTooltip.d.ts +16 -8
- package/package.json +6 -6
- package/dist/types/tests/useHeadlessTooltip.func.test.d.ts +0 -1
- package/dist/types/tests/useHeadlessTooltip.render.test.d.ts +0 -1
|
@@ -48,22 +48,35 @@ const useControlledState = (controlledValue, defaultVal) => {
|
|
|
48
48
|
return [val, setInternalValue];
|
|
49
49
|
};
|
|
50
50
|
const useHeadlessTooltip = (config) => {
|
|
51
|
-
const {
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
const {
|
|
52
|
+
hasFocus,
|
|
53
|
+
isHovering,
|
|
54
|
+
latestOpenInteraction,
|
|
55
|
+
onOpen = () => {
|
|
56
|
+
},
|
|
57
|
+
onClose = () => {
|
|
58
|
+
},
|
|
59
|
+
focusReferenceOnEscape = false
|
|
60
|
+
} = config ?? {};
|
|
54
61
|
const [finalHasFocus, setInternalHasFocus] = useControlledState(hasFocus, false);
|
|
55
62
|
const [finalIsHovering, setInternalIsHovering] = useControlledState(isHovering, false);
|
|
56
63
|
const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState(latestOpenInteraction, "");
|
|
57
64
|
const [referenceElement, setReferenceElement] = import_react.default.useState(null);
|
|
58
65
|
const [shouldShowPopover, setShouldShowPopover] = import_react.default.useState(false);
|
|
59
|
-
const showTooltip = import_react.default.useCallback(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
const showTooltip = import_react.default.useCallback(
|
|
67
|
+
(event) => {
|
|
68
|
+
setShouldShowPopover(true);
|
|
69
|
+
onOpen(event);
|
|
70
|
+
},
|
|
71
|
+
[onOpen]
|
|
72
|
+
);
|
|
73
|
+
const hideTooltip = import_react.default.useCallback(
|
|
74
|
+
(event) => {
|
|
75
|
+
setShouldShowPopover(false);
|
|
76
|
+
onClose(event);
|
|
77
|
+
},
|
|
78
|
+
[onClose]
|
|
79
|
+
);
|
|
67
80
|
const trackLatestKeyboardInteraction = import_react.default.useCallback(() => {
|
|
68
81
|
if (!shouldShowPopover) {
|
|
69
82
|
setLatestOpenInteraction("onFocus");
|
|
@@ -74,33 +87,52 @@ const useHeadlessTooltip = (config) => {
|
|
|
74
87
|
setLatestOpenInteraction("onMouseEnter");
|
|
75
88
|
}
|
|
76
89
|
}, [setLatestOpenInteraction, shouldShowPopover]);
|
|
77
|
-
const onFocus = import_react.default.useCallback(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
setInternalHasFocus
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
const onFocus = import_react.default.useCallback(
|
|
91
|
+
(event) => {
|
|
92
|
+
setInternalHasFocus(true);
|
|
93
|
+
trackLatestKeyboardInteraction();
|
|
94
|
+
if (!shouldShowPopover) {
|
|
95
|
+
showTooltip(event);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
[setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction]
|
|
99
|
+
);
|
|
100
|
+
const onBlur = import_react.default.useCallback(
|
|
101
|
+
(event) => {
|
|
102
|
+
setInternalHasFocus(false);
|
|
103
|
+
if (!finalIsHovering || finalLatestOpenInteraction === "onFocus") hideTooltip(event);
|
|
104
|
+
},
|
|
105
|
+
[setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip]
|
|
106
|
+
);
|
|
107
|
+
const onMouseEnter = import_react.default.useCallback(
|
|
108
|
+
(event) => {
|
|
109
|
+
setInternalIsHovering(true);
|
|
110
|
+
trackLatestMouseInteraction();
|
|
111
|
+
if (!shouldShowPopover) {
|
|
112
|
+
showTooltip(event);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
[setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction]
|
|
116
|
+
);
|
|
117
|
+
const onMouseLeave = import_react.default.useCallback(
|
|
118
|
+
(event) => {
|
|
119
|
+
setInternalIsHovering(false);
|
|
120
|
+
if (!finalHasFocus || finalLatestOpenInteraction === "onMouseEnter") hideTooltip(event);
|
|
121
|
+
},
|
|
122
|
+
[setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip]
|
|
123
|
+
);
|
|
99
124
|
const handleEscKey = import_react.default.useCallback(
|
|
100
|
-
(
|
|
101
|
-
|
|
125
|
+
(event) => {
|
|
126
|
+
const { key } = event;
|
|
127
|
+
if (key === "Escape") {
|
|
128
|
+
hideTooltip(event);
|
|
129
|
+
const shouldFocusReference = typeof focusReferenceOnEscape === "function" ? focusReferenceOnEscape() : focusReferenceOnEscape;
|
|
130
|
+
if (shouldFocusReference && referenceElement instanceof HTMLElement) {
|
|
131
|
+
referenceElement.focus();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
102
134
|
},
|
|
103
|
-
[hideTooltip]
|
|
135
|
+
[focusReferenceOnEscape, hideTooltip, referenceElement]
|
|
104
136
|
);
|
|
105
137
|
useGlobalKeyboardListener(handleEscKey);
|
|
106
138
|
return import_react.default.useMemo(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/DSHooksHeadlessTooltip.tsx", "../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import React from 'react';\n\n// This function is a custom hook that adds a keyboard event listener to the document\n// calls the specified function when a key is pressed.\nconst useGlobalKeyboardListener = (func: ({ key }: { key: string }) => void) => {\n React.useEffect(() => {\n document.addEventListener('keydown', func);\n return () => document.removeEventListener('keydown', func);\n }, [func]);\n};\n\nexport type LatestOpenInteraction = '' | 'onFocus' | 'onMouseEnter';\nexport type UseHeadlessTooltipConfig = {\n hasFocus?: boolean;\n isHovering?: boolean;\n latestOpenInteraction?: LatestOpenInteraction;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst useControlledState = <T,>(controlledValue?: T, defaultVal?: T) => {\n const [internalValue, setInternalValue] = React.useState<T | null>(defaultVal ?? null);\n const val = React.useMemo(() => {\n if (controlledValue !== undefined) return controlledValue;\n return internalValue;\n }, [controlledValue, internalValue]);\n return [val, setInternalValue] as const;\n};\n\n/**\n * A custom hook that provides logic for a headless tooltip. This hook can be used in a controlled or uncontrolled way.\n * @param {UseHeadlessTooltipConfig} config - The configuration object for the hook.\n * @param {boolean} config.hasFocus - Whether or not the trigger element has focus. If this is not provided, the hook will track focus internally.\n * @param {boolean} config.isHovering - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {LatestOpenInteraction} config.latestOpenInteraction - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {Function} config.onOpen - A callback that will be invoked when the tooltip is opened.\n * @param {Function} config.onClose - A callback that will be invoked when the tooltip is closed.\n * @returns {object} - An object containing the following properties:\n *\n * {boolean} hasFocus - Whether or not the trigger element has focus.\n *\n * {boolean} isHovering - Whether or not the mouse is hovering over the trigger element.\n *\n * {'' | 'onFocus' | 'onMouseEnter'} latestOpenInteraction - which was the last operation that is used to control if the tooltip should show or not.\n *\n * {string} finalLatestOpenInteraction - The most recent interaction that caused the tooltip to open.\n *\n * {HTMLDivElement} referenceElement - The trigger element.\n *\n * {function} setReferenceElement - A function that sets the trigger element.\n *\n * {boolean} shouldShowPopover - Whether or not the tooltip is visible.\n *\n * {function} showTooltip - A function that opens the tooltip.\n *\n * {function} hideTooltip - A function that closes the tooltip.\n *\n * {function} onFocus - A function that should be invoked when the trigger element receives focus.\n *\n * {function} onBlur - A function that should be invoked when the trigger element loses focus.\n *\n * {function} onMouseEnter - A function that should be invoked when the mouse enters the trigger element.\n *\n * {function} onMouseLeave - A function that should be invoked when the mouse leaves the trigger element.\n * @example\n * const tooltipHelpers = useHeadlessTooltip({\n * hasFocus: true,\n * isHovering: false,\n * onOpen: () => console.log('tooltip opened'),\n * onClose: () => console.log('tooltip closed'),\n * });\n * ...\n * <div>\n * <button\n * ref={tooltipHelpers.setReferenceElement}\n * onMouseEnter={tooltipHelpers.onMouseEnter}\n * onMouseLeave={tooltipHelpers.onMouseLeave}\n * onPointerEnter={tooltipHelpers.onMouseEnter}\n * onPointerLeave={tooltipHelpers.onMouseLeave}\n * onFocus={tooltipHelpers.onFocus}\n * onBlur={tooltipHelpers.onBlur}\n * >hello</button>\n * <DSPopperJS\n * referenceElement={tooltipHelpers.referenceElement}\n * shouldShowPopover={tooltipHelpers.shouldShowPopover}\n * >\n * <div>Tooltip content</div>\n * </DSPopperJS>\n * </div>\n */\nexport const useHeadlessTooltip = (config?: UseHeadlessTooltipConfig) => {\n // Extract the configuration values or set default values if they are not provided.\n const { hasFocus, isHovering, latestOpenInteraction, onOpen = () => {}, onClose = () => {} } = config ?? {};\n\n // this pattern is basically a way to allow usage of the hook in a controlled or uncontrolled way.\n const [finalHasFocus, setInternalHasFocus] = useControlledState<boolean>(hasFocus, false);\n const [finalIsHovering, setInternalIsHovering] = useControlledState<boolean>(isHovering, false);\n const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState<string>(latestOpenInteraction, '');\n\n // end of controlled/uncontrolled pattern\n\n // Set up state variables for the tooltip's visibility and the most recent interaction that caused it to open.\n // The most recent interaction is used to determine whether or not to close the tooltip when the user\n // moves the mouse away from the trigger element.\n const [referenceElement, setReferenceElement] = React.useState<Element | null>(null);\n const [shouldShowPopover, setShouldShowPopover] = React.useState<boolean>(false);\n\n // memoized versions of the show and hide functions\n // those include the callbacks to allow \"controlled\" usage of the hook\n const showTooltip = React.useCallback(() => {\n setShouldShowPopover(true);\n onOpen();\n }, [onOpen]);\n\n const hideTooltip = React.useCallback(() => {\n setShouldShowPopover(false);\n onClose();\n }, [onClose]);\n\n const trackLatestKeyboardInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onFocus');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n const trackLatestMouseInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onMouseEnter');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n // following here are the event handlers that are used to control the tooltip's visibility logic\n const onFocus = React.useCallback(() => {\n setInternalHasFocus(true); // uncontrolled usage tracking\n trackLatestKeyboardInteraction();\n if (!shouldShowPopover) {\n showTooltip();\n }\n }, [setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction]);\n\n const onBlur = React.useCallback(() => {\n setInternalHasFocus(false); // uncontrolled usage tracking\n // blur may triggered via keyboard navigation or mouse interaction\n // every time the mouse is hovering, we want to keep the tooltip open\n // but if the mouse is not hovering, we want to close the tooltip only if the last interaction was via keyboard\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalIsHovering || finalLatestOpenInteraction === 'onFocus') hideTooltip();\n }, [setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip]);\n\n const onMouseEnter = React.useCallback(() => {\n setInternalIsHovering(true); // uncontrolled usage tracking\n // kind of debouncing the mouse enter event to reduce the avarge O() notation of the function\n // even if this is continually invoked, it will be O(1) and controlled callbacks will be invoked only once\n trackLatestMouseInteraction();\n if (!shouldShowPopover) {\n showTooltip();\n }\n }, [setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction]);\n\n const onMouseLeave = React.useCallback(() => {\n setInternalIsHovering(false); // uncontrolled usage tracking\n // mouse leave may be triggered via keyboard navigation or mouse interaction\n // every time the trigger element has focus, we want to keep the tooltip open\n // but if the trigger element does not have focus, we want to close the tooltip only if the last interaction was via mouse\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalHasFocus || finalLatestOpenInteraction === 'onMouseEnter') hideTooltip();\n }, [setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip]);\n\n const handleEscKey = React.useCallback(\n ({ key }: { key: string }) => {\n // accessibility standard: pressing escape should close the tooltip\n if (key === 'Escape') hideTooltip();\n },\n [hideTooltip],\n );\n\n // accessibilty standard: pressing escape should close the tooltip no matter where the focus is\n useGlobalKeyboardListener(handleEscKey);\n\n return React.useMemo(\n () => ({\n hasFocus: finalHasFocus,\n isHovering: finalIsHovering,\n latestOpenInteraction: finalLatestOpenInteraction,\n referenceElement,\n setReferenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n }),\n [\n finalHasFocus,\n finalIsHovering,\n finalLatestOpenInteraction,\n referenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAkB;
|
|
4
|
+
"sourcesContent": ["import React from 'react';\n\n/**\n * ds-hooks-headless-tooltip \u2014 headless show/hide state machine for tooltip-like surfaces. It is the\n * open/close primitive under ds-floating-context, which in turn backs tooltips, popovers and the\n * AppPicker dialog panel \u2014 so \"tooltip\" here means any such surface, not only a hover tooltip.\n *\n * Controlled or uncontrolled per input: pass `hasFocus`/`isHovering`/`latestOpenInteraction` to drive\n * it, or omit them and the hook tracks focus/hover internally. `showTooltip`/`hideTooltip` and the\n * onFocus/onBlur/onMouseEnter/onMouseLeave handlers forward the originating event to onOpen/onClose.\n *\n * LOAD-BEARING GOTCHA: the Escape handler is attached to the document via an ALWAYS-ON keydown\n * listener (useGlobalKeyboardListener below) \u2014 it calls hideTooltip on any Escape press regardless of\n * whether this surface is open or where focus currently is. This is intentional (a11y: Escape must be\n * able to dismiss from anywhere), and downstream depends on it: ds-floating-context's handleClose is\n * what decides whether a given Escape is actually \"in scope\" for that surface. Do NOT add\n * open-state/focus gating here \u2014 that scoping decision belongs to the consumer.\n */\n\n// This function is a custom hook that adds a keyboard event listener to the document\n// calls the specified function when a key is pressed.\n// Note: this attaches a raw DOM listener, so `func` receives a native KeyboardEvent, never a\n// React SyntheticEvent \u2014 the type below reflects that; do not widen it to React.KeyboardEventHandler.\nconst useGlobalKeyboardListener = (func: (event: KeyboardEvent) => void) => {\n React.useEffect(() => {\n document.addEventListener('keydown', func);\n return () => document.removeEventListener('keydown', func);\n }, [func]);\n};\n\nexport type LatestOpenInteraction = '' | 'onFocus' | 'onMouseEnter';\nexport type UseHeadlessTooltipConfig = {\n hasFocus?: boolean;\n isHovering?: boolean;\n latestOpenInteraction?: LatestOpenInteraction;\n // onOpen/onClose forward the originating event. `React.KeyboardEvent` is in the open union because\n // showTooltip can be called directly by a consumer in response to a keyboard interaction: this hook\n // backs non-tooltip contextual regions too (e.g. AppPicker opens on ArrowDown), so a keyboard event\n // is a valid open cause even though it is atypical for a plain tooltip. onClose's union carries the\n // native KeyboardEvent (not React's) because an Escape close comes from a document-level listener.\n onOpen?: (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => void;\n onClose?: (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => void;\n /**\n * Whether to focus the reference element after an Escape-triggered close. Accepts a plain\n * boolean, or a thunk evaluated at the moment Escape is handled \u2014 the thunk form exists so\n * consumers whose \"should I refocus\" answer depends on state resolved after this config object\n * is built (e.g. a focus-scope check that depends on a reference element resolved later in the\n * same render) can still get a non-stale answer instead of a render-behind snapshot.\n */\n focusReferenceOnEscape?: boolean | (() => boolean);\n};\n\nconst useControlledState = <T,>(controlledValue?: T, defaultVal?: T) => {\n const [internalValue, setInternalValue] = React.useState<T | null>(defaultVal ?? null);\n const val = React.useMemo(() => {\n if (controlledValue !== undefined) return controlledValue;\n return internalValue;\n }, [controlledValue, internalValue]);\n return [val, setInternalValue] as const;\n};\n\n/**\n * A custom hook that provides logic for a headless tooltip. This hook can be used in a controlled or uncontrolled way.\n * @param {UseHeadlessTooltipConfig} config - The configuration object for the hook.\n * @param {boolean} config.hasFocus - Whether or not the trigger element has focus. If this is not provided, the hook will track focus internally.\n * @param {boolean} config.isHovering - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {LatestOpenInteraction} config.latestOpenInteraction - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {Function} config.onOpen - A callback that will be invoked when the tooltip is opened.\n * @param {Function} config.onClose - A callback that will be invoked when the tooltip is closed.\n * @returns {object} - An object containing the following properties:\n *\n * {boolean} hasFocus - Whether or not the trigger element has focus.\n *\n * {boolean} isHovering - Whether or not the mouse is hovering over the trigger element.\n *\n * {'' | 'onFocus' | 'onMouseEnter'} latestOpenInteraction - which was the last operation that is used to control if the tooltip should show or not.\n *\n * {string} finalLatestOpenInteraction - The most recent interaction that caused the tooltip to open.\n *\n * {HTMLDivElement} referenceElement - The trigger element.\n *\n * {function} setReferenceElement - A function that sets the trigger element.\n *\n * {boolean} shouldShowPopover - Whether or not the tooltip is visible.\n *\n * {function} showTooltip - A function that opens the tooltip.\n *\n * {function} hideTooltip - A function that closes the tooltip.\n *\n * {function} onFocus - A function that should be invoked when the trigger element receives focus.\n *\n * {function} onBlur - A function that should be invoked when the trigger element loses focus.\n *\n * {function} onMouseEnter - A function that should be invoked when the mouse enters the trigger element.\n *\n * {function} onMouseLeave - A function that should be invoked when the mouse leaves the trigger element.\n * @example\n * const tooltipHelpers = useHeadlessTooltip({\n * hasFocus: true,\n * isHovering: false,\n * onOpen: () => console.log('tooltip opened'),\n * onClose: () => console.log('tooltip closed'),\n * });\n * ...\n * <div>\n * <button\n * ref={tooltipHelpers.setReferenceElement}\n * onMouseEnter={tooltipHelpers.onMouseEnter}\n * onMouseLeave={tooltipHelpers.onMouseLeave}\n * onPointerEnter={tooltipHelpers.onMouseEnter}\n * onPointerLeave={tooltipHelpers.onMouseLeave}\n * onFocus={tooltipHelpers.onFocus}\n * onBlur={tooltipHelpers.onBlur}\n * >hello</button>\n * <DSPopperJS\n * referenceElement={tooltipHelpers.referenceElement}\n * shouldShowPopover={tooltipHelpers.shouldShowPopover}\n * >\n * <div>Tooltip content</div>\n * </DSPopperJS>\n * </div>\n */\nexport const useHeadlessTooltip = (config?: UseHeadlessTooltipConfig) => {\n // Extract the configuration values or set default values if they are not provided.\n const {\n hasFocus,\n isHovering,\n latestOpenInteraction,\n onOpen = () => {},\n onClose = () => {},\n focusReferenceOnEscape = false,\n } = config ?? {};\n\n // this pattern is basically a way to allow usage of the hook in a controlled or uncontrolled way.\n const [finalHasFocus, setInternalHasFocus] = useControlledState<boolean>(hasFocus, false);\n const [finalIsHovering, setInternalIsHovering] = useControlledState<boolean>(isHovering, false);\n const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState<string>(latestOpenInteraction, '');\n\n // end of controlled/uncontrolled pattern\n\n // Set up state variables for the tooltip's visibility and the most recent interaction that caused it to open.\n // The most recent interaction is used to determine whether or not to close the tooltip when the user\n // moves the mouse away from the trigger element.\n const [referenceElement, setReferenceElement] = React.useState<Element | null>(null);\n const [shouldShowPopover, setShouldShowPopover] = React.useState<boolean>(false);\n\n // memoized versions of the show and hide functions\n // those include the callbacks to allow \"controlled\" usage of the hook\n const showTooltip = React.useCallback(\n (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => {\n setShouldShowPopover(true);\n onOpen(event);\n },\n [onOpen],\n );\n\n const hideTooltip = React.useCallback(\n (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => {\n setShouldShowPopover(false);\n onClose(event);\n },\n [onClose],\n );\n\n const trackLatestKeyboardInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onFocus');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n const trackLatestMouseInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onMouseEnter');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n // following here are the event handlers that are used to control the tooltip's visibility logic\n const onFocus = React.useCallback<React.FocusEventHandler>(\n (event) => {\n setInternalHasFocus(true); // uncontrolled usage tracking\n trackLatestKeyboardInteraction();\n if (!shouldShowPopover) {\n showTooltip(event);\n }\n },\n [setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction],\n );\n\n const onBlur = React.useCallback<React.FocusEventHandler>(\n (event) => {\n setInternalHasFocus(false); // uncontrolled usage tracking\n // blur may triggered via keyboard navigation or mouse interaction\n // every time the mouse is hovering, we want to keep the tooltip open\n // but if the mouse is not hovering, we want to close the tooltip only if the last interaction was via keyboard\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalIsHovering || finalLatestOpenInteraction === 'onFocus') hideTooltip(event);\n },\n [setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip],\n );\n\n const onMouseEnter = React.useCallback<React.MouseEventHandler>(\n (event) => {\n setInternalIsHovering(true); // uncontrolled usage tracking\n // kind of debouncing the mouse enter event to reduce the avarge O() notation of the function\n // even if this is continually invoked, it will be O(1) and controlled callbacks will be invoked only once\n trackLatestMouseInteraction();\n if (!shouldShowPopover) {\n showTooltip(event);\n }\n },\n [setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction],\n );\n\n const onMouseLeave = React.useCallback<React.MouseEventHandler>(\n (event) => {\n setInternalIsHovering(false); // uncontrolled usage tracking\n // mouse leave may be triggered via keyboard navigation or mouse interaction\n // every time the trigger element has focus, we want to keep the tooltip open\n // but if the trigger element does not have focus, we want to close the tooltip only if the last interaction was via mouse\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalHasFocus || finalLatestOpenInteraction === 'onMouseEnter') hideTooltip(event);\n },\n [setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip],\n );\n\n const handleEscKey = React.useCallback(\n (event: KeyboardEvent) => {\n const { key } = event;\n // accessibility standard: pressing escape should close the tooltip\n if (key === 'Escape') {\n hideTooltip(event);\n const shouldFocusReference =\n typeof focusReferenceOnEscape === 'function' ? focusReferenceOnEscape() : focusReferenceOnEscape;\n if (shouldFocusReference && referenceElement instanceof HTMLElement) {\n referenceElement.focus();\n }\n }\n },\n [focusReferenceOnEscape, hideTooltip, referenceElement],\n );\n\n // accessibilty standard: pressing escape should close the tooltip no matter where the focus is\n useGlobalKeyboardListener(handleEscKey);\n\n return React.useMemo(\n () => ({\n hasFocus: finalHasFocus,\n isHovering: finalIsHovering,\n latestOpenInteraction: finalLatestOpenInteraction,\n referenceElement,\n setReferenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n }),\n [\n finalHasFocus,\n finalIsHovering,\n finalLatestOpenInteraction,\n referenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n ],\n );\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
package/dist/cjs/package.json
CHANGED
|
@@ -15,22 +15,35 @@ const useControlledState = (controlledValue, defaultVal) => {
|
|
|
15
15
|
return [val, setInternalValue];
|
|
16
16
|
};
|
|
17
17
|
const useHeadlessTooltip = (config) => {
|
|
18
|
-
const {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const {
|
|
19
|
+
hasFocus,
|
|
20
|
+
isHovering,
|
|
21
|
+
latestOpenInteraction,
|
|
22
|
+
onOpen = () => {
|
|
23
|
+
},
|
|
24
|
+
onClose = () => {
|
|
25
|
+
},
|
|
26
|
+
focusReferenceOnEscape = false
|
|
27
|
+
} = config ?? {};
|
|
21
28
|
const [finalHasFocus, setInternalHasFocus] = useControlledState(hasFocus, false);
|
|
22
29
|
const [finalIsHovering, setInternalIsHovering] = useControlledState(isHovering, false);
|
|
23
30
|
const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState(latestOpenInteraction, "");
|
|
24
31
|
const [referenceElement, setReferenceElement] = React2.useState(null);
|
|
25
32
|
const [shouldShowPopover, setShouldShowPopover] = React2.useState(false);
|
|
26
|
-
const showTooltip = React2.useCallback(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const showTooltip = React2.useCallback(
|
|
34
|
+
(event) => {
|
|
35
|
+
setShouldShowPopover(true);
|
|
36
|
+
onOpen(event);
|
|
37
|
+
},
|
|
38
|
+
[onOpen]
|
|
39
|
+
);
|
|
40
|
+
const hideTooltip = React2.useCallback(
|
|
41
|
+
(event) => {
|
|
42
|
+
setShouldShowPopover(false);
|
|
43
|
+
onClose(event);
|
|
44
|
+
},
|
|
45
|
+
[onClose]
|
|
46
|
+
);
|
|
34
47
|
const trackLatestKeyboardInteraction = React2.useCallback(() => {
|
|
35
48
|
if (!shouldShowPopover) {
|
|
36
49
|
setLatestOpenInteraction("onFocus");
|
|
@@ -41,33 +54,52 @@ const useHeadlessTooltip = (config) => {
|
|
|
41
54
|
setLatestOpenInteraction("onMouseEnter");
|
|
42
55
|
}
|
|
43
56
|
}, [setLatestOpenInteraction, shouldShowPopover]);
|
|
44
|
-
const onFocus = React2.useCallback(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
setInternalHasFocus
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
const onFocus = React2.useCallback(
|
|
58
|
+
(event) => {
|
|
59
|
+
setInternalHasFocus(true);
|
|
60
|
+
trackLatestKeyboardInteraction();
|
|
61
|
+
if (!shouldShowPopover) {
|
|
62
|
+
showTooltip(event);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
[setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction]
|
|
66
|
+
);
|
|
67
|
+
const onBlur = React2.useCallback(
|
|
68
|
+
(event) => {
|
|
69
|
+
setInternalHasFocus(false);
|
|
70
|
+
if (!finalIsHovering || finalLatestOpenInteraction === "onFocus") hideTooltip(event);
|
|
71
|
+
},
|
|
72
|
+
[setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip]
|
|
73
|
+
);
|
|
74
|
+
const onMouseEnter = React2.useCallback(
|
|
75
|
+
(event) => {
|
|
76
|
+
setInternalIsHovering(true);
|
|
77
|
+
trackLatestMouseInteraction();
|
|
78
|
+
if (!shouldShowPopover) {
|
|
79
|
+
showTooltip(event);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
[setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction]
|
|
83
|
+
);
|
|
84
|
+
const onMouseLeave = React2.useCallback(
|
|
85
|
+
(event) => {
|
|
86
|
+
setInternalIsHovering(false);
|
|
87
|
+
if (!finalHasFocus || finalLatestOpenInteraction === "onMouseEnter") hideTooltip(event);
|
|
88
|
+
},
|
|
89
|
+
[setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip]
|
|
90
|
+
);
|
|
66
91
|
const handleEscKey = React2.useCallback(
|
|
67
|
-
(
|
|
68
|
-
|
|
92
|
+
(event) => {
|
|
93
|
+
const { key } = event;
|
|
94
|
+
if (key === "Escape") {
|
|
95
|
+
hideTooltip(event);
|
|
96
|
+
const shouldFocusReference = typeof focusReferenceOnEscape === "function" ? focusReferenceOnEscape() : focusReferenceOnEscape;
|
|
97
|
+
if (shouldFocusReference && referenceElement instanceof HTMLElement) {
|
|
98
|
+
referenceElement.focus();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
69
101
|
},
|
|
70
|
-
[hideTooltip]
|
|
102
|
+
[focusReferenceOnEscape, hideTooltip, referenceElement]
|
|
71
103
|
);
|
|
72
104
|
useGlobalKeyboardListener(handleEscKey);
|
|
73
105
|
return React2.useMemo(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSHooksHeadlessTooltip.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\n\n// This function is a custom hook that adds a keyboard event listener to the document\n// calls the specified function when a key is pressed.\nconst useGlobalKeyboardListener = (func: ({ key }: { key: string }) => void) => {\n React.useEffect(() => {\n document.addEventListener('keydown', func);\n return () => document.removeEventListener('keydown', func);\n }, [func]);\n};\n\nexport type LatestOpenInteraction = '' | 'onFocus' | 'onMouseEnter';\nexport type UseHeadlessTooltipConfig = {\n hasFocus?: boolean;\n isHovering?: boolean;\n latestOpenInteraction?: LatestOpenInteraction;\n onOpen?: () => void;\n onClose?: () => void;\n};\n\nconst useControlledState = <T,>(controlledValue?: T, defaultVal?: T) => {\n const [internalValue, setInternalValue] = React.useState<T | null>(defaultVal ?? null);\n const val = React.useMemo(() => {\n if (controlledValue !== undefined) return controlledValue;\n return internalValue;\n }, [controlledValue, internalValue]);\n return [val, setInternalValue] as const;\n};\n\n/**\n * A custom hook that provides logic for a headless tooltip. This hook can be used in a controlled or uncontrolled way.\n * @param {UseHeadlessTooltipConfig} config - The configuration object for the hook.\n * @param {boolean} config.hasFocus - Whether or not the trigger element has focus. If this is not provided, the hook will track focus internally.\n * @param {boolean} config.isHovering - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {LatestOpenInteraction} config.latestOpenInteraction - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {Function} config.onOpen - A callback that will be invoked when the tooltip is opened.\n * @param {Function} config.onClose - A callback that will be invoked when the tooltip is closed.\n * @returns {object} - An object containing the following properties:\n *\n * {boolean} hasFocus - Whether or not the trigger element has focus.\n *\n * {boolean} isHovering - Whether or not the mouse is hovering over the trigger element.\n *\n * {'' | 'onFocus' | 'onMouseEnter'} latestOpenInteraction - which was the last operation that is used to control if the tooltip should show or not.\n *\n * {string} finalLatestOpenInteraction - The most recent interaction that caused the tooltip to open.\n *\n * {HTMLDivElement} referenceElement - The trigger element.\n *\n * {function} setReferenceElement - A function that sets the trigger element.\n *\n * {boolean} shouldShowPopover - Whether or not the tooltip is visible.\n *\n * {function} showTooltip - A function that opens the tooltip.\n *\n * {function} hideTooltip - A function that closes the tooltip.\n *\n * {function} onFocus - A function that should be invoked when the trigger element receives focus.\n *\n * {function} onBlur - A function that should be invoked when the trigger element loses focus.\n *\n * {function} onMouseEnter - A function that should be invoked when the mouse enters the trigger element.\n *\n * {function} onMouseLeave - A function that should be invoked when the mouse leaves the trigger element.\n * @example\n * const tooltipHelpers = useHeadlessTooltip({\n * hasFocus: true,\n * isHovering: false,\n * onOpen: () => console.log('tooltip opened'),\n * onClose: () => console.log('tooltip closed'),\n * });\n * ...\n * <div>\n * <button\n * ref={tooltipHelpers.setReferenceElement}\n * onMouseEnter={tooltipHelpers.onMouseEnter}\n * onMouseLeave={tooltipHelpers.onMouseLeave}\n * onPointerEnter={tooltipHelpers.onMouseEnter}\n * onPointerLeave={tooltipHelpers.onMouseLeave}\n * onFocus={tooltipHelpers.onFocus}\n * onBlur={tooltipHelpers.onBlur}\n * >hello</button>\n * <DSPopperJS\n * referenceElement={tooltipHelpers.referenceElement}\n * shouldShowPopover={tooltipHelpers.shouldShowPopover}\n * >\n * <div>Tooltip content</div>\n * </DSPopperJS>\n * </div>\n */\nexport const useHeadlessTooltip = (config?: UseHeadlessTooltipConfig) => {\n // Extract the configuration values or set default values if they are not provided.\n const { hasFocus, isHovering, latestOpenInteraction, onOpen = () => {}, onClose = () => {} } = config ?? {};\n\n // this pattern is basically a way to allow usage of the hook in a controlled or uncontrolled way.\n const [finalHasFocus, setInternalHasFocus] = useControlledState<boolean>(hasFocus, false);\n const [finalIsHovering, setInternalIsHovering] = useControlledState<boolean>(isHovering, false);\n const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState<string>(latestOpenInteraction, '');\n\n // end of controlled/uncontrolled pattern\n\n // Set up state variables for the tooltip's visibility and the most recent interaction that caused it to open.\n // The most recent interaction is used to determine whether or not to close the tooltip when the user\n // moves the mouse away from the trigger element.\n const [referenceElement, setReferenceElement] = React.useState<Element | null>(null);\n const [shouldShowPopover, setShouldShowPopover] = React.useState<boolean>(false);\n\n // memoized versions of the show and hide functions\n // those include the callbacks to allow \"controlled\" usage of the hook\n const showTooltip = React.useCallback(() => {\n setShouldShowPopover(true);\n onOpen();\n }, [onOpen]);\n\n const hideTooltip = React.useCallback(() => {\n setShouldShowPopover(false);\n onClose();\n }, [onClose]);\n\n const trackLatestKeyboardInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onFocus');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n const trackLatestMouseInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onMouseEnter');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n // following here are the event handlers that are used to control the tooltip's visibility logic\n const onFocus = React.useCallback(() => {\n setInternalHasFocus(true); // uncontrolled usage tracking\n trackLatestKeyboardInteraction();\n if (!shouldShowPopover) {\n showTooltip();\n }\n }, [setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction]);\n\n const onBlur = React.useCallback(() => {\n setInternalHasFocus(false); // uncontrolled usage tracking\n // blur may triggered via keyboard navigation or mouse interaction\n // every time the mouse is hovering, we want to keep the tooltip open\n // but if the mouse is not hovering, we want to close the tooltip only if the last interaction was via keyboard\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalIsHovering || finalLatestOpenInteraction === 'onFocus') hideTooltip();\n }, [setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip]);\n\n const onMouseEnter = React.useCallback(() => {\n setInternalIsHovering(true); // uncontrolled usage tracking\n // kind of debouncing the mouse enter event to reduce the avarge O() notation of the function\n // even if this is continually invoked, it will be O(1) and controlled callbacks will be invoked only once\n trackLatestMouseInteraction();\n if (!shouldShowPopover) {\n showTooltip();\n }\n }, [setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction]);\n\n const onMouseLeave = React.useCallback(() => {\n setInternalIsHovering(false); // uncontrolled usage tracking\n // mouse leave may be triggered via keyboard navigation or mouse interaction\n // every time the trigger element has focus, we want to keep the tooltip open\n // but if the trigger element does not have focus, we want to close the tooltip only if the last interaction was via mouse\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalHasFocus || finalLatestOpenInteraction === 'onMouseEnter') hideTooltip();\n }, [setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip]);\n\n const handleEscKey = React.useCallback(\n ({ key }: { key: string }) => {\n // accessibility standard: pressing escape should close the tooltip\n if (key === 'Escape') hideTooltip();\n },\n [hideTooltip],\n );\n\n // accessibilty standard: pressing escape should close the tooltip no matter where the focus is\n useGlobalKeyboardListener(handleEscKey);\n\n return React.useMemo(\n () => ({\n hasFocus: finalHasFocus,\n isHovering: finalIsHovering,\n latestOpenInteraction: finalLatestOpenInteraction,\n referenceElement,\n setReferenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n }),\n [\n finalHasFocus,\n finalIsHovering,\n finalLatestOpenInteraction,\n referenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n ],\n );\n};\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,YAAW;
|
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\n\n/**\n * ds-hooks-headless-tooltip \u2014 headless show/hide state machine for tooltip-like surfaces. It is the\n * open/close primitive under ds-floating-context, which in turn backs tooltips, popovers and the\n * AppPicker dialog panel \u2014 so \"tooltip\" here means any such surface, not only a hover tooltip.\n *\n * Controlled or uncontrolled per input: pass `hasFocus`/`isHovering`/`latestOpenInteraction` to drive\n * it, or omit them and the hook tracks focus/hover internally. `showTooltip`/`hideTooltip` and the\n * onFocus/onBlur/onMouseEnter/onMouseLeave handlers forward the originating event to onOpen/onClose.\n *\n * LOAD-BEARING GOTCHA: the Escape handler is attached to the document via an ALWAYS-ON keydown\n * listener (useGlobalKeyboardListener below) \u2014 it calls hideTooltip on any Escape press regardless of\n * whether this surface is open or where focus currently is. This is intentional (a11y: Escape must be\n * able to dismiss from anywhere), and downstream depends on it: ds-floating-context's handleClose is\n * what decides whether a given Escape is actually \"in scope\" for that surface. Do NOT add\n * open-state/focus gating here \u2014 that scoping decision belongs to the consumer.\n */\n\n// This function is a custom hook that adds a keyboard event listener to the document\n// calls the specified function when a key is pressed.\n// Note: this attaches a raw DOM listener, so `func` receives a native KeyboardEvent, never a\n// React SyntheticEvent \u2014 the type below reflects that; do not widen it to React.KeyboardEventHandler.\nconst useGlobalKeyboardListener = (func: (event: KeyboardEvent) => void) => {\n React.useEffect(() => {\n document.addEventListener('keydown', func);\n return () => document.removeEventListener('keydown', func);\n }, [func]);\n};\n\nexport type LatestOpenInteraction = '' | 'onFocus' | 'onMouseEnter';\nexport type UseHeadlessTooltipConfig = {\n hasFocus?: boolean;\n isHovering?: boolean;\n latestOpenInteraction?: LatestOpenInteraction;\n // onOpen/onClose forward the originating event. `React.KeyboardEvent` is in the open union because\n // showTooltip can be called directly by a consumer in response to a keyboard interaction: this hook\n // backs non-tooltip contextual regions too (e.g. AppPicker opens on ArrowDown), so a keyboard event\n // is a valid open cause even though it is atypical for a plain tooltip. onClose's union carries the\n // native KeyboardEvent (not React's) because an Escape close comes from a document-level listener.\n onOpen?: (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => void;\n onClose?: (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => void;\n /**\n * Whether to focus the reference element after an Escape-triggered close. Accepts a plain\n * boolean, or a thunk evaluated at the moment Escape is handled \u2014 the thunk form exists so\n * consumers whose \"should I refocus\" answer depends on state resolved after this config object\n * is built (e.g. a focus-scope check that depends on a reference element resolved later in the\n * same render) can still get a non-stale answer instead of a render-behind snapshot.\n */\n focusReferenceOnEscape?: boolean | (() => boolean);\n};\n\nconst useControlledState = <T,>(controlledValue?: T, defaultVal?: T) => {\n const [internalValue, setInternalValue] = React.useState<T | null>(defaultVal ?? null);\n const val = React.useMemo(() => {\n if (controlledValue !== undefined) return controlledValue;\n return internalValue;\n }, [controlledValue, internalValue]);\n return [val, setInternalValue] as const;\n};\n\n/**\n * A custom hook that provides logic for a headless tooltip. This hook can be used in a controlled or uncontrolled way.\n * @param {UseHeadlessTooltipConfig} config - The configuration object for the hook.\n * @param {boolean} config.hasFocus - Whether or not the trigger element has focus. If this is not provided, the hook will track focus internally.\n * @param {boolean} config.isHovering - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {LatestOpenInteraction} config.latestOpenInteraction - Whether or not the mouse is hovering over the trigger element. If this is not provided, the hook will track hover internally.\n * @param {Function} config.onOpen - A callback that will be invoked when the tooltip is opened.\n * @param {Function} config.onClose - A callback that will be invoked when the tooltip is closed.\n * @returns {object} - An object containing the following properties:\n *\n * {boolean} hasFocus - Whether or not the trigger element has focus.\n *\n * {boolean} isHovering - Whether or not the mouse is hovering over the trigger element.\n *\n * {'' | 'onFocus' | 'onMouseEnter'} latestOpenInteraction - which was the last operation that is used to control if the tooltip should show or not.\n *\n * {string} finalLatestOpenInteraction - The most recent interaction that caused the tooltip to open.\n *\n * {HTMLDivElement} referenceElement - The trigger element.\n *\n * {function} setReferenceElement - A function that sets the trigger element.\n *\n * {boolean} shouldShowPopover - Whether or not the tooltip is visible.\n *\n * {function} showTooltip - A function that opens the tooltip.\n *\n * {function} hideTooltip - A function that closes the tooltip.\n *\n * {function} onFocus - A function that should be invoked when the trigger element receives focus.\n *\n * {function} onBlur - A function that should be invoked when the trigger element loses focus.\n *\n * {function} onMouseEnter - A function that should be invoked when the mouse enters the trigger element.\n *\n * {function} onMouseLeave - A function that should be invoked when the mouse leaves the trigger element.\n * @example\n * const tooltipHelpers = useHeadlessTooltip({\n * hasFocus: true,\n * isHovering: false,\n * onOpen: () => console.log('tooltip opened'),\n * onClose: () => console.log('tooltip closed'),\n * });\n * ...\n * <div>\n * <button\n * ref={tooltipHelpers.setReferenceElement}\n * onMouseEnter={tooltipHelpers.onMouseEnter}\n * onMouseLeave={tooltipHelpers.onMouseLeave}\n * onPointerEnter={tooltipHelpers.onMouseEnter}\n * onPointerLeave={tooltipHelpers.onMouseLeave}\n * onFocus={tooltipHelpers.onFocus}\n * onBlur={tooltipHelpers.onBlur}\n * >hello</button>\n * <DSPopperJS\n * referenceElement={tooltipHelpers.referenceElement}\n * shouldShowPopover={tooltipHelpers.shouldShowPopover}\n * >\n * <div>Tooltip content</div>\n * </DSPopperJS>\n * </div>\n */\nexport const useHeadlessTooltip = (config?: UseHeadlessTooltipConfig) => {\n // Extract the configuration values or set default values if they are not provided.\n const {\n hasFocus,\n isHovering,\n latestOpenInteraction,\n onOpen = () => {},\n onClose = () => {},\n focusReferenceOnEscape = false,\n } = config ?? {};\n\n // this pattern is basically a way to allow usage of the hook in a controlled or uncontrolled way.\n const [finalHasFocus, setInternalHasFocus] = useControlledState<boolean>(hasFocus, false);\n const [finalIsHovering, setInternalIsHovering] = useControlledState<boolean>(isHovering, false);\n const [finalLatestOpenInteraction, setLatestOpenInteraction] = useControlledState<string>(latestOpenInteraction, '');\n\n // end of controlled/uncontrolled pattern\n\n // Set up state variables for the tooltip's visibility and the most recent interaction that caused it to open.\n // The most recent interaction is used to determine whether or not to close the tooltip when the user\n // moves the mouse away from the trigger element.\n const [referenceElement, setReferenceElement] = React.useState<Element | null>(null);\n const [shouldShowPopover, setShouldShowPopover] = React.useState<boolean>(false);\n\n // memoized versions of the show and hide functions\n // those include the callbacks to allow \"controlled\" usage of the hook\n const showTooltip = React.useCallback(\n (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => {\n setShouldShowPopover(true);\n onOpen(event);\n },\n [onOpen],\n );\n\n const hideTooltip = React.useCallback(\n (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => {\n setShouldShowPopover(false);\n onClose(event);\n },\n [onClose],\n );\n\n const trackLatestKeyboardInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onFocus');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n const trackLatestMouseInteraction = React.useCallback(() => {\n if (!shouldShowPopover) {\n setLatestOpenInteraction('onMouseEnter');\n }\n }, [setLatestOpenInteraction, shouldShowPopover]);\n\n // following here are the event handlers that are used to control the tooltip's visibility logic\n const onFocus = React.useCallback<React.FocusEventHandler>(\n (event) => {\n setInternalHasFocus(true); // uncontrolled usage tracking\n trackLatestKeyboardInteraction();\n if (!shouldShowPopover) {\n showTooltip(event);\n }\n },\n [setInternalHasFocus, shouldShowPopover, showTooltip, trackLatestKeyboardInteraction],\n );\n\n const onBlur = React.useCallback<React.FocusEventHandler>(\n (event) => {\n setInternalHasFocus(false); // uncontrolled usage tracking\n // blur may triggered via keyboard navigation or mouse interaction\n // every time the mouse is hovering, we want to keep the tooltip open\n // but if the mouse is not hovering, we want to close the tooltip only if the last interaction was via keyboard\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalIsHovering || finalLatestOpenInteraction === 'onFocus') hideTooltip(event);\n },\n [setInternalHasFocus, finalIsHovering, finalLatestOpenInteraction, hideTooltip],\n );\n\n const onMouseEnter = React.useCallback<React.MouseEventHandler>(\n (event) => {\n setInternalIsHovering(true); // uncontrolled usage tracking\n // kind of debouncing the mouse enter event to reduce the avarge O() notation of the function\n // even if this is continually invoked, it will be O(1) and controlled callbacks will be invoked only once\n trackLatestMouseInteraction();\n if (!shouldShowPopover) {\n showTooltip(event);\n }\n },\n [setInternalIsHovering, shouldShowPopover, showTooltip, trackLatestMouseInteraction],\n );\n\n const onMouseLeave = React.useCallback<React.MouseEventHandler>(\n (event) => {\n setInternalIsHovering(false); // uncontrolled usage tracking\n // mouse leave may be triggered via keyboard navigation or mouse interaction\n // every time the trigger element has focus, we want to keep the tooltip open\n // but if the trigger element does not have focus, we want to close the tooltip only if the last interaction was via mouse\n // e.g if the user keyboard navigates to the trigger element and then moves the mouse away, we want to keep the tooltip open\n if (!finalHasFocus || finalLatestOpenInteraction === 'onMouseEnter') hideTooltip(event);\n },\n [setInternalIsHovering, finalHasFocus, finalLatestOpenInteraction, hideTooltip],\n );\n\n const handleEscKey = React.useCallback(\n (event: KeyboardEvent) => {\n const { key } = event;\n // accessibility standard: pressing escape should close the tooltip\n if (key === 'Escape') {\n hideTooltip(event);\n const shouldFocusReference =\n typeof focusReferenceOnEscape === 'function' ? focusReferenceOnEscape() : focusReferenceOnEscape;\n if (shouldFocusReference && referenceElement instanceof HTMLElement) {\n referenceElement.focus();\n }\n }\n },\n [focusReferenceOnEscape, hideTooltip, referenceElement],\n );\n\n // accessibilty standard: pressing escape should close the tooltip no matter where the focus is\n useGlobalKeyboardListener(handleEscKey);\n\n return React.useMemo(\n () => ({\n hasFocus: finalHasFocus,\n isHovering: finalIsHovering,\n latestOpenInteraction: finalLatestOpenInteraction,\n referenceElement,\n setReferenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n }),\n [\n finalHasFocus,\n finalIsHovering,\n finalLatestOpenInteraction,\n referenceElement,\n shouldShowPopover,\n showTooltip,\n hideTooltip,\n onFocus,\n onBlur,\n onMouseEnter,\n onMouseLeave,\n ],\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
package/dist/esm/package.json
CHANGED
|
@@ -4,8 +4,16 @@ export type UseHeadlessTooltipConfig = {
|
|
|
4
4
|
hasFocus?: boolean;
|
|
5
5
|
isHovering?: boolean;
|
|
6
6
|
latestOpenInteraction?: LatestOpenInteraction;
|
|
7
|
-
onOpen?: () => void;
|
|
8
|
-
onClose?: () => void;
|
|
7
|
+
onOpen?: (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => void;
|
|
8
|
+
onClose?: (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => void;
|
|
9
|
+
/**
|
|
10
|
+
* Whether to focus the reference element after an Escape-triggered close. Accepts a plain
|
|
11
|
+
* boolean, or a thunk evaluated at the moment Escape is handled — the thunk form exists so
|
|
12
|
+
* consumers whose "should I refocus" answer depends on state resolved after this config object
|
|
13
|
+
* is built (e.g. a focus-scope check that depends on a reference element resolved later in the
|
|
14
|
+
* same render) can still get a non-stale answer instead of a render-behind snapshot.
|
|
15
|
+
*/
|
|
16
|
+
focusReferenceOnEscape?: boolean | (() => boolean);
|
|
9
17
|
};
|
|
10
18
|
/**
|
|
11
19
|
* A custom hook that provides logic for a headless tooltip. This hook can be used in a controlled or uncontrolled way.
|
|
@@ -75,10 +83,10 @@ export declare const useHeadlessTooltip: (config?: UseHeadlessTooltipConfig) =>
|
|
|
75
83
|
referenceElement: Element | null;
|
|
76
84
|
setReferenceElement: React.Dispatch<React.SetStateAction<Element | null>>;
|
|
77
85
|
shouldShowPopover: boolean;
|
|
78
|
-
showTooltip: () => void;
|
|
79
|
-
hideTooltip: () => void;
|
|
80
|
-
onFocus:
|
|
81
|
-
onBlur:
|
|
82
|
-
onMouseEnter:
|
|
83
|
-
onMouseLeave:
|
|
86
|
+
showTooltip: (event?: React.FocusEvent | React.MouseEvent | React.KeyboardEvent) => void;
|
|
87
|
+
hideTooltip: (event?: React.FocusEvent | React.MouseEvent | KeyboardEvent) => void;
|
|
88
|
+
onFocus: React.FocusEventHandler<Element>;
|
|
89
|
+
onBlur: React.FocusEventHandler<Element>;
|
|
90
|
+
onMouseEnter: React.MouseEventHandler<Element>;
|
|
91
|
+
onMouseLeave: React.MouseEventHandler<Element>;
|
|
84
92
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elliemae/ds-hooks-headless-tooltip",
|
|
3
|
-
"version": "3.70.0-
|
|
3
|
+
"version": "3.70.0-rc.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "ICE MT - Dimsum - Headless tooltip Hook",
|
|
6
6
|
"files": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "https://
|
|
25
|
+
"url": "https://github.com/intcx/PLATFORM-UI.dimsum.git"
|
|
26
26
|
},
|
|
27
27
|
"engines": {
|
|
28
28
|
"pnpm": ">=9",
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"jest": "^30.0.0",
|
|
40
|
-
"@elliemae/ds-monorepo-devops": "3.70.0-
|
|
40
|
+
"@elliemae/ds-monorepo-devops": "3.70.0-rc.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"lodash-es": "^4.
|
|
43
|
+
"lodash-es": "^4.18.1",
|
|
44
44
|
"react": "^18.3.1",
|
|
45
45
|
"react-dom": "^18.3.1",
|
|
46
|
-
"styled-components": "~5.3.
|
|
46
|
+
"styled-components": "~5.3.11",
|
|
47
47
|
"styled-system": "^5.1.5"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
@@ -59,4 +59,4 @@
|
|
|
59
59
|
"build": "cross-env NODE_ENV=production node ../../../scripts/build/build.mjs",
|
|
60
60
|
"checkDeps": "npx -yes ../../util/ds-codemods check-missing-packages --projectFolderPath=\"./\" --ignorePackagesGlobPattern=\"\" --ignoreFilesGlobPattern=\"**/test-ables/*,**/tests/*\""
|
|
61
61
|
}
|
|
62
|
-
}
|
|
62
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|