@stackone/malachite 2.54.0 → 2.55.0
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/COMPONENTS.md +3 -3
- package/dist/components/ActionMenu.js +141 -134
- package/dist/components/ActionMenu.js.map +1 -1
- package/dist/components/PageLayout/regularLayout.js +58 -61
- package/dist/components/PageLayout/regularLayout.js.map +1 -1
- package/dist/components/Tag.js +22 -21
- package/dist/components/Tag.js.map +1 -1
- package/dist/components/Tooltip.js +97 -93
- package/dist/components/Tooltip.js.map +1 -1
- package/dist/components/actionMenuStyles.js +28 -19
- package/dist/components/actionMenuStyles.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/package.json +1 -1
|
@@ -1,84 +1,86 @@
|
|
|
1
|
-
import { jsx as f, jsxs as
|
|
2
|
-
import
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { jsx as f, jsxs as Y, Fragment as oe } from "react/jsx-runtime";
|
|
2
|
+
import $, { useState as b, useRef as d, useCallback as ie, useId as ae, useEffect as g, useInsertionEffect as se } from "react";
|
|
3
|
+
import { createPortal as le } from "react-dom";
|
|
4
|
+
import { FOCUS_RING as ce } from "./focusRing.js";
|
|
5
|
+
import { ensureOverlayStyles as de, overlayIdentity as fe } from "./portalOverlay.js";
|
|
6
|
+
import { useTopLayer as ue } from "./topLayer.js";
|
|
7
|
+
const me = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), pe = (n) => n.split(me).map((a, w) => /* @__PURE__ */ Y($.Fragment, { children: [
|
|
8
|
+
a,
|
|
8
9
|
/* @__PURE__ */ f("wbr", {})
|
|
9
|
-
] },
|
|
10
|
+
] }, w)), he = {
|
|
10
11
|
minWidth: 0,
|
|
11
12
|
overflow: "hidden"
|
|
12
|
-
},
|
|
13
|
+
}, z = {
|
|
13
14
|
flex: 1,
|
|
14
15
|
minWidth: 0
|
|
15
|
-
},
|
|
16
|
+
}, U = 8, Ee = ({
|
|
16
17
|
text: n,
|
|
17
|
-
children:
|
|
18
|
-
delay:
|
|
19
|
-
wrapChildren:
|
|
18
|
+
children: a,
|
|
19
|
+
delay: w = 1,
|
|
20
|
+
wrapChildren: G = !1,
|
|
20
21
|
triggerAs: O = "div",
|
|
21
|
-
inline:
|
|
22
|
-
placement:
|
|
23
|
-
isShrinkable:
|
|
24
|
-
maxWidth:
|
|
25
|
-
fill:
|
|
22
|
+
inline: A = !1,
|
|
23
|
+
placement: q = "top",
|
|
24
|
+
isShrinkable: B = !1,
|
|
25
|
+
maxWidth: x = "320px",
|
|
26
|
+
fill: E = !1,
|
|
26
27
|
shouldShow: u,
|
|
27
|
-
suppressed:
|
|
28
|
-
describesTrigger:
|
|
29
|
-
showOnFocus:
|
|
28
|
+
suppressed: r = !1,
|
|
29
|
+
describesTrigger: F = !0,
|
|
30
|
+
showOnFocus: c = !0,
|
|
31
|
+
focusableTrigger: m = !1
|
|
30
32
|
}) => {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
}, []),
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const K = B || E ? { ...B ? he : {}, ...E ? z : {} } : void 0, [t, p] = b(!1), [h, X] = b(m), v = d(null), s = d(null), o = ie(() => {
|
|
34
|
+
v.current && (clearTimeout(v.current), v.current = null), s.current !== null && (cancelAnimationFrame(s.current), s.current = null);
|
|
35
|
+
}, []), T = () => {
|
|
36
|
+
X(!0), s.current !== null && cancelAnimationFrame(s.current), s.current = requestAnimationFrame(() => {
|
|
37
|
+
s.current = null, p(!0);
|
|
36
38
|
});
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
e.stopPropagation(), !(!l ||
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
e.stopPropagation(),
|
|
45
|
-
},
|
|
46
|
-
!
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
}, M = c
|
|
50
|
-
|
|
39
|
+
}, R = d(null), y = d(null);
|
|
40
|
+
ue(R, t);
|
|
41
|
+
const W = ae(), l = n != null && n !== "" && n !== !1, D = (e) => {
|
|
42
|
+
e.stopPropagation(), !(!l || r || u && !u()) && (o(), v.current = setTimeout(() => {
|
|
43
|
+
T();
|
|
44
|
+
}, w * 1e3));
|
|
45
|
+
}, J = (e) => {
|
|
46
|
+
e.stopPropagation(), o(), p(!1);
|
|
47
|
+
}, _ = () => {
|
|
48
|
+
!c || !l || r || u && !u() || (o(), T());
|
|
49
|
+
}, Q = () => {
|
|
50
|
+
o(), p(!1);
|
|
51
|
+
}, M = d(c);
|
|
52
|
+
g(() => {
|
|
51
53
|
var i;
|
|
52
|
-
const e =
|
|
53
|
-
M.current =
|
|
54
|
+
const e = c && !M.current;
|
|
55
|
+
M.current = c, e && ((i = y.current) != null && i.matches(":focus-within")) && _();
|
|
54
56
|
});
|
|
55
|
-
const [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}, [
|
|
59
|
-
const [,
|
|
60
|
-
|
|
57
|
+
const [Z, ee] = b(r);
|
|
58
|
+
r !== Z && (ee(r), r && p(!1)), g(() => {
|
|
59
|
+
r && o();
|
|
60
|
+
}, [r, o]);
|
|
61
|
+
const [, C] = b({});
|
|
62
|
+
g(() => {
|
|
61
63
|
if (!t)
|
|
62
64
|
return () => {
|
|
63
|
-
|
|
65
|
+
o();
|
|
64
66
|
};
|
|
65
67
|
const e = () => {
|
|
66
|
-
|
|
68
|
+
C({});
|
|
67
69
|
};
|
|
68
70
|
return window.addEventListener("scroll", e, !0), window.addEventListener("resize", e), () => {
|
|
69
|
-
|
|
71
|
+
o(), window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
|
|
70
72
|
};
|
|
71
|
-
}, [t,
|
|
72
|
-
t &&
|
|
73
|
+
}, [t, o]), g(() => {
|
|
74
|
+
t && C({});
|
|
73
75
|
}, [t]);
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
76
|
+
const te = () => {
|
|
77
|
+
if (!y.current)
|
|
76
78
|
return { display: "none" };
|
|
77
|
-
const e =
|
|
79
|
+
const e = y.current.getBoundingClientRect(), i = {
|
|
78
80
|
position: "fixed",
|
|
79
81
|
display: "flex",
|
|
80
82
|
width: "max-content",
|
|
81
|
-
maxWidth: typeof
|
|
83
|
+
maxWidth: typeof x == "number" ? `${x}px` : x,
|
|
82
84
|
minWidth: "32px",
|
|
83
85
|
minHeight: "32px",
|
|
84
86
|
padding: "8px 12px",
|
|
@@ -96,27 +98,27 @@ const ce = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), fe = (n) => n.split(ce).map((s
|
|
|
96
98
|
opacity: t ? 1 : 0,
|
|
97
99
|
visibility: t ? "visible" : "hidden",
|
|
98
100
|
transition: "opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out"
|
|
99
|
-
},
|
|
100
|
-
var
|
|
101
|
-
const
|
|
102
|
-
if (
|
|
103
|
-
return
|
|
104
|
-
const
|
|
105
|
-
return
|
|
101
|
+
}, L = () => {
|
|
102
|
+
var k;
|
|
103
|
+
const I = e.left + e.width / 2, V = ((k = R.current) == null ? void 0 : k.getBoundingClientRect().width) ?? 0;
|
|
104
|
+
if (V === 0)
|
|
105
|
+
return I;
|
|
106
|
+
const H = V / 2, N = U + H, j = window.innerWidth - U - H;
|
|
107
|
+
return N > j ? I : Math.min(Math.max(I, N), j);
|
|
106
108
|
};
|
|
107
|
-
switch (
|
|
109
|
+
switch (q) {
|
|
108
110
|
case "top":
|
|
109
111
|
return {
|
|
110
112
|
...i,
|
|
111
113
|
top: e.top - 8,
|
|
112
|
-
left:
|
|
114
|
+
left: L(),
|
|
113
115
|
transform: `translate(-50%, -100%) ${t ? "scale(1)" : "scale(0.95)"}`
|
|
114
116
|
};
|
|
115
117
|
case "bottom":
|
|
116
118
|
return {
|
|
117
119
|
...i,
|
|
118
120
|
top: e.bottom + 8,
|
|
119
|
-
left:
|
|
121
|
+
left: L(),
|
|
120
122
|
transform: `translateX(-50%) ${t ? "scale(1)" : "scale(0.95)"}`
|
|
121
123
|
};
|
|
122
124
|
case "left":
|
|
@@ -137,41 +139,43 @@ const ce = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), fe = (n) => n.split(ce).map((s
|
|
|
137
139
|
return {
|
|
138
140
|
...i,
|
|
139
141
|
top: e.top - 8,
|
|
140
|
-
left:
|
|
142
|
+
left: L(),
|
|
141
143
|
transform: `translate(-50%, -100%) ${t ? "scale(1)" : "scale(0.95)"}`
|
|
142
144
|
};
|
|
143
145
|
}
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
l &&
|
|
147
|
-
}, [l,
|
|
148
|
-
const
|
|
149
|
-
"aria-describedby": [
|
|
150
|
-
});
|
|
151
|
-
return /* @__PURE__ */
|
|
146
|
+
}, S = l && h && F ? W : void 0;
|
|
147
|
+
se(() => {
|
|
148
|
+
l && h && de();
|
|
149
|
+
}, [l, h]);
|
|
150
|
+
const ne = m ? a : G || !$.isValidElement(a) ? /* @__PURE__ */ f("span", { "aria-describedby": S, style: E ? z : void 0, children: a }) : $.cloneElement(a, {
|
|
151
|
+
"aria-describedby": [a.props["aria-describedby"], S].filter(Boolean).join(" ") || void 0
|
|
152
|
+
}), re = A ? "span" : O, P = m && l && !r && c;
|
|
153
|
+
return /* @__PURE__ */ Y(oe, { children: [
|
|
152
154
|
/* @__PURE__ */ f(
|
|
153
|
-
|
|
155
|
+
re,
|
|
154
156
|
{
|
|
155
|
-
ref:
|
|
156
|
-
className: `relative ${
|
|
157
|
-
style:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
ref: y,
|
|
158
|
+
className: `relative ${A ? "inline-flex max-w-full align-middle" : "flex"} items-center${P ? ` ${ce}` : ""}`,
|
|
159
|
+
style: K,
|
|
160
|
+
tabIndex: P ? 0 : void 0,
|
|
161
|
+
"aria-describedby": m ? S : void 0,
|
|
162
|
+
onMouseEnter: D,
|
|
163
|
+
onMouseLeave: J,
|
|
164
|
+
onFocus: _,
|
|
165
|
+
onBlur: Q,
|
|
166
|
+
children: ne
|
|
163
167
|
}
|
|
164
168
|
),
|
|
165
|
-
l &&
|
|
169
|
+
l && h && le(
|
|
166
170
|
/* @__PURE__ */ f(
|
|
167
171
|
"div",
|
|
168
172
|
{
|
|
169
|
-
ref:
|
|
170
|
-
id:
|
|
173
|
+
ref: R,
|
|
174
|
+
id: W,
|
|
171
175
|
role: "tooltip",
|
|
172
|
-
"aria-hidden":
|
|
173
|
-
...
|
|
174
|
-
style:
|
|
176
|
+
"aria-hidden": F ? void 0 : !0,
|
|
177
|
+
...fe("tooltip"),
|
|
178
|
+
style: te(),
|
|
175
179
|
children: /* @__PURE__ */ f(
|
|
176
180
|
"span",
|
|
177
181
|
{
|
|
@@ -179,7 +183,7 @@ const ce = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), fe = (n) => n.split(ce).map((s
|
|
|
179
183
|
minWidth: 0,
|
|
180
184
|
overflowWrap: "anywhere"
|
|
181
185
|
},
|
|
182
|
-
children: typeof n == "string" ?
|
|
186
|
+
children: typeof n == "string" ? pe(n) : n
|
|
183
187
|
}
|
|
184
188
|
)
|
|
185
189
|
}
|
|
@@ -189,6 +193,6 @@ const ce = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), fe = (n) => n.split(ce).map((s
|
|
|
189
193
|
] });
|
|
190
194
|
};
|
|
191
195
|
export {
|
|
192
|
-
|
|
196
|
+
Ee as default
|
|
193
197
|
};
|
|
194
198
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","sources":["../../src/components/Tooltip.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId, useInsertionEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ensureOverlayStyles, overlayIdentity } from './portalOverlay';\nimport { useTopLayer } from './topLayer';\n\n// Split after each delimiter so long values (URLs, dotted paths) wrap at \"/\" or \".\"\n// instead of mid-token. <wbr> is copy-safe (a zero-width space would corrupt a copied\n// URL); overflow-wrap still handles a single run too long to fit.\nconst WRAP_AFTER = /(?<=[/\\\\.\\-_?&#=:@])/;\nconst withBreakOpportunities = (value: string): React.ReactNode =>\n value.split(WRAP_AFTER).map((chunk, i) => (\n <React.Fragment key={i}>\n {chunk}\n <wbr />\n </React.Fragment>\n ));\n\ninterface TooltipProps {\n text: React.ReactNode | string;\n children: React.ReactNode;\n delay?: number;\n wrapChildren?: boolean;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n isShrinkable?: boolean;\n fill?: boolean;\n /** Max width of tooltip. Default: 320px */\n maxWidth?: number | string;\n /** Called synchronously when the trigger is hovered/focused; return false to\n * suppress the tooltip for this interaction. Lets wrappers defer expensive\n * checks (e.g. truncation measurement) to interaction time instead of mount. */\n shouldShow?: () => boolean;\n suppressed?: boolean;\n triggerAs?: 'div' | 'span';\n inline?: boolean;\n /** Whether the tooltip acts as the trigger's accessible description. False where the\n * trigger already points at the same sentence on screen, so it is not announced twice. */\n describesTrigger?: boolean;\n /** False to open on hover only, e.g. where script moves focus onto the trigger. */\n showOnFocus?: boolean;\n}\n\nconst SHRINKABLE_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n};\n\nconst FILL_STYLE: React.CSSProperties = {\n flex: 1,\n minWidth: 0,\n};\n\n/** Kept clear of the viewport edge so a clamped tooltip does not sit flush against it. */\nconst VIEWPORT_MARGIN = 8;\n\nconst Tooltip: React.FC<TooltipProps> = ({\n text,\n children,\n delay = 1,\n wrapChildren = false,\n triggerAs = 'div',\n inline = false,\n placement = 'top',\n isShrinkable = false,\n maxWidth = '320px',\n fill = false,\n shouldShow,\n suppressed = false,\n describesTrigger = true,\n showOnFocus = true,\n}) => {\n const triggerStyle =\n isShrinkable || fill\n ? { ...(isShrinkable ? SHRINKABLE_STYLE : {}), ...(fill ? FILL_STYLE : {}) }\n : undefined;\n\n const [isVisible, setIsVisible] = useState(false);\n // Portal mounts on first show, not on mount: an at-rest tooltip otherwise\n // costs a hidden document.body node plus a getBoundingClientRect per render —\n // multiplied by every row in a large table.\n const [hasShown, setHasShown] = useState(false);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showFrameRef = useRef<number | null>(null);\n\n const cancelPendingShow = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n showFrameRef.current = null;\n }\n }, []);\n\n const scheduleVisible = () => {\n // Two steps so the portal mounts hidden first and the fade-in transition\n // still runs on the very first show. The frame is tracked so leave/blur/\n // unmount can cancel a show that is already past its delay.\n setHasShown(true);\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n }\n showFrameRef.current = requestAnimationFrame(() => {\n showFrameRef.current = null;\n setIsVisible(true);\n });\n };\n const tooltipRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n // Tied to visibility, not mount: the node is latched into the DOM after its first show, and\n // re-entering on each show keeps a tooltip above the panel it is annotating.\n useTopLayer(tooltipRef, isVisible);\n\n const tooltipId = useId();\n\n const hasText = text !== null && text !== undefined && text !== '' && text !== false;\n\n const handleMouseEnter = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n if (!hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n\n timeoutRef.current = setTimeout(() => {\n scheduleVisible();\n }, delay * 1000);\n };\n\n const handleMouseLeave = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const handleFocus = () => {\n if (!showOnFocus || !hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n scheduleVisible();\n };\n\n const handleBlur = () => {\n cancelPendingShow();\n setIsVisible(false);\n };\n\n // Turning on while the trigger already holds focus fires no focus event to open on.\n const showOnFocusRef = useRef(showOnFocus);\n useEffect(() => {\n const switchedOn = showOnFocus && !showOnFocusRef.current;\n showOnFocusRef.current = showOnFocus;\n if (switchedOn && triggerRef.current?.matches(':focus-within')) {\n handleFocus();\n }\n });\n\n const [wasSuppressed, setWasSuppressed] = useState(suppressed);\n if (suppressed !== wasSuppressed) {\n setWasSuppressed(suppressed);\n if (suppressed) {\n setIsVisible(false);\n }\n }\n\n useEffect(() => {\n if (suppressed) {\n cancelPendingShow();\n }\n }, [suppressed, cancelPendingShow]);\n\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // Only a VISIBLE tooltip needs to track scroll/resize; keeping global\n // listeners per mounted instance made every scroll event fan out across\n // every tooltip on the page.\n if (!isVisible) {\n return () => {\n cancelPendingShow();\n };\n }\n const handleUpdate = () => {\n forceUpdate({});\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n cancelPendingShow();\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [isVisible, cancelPendingShow]);\n\n // The first render that mounts the tooltip has no measured width yet, so the clamp below\n // cannot run on it. One extra pass once it is in the DOM gives the clamp its measurement\n // — before the opacity transition finishes, so nothing is seen sliding into place.\n useEffect(() => {\n if (isVisible) {\n forceUpdate({});\n }\n }, [isVisible]);\n\n const getTooltipStyles = (): React.CSSProperties => {\n if (!triggerRef.current) {\n return { display: 'none' };\n }\n\n const rect = triggerRef.current.getBoundingClientRect();\n\n const baseStyles: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n width: 'max-content',\n maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth,\n minWidth: '32px',\n minHeight: '32px',\n padding: '8px 12px',\n alignItems: 'center',\n gap: '8px',\n borderRadius: '12px',\n backgroundColor: 'var(--malachite-tooltip-background, rgb(59, 59, 59))',\n color: 'var(--malachite-tooltip-foreground, rgb(255, 255, 255))',\n boxShadow: 'var(--malachite-tooltip-shadow, 0px 0px 10px 0px rgba(0, 0, 0, 0.20))',\n fontSize: '14px',\n lineHeight: '1.4',\n whiteSpace: 'normal',\n textAlign: 'left',\n pointerEvents: 'none',\n opacity: isVisible ? 1 : 0,\n visibility: isVisible ? 'visible' : 'hidden',\n transition:\n 'opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out',\n };\n\n // A trigger near the viewport edge would otherwise centre a wide tooltip half off\n // screen, where the panel or the window crops it. Clamping the CENTRE keeps the\n // `translateX(-50%)` placement honest: the box stays put, it just stops short.\n const centeredLeft = (): number => {\n const desired = rect.left + rect.width / 2;\n const width = tooltipRef.current?.getBoundingClientRect().width ?? 0;\n\n if (width === 0) {\n return desired;\n }\n\n const half = width / 2;\n const min = VIEWPORT_MARGIN + half;\n const max = window.innerWidth - VIEWPORT_MARGIN - half;\n\n // A tooltip wider than the viewport has no in-bounds centre; leave it centred\n // rather than pinning it to a nonsensical one.\n return min > max ? desired : Math.min(Math.max(desired, min), max);\n };\n\n switch (placement) {\n case 'top':\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'bottom':\n return {\n ...baseStyles,\n top: rect.bottom + 8,\n left: centeredLeft(),\n transform: `translateX(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'left':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.left - 8,\n transform: `translate(-100%, -50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'right':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.right + 8,\n transform: `translateY(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n default:\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n }\n };\n\n // Only reference the tooltip id once the portal can exist — a dangling\n // aria-describedby (text set, never shown) confuses assistive tech.\n const describedBy = hasText && hasShown && describesTrigger ? tooltipId : undefined;\n useInsertionEffect(() => {\n if (hasText && hasShown) {\n ensureOverlayStyles();\n }\n }, [hasText, hasShown]);\n const renderedChildren =\n wrapChildren || !React.isValidElement(children) ? (\n <span aria-describedby={describedBy} style={fill ? FILL_STYLE : undefined}>\n {children}\n </span>\n ) : (\n React.cloneElement(children as React.ReactElement, {\n 'aria-describedby':\n [(children as React.ReactElement).props['aria-describedby'], describedBy]\n .filter(Boolean)\n .join(' ') || undefined,\n })\n );\n\n const Trigger = inline ? 'span' : triggerAs;\n\n // Create the tooltip content without its own shadow root\n return (\n <>\n <Trigger\n ref={triggerRef}\n className={`relative ${inline ? 'inline-flex max-w-full align-middle' : 'flex'} items-center`}\n style={triggerStyle}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n {renderedChildren}\n </Trigger>\n\n {hasText &&\n hasShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n // Nothing references it, and the sentence is already on screen and\n // described: left in the tree it is a second copy to read past.\n aria-hidden={describesTrigger ? undefined : true}\n {...overlayIdentity('tooltip')}\n style={getTooltipStyles()}\n >\n {/* min-w-0 + overflow-wrap let long values wrap within maxWidth. */}\n <span\n style={{\n minWidth: 0,\n overflowWrap: 'anywhere',\n }}\n >\n {typeof text === 'string' ? withBreakOpportunities(text) : text}\n </span>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport default Tooltip;\n"],"names":["WRAP_AFTER","withBreakOpportunities","value","chunk","i","jsxs","React","SHRINKABLE_STYLE","FILL_STYLE","VIEWPORT_MARGIN","Tooltip","text","children","delay","wrapChildren","triggerAs","inline","placement","isShrinkable","maxWidth","fill","shouldShow","suppressed","describesTrigger","showOnFocus","triggerStyle","isVisible","setIsVisible","useState","hasShown","setHasShown","timeoutRef","useRef","showFrameRef","cancelPendingShow","useCallback","scheduleVisible","tooltipRef","triggerRef","useTopLayer","tooltipId","useId","hasText","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","showOnFocusRef","useEffect","switchedOn","_a","wasSuppressed","setWasSuppressed","forceUpdate","handleUpdate","getTooltipStyles","rect","baseStyles","centeredLeft","desired","width","half","min","max","describedBy","useInsertionEffect","ensureOverlayStyles","renderedChildren","jsx","Fragment","createPortal","overlayIdentity"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../../src/components/Tooltip.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId, useInsertionEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { FOCUS_RING } from './focusRing';\nimport { ensureOverlayStyles, overlayIdentity } from './portalOverlay';\nimport { useTopLayer } from './topLayer';\n\n// Split after each delimiter so long values (URLs, dotted paths) wrap at \"/\" or \".\"\n// instead of mid-token. <wbr> is copy-safe (a zero-width space would corrupt a copied\n// URL); overflow-wrap still handles a single run too long to fit.\nconst WRAP_AFTER = /(?<=[/\\\\.\\-_?&#=:@])/;\nconst withBreakOpportunities = (value: string): React.ReactNode =>\n value.split(WRAP_AFTER).map((chunk, i) => (\n <React.Fragment key={i}>\n {chunk}\n <wbr />\n </React.Fragment>\n ));\n\ninterface TooltipProps {\n text: React.ReactNode | string;\n children: React.ReactNode;\n delay?: number;\n wrapChildren?: boolean;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n isShrinkable?: boolean;\n fill?: boolean;\n /** Max width of tooltip. Default: 320px */\n maxWidth?: number | string;\n /** Called synchronously when the trigger is hovered/focused; return false to\n * suppress the tooltip for this interaction. Lets wrappers defer expensive\n * checks (e.g. truncation measurement) to interaction time instead of mount. */\n shouldShow?: () => boolean;\n suppressed?: boolean;\n triggerAs?: 'div' | 'span';\n inline?: boolean;\n /** Whether the tooltip acts as the trigger's accessible description. False where the\n * trigger already points at the same sentence on screen, so it is not announced twice. */\n describesTrigger?: boolean;\n /** False to open on hover only, e.g. where script moves focus onto the trigger. */\n showOnFocus?: boolean;\n /** Makes a trigger that cannot take focus a tab stop. Not for focusable children. */\n focusableTrigger?: boolean;\n}\n\nconst SHRINKABLE_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n};\n\nconst FILL_STYLE: React.CSSProperties = {\n flex: 1,\n minWidth: 0,\n};\n\n/** Kept clear of the viewport edge so a clamped tooltip does not sit flush against it. */\nconst VIEWPORT_MARGIN = 8;\n\nconst Tooltip: React.FC<TooltipProps> = ({\n text,\n children,\n delay = 1,\n wrapChildren = false,\n triggerAs = 'div',\n inline = false,\n placement = 'top',\n isShrinkable = false,\n maxWidth = '320px',\n fill = false,\n shouldShow,\n suppressed = false,\n describesTrigger = true,\n showOnFocus = true,\n focusableTrigger = false,\n}) => {\n const triggerStyle =\n isShrinkable || fill\n ? { ...(isShrinkable ? SHRINKABLE_STYLE : {}), ...(fill ? FILL_STYLE : {}) }\n : undefined;\n\n const [isVisible, setIsVisible] = useState(false);\n // Portal mounts on first show, not on mount: an at-rest tooltip otherwise\n // costs a hidden document.body node plus a getBoundingClientRect per render —\n // multiplied by every row in a large table.\n // Mounted up front so a focusable trigger is described on first focus.\n const [hasShown, setHasShown] = useState(focusableTrigger);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showFrameRef = useRef<number | null>(null);\n\n const cancelPendingShow = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n showFrameRef.current = null;\n }\n }, []);\n\n const scheduleVisible = () => {\n // Two steps so the portal mounts hidden first and the fade-in transition\n // still runs on the very first show. The frame is tracked so leave/blur/\n // unmount can cancel a show that is already past its delay.\n setHasShown(true);\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n }\n showFrameRef.current = requestAnimationFrame(() => {\n showFrameRef.current = null;\n setIsVisible(true);\n });\n };\n const tooltipRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n // Tied to visibility, not mount: the node is latched into the DOM after its first show, and\n // re-entering on each show keeps a tooltip above the panel it is annotating.\n useTopLayer(tooltipRef, isVisible);\n\n const tooltipId = useId();\n\n const hasText = text !== null && text !== undefined && text !== '' && text !== false;\n\n const handleMouseEnter = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n if (!hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n\n timeoutRef.current = setTimeout(() => {\n scheduleVisible();\n }, delay * 1000);\n };\n\n const handleMouseLeave = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const handleFocus = () => {\n if (!showOnFocus || !hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n scheduleVisible();\n };\n\n const handleBlur = () => {\n cancelPendingShow();\n setIsVisible(false);\n };\n\n // Turning on while the trigger already holds focus fires no focus event to open on.\n const showOnFocusRef = useRef(showOnFocus);\n useEffect(() => {\n const switchedOn = showOnFocus && !showOnFocusRef.current;\n showOnFocusRef.current = showOnFocus;\n if (switchedOn && triggerRef.current?.matches(':focus-within')) {\n handleFocus();\n }\n });\n\n const [wasSuppressed, setWasSuppressed] = useState(suppressed);\n if (suppressed !== wasSuppressed) {\n setWasSuppressed(suppressed);\n if (suppressed) {\n setIsVisible(false);\n }\n }\n\n useEffect(() => {\n if (suppressed) {\n cancelPendingShow();\n }\n }, [suppressed, cancelPendingShow]);\n\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // Only a VISIBLE tooltip needs to track scroll/resize; keeping global\n // listeners per mounted instance made every scroll event fan out across\n // every tooltip on the page.\n if (!isVisible) {\n return () => {\n cancelPendingShow();\n };\n }\n const handleUpdate = () => {\n forceUpdate({});\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n cancelPendingShow();\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [isVisible, cancelPendingShow]);\n\n // The first render that mounts the tooltip has no measured width yet, so the clamp below\n // cannot run on it. One extra pass once it is in the DOM gives the clamp its measurement\n // — before the opacity transition finishes, so nothing is seen sliding into place.\n useEffect(() => {\n if (isVisible) {\n forceUpdate({});\n }\n }, [isVisible]);\n\n const getTooltipStyles = (): React.CSSProperties => {\n if (!triggerRef.current) {\n return { display: 'none' };\n }\n\n const rect = triggerRef.current.getBoundingClientRect();\n\n const baseStyles: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n width: 'max-content',\n maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth,\n minWidth: '32px',\n minHeight: '32px',\n padding: '8px 12px',\n alignItems: 'center',\n gap: '8px',\n borderRadius: '12px',\n backgroundColor: 'var(--malachite-tooltip-background, rgb(59, 59, 59))',\n color: 'var(--malachite-tooltip-foreground, rgb(255, 255, 255))',\n boxShadow: 'var(--malachite-tooltip-shadow, 0px 0px 10px 0px rgba(0, 0, 0, 0.20))',\n fontSize: '14px',\n lineHeight: '1.4',\n whiteSpace: 'normal',\n textAlign: 'left',\n pointerEvents: 'none',\n opacity: isVisible ? 1 : 0,\n visibility: isVisible ? 'visible' : 'hidden',\n transition:\n 'opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out',\n };\n\n // A trigger near the viewport edge would otherwise centre a wide tooltip half off\n // screen, where the panel or the window crops it. Clamping the CENTRE keeps the\n // `translateX(-50%)` placement honest: the box stays put, it just stops short.\n const centeredLeft = (): number => {\n const desired = rect.left + rect.width / 2;\n const width = tooltipRef.current?.getBoundingClientRect().width ?? 0;\n\n if (width === 0) {\n return desired;\n }\n\n const half = width / 2;\n const min = VIEWPORT_MARGIN + half;\n const max = window.innerWidth - VIEWPORT_MARGIN - half;\n\n // A tooltip wider than the viewport has no in-bounds centre; leave it centred\n // rather than pinning it to a nonsensical one.\n return min > max ? desired : Math.min(Math.max(desired, min), max);\n };\n\n switch (placement) {\n case 'top':\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'bottom':\n return {\n ...baseStyles,\n top: rect.bottom + 8,\n left: centeredLeft(),\n transform: `translateX(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'left':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.left - 8,\n transform: `translate(-100%, -50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'right':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.right + 8,\n transform: `translateY(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n default:\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n }\n };\n\n // Only reference the tooltip id once the portal can exist — a dangling\n // aria-describedby (text set, never shown) confuses assistive tech.\n const describedBy = hasText && hasShown && describesTrigger ? tooltipId : undefined;\n useInsertionEffect(() => {\n if (hasText && hasShown) {\n ensureOverlayStyles();\n }\n }, [hasText, hasShown]);\n const renderedChildren = focusableTrigger ? (\n children\n ) : wrapChildren || !React.isValidElement(children) ? (\n <span aria-describedby={describedBy} style={fill ? FILL_STYLE : undefined}>\n {children}\n </span>\n ) : (\n React.cloneElement(children as React.ReactElement, {\n 'aria-describedby':\n [(children as React.ReactElement).props['aria-describedby'], describedBy]\n .filter(Boolean)\n .join(' ') || undefined,\n })\n );\n\n const Trigger = inline ? 'span' : triggerAs;\n const isTabStop = focusableTrigger && hasText && !suppressed && showOnFocus;\n\n // Create the tooltip content without its own shadow root\n return (\n <>\n <Trigger\n ref={triggerRef}\n className={`relative ${inline ? 'inline-flex max-w-full align-middle' : 'flex'} items-center${isTabStop ? ` ${FOCUS_RING}` : ''}`}\n style={triggerStyle}\n tabIndex={isTabStop ? 0 : undefined}\n aria-describedby={focusableTrigger ? describedBy : undefined}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n {renderedChildren}\n </Trigger>\n\n {hasText &&\n hasShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n // Nothing references it, and the sentence is already on screen and\n // described: left in the tree it is a second copy to read past.\n aria-hidden={describesTrigger ? undefined : true}\n {...overlayIdentity('tooltip')}\n style={getTooltipStyles()}\n >\n {/* min-w-0 + overflow-wrap let long values wrap within maxWidth. */}\n <span\n style={{\n minWidth: 0,\n overflowWrap: 'anywhere',\n }}\n >\n {typeof text === 'string' ? withBreakOpportunities(text) : text}\n </span>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport default Tooltip;\n"],"names":["WRAP_AFTER","withBreakOpportunities","value","chunk","i","jsxs","React","SHRINKABLE_STYLE","FILL_STYLE","VIEWPORT_MARGIN","Tooltip","text","children","delay","wrapChildren","triggerAs","inline","placement","isShrinkable","maxWidth","fill","shouldShow","suppressed","describesTrigger","showOnFocus","focusableTrigger","triggerStyle","isVisible","setIsVisible","useState","hasShown","setHasShown","timeoutRef","useRef","showFrameRef","cancelPendingShow","useCallback","scheduleVisible","tooltipRef","triggerRef","useTopLayer","tooltipId","useId","hasText","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","showOnFocusRef","useEffect","switchedOn","_a","wasSuppressed","setWasSuppressed","forceUpdate","handleUpdate","getTooltipStyles","rect","baseStyles","centeredLeft","desired","width","half","min","max","describedBy","useInsertionEffect","ensureOverlayStyles","renderedChildren","jsx","Trigger","isTabStop","Fragment","FOCUS_RING","createPortal","overlayIdentity"],"mappings":";;;;;;AASA,MAAMA,KAAa,WAAA,yBAAA,GACbC,KAAyB,CAACC,MAC5BA,EAAM,MAAMF,EAAU,EAAE,IAAI,CAACG,GAAOC,MAChC,gBAAAC,EAACC,EAAM,UAAN,EACI,UAAA;AAAA,EAAAH;AAAA,oBACA,OAAA,CAAA,CAAI;AAAA,EAAA,GAFYC,CAGrB,CACH,GA4BCG,KAAwC;AAAA,EAC1C,UAAU;AAAA,EACV,UAAU;AACd,GAEMC,IAAkC;AAAA,EACpC,MAAM;AAAA,EACN,UAAU;AACd,GAGMC,IAAkB,GAElBC,KAAkC,CAAC;AAAA,EACrC,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,cAAAC,IAAe;AAAA,EACf,WAAAC,IAAY;AAAA,EACZ,QAAAC,IAAS;AAAA,EACT,WAAAC,IAAY;AAAA,EACZ,cAAAC,IAAe;AAAA,EACf,UAAAC,IAAW;AAAA,EACX,MAAAC,IAAO;AAAA,EACP,YAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,kBAAAC,IAAmB;AAAA,EACnB,aAAAC,IAAc;AAAA,EACd,kBAAAC,IAAmB;AACvB,MAAM;AACF,QAAMC,IACFR,KAAgBE,IACV,EAAE,GAAIF,IAAeX,KAAmB,CAAA,GAAK,GAAIa,IAAOZ,IAAa,CAAA,MACrE,QAEJ,CAACmB,GAAWC,CAAY,IAAIC,EAAS,EAAK,GAK1C,CAACC,GAAUC,CAAW,IAAIF,EAASJ,CAAgB,GACnDO,IAAaC,EAA8B,IAAI,GAC/CC,IAAeD,EAAsB,IAAI,GAEzCE,IAAoBC,GAAY,MAAM;AACxC,IAAIJ,EAAW,YACX,aAAaA,EAAW,OAAO,GAC/BA,EAAW,UAAU,OAErBE,EAAa,YAAY,SACzB,qBAAqBA,EAAa,OAAO,GACzCA,EAAa,UAAU;AAAA,EAE/B,GAAG,CAAA,CAAE,GAECG,IAAkB,MAAM;AAI1B,IAAAN,EAAY,EAAI,GACZG,EAAa,YAAY,QACzB,qBAAqBA,EAAa,OAAO,GAE7CA,EAAa,UAAU,sBAAsB,MAAM;AAC/C,MAAAA,EAAa,UAAU,MACvBN,EAAa,EAAI;AAAA,IACrB,CAAC;AAAA,EACL,GACMU,IAAaL,EAAuB,IAAI,GACxCM,IAAaN,EAAuB,IAAI;AAI9C,EAAAO,GAAYF,GAAYX,CAAS;AAEjC,QAAMc,IAAYC,GAAA,GAEZC,IAAUhC,KAAS,QAA8BA,MAAS,MAAMA,MAAS,IAEzEiC,IAAmB,CAAC,MAAwB;AAG9C,IAFA,EAAE,gBAAA,GAEE,GAACD,KAAWrB,KAAeD,KAAc,CAACA,SAI9Cc,EAAA,GAEAH,EAAW,UAAU,WAAW,MAAM;AAClC,MAAAK,EAAA;AAAA,IACJ,GAAGxB,IAAQ,GAAI;AAAA,EACnB,GAEMgC,IAAmB,CAAC,MAAwB;AAC9C,MAAE,gBAAA,GAEFV,EAAA,GACAP,EAAa,EAAK;AAAA,EACtB,GAEMkB,IAAc,MAAM;AACtB,IAAI,CAACtB,KAAe,CAACmB,KAAWrB,KAAeD,KAAc,CAACA,QAI9Dc,EAAA,GACAE,EAAA;AAAA,EACJ,GAEMU,IAAa,MAAM;AACrB,IAAAZ,EAAA,GACAP,EAAa,EAAK;AAAA,EACtB,GAGMoB,IAAiBf,EAAOT,CAAW;AACzC,EAAAyB,EAAU,MAAM;;AACZ,UAAMC,IAAa1B,KAAe,CAACwB,EAAe;AAClD,IAAAA,EAAe,UAAUxB,GACrB0B,OAAcC,IAAAZ,EAAW,YAAX,QAAAY,EAAoB,QAAQ,qBAC1CL,EAAA;AAAA,EAER,CAAC;AAED,QAAM,CAACM,GAAeC,EAAgB,IAAIxB,EAASP,CAAU;AAC7D,EAAIA,MAAe8B,MACfC,GAAiB/B,CAAU,GACvBA,KACAM,EAAa,EAAK,IAI1BqB,EAAU,MAAM;AACZ,IAAI3B,KACAa,EAAA;AAAA,EAER,GAAG,CAACb,GAAYa,CAAiB,CAAC;AAElC,QAAM,GAAGmB,CAAW,IAAIzB,EAAS,EAAE;AAEnC,EAAAoB,EAAU,MAAM;AAIZ,QAAI,CAACtB;AACD,aAAO,MAAM;AACT,QAAAQ,EAAA;AAAA,MACJ;AAEJ,UAAMoB,IAAe,MAAM;AACvB,MAAAD,EAAY,CAAA,CAAE;AAAA,IAClB;AAEA,kBAAO,iBAAiB,UAAUC,GAAc,EAAI,GACpD,OAAO,iBAAiB,UAAUA,CAAY,GAEvC,MAAM;AACT,MAAApB,EAAA,GACA,OAAO,oBAAoB,UAAUoB,GAAc,EAAI,GACvD,OAAO,oBAAoB,UAAUA,CAAY;AAAA,IACrD;AAAA,EACJ,GAAG,CAAC5B,GAAWQ,CAAiB,CAAC,GAKjCc,EAAU,MAAM;AACZ,IAAItB,KACA2B,EAAY,CAAA,CAAE;AAAA,EAEtB,GAAG,CAAC3B,CAAS,CAAC;AAEd,QAAM6B,KAAmB,MAA2B;AAChD,QAAI,CAACjB,EAAW;AACZ,aAAO,EAAE,SAAS,OAAA;AAGtB,UAAMkB,IAAOlB,EAAW,QAAQ,sBAAA,GAE1BmB,IAAkC;AAAA,MACpC,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU,OAAOvC,KAAa,WAAW,GAAGA,CAAQ,OAAOA;AAAA,MAC3D,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,WAAW;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,eAAe;AAAA,MACf,SAASQ,IAAY,IAAI;AAAA,MACzB,YAAYA,IAAY,YAAY;AAAA,MACpC,YACI;AAAA,IAAA,GAMFgC,IAAe,MAAc;;AAC/B,YAAMC,IAAUH,EAAK,OAAOA,EAAK,QAAQ,GACnCI,MAAQV,IAAAb,EAAW,YAAX,gBAAAa,EAAoB,wBAAwB,UAAS;AAEnE,UAAIU,MAAU;AACV,eAAOD;AAGX,YAAME,IAAOD,IAAQ,GACfE,IAAMtD,IAAkBqD,GACxBE,IAAM,OAAO,aAAavD,IAAkBqD;AAIlD,aAAOC,IAAMC,IAAMJ,IAAU,KAAK,IAAI,KAAK,IAAIA,GAASG,CAAG,GAAGC,CAAG;AAAA,IACrE;AAEA,YAAQ/C,GAAA;AAAA,MACJ,KAAK;AACD,eAAO;AAAA,UACH,GAAGyC;AAAA,UACH,KAAKD,EAAK,MAAM;AAAA,UAChB,MAAME,EAAA;AAAA,UACN,WAAW,0BAA0BhC,IAAY,aAAa,aAAa;AAAA,QAAA;AAAA,MAEnF,KAAK;AACD,eAAO;AAAA,UACH,GAAG+B;AAAA,UACH,KAAKD,EAAK,SAAS;AAAA,UACnB,MAAME,EAAA;AAAA,UACN,WAAW,oBAAoBhC,IAAY,aAAa,aAAa;AAAA,QAAA;AAAA,MAE7E,KAAK;AACD,eAAO;AAAA,UACH,GAAG+B;AAAA,UACH,KAAKD,EAAK,MAAMA,EAAK,SAAS;AAAA,UAC9B,MAAMA,EAAK,OAAO;AAAA,UAClB,WAAW,0BAA0B9B,IAAY,aAAa,aAAa;AAAA,QAAA;AAAA,MAEnF,KAAK;AACD,eAAO;AAAA,UACH,GAAG+B;AAAA,UACH,KAAKD,EAAK,MAAMA,EAAK,SAAS;AAAA,UAC9B,MAAMA,EAAK,QAAQ;AAAA,UACnB,WAAW,oBAAoB9B,IAAY,aAAa,aAAa;AAAA,QAAA;AAAA,MAE7E;AACI,eAAO;AAAA,UACH,GAAG+B;AAAA,UACH,KAAKD,EAAK,MAAM;AAAA,UAChB,MAAME,EAAA;AAAA,UACN,WAAW,0BAA0BhC,IAAY,aAAa,aAAa;AAAA,QAAA;AAAA,IAC/E;AAAA,EAEZ,GAIMsC,IAActB,KAAWb,KAAYP,IAAmBkB,IAAY;AAC1E,EAAAyB,GAAmB,MAAM;AACrB,IAAIvB,KAAWb,KACXqC,GAAA;AAAA,EAER,GAAG,CAACxB,GAASb,CAAQ,CAAC;AACtB,QAAMsC,KAAmB3C,IACrBb,IACAE,KAAgB,CAACR,EAAM,eAAeM,CAAQ,IAC9C,gBAAAyD,EAAC,UAAK,oBAAkBJ,GAAa,OAAO7C,IAAOZ,IAAa,QAC3D,UAAAI,EAAA,CACL,IAEAN,EAAM,aAAaM,GAAgC;AAAA,IAC/C,oBACI,CAAEA,EAAgC,MAAM,kBAAkB,GAAGqD,CAAW,EACnE,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAAA,EAAA,CACzB,GAGCK,KAAUtD,IAAS,SAASD,GAC5BwD,IAAY9C,KAAoBkB,KAAW,CAACrB,KAAcE;AAGhE,SACI,gBAAAnB,EAAAmE,IAAA,EACI,UAAA;AAAA,IAAA,gBAAAH;AAAA,MAACC;AAAA,MAAA;AAAA,QACG,KAAK/B;AAAA,QACL,WAAW,YAAYvB,IAAS,wCAAwC,MAAM,gBAAgBuD,IAAY,IAAIE,EAAU,KAAK,EAAE;AAAA,QAC/H,OAAO/C;AAAA,QACP,UAAU6C,IAAY,IAAI;AAAA,QAC1B,oBAAkB9C,IAAmBwC,IAAc;AAAA,QACnD,cAAcrB;AAAA,QACd,cAAcC;AAAA,QACd,SAASC;AAAA,QACT,QAAQC;AAAA,QAEP,UAAAqB;AAAA,MAAA;AAAA,IAAA;AAAA,IAGJzB,KACGb,KACA4C;AAAA,MACI,gBAAAL;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,KAAK/B;AAAA,UACL,IAAIG;AAAA,UACJ,MAAK;AAAA,UAGL,eAAalB,IAAmB,SAAY;AAAA,UAC3C,GAAGoD,GAAgB,SAAS;AAAA,UAC7B,OAAOnB,GAAA;AAAA,UAGP,UAAA,gBAAAa;AAAA,YAAC;AAAA,YAAA;AAAA,cACG,OAAO;AAAA,gBACH,UAAU;AAAA,gBACV,cAAc;AAAA,cAAA;AAAA,cAGjB,UAAA,OAAO1D,KAAS,WAAWV,GAAuBU,CAAI,IAAIA;AAAA,YAAA;AAAA,UAAA;AAAA,QAC/D;AAAA,MAAA;AAAA,MAEJ,SAAS;AAAA,IAAA;AAAA,EACb,GACR;AAER;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MENU_SPECS as r } from "./floatingMenuGeometry.js";
|
|
2
|
-
import { injectStyleSheet as
|
|
2
|
+
import { injectStyleSheet as i } from "./injectStyleSheet.js";
|
|
3
3
|
import { ensureOverlayStyles as s } from "./portalOverlay.js";
|
|
4
|
-
import { SELECTED_ROW_BACKGROUND as
|
|
4
|
+
import { SELECTED_ROW_BACKGROUND as l, SELECTED_ROW_FOREGROUND as d } from "./selectedRow.js";
|
|
5
5
|
const y = {
|
|
6
6
|
small: { icon: 16, iconBox: "text-[16px] [&_svg]:size-[16px]!" },
|
|
7
7
|
xsmall: { icon: 11, iconBox: "text-[11px] [&_svg]:size-[11px]!" }
|
|
@@ -9,21 +9,29 @@ const y = {
|
|
|
9
9
|
minWidth: 0,
|
|
10
10
|
overflow: "hidden",
|
|
11
11
|
textOverflow: "ellipsis"
|
|
12
|
+
}, w = {
|
|
13
|
+
position: "absolute",
|
|
14
|
+
width: 1,
|
|
15
|
+
height: 1,
|
|
16
|
+
margin: -1,
|
|
17
|
+
overflow: "hidden",
|
|
18
|
+
clipPath: "inset(50%)",
|
|
19
|
+
whiteSpace: "nowrap"
|
|
12
20
|
}, m = {
|
|
13
21
|
padding: "6px 10px",
|
|
14
22
|
fontSize: "var(--malachite-font-size-small, 13px)",
|
|
15
23
|
color: "var(--malachite-text-dimmed, rgb(161, 161, 161))",
|
|
16
24
|
userSelect: "none"
|
|
17
|
-
},
|
|
25
|
+
}, h = {
|
|
18
26
|
...m,
|
|
19
27
|
color: "var(--malachite-text-secondary, rgb(123, 123, 123))",
|
|
20
28
|
overflow: "hidden",
|
|
21
29
|
textOverflow: "ellipsis",
|
|
22
30
|
whiteSpace: "nowrap"
|
|
23
|
-
},
|
|
24
|
-
...
|
|
31
|
+
}, u = { display: "inline-flex", flexShrink: 0 }, R = {
|
|
32
|
+
...u,
|
|
25
33
|
color: "var(--malachite-text-dimmed, rgb(161, 161, 161))"
|
|
26
|
-
}, n = "malachite-actionmenu-item-icon", a = "malachite-actionmenu-item",
|
|
34
|
+
}, n = "malachite-actionmenu-item-icon", a = "malachite-actionmenu-item", g = "data-malachite-actionmenu-tag", I = { display: "inline-flex", flexShrink: 0 }, L = { [g]: "" }, x = [
|
|
27
35
|
`.${a} { background: transparent; }`,
|
|
28
36
|
`.${a}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,
|
|
29
37
|
`.${a}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`
|
|
@@ -31,18 +39,18 @@ const y = {
|
|
|
31
39
|
`${t} { color: var(--malachite-text-primary, rgb(10, 10, 10)); }`,
|
|
32
40
|
`${t}[data-tone="muted"] { color: var(--malachite-text-secondary, rgb(123, 123, 123)); }`,
|
|
33
41
|
`${t} > .${n} { color: var(--malachite-text-dimmed, rgb(161, 161, 161)); }`,
|
|
34
|
-
`${t}[aria-current] { color: ${d}; background: ${
|
|
42
|
+
`${t}[aria-current] { color: ${d}; background: ${l}; }`,
|
|
35
43
|
`${c} { color: var(--malachite-text-destructive, rgb(237, 53, 54)); background: var(--malachite-error-background-glass, rgba(197, 63, 63, 0.08)); }`,
|
|
36
44
|
`${c} > .${n} { color: inherit; }`
|
|
37
|
-
], v = () =>
|
|
45
|
+
], v = () => i("malachite-actionmenu-danger-hover-styles", b), A = () => (s(), v(), i("malachite-actionmenu-item-styles", x)), S = {
|
|
38
46
|
default: "var(--malachite-text-primary, rgb(10, 10, 10))",
|
|
39
47
|
muted: "var(--malachite-text-secondary, rgb(123, 123, 123))"
|
|
40
|
-
},
|
|
48
|
+
}, E = (e, o) => {
|
|
41
49
|
if (e.danger === !0)
|
|
42
50
|
return "var(--malachite-text-destructive, rgb(237, 53, 54))";
|
|
43
51
|
if (e.danger !== "hover")
|
|
44
52
|
return e.current ? d : S[o];
|
|
45
|
-
}, $ = (e, o = "default") => e.type === "text" ?
|
|
53
|
+
}, $ = (e, o = "default") => e.type === "text" ? h : e.type === "divider" ? {
|
|
46
54
|
height: 1,
|
|
47
55
|
background: "var(--malachite-card-border, rgb(232, 232, 232))",
|
|
48
56
|
margin: "4px 0"
|
|
@@ -54,8 +62,8 @@ const y = {
|
|
|
54
62
|
borderRadius: 8,
|
|
55
63
|
fontSize: "var(--malachite-font-size-small, 13px)",
|
|
56
64
|
fontWeight: 400,
|
|
57
|
-
color:
|
|
58
|
-
background: e.current && e.danger !== "hover" ?
|
|
65
|
+
color: E(e, o),
|
|
66
|
+
background: e.current && e.danger !== "hover" ? l : void 0,
|
|
59
67
|
cursor: e.disabled ? "not-allowed" : "pointer",
|
|
60
68
|
opacity: e.disabled ? 0.5 : 1,
|
|
61
69
|
userSelect: "none",
|
|
@@ -66,7 +74,7 @@ const y = {
|
|
|
66
74
|
textDecoration: "none",
|
|
67
75
|
boxSizing: "border-box",
|
|
68
76
|
width: "100%"
|
|
69
|
-
},
|
|
77
|
+
}, N = (e) => ({
|
|
70
78
|
position: "fixed",
|
|
71
79
|
top: (e == null ? void 0 : e.top) ?? 0,
|
|
72
80
|
left: (e == null ? void 0 : e.left) ?? 0,
|
|
@@ -88,17 +96,18 @@ export {
|
|
|
88
96
|
m as EMPTY_ITEM_STYLE,
|
|
89
97
|
a as ITEM_CLASS,
|
|
90
98
|
n as ITEM_ICON_CLASS,
|
|
91
|
-
|
|
99
|
+
u as ITEM_ICON_LAYOUT,
|
|
92
100
|
R as ITEM_ICON_STYLE,
|
|
93
101
|
O as LABEL_STYLE,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
g as TAG_HOST_ATTR,
|
|
103
|
+
L as TAG_HOST_PROPS,
|
|
104
|
+
I as TAG_HOST_STYLE,
|
|
105
|
+
h as TEXT_ITEM_STYLE,
|
|
98
106
|
y as TRIGGER_SIZES,
|
|
107
|
+
w as VISUALLY_HIDDEN_STYLE,
|
|
99
108
|
A as ensureActionMenuStyles,
|
|
100
109
|
v as ensureDangerOnHoverStyles,
|
|
101
110
|
$ as itemStyle,
|
|
102
|
-
|
|
111
|
+
N as menuStyle
|
|
103
112
|
};
|
|
104
113
|
//# sourceMappingURL=actionMenuStyles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actionMenuStyles.js","sources":["../../src/components/actionMenuStyles.ts"],"sourcesContent":["import type React from 'react';\nimport type { ActionMenuItem } from './actionMenuTypes';\nimport { MENU_SPECS, type MenuGeometry } from './floatingMenuGeometry';\nimport { injectStyleSheet } from './injectStyleSheet';\nimport { ensureOverlayStyles } from './portalOverlay';\nimport { SELECTED_ROW_BACKGROUND, SELECTED_ROW_FOREGROUND } from './selectedRow';\n\nexport const TRIGGER_SIZES: Record<'small' | 'xsmall', { icon: number; iconBox: string }> = {\n small: { icon: 16, iconBox: 'text-[16px] [&_svg]:size-[16px]!' },\n xsmall: { icon: 11, iconBox: 'text-[11px] [&_svg]:size-[11px]!' },\n};\n\nexport const LABEL_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n};\n\nexport const EMPTY_ITEM_STYLE: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 'var(--malachite-font-size-small, 13px)',\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n userSelect: 'none',\n};\n\nexport const TEXT_ITEM_STYLE: React.CSSProperties = {\n ...EMPTY_ITEM_STYLE,\n color: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nexport const ITEM_ICON_LAYOUT: React.CSSProperties = { display: 'inline-flex', flexShrink: 0 };\n\nexport const ITEM_ICON_STYLE: React.CSSProperties = {\n ...ITEM_ICON_LAYOUT,\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n};\n\nexport const ITEM_ICON_CLASS = 'malachite-actionmenu-item-icon';\n\nexport const ITEM_CLASS = 'malachite-actionmenu-item';\n\nexport const TAG_HOST_ATTR = 'data-malachite-actionmenu-tag' as const;\n\nexport const TAG_HOST_STYLE: React.CSSProperties = { display: 'inline-flex', flexShrink: 0 };\n\nexport const TAG_HOST_PROPS = { [TAG_HOST_ATTR]: '' };\n\nconst ITEM_RULES = [\n `.${ITEM_CLASS} { background: transparent; }`,\n `.${ITEM_CLASS}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,\n `.${ITEM_CLASS}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`,\n];\n\nconst DANGER_ON_HOVER = `.${ITEM_CLASS}[data-danger=\"hover\"]`;\nconst DANGER_ON_HOVER_ACTIVE = `${DANGER_ON_HOVER}:not(:disabled):is(:hover, :focus-visible)`;\n\nconst DANGER_ON_HOVER_RULES = [\n `${DANGER_ON_HOVER} { color: var(--malachite-text-primary, rgb(10, 10, 10)); }`,\n `${DANGER_ON_HOVER}[data-tone=\"muted\"] { color: var(--malachite-text-secondary, rgb(123, 123, 123)); }`,\n `${DANGER_ON_HOVER} > .${ITEM_ICON_CLASS} { color: var(--malachite-text-dimmed, rgb(161, 161, 161)); }`,\n `${DANGER_ON_HOVER}[aria-current] { color: ${SELECTED_ROW_FOREGROUND}; background: ${SELECTED_ROW_BACKGROUND}; }`,\n `${DANGER_ON_HOVER_ACTIVE} { color: var(--malachite-text-destructive, rgb(237, 53, 54)); background: var(--malachite-error-background-glass, rgba(197, 63, 63, 0.08)); }`,\n `${DANGER_ON_HOVER_ACTIVE} > .${ITEM_ICON_CLASS} { color: inherit; }`,\n];\n\nexport const ensureDangerOnHoverStyles = (): CSSStyleSheet | null =>\n injectStyleSheet('malachite-actionmenu-danger-hover-styles', DANGER_ON_HOVER_RULES);\n\nexport const ensureActionMenuStyles = (): CSSStyleSheet | null => {\n ensureOverlayStyles();\n ensureDangerOnHoverStyles();\n return injectStyleSheet('malachite-actionmenu-item-styles', ITEM_RULES);\n};\n\nexport type ActionMenuTone = 'default' | 'muted';\n\nconst ITEM_TEXT: Record<ActionMenuTone, string> = {\n default: 'var(--malachite-text-primary, rgb(10, 10, 10))',\n muted: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n};\n\ntype ActionItem = Exclude<ActionMenuItem, { type: 'text' } | { type: 'divider' }>;\n\nconst actionItemColor = (item: ActionItem, tone: ActionMenuTone): string | undefined => {\n if (item.danger === true) {\n return 'var(--malachite-text-destructive, rgb(237, 53, 54))';\n }\n if (item.danger === 'hover') {\n return undefined;\n }\n if (item.current) {\n return SELECTED_ROW_FOREGROUND;\n }\n return ITEM_TEXT[tone];\n};\n\nexport const itemStyle = (\n item: ActionMenuItem,\n tone: ActionMenuTone = 'default',\n): React.CSSProperties => {\n if (item.type === 'text') {\n return TEXT_ITEM_STYLE;\n }\n if (item.type === 'divider') {\n return {\n height: 1,\n background: 'var(--malachite-card-border, rgb(232, 232, 232))',\n margin: '4px 0',\n };\n }\n return {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 10px',\n borderRadius: 8,\n fontSize: 'var(--malachite-font-size-small, 13px)',\n fontWeight: 400,\n color: actionItemColor(item, tone),\n background: item.current && item.danger !== 'hover' ? SELECTED_ROW_BACKGROUND : undefined,\n cursor: item.disabled ? 'not-allowed' : 'pointer',\n opacity: item.disabled ? 0.5 : 1,\n userSelect: 'none',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n border: 'none',\n textAlign: 'left',\n textDecoration: 'none',\n boxSizing: 'border-box',\n width: '100%',\n };\n};\n\nexport const menuStyle = (position: MenuGeometry | null): React.CSSProperties => ({\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n width: position?.width,\n maxHeight: position?.maxHeight,\n overflowY: 'auto',\n background: MENU_SPECS.options.background,\n border: MENU_SPECS.options.border,\n borderRadius: MENU_SPECS.options.radius,\n boxShadow: MENU_SPECS.options.shadow,\n padding: MENU_SPECS.options.padding,\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n visibility: position ? 'visible' : 'hidden',\n opacity: position ? 1 : 0,\n});\n"],"names":["TRIGGER_SIZES","LABEL_STYLE","EMPTY_ITEM_STYLE","TEXT_ITEM_STYLE","ITEM_ICON_LAYOUT","ITEM_ICON_STYLE","ITEM_ICON_CLASS","ITEM_CLASS","TAG_HOST_ATTR","TAG_HOST_STYLE","TAG_HOST_PROPS","ITEM_RULES","DANGER_ON_HOVER","DANGER_ON_HOVER_ACTIVE","DANGER_ON_HOVER_RULES","SELECTED_ROW_FOREGROUND","SELECTED_ROW_BACKGROUND","ensureDangerOnHoverStyles","injectStyleSheet","ensureActionMenuStyles","ensureOverlayStyles","ITEM_TEXT","actionItemColor","item","tone","itemStyle","menuStyle","position","MENU_SPECS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"actionMenuStyles.js","sources":["../../src/components/actionMenuStyles.ts"],"sourcesContent":["import type React from 'react';\nimport type { ActionMenuItem } from './actionMenuTypes';\nimport { MENU_SPECS, type MenuGeometry } from './floatingMenuGeometry';\nimport { injectStyleSheet } from './injectStyleSheet';\nimport { ensureOverlayStyles } from './portalOverlay';\nimport { SELECTED_ROW_BACKGROUND, SELECTED_ROW_FOREGROUND } from './selectedRow';\n\nexport const TRIGGER_SIZES: Record<'small' | 'xsmall', { icon: number; iconBox: string }> = {\n small: { icon: 16, iconBox: 'text-[16px] [&_svg]:size-[16px]!' },\n xsmall: { icon: 11, iconBox: 'text-[11px] [&_svg]:size-[11px]!' },\n};\n\nexport const LABEL_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n};\n\n// Not `sr-only`: the menu portals outside the shadow root's stylesheet.\nexport const VISUALLY_HIDDEN_STYLE: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n};\n\nexport const EMPTY_ITEM_STYLE: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 'var(--malachite-font-size-small, 13px)',\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n userSelect: 'none',\n};\n\nexport const TEXT_ITEM_STYLE: React.CSSProperties = {\n ...EMPTY_ITEM_STYLE,\n color: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nexport const ITEM_ICON_LAYOUT: React.CSSProperties = { display: 'inline-flex', flexShrink: 0 };\n\nexport const ITEM_ICON_STYLE: React.CSSProperties = {\n ...ITEM_ICON_LAYOUT,\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n};\n\nexport const ITEM_ICON_CLASS = 'malachite-actionmenu-item-icon';\n\nexport const ITEM_CLASS = 'malachite-actionmenu-item';\n\nexport const TAG_HOST_ATTR = 'data-malachite-actionmenu-tag' as const;\n\nexport const TAG_HOST_STYLE: React.CSSProperties = { display: 'inline-flex', flexShrink: 0 };\n\nexport const TAG_HOST_PROPS = { [TAG_HOST_ATTR]: '' };\n\nconst ITEM_RULES = [\n `.${ITEM_CLASS} { background: transparent; }`,\n `.${ITEM_CLASS}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,\n `.${ITEM_CLASS}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`,\n];\n\nconst DANGER_ON_HOVER = `.${ITEM_CLASS}[data-danger=\"hover\"]`;\nconst DANGER_ON_HOVER_ACTIVE = `${DANGER_ON_HOVER}:not(:disabled):is(:hover, :focus-visible)`;\n\nconst DANGER_ON_HOVER_RULES = [\n `${DANGER_ON_HOVER} { color: var(--malachite-text-primary, rgb(10, 10, 10)); }`,\n `${DANGER_ON_HOVER}[data-tone=\"muted\"] { color: var(--malachite-text-secondary, rgb(123, 123, 123)); }`,\n `${DANGER_ON_HOVER} > .${ITEM_ICON_CLASS} { color: var(--malachite-text-dimmed, rgb(161, 161, 161)); }`,\n `${DANGER_ON_HOVER}[aria-current] { color: ${SELECTED_ROW_FOREGROUND}; background: ${SELECTED_ROW_BACKGROUND}; }`,\n `${DANGER_ON_HOVER_ACTIVE} { color: var(--malachite-text-destructive, rgb(237, 53, 54)); background: var(--malachite-error-background-glass, rgba(197, 63, 63, 0.08)); }`,\n `${DANGER_ON_HOVER_ACTIVE} > .${ITEM_ICON_CLASS} { color: inherit; }`,\n];\n\nexport const ensureDangerOnHoverStyles = (): CSSStyleSheet | null =>\n injectStyleSheet('malachite-actionmenu-danger-hover-styles', DANGER_ON_HOVER_RULES);\n\nexport const ensureActionMenuStyles = (): CSSStyleSheet | null => {\n ensureOverlayStyles();\n ensureDangerOnHoverStyles();\n return injectStyleSheet('malachite-actionmenu-item-styles', ITEM_RULES);\n};\n\nexport type ActionMenuTone = 'default' | 'muted';\n\nconst ITEM_TEXT: Record<ActionMenuTone, string> = {\n default: 'var(--malachite-text-primary, rgb(10, 10, 10))',\n muted: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n};\n\ntype ActionItem = Exclude<ActionMenuItem, { type: 'text' } | { type: 'divider' }>;\n\nconst actionItemColor = (item: ActionItem, tone: ActionMenuTone): string | undefined => {\n if (item.danger === true) {\n return 'var(--malachite-text-destructive, rgb(237, 53, 54))';\n }\n if (item.danger === 'hover') {\n return undefined;\n }\n if (item.current) {\n return SELECTED_ROW_FOREGROUND;\n }\n return ITEM_TEXT[tone];\n};\n\nexport const itemStyle = (\n item: ActionMenuItem,\n tone: ActionMenuTone = 'default',\n): React.CSSProperties => {\n if (item.type === 'text') {\n return TEXT_ITEM_STYLE;\n }\n if (item.type === 'divider') {\n return {\n height: 1,\n background: 'var(--malachite-card-border, rgb(232, 232, 232))',\n margin: '4px 0',\n };\n }\n return {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 10px',\n borderRadius: 8,\n fontSize: 'var(--malachite-font-size-small, 13px)',\n fontWeight: 400,\n color: actionItemColor(item, tone),\n background: item.current && item.danger !== 'hover' ? SELECTED_ROW_BACKGROUND : undefined,\n cursor: item.disabled ? 'not-allowed' : 'pointer',\n opacity: item.disabled ? 0.5 : 1,\n userSelect: 'none',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n border: 'none',\n textAlign: 'left',\n textDecoration: 'none',\n boxSizing: 'border-box',\n width: '100%',\n };\n};\n\nexport const menuStyle = (position: MenuGeometry | null): React.CSSProperties => ({\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n width: position?.width,\n maxHeight: position?.maxHeight,\n overflowY: 'auto',\n background: MENU_SPECS.options.background,\n border: MENU_SPECS.options.border,\n borderRadius: MENU_SPECS.options.radius,\n boxShadow: MENU_SPECS.options.shadow,\n padding: MENU_SPECS.options.padding,\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n visibility: position ? 'visible' : 'hidden',\n opacity: position ? 1 : 0,\n});\n"],"names":["TRIGGER_SIZES","LABEL_STYLE","VISUALLY_HIDDEN_STYLE","EMPTY_ITEM_STYLE","TEXT_ITEM_STYLE","ITEM_ICON_LAYOUT","ITEM_ICON_STYLE","ITEM_ICON_CLASS","ITEM_CLASS","TAG_HOST_ATTR","TAG_HOST_STYLE","TAG_HOST_PROPS","ITEM_RULES","DANGER_ON_HOVER","DANGER_ON_HOVER_ACTIVE","DANGER_ON_HOVER_RULES","SELECTED_ROW_FOREGROUND","SELECTED_ROW_BACKGROUND","ensureDangerOnHoverStyles","injectStyleSheet","ensureActionMenuStyles","ensureOverlayStyles","ITEM_TEXT","actionItemColor","item","tone","itemStyle","menuStyle","position","MENU_SPECS"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,8 @@ export declare type ActionMenuItem = {
|
|
|
103
103
|
onClick?: () => void;
|
|
104
104
|
/** Renders a link; a plain click runs `onClick` instead of following it, when one is given. */
|
|
105
105
|
href?: string;
|
|
106
|
+
/** Where `href` opens; `'_blank'` also adds `noopener noreferrer`. */
|
|
107
|
+
target?: default_2.HTMLAttributeAnchorTarget;
|
|
106
108
|
disabled?: boolean;
|
|
107
109
|
/** `'hover'` turns the item destructive only on hover or focus. */
|
|
108
110
|
danger?: boolean | 'hover';
|
|
@@ -4856,6 +4858,7 @@ export declare interface TagProps {
|
|
|
4856
4858
|
/** The cursor over a tag that is not clickable. Unset, it is whatever an ancestor sets
|
|
4857
4859
|
* through `--malachite-ctx-tag-cursor` (a `NavItem` row sets its pointer), else the arrow. */
|
|
4858
4860
|
pointerType?: 'pointer' | 'default';
|
|
4861
|
+
/** Makes it a button, unless `onRemove` is set; keep `value` and `icon` non-interactive. */
|
|
4859
4862
|
onClick?: () => void;
|
|
4860
4863
|
onRemove?: (e: default_2.MouseEvent) => void;
|
|
4861
4864
|
/** Explains the tag on hover. Takes the place of the truncation tooltip, which only repeats
|
|
@@ -5101,6 +5104,8 @@ declare interface TooltipProps {
|
|
|
5101
5104
|
describesTrigger?: boolean;
|
|
5102
5105
|
/** False to open on hover only, e.g. where script moves focus onto the trigger. */
|
|
5103
5106
|
showOnFocus?: boolean;
|
|
5107
|
+
/** Makes a trigger that cannot take focus a tab stop. Not for focusable children. */
|
|
5108
|
+
focusableTrigger?: boolean;
|
|
5104
5109
|
}
|
|
5105
5110
|
|
|
5106
5111
|
export declare const TrashIcon: React.FC<IconProps_106>;
|
package/package.json
CHANGED