@asnewyla/unstyled-tooltip 0.2.0 → 0.2.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/index.js +66 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38 -11
- package/dist/index.mjs.map +1 -1
- package/dist/test-utils.js +36 -11
- package/dist/test-utils.js.map +1 -1
- package/dist/test-utils.mjs +7 -4
- package/dist/test-utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
|
-
'use
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
20
|
|
|
3
|
-
|
|
4
|
-
var
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
Tooltip: () => Tooltip,
|
|
25
|
+
TooltipContent: () => TooltipContent,
|
|
26
|
+
TooltipTrigger: () => TooltipTrigger
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
5
29
|
|
|
6
30
|
// src/components/Tooltip.tsx
|
|
7
|
-
var
|
|
31
|
+
var import_react2 = require("react");
|
|
32
|
+
|
|
33
|
+
// src/components/TooltipContext.tsx
|
|
34
|
+
var import_react = require("react");
|
|
35
|
+
var TooltipContext = (0, import_react.createContext)(null);
|
|
8
36
|
function useTooltipContext() {
|
|
9
|
-
const context =
|
|
37
|
+
const context = (0, import_react.useContext)(TooltipContext);
|
|
10
38
|
if (!context) {
|
|
11
39
|
throw new Error(
|
|
12
40
|
"Tooltip compound components (TooltipTrigger, TooltipContent) must be rendered inside <Tooltip>"
|
|
@@ -20,9 +48,9 @@ function useTooltipOpen({
|
|
|
20
48
|
onOpenChange
|
|
21
49
|
}) {
|
|
22
50
|
const isControlled = open !== void 0;
|
|
23
|
-
const [internalOpen, setInternalOpen] =
|
|
51
|
+
const [internalOpen, setInternalOpen] = (0, import_react.useState)(defaultOpen ?? false);
|
|
24
52
|
const actualOpen = isControlled ? open : internalOpen;
|
|
25
|
-
const setOpen =
|
|
53
|
+
const setOpen = (0, import_react.useCallback)(
|
|
26
54
|
(next) => {
|
|
27
55
|
if (!isControlled) {
|
|
28
56
|
setInternalOpen(next);
|
|
@@ -33,6 +61,9 @@ function useTooltipOpen({
|
|
|
33
61
|
);
|
|
34
62
|
return { open: actualOpen, setOpen };
|
|
35
63
|
}
|
|
64
|
+
|
|
65
|
+
// src/components/Tooltip.tsx
|
|
66
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
67
|
function TooltipInner({
|
|
37
68
|
open,
|
|
38
69
|
defaultOpen,
|
|
@@ -42,28 +73,28 @@ function TooltipInner({
|
|
|
42
73
|
style,
|
|
43
74
|
...rest
|
|
44
75
|
}, ref) {
|
|
45
|
-
const contentId =
|
|
76
|
+
const contentId = (0, import_react2.useId)();
|
|
46
77
|
const { open: isOpen, setOpen } = useTooltipOpen({
|
|
47
78
|
open,
|
|
48
79
|
defaultOpen,
|
|
49
80
|
onOpenChange
|
|
50
81
|
});
|
|
51
|
-
const openTimer =
|
|
52
|
-
const clearOpenTimer =
|
|
82
|
+
const openTimer = (0, import_react2.useRef)(null);
|
|
83
|
+
const clearOpenTimer = (0, import_react2.useCallback)(() => {
|
|
53
84
|
if (openTimer.current !== null) {
|
|
54
85
|
clearTimeout(openTimer.current);
|
|
55
86
|
openTimer.current = null;
|
|
56
87
|
}
|
|
57
88
|
}, []);
|
|
58
|
-
const close =
|
|
89
|
+
const close = (0, import_react2.useCallback)(() => {
|
|
59
90
|
clearOpenTimer();
|
|
60
91
|
setOpen(false);
|
|
61
92
|
}, [clearOpenTimer, setOpen]);
|
|
62
|
-
const openNow =
|
|
93
|
+
const openNow = (0, import_react2.useCallback)(() => {
|
|
63
94
|
clearOpenTimer();
|
|
64
95
|
setOpen(true);
|
|
65
96
|
}, [clearOpenTimer, setOpen]);
|
|
66
|
-
const openWithDelay =
|
|
97
|
+
const openWithDelay = (0, import_react2.useCallback)(() => {
|
|
67
98
|
clearOpenTimer();
|
|
68
99
|
if (delay <= 0) {
|
|
69
100
|
setOpen(true);
|
|
@@ -74,8 +105,8 @@ function TooltipInner({
|
|
|
74
105
|
setOpen(true);
|
|
75
106
|
}, delay);
|
|
76
107
|
}, [clearOpenTimer, delay, setOpen]);
|
|
77
|
-
|
|
78
|
-
|
|
108
|
+
(0, import_react2.useEffect)(() => clearOpenTimer, [clearOpenTimer]);
|
|
109
|
+
(0, import_react2.useEffect)(() => {
|
|
79
110
|
if (!isOpen) return;
|
|
80
111
|
const onKeyDown = (event) => {
|
|
81
112
|
if (event.key === "Escape") {
|
|
@@ -85,7 +116,7 @@ function TooltipInner({
|
|
|
85
116
|
document.addEventListener("keydown", onKeyDown);
|
|
86
117
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
87
118
|
}, [isOpen, close]);
|
|
88
|
-
const contextValue =
|
|
119
|
+
const contextValue = (0, import_react2.useMemo)(
|
|
89
120
|
() => ({ open: isOpen, contentId, openNow, openWithDelay, close }),
|
|
90
121
|
[isOpen, contentId, openNow, openWithDelay, close]
|
|
91
122
|
);
|
|
@@ -94,20 +125,27 @@ function TooltipInner({
|
|
|
94
125
|
display: "inline-block",
|
|
95
126
|
...style
|
|
96
127
|
};
|
|
97
|
-
return /* @__PURE__ */
|
|
128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TooltipContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...rest, ref, style: wrapperStyle, children }) });
|
|
98
129
|
}
|
|
99
|
-
var Tooltip =
|
|
130
|
+
var Tooltip = (0, import_react2.forwardRef)(TooltipInner);
|
|
131
|
+
|
|
132
|
+
// src/components/TooltipContent.tsx
|
|
133
|
+
var import_react3 = require("react");
|
|
134
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
100
135
|
function TooltipContentInner({ side = "top", ...rest }, ref) {
|
|
101
136
|
const { open, contentId } = useTooltipContext();
|
|
102
137
|
if (!open) {
|
|
103
138
|
return null;
|
|
104
139
|
}
|
|
105
|
-
return /* @__PURE__ */
|
|
140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...rest, ref, role: "tooltip", id: contentId, "data-side": side });
|
|
106
141
|
}
|
|
107
|
-
var TooltipContent =
|
|
142
|
+
var TooltipContent = (0, import_react3.forwardRef)(
|
|
108
143
|
TooltipContentInner
|
|
109
144
|
);
|
|
110
145
|
|
|
146
|
+
// src/components/TooltipTrigger.tsx
|
|
147
|
+
var import_react4 = require("react");
|
|
148
|
+
|
|
111
149
|
// src/components/composeEventHandlers.ts
|
|
112
150
|
function composeEventHandlers(consumerHandler, ownHandler) {
|
|
113
151
|
return (event) => {
|
|
@@ -121,10 +159,10 @@ function TooltipTrigger({
|
|
|
121
159
|
children
|
|
122
160
|
}) {
|
|
123
161
|
const { open, contentId, openNow, openWithDelay, close } = useTooltipContext();
|
|
124
|
-
const child =
|
|
162
|
+
const child = import_react4.Children.only(children);
|
|
125
163
|
const childProps = child.props;
|
|
126
164
|
const describedBy = open ? [childProps["aria-describedby"], contentId].filter(Boolean).join(" ") : childProps["aria-describedby"];
|
|
127
|
-
return
|
|
165
|
+
return (0, import_react4.cloneElement)(child, {
|
|
128
166
|
"aria-describedby": describedBy,
|
|
129
167
|
onPointerEnter: composeEventHandlers(
|
|
130
168
|
childProps.onPointerEnter,
|
|
@@ -136,9 +174,10 @@ function TooltipTrigger({
|
|
|
136
174
|
onBlur: composeEventHandlers(childProps.onBlur, close)
|
|
137
175
|
});
|
|
138
176
|
}
|
|
139
|
-
|
|
140
|
-
exports
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
177
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
178
|
+
0 && (module.exports = {
|
|
179
|
+
Tooltip,
|
|
180
|
+
TooltipContent,
|
|
181
|
+
TooltipTrigger
|
|
182
|
+
});
|
|
144
183
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/TooltipContext.tsx","../src/components/Tooltip.tsx","../src/components/TooltipContent.tsx","../src/components/composeEventHandlers.ts","../src/components/TooltipTrigger.tsx"],"names":["createContext","useContext","useState","useCallback","useId","useRef","useEffect","useMemo","jsx","forwardRef","Children","cloneElement"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useCallback, useContext, useState } from 'react';\n\nexport type TooltipContextValue = {\n open: boolean;\n contentId: string;\n /** Open now, no delay — used for keyboard focus. */\n openNow: () => void;\n /** Open after the configured hover delay — used for pointer enter. */\n openWithDelay: () => void;\n /** Close now and cancel any pending open. */\n close: () => void;\n};\n\nexport const TooltipContext = createContext<TooltipContextValue | null>(null);\n\nexport function useTooltipContext(): TooltipContextValue {\n const context = useContext(TooltipContext);\n if (!context) {\n throw new Error(\n 'Tooltip compound components (TooltipTrigger, TooltipContent) must be rendered inside <Tooltip>',\n );\n }\n return context;\n}\n\nexport function useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n}: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): { open: boolean; setOpen: (next: boolean) => void } {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const actualOpen = isControlled ? open : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n return { open: actualOpen, setOpen };\n}\n","import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { TooltipContext, useTooltipOpen } from './TooltipContext';\n\nexport type TooltipProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Hover open delay in ms. Keyboard focus always opens with no delay. */\n delay?: number;\n children: ReactNode;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'onChange' | 'children'>;\n\nfunction TooltipInner(\n {\n open,\n defaultOpen,\n onOpenChange,\n delay = 700,\n children,\n style,\n ...rest\n }: TooltipProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const contentId = useId();\n const { open: isOpen, setOpen } = useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearOpenTimer = useCallback(() => {\n if (openTimer.current !== null) {\n clearTimeout(openTimer.current);\n openTimer.current = null;\n }\n }, []);\n\n const close = useCallback(() => {\n clearOpenTimer();\n setOpen(false);\n }, [clearOpenTimer, setOpen]);\n\n const openNow = useCallback(() => {\n clearOpenTimer();\n setOpen(true);\n }, [clearOpenTimer, setOpen]);\n\n const openWithDelay = useCallback(() => {\n clearOpenTimer();\n if (delay <= 0) {\n setOpen(true);\n return;\n }\n openTimer.current = setTimeout(() => {\n openTimer.current = null;\n setOpen(true);\n }, delay);\n }, [clearOpenTimer, delay, setOpen]);\n\n useEffect(() => clearOpenTimer, [clearOpenTimer]);\n\n // Escape closes an open tooltip — WAI-ARIA APG's one hard requirement.\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, close]);\n\n const contextValue = useMemo(\n () => ({ open: isOpen, contentId, openNow, openWithDelay, close }),\n [isOpen, contentId, openNow, openWithDelay, close],\n );\n\n // A shrink-wrapped positioned box so TooltipContent can place itself with\n // plain CSS (position: absolute + data-side) — no portal, no measurement.\n const wrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-block',\n ...style,\n };\n\n return (\n <TooltipContext.Provider value={contextValue}>\n <span {...rest} ref={ref} style={wrapperStyle}>\n {children}\n </span>\n </TooltipContext.Provider>\n );\n}\n\nexport const Tooltip = forwardRef<HTMLSpanElement, TooltipProps>(TooltipInner);\n","import {\n type ComponentPropsWithoutRef,\n type ForwardedRef,\n forwardRef,\n} from 'react';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\n\nexport type TooltipContentProps = {\n side?: TooltipSide;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'role' | 'id'>;\n\nfunction TooltipContentInner(\n { side = 'top', ...rest }: TooltipContentProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const { open, contentId } = useTooltipContext();\n\n if (!open) {\n return null;\n }\n\n return (\n <span {...rest} ref={ref} role=\"tooltip\" id={contentId} data-side={side} />\n );\n}\n\nexport const TooltipContent = forwardRef<HTMLSpanElement, TooltipContentProps>(\n TooltipContentInner,\n);\n","/**\n * Wraps a consumer-supplied event handler so the component's own handler runs\n * after it. Both always run — a tooltip never wants the consumer to be able to\n * silently suppress its open/close behavior.\n */\nexport function composeEventHandlers<E>(\n consumerHandler: ((event: E) => void) | undefined,\n ownHandler: (event: E) => void,\n): (event: E) => void {\n return (event: E) => {\n consumerHandler?.(event);\n ownHandler(event);\n };\n}\n","import {\n Children,\n cloneElement,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { composeEventHandlers } from './composeEventHandlers';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipTriggerProps = {\n /** A single focusable element. It is cloned, not wrapped. */\n children: ReactNode;\n};\n\ntype TriggerChildProps = {\n 'aria-describedby'?: string;\n onPointerEnter?: (event: PointerEvent) => void;\n onPointerLeave?: (event: PointerEvent) => void;\n onPointerDown?: (event: PointerEvent) => void;\n onFocus?: (event: React.FocusEvent) => void;\n onBlur?: (event: React.FocusEvent) => void;\n};\n\nexport function TooltipTrigger({\n children,\n}: TooltipTriggerProps): ReactElement {\n const { open, contentId, openNow, openWithDelay, close } =\n useTooltipContext();\n const child = Children.only(children) as ReactElement<TriggerChildProps>;\n const childProps = child.props;\n\n const describedBy = open\n ? [childProps['aria-describedby'], contentId].filter(Boolean).join(' ')\n : childProps['aria-describedby'];\n\n return cloneElement(child, {\n 'aria-describedby': describedBy,\n onPointerEnter: composeEventHandlers(\n childProps.onPointerEnter,\n openWithDelay,\n ),\n onPointerLeave: composeEventHandlers(childProps.onPointerLeave, close),\n onPointerDown: composeEventHandlers(childProps.onPointerDown, close),\n onFocus: composeEventHandlers(childProps.onFocus, openNow),\n onBlur: composeEventHandlers(childProps.onBlur, close),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/Tooltip.tsx","../src/components/TooltipContext.tsx","../src/components/TooltipContent.tsx","../src/components/TooltipTrigger.tsx","../src/components/composeEventHandlers.ts"],"sourcesContent":["export {\n Tooltip,\n TooltipContent,\n type TooltipContentProps,\n type TooltipProps,\n type TooltipSide,\n TooltipTrigger,\n type TooltipTriggerProps,\n} from './components';\n","import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { TooltipContext, useTooltipOpen } from './TooltipContext';\n\nexport type TooltipProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Hover open delay in ms. Keyboard focus always opens with no delay. */\n delay?: number;\n children: ReactNode;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'onChange' | 'children'>;\n\nfunction TooltipInner(\n {\n open,\n defaultOpen,\n onOpenChange,\n delay = 700,\n children,\n style,\n ...rest\n }: TooltipProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const contentId = useId();\n const { open: isOpen, setOpen } = useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearOpenTimer = useCallback(() => {\n if (openTimer.current !== null) {\n clearTimeout(openTimer.current);\n openTimer.current = null;\n }\n }, []);\n\n const close = useCallback(() => {\n clearOpenTimer();\n setOpen(false);\n }, [clearOpenTimer, setOpen]);\n\n const openNow = useCallback(() => {\n clearOpenTimer();\n setOpen(true);\n }, [clearOpenTimer, setOpen]);\n\n const openWithDelay = useCallback(() => {\n clearOpenTimer();\n if (delay <= 0) {\n setOpen(true);\n return;\n }\n openTimer.current = setTimeout(() => {\n openTimer.current = null;\n setOpen(true);\n }, delay);\n }, [clearOpenTimer, delay, setOpen]);\n\n useEffect(() => clearOpenTimer, [clearOpenTimer]);\n\n // Escape closes an open tooltip — WAI-ARIA APG's one hard requirement.\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, close]);\n\n const contextValue = useMemo(\n () => ({ open: isOpen, contentId, openNow, openWithDelay, close }),\n [isOpen, contentId, openNow, openWithDelay, close],\n );\n\n // A shrink-wrapped positioned box so TooltipContent can place itself with\n // plain CSS (position: absolute + data-side) — no portal, no measurement.\n const wrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-block',\n ...style,\n };\n\n return (\n <TooltipContext.Provider value={contextValue}>\n <span {...rest} ref={ref} style={wrapperStyle}>\n {children}\n </span>\n </TooltipContext.Provider>\n );\n}\n\nexport const Tooltip = forwardRef<HTMLSpanElement, TooltipProps>(TooltipInner);\n","import { createContext, useCallback, useContext, useState } from 'react';\n\nexport type TooltipContextValue = {\n open: boolean;\n contentId: string;\n /** Open now, no delay — used for keyboard focus. */\n openNow: () => void;\n /** Open after the configured hover delay — used for pointer enter. */\n openWithDelay: () => void;\n /** Close now and cancel any pending open. */\n close: () => void;\n};\n\nexport const TooltipContext = createContext<TooltipContextValue | null>(null);\n\nexport function useTooltipContext(): TooltipContextValue {\n const context = useContext(TooltipContext);\n if (!context) {\n throw new Error(\n 'Tooltip compound components (TooltipTrigger, TooltipContent) must be rendered inside <Tooltip>',\n );\n }\n return context;\n}\n\nexport function useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n}: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): { open: boolean; setOpen: (next: boolean) => void } {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const actualOpen = isControlled ? open : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n return { open: actualOpen, setOpen };\n}\n","import {\n type ComponentPropsWithoutRef,\n type ForwardedRef,\n forwardRef,\n} from 'react';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\n\nexport type TooltipContentProps = {\n side?: TooltipSide;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'role' | 'id'>;\n\nfunction TooltipContentInner(\n { side = 'top', ...rest }: TooltipContentProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const { open, contentId } = useTooltipContext();\n\n if (!open) {\n return null;\n }\n\n return (\n <span {...rest} ref={ref} role=\"tooltip\" id={contentId} data-side={side} />\n );\n}\n\nexport const TooltipContent = forwardRef<HTMLSpanElement, TooltipContentProps>(\n TooltipContentInner,\n);\n","import {\n Children,\n cloneElement,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { composeEventHandlers } from './composeEventHandlers';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipTriggerProps = {\n /** A single focusable element. It is cloned, not wrapped. */\n children: ReactNode;\n};\n\ntype TriggerChildProps = {\n 'aria-describedby'?: string;\n onPointerEnter?: (event: PointerEvent) => void;\n onPointerLeave?: (event: PointerEvent) => void;\n onPointerDown?: (event: PointerEvent) => void;\n onFocus?: (event: React.FocusEvent) => void;\n onBlur?: (event: React.FocusEvent) => void;\n};\n\nexport function TooltipTrigger({\n children,\n}: TooltipTriggerProps): ReactElement {\n const { open, contentId, openNow, openWithDelay, close } =\n useTooltipContext();\n const child = Children.only(children) as ReactElement<TriggerChildProps>;\n const childProps = child.props;\n\n const describedBy = open\n ? [childProps['aria-describedby'], contentId].filter(Boolean).join(' ')\n : childProps['aria-describedby'];\n\n return cloneElement(child, {\n 'aria-describedby': describedBy,\n onPointerEnter: composeEventHandlers(\n childProps.onPointerEnter,\n openWithDelay,\n ),\n onPointerLeave: composeEventHandlers(childProps.onPointerLeave, close),\n onPointerDown: composeEventHandlers(childProps.onPointerDown, close),\n onFocus: composeEventHandlers(childProps.onFocus, openNow),\n onBlur: composeEventHandlers(childProps.onBlur, close),\n });\n}\n","/**\n * Wraps a consumer-supplied event handler so the component's own handler runs\n * after it. Both always run — a tooltip never wants the consumer to be able to\n * silently suppress its open/close behavior.\n */\nexport function composeEventHandlers<E>(\n consumerHandler: ((event: E) => void) | undefined,\n ownHandler: (event: E) => void,\n): (event: E) => void {\n return (event: E) => {\n consumerHandler?.(event);\n ownHandler(event);\n };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
1
|
+
'use client';
|
|
3
2
|
|
|
4
3
|
// src/components/Tooltip.tsx
|
|
4
|
+
import {
|
|
5
|
+
forwardRef,
|
|
6
|
+
useCallback as useCallback2,
|
|
7
|
+
useEffect,
|
|
8
|
+
useId,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef
|
|
11
|
+
} from "react";
|
|
12
|
+
|
|
13
|
+
// src/components/TooltipContext.tsx
|
|
14
|
+
import { createContext, useCallback, useContext, useState } from "react";
|
|
5
15
|
var TooltipContext = createContext(null);
|
|
6
16
|
function useTooltipContext() {
|
|
7
17
|
const context = useContext(TooltipContext);
|
|
@@ -31,6 +41,9 @@ function useTooltipOpen({
|
|
|
31
41
|
);
|
|
32
42
|
return { open: actualOpen, setOpen };
|
|
33
43
|
}
|
|
44
|
+
|
|
45
|
+
// src/components/Tooltip.tsx
|
|
46
|
+
import { jsx } from "react/jsx-runtime";
|
|
34
47
|
function TooltipInner({
|
|
35
48
|
open,
|
|
36
49
|
defaultOpen,
|
|
@@ -47,21 +60,21 @@ function TooltipInner({
|
|
|
47
60
|
onOpenChange
|
|
48
61
|
});
|
|
49
62
|
const openTimer = useRef(null);
|
|
50
|
-
const clearOpenTimer =
|
|
63
|
+
const clearOpenTimer = useCallback2(() => {
|
|
51
64
|
if (openTimer.current !== null) {
|
|
52
65
|
clearTimeout(openTimer.current);
|
|
53
66
|
openTimer.current = null;
|
|
54
67
|
}
|
|
55
68
|
}, []);
|
|
56
|
-
const close =
|
|
69
|
+
const close = useCallback2(() => {
|
|
57
70
|
clearOpenTimer();
|
|
58
71
|
setOpen(false);
|
|
59
72
|
}, [clearOpenTimer, setOpen]);
|
|
60
|
-
const openNow =
|
|
73
|
+
const openNow = useCallback2(() => {
|
|
61
74
|
clearOpenTimer();
|
|
62
75
|
setOpen(true);
|
|
63
76
|
}, [clearOpenTimer, setOpen]);
|
|
64
|
-
const openWithDelay =
|
|
77
|
+
const openWithDelay = useCallback2(() => {
|
|
65
78
|
clearOpenTimer();
|
|
66
79
|
if (delay <= 0) {
|
|
67
80
|
setOpen(true);
|
|
@@ -95,17 +108,29 @@ function TooltipInner({
|
|
|
95
108
|
return /* @__PURE__ */ jsx(TooltipContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("span", { ...rest, ref, style: wrapperStyle, children }) });
|
|
96
109
|
}
|
|
97
110
|
var Tooltip = forwardRef(TooltipInner);
|
|
111
|
+
|
|
112
|
+
// src/components/TooltipContent.tsx
|
|
113
|
+
import {
|
|
114
|
+
forwardRef as forwardRef2
|
|
115
|
+
} from "react";
|
|
116
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
98
117
|
function TooltipContentInner({ side = "top", ...rest }, ref) {
|
|
99
118
|
const { open, contentId } = useTooltipContext();
|
|
100
119
|
if (!open) {
|
|
101
120
|
return null;
|
|
102
121
|
}
|
|
103
|
-
return /* @__PURE__ */
|
|
122
|
+
return /* @__PURE__ */ jsx2("span", { ...rest, ref, role: "tooltip", id: contentId, "data-side": side });
|
|
104
123
|
}
|
|
105
|
-
var TooltipContent =
|
|
124
|
+
var TooltipContent = forwardRef2(
|
|
106
125
|
TooltipContentInner
|
|
107
126
|
);
|
|
108
127
|
|
|
128
|
+
// src/components/TooltipTrigger.tsx
|
|
129
|
+
import {
|
|
130
|
+
Children,
|
|
131
|
+
cloneElement
|
|
132
|
+
} from "react";
|
|
133
|
+
|
|
109
134
|
// src/components/composeEventHandlers.ts
|
|
110
135
|
function composeEventHandlers(consumerHandler, ownHandler) {
|
|
111
136
|
return (event) => {
|
|
@@ -134,7 +159,9 @@ function TooltipTrigger({
|
|
|
134
159
|
onBlur: composeEventHandlers(childProps.onBlur, close)
|
|
135
160
|
});
|
|
136
161
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
162
|
+
export {
|
|
163
|
+
Tooltip,
|
|
164
|
+
TooltipContent,
|
|
165
|
+
TooltipTrigger
|
|
166
|
+
};
|
|
140
167
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/TooltipContext.tsx","../src/components/Tooltip.tsx","../src/components/TooltipContent.tsx","../src/components/composeEventHandlers.ts","../src/components/TooltipTrigger.tsx"],"names":["useCallback","jsx","forwardRef"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext, useCallback, useContext, useState } from 'react';\n\nexport type TooltipContextValue = {\n open: boolean;\n contentId: string;\n /** Open now, no delay — used for keyboard focus. */\n openNow: () => void;\n /** Open after the configured hover delay — used for pointer enter. */\n openWithDelay: () => void;\n /** Close now and cancel any pending open. */\n close: () => void;\n};\n\nexport const TooltipContext = createContext<TooltipContextValue | null>(null);\n\nexport function useTooltipContext(): TooltipContextValue {\n const context = useContext(TooltipContext);\n if (!context) {\n throw new Error(\n 'Tooltip compound components (TooltipTrigger, TooltipContent) must be rendered inside <Tooltip>',\n );\n }\n return context;\n}\n\nexport function useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n}: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): { open: boolean; setOpen: (next: boolean) => void } {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const actualOpen = isControlled ? open : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n return { open: actualOpen, setOpen };\n}\n","import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { TooltipContext, useTooltipOpen } from './TooltipContext';\n\nexport type TooltipProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Hover open delay in ms. Keyboard focus always opens with no delay. */\n delay?: number;\n children: ReactNode;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'onChange' | 'children'>;\n\nfunction TooltipInner(\n {\n open,\n defaultOpen,\n onOpenChange,\n delay = 700,\n children,\n style,\n ...rest\n }: TooltipProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const contentId = useId();\n const { open: isOpen, setOpen } = useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearOpenTimer = useCallback(() => {\n if (openTimer.current !== null) {\n clearTimeout(openTimer.current);\n openTimer.current = null;\n }\n }, []);\n\n const close = useCallback(() => {\n clearOpenTimer();\n setOpen(false);\n }, [clearOpenTimer, setOpen]);\n\n const openNow = useCallback(() => {\n clearOpenTimer();\n setOpen(true);\n }, [clearOpenTimer, setOpen]);\n\n const openWithDelay = useCallback(() => {\n clearOpenTimer();\n if (delay <= 0) {\n setOpen(true);\n return;\n }\n openTimer.current = setTimeout(() => {\n openTimer.current = null;\n setOpen(true);\n }, delay);\n }, [clearOpenTimer, delay, setOpen]);\n\n useEffect(() => clearOpenTimer, [clearOpenTimer]);\n\n // Escape closes an open tooltip — WAI-ARIA APG's one hard requirement.\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, close]);\n\n const contextValue = useMemo(\n () => ({ open: isOpen, contentId, openNow, openWithDelay, close }),\n [isOpen, contentId, openNow, openWithDelay, close],\n );\n\n // A shrink-wrapped positioned box so TooltipContent can place itself with\n // plain CSS (position: absolute + data-side) — no portal, no measurement.\n const wrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-block',\n ...style,\n };\n\n return (\n <TooltipContext.Provider value={contextValue}>\n <span {...rest} ref={ref} style={wrapperStyle}>\n {children}\n </span>\n </TooltipContext.Provider>\n );\n}\n\nexport const Tooltip = forwardRef<HTMLSpanElement, TooltipProps>(TooltipInner);\n","import {\n type ComponentPropsWithoutRef,\n type ForwardedRef,\n forwardRef,\n} from 'react';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\n\nexport type TooltipContentProps = {\n side?: TooltipSide;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'role' | 'id'>;\n\nfunction TooltipContentInner(\n { side = 'top', ...rest }: TooltipContentProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const { open, contentId } = useTooltipContext();\n\n if (!open) {\n return null;\n }\n\n return (\n <span {...rest} ref={ref} role=\"tooltip\" id={contentId} data-side={side} />\n );\n}\n\nexport const TooltipContent = forwardRef<HTMLSpanElement, TooltipContentProps>(\n TooltipContentInner,\n);\n","/**\n * Wraps a consumer-supplied event handler so the component's own handler runs\n * after it. Both always run — a tooltip never wants the consumer to be able to\n * silently suppress its open/close behavior.\n */\nexport function composeEventHandlers<E>(\n consumerHandler: ((event: E) => void) | undefined,\n ownHandler: (event: E) => void,\n): (event: E) => void {\n return (event: E) => {\n consumerHandler?.(event);\n ownHandler(event);\n };\n}\n","import {\n Children,\n cloneElement,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { composeEventHandlers } from './composeEventHandlers';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipTriggerProps = {\n /** A single focusable element. It is cloned, not wrapped. */\n children: ReactNode;\n};\n\ntype TriggerChildProps = {\n 'aria-describedby'?: string;\n onPointerEnter?: (event: PointerEvent) => void;\n onPointerLeave?: (event: PointerEvent) => void;\n onPointerDown?: (event: PointerEvent) => void;\n onFocus?: (event: React.FocusEvent) => void;\n onBlur?: (event: React.FocusEvent) => void;\n};\n\nexport function TooltipTrigger({\n children,\n}: TooltipTriggerProps): ReactElement {\n const { open, contentId, openNow, openWithDelay, close } =\n useTooltipContext();\n const child = Children.only(children) as ReactElement<TriggerChildProps>;\n const childProps = child.props;\n\n const describedBy = open\n ? [childProps['aria-describedby'], contentId].filter(Boolean).join(' ')\n : childProps['aria-describedby'];\n\n return cloneElement(child, {\n 'aria-describedby': describedBy,\n onPointerEnter: composeEventHandlers(\n childProps.onPointerEnter,\n openWithDelay,\n ),\n onPointerLeave: composeEventHandlers(childProps.onPointerLeave, close),\n onPointerDown: composeEventHandlers(childProps.onPointerDown, close),\n onFocus: composeEventHandlers(childProps.onFocus, openNow),\n onBlur: composeEventHandlers(childProps.onBlur, close),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/Tooltip.tsx","../src/components/TooltipContext.tsx","../src/components/TooltipContent.tsx","../src/components/TooltipTrigger.tsx","../src/components/composeEventHandlers.ts"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type ForwardedRef,\n forwardRef,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { TooltipContext, useTooltipOpen } from './TooltipContext';\n\nexport type TooltipProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Hover open delay in ms. Keyboard focus always opens with no delay. */\n delay?: number;\n children: ReactNode;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'onChange' | 'children'>;\n\nfunction TooltipInner(\n {\n open,\n defaultOpen,\n onOpenChange,\n delay = 700,\n children,\n style,\n ...rest\n }: TooltipProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const contentId = useId();\n const { open: isOpen, setOpen } = useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n });\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearOpenTimer = useCallback(() => {\n if (openTimer.current !== null) {\n clearTimeout(openTimer.current);\n openTimer.current = null;\n }\n }, []);\n\n const close = useCallback(() => {\n clearOpenTimer();\n setOpen(false);\n }, [clearOpenTimer, setOpen]);\n\n const openNow = useCallback(() => {\n clearOpenTimer();\n setOpen(true);\n }, [clearOpenTimer, setOpen]);\n\n const openWithDelay = useCallback(() => {\n clearOpenTimer();\n if (delay <= 0) {\n setOpen(true);\n return;\n }\n openTimer.current = setTimeout(() => {\n openTimer.current = null;\n setOpen(true);\n }, delay);\n }, [clearOpenTimer, delay, setOpen]);\n\n useEffect(() => clearOpenTimer, [clearOpenTimer]);\n\n // Escape closes an open tooltip — WAI-ARIA APG's one hard requirement.\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, close]);\n\n const contextValue = useMemo(\n () => ({ open: isOpen, contentId, openNow, openWithDelay, close }),\n [isOpen, contentId, openNow, openWithDelay, close],\n );\n\n // A shrink-wrapped positioned box so TooltipContent can place itself with\n // plain CSS (position: absolute + data-side) — no portal, no measurement.\n const wrapperStyle: CSSProperties = {\n position: 'relative',\n display: 'inline-block',\n ...style,\n };\n\n return (\n <TooltipContext.Provider value={contextValue}>\n <span {...rest} ref={ref} style={wrapperStyle}>\n {children}\n </span>\n </TooltipContext.Provider>\n );\n}\n\nexport const Tooltip = forwardRef<HTMLSpanElement, TooltipProps>(TooltipInner);\n","import { createContext, useCallback, useContext, useState } from 'react';\n\nexport type TooltipContextValue = {\n open: boolean;\n contentId: string;\n /** Open now, no delay — used for keyboard focus. */\n openNow: () => void;\n /** Open after the configured hover delay — used for pointer enter. */\n openWithDelay: () => void;\n /** Close now and cancel any pending open. */\n close: () => void;\n};\n\nexport const TooltipContext = createContext<TooltipContextValue | null>(null);\n\nexport function useTooltipContext(): TooltipContextValue {\n const context = useContext(TooltipContext);\n if (!context) {\n throw new Error(\n 'Tooltip compound components (TooltipTrigger, TooltipContent) must be rendered inside <Tooltip>',\n );\n }\n return context;\n}\n\nexport function useTooltipOpen({\n open,\n defaultOpen,\n onOpenChange,\n}: {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}): { open: boolean; setOpen: (next: boolean) => void } {\n const isControlled = open !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const actualOpen = isControlled ? open : internalOpen;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n return { open: actualOpen, setOpen };\n}\n","import {\n type ComponentPropsWithoutRef,\n type ForwardedRef,\n forwardRef,\n} from 'react';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\n\nexport type TooltipContentProps = {\n side?: TooltipSide;\n} & Omit<ComponentPropsWithoutRef<'span'>, 'role' | 'id'>;\n\nfunction TooltipContentInner(\n { side = 'top', ...rest }: TooltipContentProps,\n ref: ForwardedRef<HTMLSpanElement>,\n) {\n const { open, contentId } = useTooltipContext();\n\n if (!open) {\n return null;\n }\n\n return (\n <span {...rest} ref={ref} role=\"tooltip\" id={contentId} data-side={side} />\n );\n}\n\nexport const TooltipContent = forwardRef<HTMLSpanElement, TooltipContentProps>(\n TooltipContentInner,\n);\n","import {\n Children,\n cloneElement,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { composeEventHandlers } from './composeEventHandlers';\nimport { useTooltipContext } from './TooltipContext';\n\nexport type TooltipTriggerProps = {\n /** A single focusable element. It is cloned, not wrapped. */\n children: ReactNode;\n};\n\ntype TriggerChildProps = {\n 'aria-describedby'?: string;\n onPointerEnter?: (event: PointerEvent) => void;\n onPointerLeave?: (event: PointerEvent) => void;\n onPointerDown?: (event: PointerEvent) => void;\n onFocus?: (event: React.FocusEvent) => void;\n onBlur?: (event: React.FocusEvent) => void;\n};\n\nexport function TooltipTrigger({\n children,\n}: TooltipTriggerProps): ReactElement {\n const { open, contentId, openNow, openWithDelay, close } =\n useTooltipContext();\n const child = Children.only(children) as ReactElement<TriggerChildProps>;\n const childProps = child.props;\n\n const describedBy = open\n ? [childProps['aria-describedby'], contentId].filter(Boolean).join(' ')\n : childProps['aria-describedby'];\n\n return cloneElement(child, {\n 'aria-describedby': describedBy,\n onPointerEnter: composeEventHandlers(\n childProps.onPointerEnter,\n openWithDelay,\n ),\n onPointerLeave: composeEventHandlers(childProps.onPointerLeave, close),\n onPointerDown: composeEventHandlers(childProps.onPointerDown, close),\n onFocus: composeEventHandlers(childProps.onFocus, openNow),\n onBlur: composeEventHandlers(childProps.onBlur, close),\n });\n}\n","/**\n * Wraps a consumer-supplied event handler so the component's own handler runs\n * after it. Both always run — a tooltip never wants the consumer to be able to\n * silently suppress its open/close behavior.\n */\nexport function composeEventHandlers<E>(\n consumerHandler: ((event: E) => void) | undefined,\n ownHandler: (event: E) => void,\n): (event: E) => void {\n return (event: E) => {\n consumerHandler?.(event);\n ownHandler(event);\n };\n}\n"],"mappings":"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","names":["useCallback","useCallback","forwardRef","jsx","forwardRef"]}
|
package/dist/test-utils.js
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
|
-
'use
|
|
2
|
-
|
|
3
|
-
var
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
4
20
|
|
|
5
21
|
// src/test-utils.ts
|
|
22
|
+
var test_utils_exports = {};
|
|
23
|
+
__export(test_utils_exports, {
|
|
24
|
+
getTooltip: () => getTooltip,
|
|
25
|
+
getTrigger: () => getTrigger,
|
|
26
|
+
queryTooltip: () => queryTooltip
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(test_utils_exports);
|
|
29
|
+
var import_react = require("@testing-library/react");
|
|
6
30
|
function getTooltip() {
|
|
7
|
-
return
|
|
31
|
+
return import_react.screen.getByRole("tooltip");
|
|
8
32
|
}
|
|
9
33
|
function queryTooltip() {
|
|
10
|
-
return
|
|
34
|
+
return import_react.screen.queryByRole("tooltip");
|
|
11
35
|
}
|
|
12
36
|
function getTrigger(name) {
|
|
13
|
-
return
|
|
37
|
+
return import_react.screen.getByRole("button", { name });
|
|
14
38
|
}
|
|
15
|
-
|
|
16
|
-
exports
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
getTooltip,
|
|
42
|
+
getTrigger,
|
|
43
|
+
queryTooltip
|
|
44
|
+
});
|
|
20
45
|
//# sourceMappingURL=test-utils.js.map
|
package/dist/test-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/test-utils.ts"],"
|
|
1
|
+
{"version":3,"sources":["../src/test-utils.ts"],"sourcesContent":["import { screen } from '@testing-library/react';\n\nexport function getTooltip(): HTMLElement {\n return screen.getByRole('tooltip');\n}\n\nexport function queryTooltip(): HTMLElement | null {\n return screen.queryByRole('tooltip');\n}\n\nexport function getTrigger(name: string | RegExp): HTMLElement {\n return screen.getByRole('button', { name });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAuB;AAEhB,SAAS,aAA0B;AACxC,SAAO,oBAAO,UAAU,SAAS;AACnC;AAEO,SAAS,eAAmC;AACjD,SAAO,oBAAO,YAAY,SAAS;AACrC;AAEO,SAAS,WAAW,MAAoC;AAC7D,SAAO,oBAAO,UAAU,UAAU,EAAE,KAAK,CAAC;AAC5C;","names":[]}
|
package/dist/test-utils.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
|
|
3
3
|
// src/test-utils.ts
|
|
4
|
+
import { screen } from "@testing-library/react";
|
|
4
5
|
function getTooltip() {
|
|
5
6
|
return screen.getByRole("tooltip");
|
|
6
7
|
}
|
|
@@ -10,7 +11,9 @@ function queryTooltip() {
|
|
|
10
11
|
function getTrigger(name) {
|
|
11
12
|
return screen.getByRole("button", { name });
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
export {
|
|
15
|
+
getTooltip,
|
|
16
|
+
getTrigger,
|
|
17
|
+
queryTooltip
|
|
18
|
+
};
|
|
16
19
|
//# sourceMappingURL=test-utils.mjs.map
|
package/dist/test-utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/test-utils.ts"],"
|
|
1
|
+
{"version":3,"sources":["../src/test-utils.ts"],"sourcesContent":["import { screen } from '@testing-library/react';\n\nexport function getTooltip(): HTMLElement {\n return screen.getByRole('tooltip');\n}\n\nexport function queryTooltip(): HTMLElement | null {\n return screen.queryByRole('tooltip');\n}\n\nexport function getTrigger(name: string | RegExp): HTMLElement {\n return screen.getByRole('button', { name });\n}\n"],"mappings":";;;AAAA,SAAS,cAAc;AAEhB,SAAS,aAA0B;AACxC,SAAO,OAAO,UAAU,SAAS;AACnC;AAEO,SAAS,eAAmC;AACjD,SAAO,OAAO,YAAY,SAAS;AACrC;AAEO,SAAS,WAAW,MAAoC;AAC7D,SAAO,OAAO,UAAU,UAAU,EAAE,KAAK,CAAC;AAC5C;","names":[]}
|
package/package.json
CHANGED