@stackone/malachite 2.66.0 → 2.67.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 +1 -1
- package/dist/components/Popover.js +196 -173
- package/dist/components/Popover.js.map +1 -1
- package/dist/components/PopoverParts.js +61 -31
- package/dist/components/PopoverParts.js.map +1 -1
- package/dist/components/popoverTree.js +5 -4
- package/dist/components/popoverTree.js.map +1 -1
- package/dist/index.d.ts +26 -5
- package/package.json +1 -1
package/COMPONENTS.md
CHANGED
|
@@ -25,7 +25,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
25
25
|
- **`Divider`** — Separator; supports a dashed line style. Horizontal by default and spanning its container; `orientation="vertical"` draws a rule between inline controls (e.g. groups in a toolbar) and holds its width in a tight flex row. `length` sizes it along its own axis on a fixed scale, and it never shrinks below 1px. _Key props:_ `orientation="horizontal" | "vertical"`, `length` (`small` | `medium` | `large`), `lineStyle="solid" | "dashed"`, `DividerVariant`, `SpacingSize`, `PaddingSize`.
|
|
26
26
|
- **`OverflowRow`** — Horizontal row that collapses items that do not fit into an overflow affordance.
|
|
27
27
|
- **`ActionBar`** — A row of actions that collapses into a single `ActionMenu` once its container drops below `collapseBelow`. Measures the nearest genuinely-wider ancestor rather than itself, since the row shrinks to its own content. `dividerBefore` renders a vertical rule in the row and a divider in the collapsed menu, so both forms group the actions the same way. _Key props:_ `buttons` (`label`, `onClick`, `icon`, `variant`, `size`, `radius`, `tooltip`, `disabled`, `dividerBefore`), `collapseBelow`, `menuLabel`, `className`.
|
|
28
|
-
- **`Popover`** — An anchored, non-modal panel for arbitrary content — a workspace switcher, an org flyout. The panel renders in its own shadow root, so malachite components inside it are styled, and joins the top layer like the other overlays. It prefers its `placement` and flips to the opposite side when there is no room, clamping along the other axis. Click-opened panels take focus and hand it back to the trigger on close; `openOn="hover"` also opens on focus and stays open while the pointer or focus is in the panel. A nested Popover counts as inside its parent for outside-press and hover dismissal, and Escape closes the topmost only. A click panel also closes when focus moves somewhere outside it and its trigger, and on close it hands focus back to the trigger only if focus would otherwise fall to the page. _Key props:_ `trigger`, `children`, `open`, `defaultOpen`, `onOpenChange`, `placement` (`bottom-start` | `bottom-end` | `top-start` | `top-center` | `right-start` | `right-end` | `left-start`), `openOn` (`click` | `hover`), `width` (`content` | `trigger`), `padding` (`none` | `small` | `medium`), `anchorRef` (position against another element, e.g. the section a trigger row sits in), `offset` (`small` 8px | `medium` 12px | `large` 14px), `elevation` (`default` | `raised`), `
|
|
28
|
+
- **`Popover`** — An anchored, non-modal panel for arbitrary content — a workspace switcher, an org flyout. The panel renders in its own shadow root, so malachite components inside it are styled, and joins the top layer like the other overlays. It prefers its `placement` and flips to the opposite side when there is no room, clamping along the other axis. Click-opened panels take focus and hand it back to the trigger on close; `openOn="hover"` also opens on focus and stays open while the pointer or focus is in the panel. A nested Popover counts as inside its parent for outside-press and hover dismissal, and Escape closes the topmost only. A click panel also closes when focus moves somewhere outside it and its trigger, and on close it hands focus back to the trigger only if focus would otherwise fall to the page. _Key props:_ `trigger`, `children`, `open`, `defaultOpen`, `onOpenChange`, `placement` (`bottom-start` | `bottom-end` | `top-start` | `top-center` | `right-start` | `right-end` | `left-start`), `openOn` (`click` | `hover`), `width` (`content` | `trigger`), `padding` (`none` | `small` | `medium`), `anchorRef` (position against another element, e.g. the section a trigger row sits in), `offset` (`small` 8px | `medium` 12px | `large` 14px), `elevation` (`default` | `raised`), `initialFocus` (a ref, or a function read when the panel is shown, for what takes focus in place of the first focusable; it is read again as the panel's content changes, so focus follows content that mounts late or a focused element that is removed, but never leaves an element the user moved to; `initialFocusRef` is its deprecated form, read on open only), `openOnArrowKey` (a click panel also opens, focus inside, on the arrow key its placement points at — ArrowDown for a `bottom-*` placement; a text field trigger keeps its arrow keys), `role` (`dialog` | `menu` | `listbox`; `menu` brings no roving focus of its own), `aria-label` or `aria-labelledby` (one is required), `className`. The panel is capped to the viewport width, and only overlays opened from inside it (menus, dropdowns, modals) count as inside for outside-press dismissal. A side placement stays level with its anchor and scrolls within the room below, sliding up only when under 160px is left. Parts for the panel body: `Popover.Header` (`title`, `action`), `Popover.Action` (`icon`, `aria-label`, `onClick`, `href` (a link that opens in a new tab on Cmd/Ctrl-click or a middle click; a plain click runs `onClick` when one is given), `disabled`, `tooltip`), `Popover.List` (a scrolling list; `scrollToSelected` scrolls the list, never the page, to its selected row, one marked `aria-current`, `aria-selected` or a checked radio, each time the popover is shown, once that row mounts), `Popover.Section` (a bordered section) and `Popover.Empty` (an empty-state line).
|
|
29
29
|
- **`Modal`** — Centred dialog over a scrim, with header slots (icon/title/subtitle/extra), a scrolling body and a pinned footer. Locks background scroll and dismisses on ESC, the close button, or a scrim click unless `closeOnOverlayClick` is off; `busy` suppresses the two pointer routes while a request is in flight and sets `aria-busy`, so a stray click cannot tear the dialog down mid-write — but never ESC, which is the only guaranteed keyboard exit from a focus trap and so always reaches `onClose`. ESC, the Tab focus trap and `aria-modal` all apply to the topmost overlay only, so these may be stacked — a dialog opened from a panel keeps Tab to itself and the panel stops claiming to be modal. The Tab trap follows focus into a malachite popup portaled out of the dialog’s own tree — a `MultiSelect` listbox or a `Popover` opened from the body — and traps Tab within that popup while it holds focus, so Tab walks and wraps that popup’s own stops rather than being yanked back to the dialog’s first control or escaping the dialog altogether. A `Dropdown` list or an `ActionMenu` is dismissed by Tab rather than trapping it: it closes and focus returns to its trigger, so Tab carries on from there. A consumer’s own portaled popup is not known to the trap and Tab will pull focus out of it. Set `role="alertdialog"` for a consequential choice, which asks assistive tech to announce the body and not just the name, and point `aria-describedby` at whichever element carries it. Width comes from the `size` union (`small` 420px | `medium` 612px | `large` 760px) rather than a raw pixel prop. `titleAdornment` sits immediately after the title behind a hairline divider, for naming the thing being acted on — distinct from `headerExtra`, which pins to the far right. `tray` paints a tinted plate around the card and hangs a `caption` beneath it; the plate is the dialog element itself, so that caption stays inside the `aria-modal` subtree rather than being stranded outside it by the visual nesting, and it is added to `aria-describedby` automatically because it says what the dialog is asking. It takes a tone (`neutral` | `warning` | `error` | `success`) rather than a colour, so no consumer can paint it off-palette — and the tone sets the plate and its caption colour together, so the two cannot disagree. The caption is a `{ label?, message }` pair rather than a node, because its row height, type scale and colour belong to the plate. `size` names the card, and the plate’s 4px ring is added on top. Like `SidePanel` it sits in a z-index band from 1000 — one step per stacked overlay, so what paints on top is what holds the keyboard — and stays out of the browser top layer, so a host app’s own dialogs can still cover it. `callouts` stacks full-bleed `Alert` bands at the top of the body, as on `SidePanel`; they ignore `bodyPadding` and lead `aria-describedby`, ahead of the consumer’s own description and the tray caption. For a confirmation use `ConfirmationDialog`, which is a preset over this. _Key props:_ `open`, `onClose`, `title`, `subtitle`, `icon`, `headerExtra`, `titleAdornment`, `tray`, `callouts`, `renderLink`, `headerDivider`, `footer`, `size`, `showCloseButton`, `closeOnOverlayClick`, `bodyPadding`, `busy`, `role` (`dialog` | `alertdialog`), `aria-label`, `aria-labelledby`, `aria-describedby`.
|
|
30
30
|
- **`SidePanel`** — Right-hand slide-in overlay panel (drawer) with header slots (back/icon/title/subtitle/extra), scrollable body and optional footer. Locks background scroll and dismisses on ESC, an overlay click or close. ESC and the Tab focus trap apply to the topmost overlay only, so a `Modal` may be stacked over it. The Tab trap follows focus into a malachite popup portaled out of the panel’s own tree — a `MultiSelect` listbox or a `Popover` opened from the body — and traps Tab within that popup while it holds focus, so Tab walks and wraps that popup’s own stops rather than being yanked back to the panel’s first control or escaping the panel altogether. A `Dropdown` list or an `ActionMenu` is dismissed by Tab rather than trapping it: it closes and focus returns to its trigger, so Tab carries on from there. A consumer’s own portaled popup is not known to the trap and Tab will pull focus out of it. `callouts` stacks full-bleed `Alert` bands at the top of the body, above `children` and unaffected by `bodyPadding` — the same band `ConfirmationDialog` gives its `callout` — and `renderLink` routes their root-relative markdown links through the app’s router. The callouts are announced as the panel’s description, ahead of `description`.
|
|
31
31
|
- **`useHasOpenOverlay`** — Hook reporting whether any modal-type overlay - `SidePanel` or `Modal` - is open anywhere in the app. For host chrome that has to get out of an overlay’s way, a floating support widget being the case it was added for: overlays render through a portal, so a host has no DOM signal of its own to read, and reading the library’s internal markers would couple it to something it does not own. Dropdowns and tooltips are deliberately not counted - they do not trap focus, and chrome does not need to move for them. _Key props:_ No arguments. Returns a boolean.
|
|
@@ -1,257 +1,280 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
3
|
-
import { createPortal as
|
|
4
|
-
import { ShadowRootWrapper as
|
|
5
|
-
import { PopoverEmpty as
|
|
6
|
-
import { getDeepActiveElement as
|
|
7
|
-
import { elementRef as
|
|
8
|
-
import { pushEscapeLayer as
|
|
9
|
-
import { MENU_VIEWPORT_PADDING_PX as
|
|
10
|
-
import { firstTabStopIn as
|
|
11
|
-
import { usePopupLayer as
|
|
12
|
-
import { PopoverTreeContext as
|
|
13
|
-
import { useHoverClose as
|
|
14
|
-
import { useLatestRef as
|
|
15
|
-
import { usePopoverPosition as
|
|
16
|
-
import { usePopoverTree as
|
|
17
|
-
const
|
|
1
|
+
import { jsxs as ye, Fragment as Me, jsx as O } from "react/jsx-runtime";
|
|
2
|
+
import Ce, { useContext as Se, useState as Q, useSyncExternalStore as De, useRef as d, useCallback as Z, useEffect as $, useMemo as _e } from "react";
|
|
3
|
+
import { createPortal as Ae } from "react-dom";
|
|
4
|
+
import { ShadowRootWrapper as Ie } from "../ShadowRootWrapper.js";
|
|
5
|
+
import { PopoverEmpty as Ne, PopoverSection as Oe, PopoverList as ke, PopoverAction as Ke, PopoverHeader as Re } from "./PopoverParts.js";
|
|
6
|
+
import { getDeepActiveElement as U } from "./activeElement.js";
|
|
7
|
+
import { elementRef as He, composeRefs as Be, chainHandler as p } from "./composeRefs.js";
|
|
8
|
+
import { pushEscapeLayer as $e } from "./escapeLayers.js";
|
|
9
|
+
import { MENU_VIEWPORT_PADDING_PX as Ue } from "./floatingMenuGeometry.js";
|
|
10
|
+
import { firstTabStopIn as re } from "./overlayBehaviour.js";
|
|
11
|
+
import { usePopupLayer as We } from "./overlayLayers.js";
|
|
12
|
+
import { PopoverTreeContext as ee, PopoverShownContext as je } from "./popoverTree.js";
|
|
13
|
+
import { useHoverClose as Fe } from "./useHoverClose.js";
|
|
14
|
+
import { useLatestRef as k } from "./useLatestRef.js";
|
|
15
|
+
import { usePopoverPosition as Ge } from "./usePopoverPosition.js";
|
|
16
|
+
import { usePopoverTree as Ve } from "./usePopoverTree.js";
|
|
17
|
+
const Xe = "font-sans box-border overflow-auto outline-none rounded-[var(--malachite-radius-xl,12px)] border border-solid border-[var(--malachite-card-border,rgb(232,232,232))] bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-primary,rgb(10,10,10))]", Ye = {
|
|
18
18
|
default: "[box-shadow:0px_4px_10px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]",
|
|
19
19
|
raised: "[box-shadow:0px_8px_24px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]"
|
|
20
|
-
},
|
|
20
|
+
}, qe = {
|
|
21
21
|
none: "p-0",
|
|
22
22
|
small: "p-1",
|
|
23
23
|
medium: "p-2"
|
|
24
|
-
},
|
|
25
|
-
for (const
|
|
26
|
-
if (
|
|
24
|
+
}, ze = (r, a) => {
|
|
25
|
+
for (const g of a)
|
|
26
|
+
if (g && r.includes(g))
|
|
27
27
|
return !0;
|
|
28
28
|
return !1;
|
|
29
|
-
},
|
|
29
|
+
}, Je = {
|
|
30
30
|
bottom: "ArrowDown",
|
|
31
31
|
top: "ArrowUp",
|
|
32
32
|
right: "ArrowRight",
|
|
33
33
|
left: "ArrowLeft"
|
|
34
|
-
},
|
|
34
|
+
}, Qe = (r) => r instanceof HTMLElement && (r.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(r.tagName)), te = (r) => {
|
|
35
35
|
if (!(r instanceof Node))
|
|
36
36
|
return [];
|
|
37
|
-
const
|
|
38
|
-
return [r, ...
|
|
39
|
-
},
|
|
40
|
-
},
|
|
37
|
+
const a = r.getRootNode();
|
|
38
|
+
return [r, ...a instanceof ShadowRoot ? te(a.host) : []];
|
|
39
|
+
}, Ze = () => () => {
|
|
40
|
+
}, er = () => !0, rr = () => !1, W = (r, a) => a ?? re(r) ?? r, K = (r) => typeof r == "function" ? r() : r == null ? void 0 : r.current, tr = (r, a) => !r || r === document.body || !r.isConnected || r === a, or = ({
|
|
41
41
|
trigger: r,
|
|
42
|
-
children:
|
|
43
|
-
open:
|
|
44
|
-
defaultOpen:
|
|
45
|
-
onOpenChange:
|
|
46
|
-
placement:
|
|
47
|
-
openOn:
|
|
48
|
-
width:
|
|
49
|
-
padding:
|
|
50
|
-
anchorRef:
|
|
51
|
-
offset:
|
|
52
|
-
elevation:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
"aria-
|
|
58
|
-
|
|
42
|
+
children: a,
|
|
43
|
+
open: g,
|
|
44
|
+
defaultOpen: oe = !1,
|
|
45
|
+
onOpenChange: ne,
|
|
46
|
+
placement: j = "bottom-start",
|
|
47
|
+
openOn: m = "click",
|
|
48
|
+
width: se = "content",
|
|
49
|
+
padding: ce = "small",
|
|
50
|
+
anchorRef: ue,
|
|
51
|
+
offset: ae = "small",
|
|
52
|
+
elevation: le = "default",
|
|
53
|
+
initialFocus: F,
|
|
54
|
+
initialFocusRef: v,
|
|
55
|
+
openOnArrowKey: ie = !1,
|
|
56
|
+
role: G = "dialog",
|
|
57
|
+
"aria-label": fe,
|
|
58
|
+
"aria-labelledby": de,
|
|
59
|
+
className: pe = ""
|
|
59
60
|
}) => {
|
|
60
|
-
const
|
|
61
|
+
const me = Se(ee), [ve, he] = Q(oe), c = g ?? ve, be = De(Ze, er, rr), w = d(null), b = d(null), Pe = We("popover", c, b), [t, Ee] = Q(null), V = d(0), R = d(!1), S = d(!1), D = d(!1), x = d(null), T = d(null), _ = k(c), X = k(g), A = k(ne), P = k(F), L = F !== void 0, l = Z(
|
|
61
62
|
(e) => {
|
|
62
|
-
var
|
|
63
|
-
e !==
|
|
63
|
+
var u;
|
|
64
|
+
e !== _.current && (X.current === void 0 && he(e), (u = A.current) == null || u.call(A, e));
|
|
64
65
|
},
|
|
65
|
-
[
|
|
66
|
-
), { pointerInside:
|
|
67
|
-
isOpenRef:
|
|
68
|
-
heldByChildren:
|
|
69
|
-
setOpen:
|
|
70
|
-
}), { tree:
|
|
71
|
-
parent:
|
|
72
|
-
isOpen:
|
|
73
|
-
openOn:
|
|
74
|
-
isOpenRef:
|
|
75
|
-
heldByChildren:
|
|
76
|
-
cancelClose:
|
|
77
|
-
scheduleClose:
|
|
78
|
-
}), o =
|
|
79
|
-
isOpen:
|
|
80
|
-
panel:
|
|
81
|
-
hostRef:
|
|
82
|
-
triggerRef:
|
|
83
|
-
anchorRef:
|
|
84
|
-
placement:
|
|
85
|
-
width:
|
|
86
|
-
offset:
|
|
66
|
+
[_, X, A]
|
|
67
|
+
), { pointerInside: y, focusInside: M, triggerFocused: Y, cancelClose: h, scheduleClose: I } = Fe({
|
|
68
|
+
isOpenRef: _,
|
|
69
|
+
heldByChildren: V,
|
|
70
|
+
setOpen: l
|
|
71
|
+
}), { tree: ge, ownedSources: H } = Ve({
|
|
72
|
+
parent: me,
|
|
73
|
+
isOpen: c,
|
|
74
|
+
openOn: m,
|
|
75
|
+
isOpenRef: _,
|
|
76
|
+
heldByChildren: V,
|
|
77
|
+
cancelClose: h,
|
|
78
|
+
scheduleClose: I
|
|
79
|
+
}), o = Ge({
|
|
80
|
+
isOpen: c,
|
|
81
|
+
panel: t,
|
|
82
|
+
hostRef: b,
|
|
83
|
+
triggerRef: w,
|
|
84
|
+
anchorRef: ue,
|
|
85
|
+
placement: j,
|
|
86
|
+
width: se,
|
|
87
|
+
offset: ae
|
|
87
88
|
});
|
|
88
|
-
|
|
89
|
-
if (!
|
|
89
|
+
$(() => {
|
|
90
|
+
if (!c)
|
|
90
91
|
return;
|
|
91
|
-
const e = (
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
...[...
|
|
97
|
-
]) ||
|
|
92
|
+
const e = (n) => {
|
|
93
|
+
const s = n.composedPath();
|
|
94
|
+
ze(s, [
|
|
95
|
+
w.current,
|
|
96
|
+
b.current,
|
|
97
|
+
...[...H.current].map((Le) => Le())
|
|
98
|
+
]) || l(!1);
|
|
98
99
|
};
|
|
99
100
|
document.addEventListener("mousedown", e, !0);
|
|
100
|
-
const
|
|
101
|
+
const u = $e(() => l(!1));
|
|
101
102
|
return () => {
|
|
102
|
-
var
|
|
103
|
-
document.removeEventListener("mousedown", e, !0),
|
|
104
|
-
const
|
|
105
|
-
|
|
103
|
+
var s;
|
|
104
|
+
document.removeEventListener("mousedown", e, !0), u(), y.current = !1;
|
|
105
|
+
const n = U();
|
|
106
|
+
M.current && (!n || n === document.body) && (S.current = !0, (s = w.current) == null || s.focus({ preventScroll: !0 }), S.current = !1), M.current = !1, x.current = null, T.current = null;
|
|
106
107
|
};
|
|
107
|
-
}, [
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
}, [c, l, H, y, M]);
|
|
109
|
+
const C = c && t !== null && o !== null, E = Z((e) => {
|
|
110
|
+
x.current = e, e.focus({ preventScroll: !0 });
|
|
111
|
+
}, []);
|
|
112
|
+
$(() => {
|
|
113
|
+
const e = m === "click" || R.current;
|
|
114
|
+
if (!C || !t || !e)
|
|
115
|
+
return;
|
|
116
|
+
R.current = !1;
|
|
117
|
+
const u = L ? K(P.current) : v == null ? void 0 : v.current;
|
|
118
|
+
E(W(t, u));
|
|
119
|
+
}, [C, t, m, L, v, P, E]), $(() => {
|
|
120
|
+
if (!C || !t || !L)
|
|
121
|
+
return;
|
|
122
|
+
const e = () => {
|
|
123
|
+
const n = U();
|
|
124
|
+
if (tr(n, b.current)) {
|
|
125
|
+
T.current && !T.current.isConnected && E(W(t, K(P.current)));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (n !== x.current)
|
|
129
|
+
return;
|
|
130
|
+
const s = K(P.current) ?? (n === t ? re(t) : null);
|
|
131
|
+
s && s !== n && s.isConnected && E(s);
|
|
132
|
+
}, u = new MutationObserver(e);
|
|
133
|
+
return u.observe(t, { childList: !0, subtree: !0 }), () => u.disconnect();
|
|
134
|
+
}, [C, t, L, P, E]);
|
|
135
|
+
const B = () => {
|
|
136
|
+
if (h(), c && t) {
|
|
137
|
+
const e = L ? K(P.current) : v == null ? void 0 : v.current;
|
|
138
|
+
E(W(t, e));
|
|
116
139
|
return;
|
|
117
140
|
}
|
|
118
|
-
|
|
119
|
-
},
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
...[...
|
|
141
|
+
R.current = !0, l(!0);
|
|
142
|
+
}, N = (e) => {
|
|
143
|
+
const u = [
|
|
144
|
+
w.current,
|
|
145
|
+
b.current,
|
|
146
|
+
t,
|
|
147
|
+
...[...H.current].map((n) => n())
|
|
125
148
|
];
|
|
126
|
-
return
|
|
127
|
-
(
|
|
149
|
+
return te(e).some(
|
|
150
|
+
(n) => u.some((s) => s == null ? void 0 : s.contains(n))
|
|
128
151
|
);
|
|
129
|
-
},
|
|
152
|
+
}, q = (e) => {
|
|
130
153
|
e && queueMicrotask(() => {
|
|
131
|
-
!
|
|
154
|
+
!N(e) && !N(U()) && l(!1);
|
|
132
155
|
});
|
|
133
|
-
},
|
|
156
|
+
}, i = m === "hover" ? {
|
|
134
157
|
onMouseEnter: () => {
|
|
135
|
-
|
|
158
|
+
y.current = !0, h(), l(!0);
|
|
136
159
|
},
|
|
137
160
|
onMouseLeave: () => {
|
|
138
|
-
|
|
161
|
+
y.current = !1, I();
|
|
139
162
|
},
|
|
140
163
|
onPanelMouseOver: () => {
|
|
141
|
-
|
|
164
|
+
y.current = !0, h();
|
|
142
165
|
}
|
|
143
|
-
} : null,
|
|
144
|
-
() =>
|
|
145
|
-
[
|
|
146
|
-
),
|
|
147
|
-
ref:
|
|
148
|
-
"aria-haspopup":
|
|
149
|
-
"aria-expanded":
|
|
166
|
+
} : null, f = r.props, z = He(r), we = _e(
|
|
167
|
+
() => Be(z, w),
|
|
168
|
+
[z]
|
|
169
|
+
), J = Je[j.split("-")[0]], xe = Ce.cloneElement(r, {
|
|
170
|
+
ref: we,
|
|
171
|
+
"aria-haspopup": G,
|
|
172
|
+
"aria-expanded": c,
|
|
150
173
|
onClick: p(
|
|
151
|
-
|
|
174
|
+
f.onClick,
|
|
152
175
|
(e) => {
|
|
153
|
-
if (
|
|
154
|
-
|
|
176
|
+
if (m !== "hover") {
|
|
177
|
+
l(!c);
|
|
155
178
|
return;
|
|
156
179
|
}
|
|
157
180
|
if (e.detail === 0) {
|
|
158
|
-
|
|
181
|
+
B();
|
|
159
182
|
return;
|
|
160
183
|
}
|
|
161
|
-
|
|
184
|
+
h(), l(!0);
|
|
162
185
|
}
|
|
163
186
|
),
|
|
164
|
-
...
|
|
187
|
+
...i ? {
|
|
165
188
|
onMouseEnter: p(
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
f.onMouseEnter,
|
|
190
|
+
i.onMouseEnter
|
|
168
191
|
),
|
|
169
192
|
onMouseLeave: p(
|
|
170
|
-
|
|
171
|
-
|
|
193
|
+
f.onMouseLeave,
|
|
194
|
+
i.onMouseLeave
|
|
172
195
|
),
|
|
173
196
|
onMouseDown: p(
|
|
174
|
-
|
|
197
|
+
f.onMouseDown,
|
|
175
198
|
() => {
|
|
176
|
-
|
|
177
|
-
|
|
199
|
+
D.current = !0, setTimeout(() => {
|
|
200
|
+
D.current = !1;
|
|
178
201
|
});
|
|
179
202
|
}
|
|
180
203
|
),
|
|
181
|
-
onFocus: p(
|
|
182
|
-
const e =
|
|
183
|
-
|
|
204
|
+
onFocus: p(f.onFocus, () => {
|
|
205
|
+
const e = D.current;
|
|
206
|
+
D.current = !1, Y.current = !e && !S.current, !S.current && (h(), l(!0));
|
|
184
207
|
}),
|
|
185
208
|
onKeyDown: p(
|
|
186
|
-
|
|
209
|
+
f.onKeyDown,
|
|
187
210
|
(e) => {
|
|
188
|
-
e.key ===
|
|
211
|
+
e.key === J && (e.preventDefault(), B());
|
|
189
212
|
}
|
|
190
213
|
)
|
|
191
|
-
} :
|
|
214
|
+
} : ie ? {
|
|
192
215
|
onKeyDown: p(
|
|
193
|
-
|
|
216
|
+
f.onKeyDown,
|
|
194
217
|
(e) => {
|
|
195
|
-
e.key !==
|
|
218
|
+
e.key !== J || Qe(e.target) || (e.preventDefault(), B());
|
|
196
219
|
}
|
|
197
220
|
)
|
|
198
221
|
} : {},
|
|
199
222
|
onBlur: p(
|
|
200
|
-
|
|
223
|
+
f.onBlur,
|
|
201
224
|
(e) => {
|
|
202
|
-
if (
|
|
203
|
-
if (
|
|
204
|
-
|
|
225
|
+
if (Y.current = !1, !(!c || N(e.relatedTarget))) {
|
|
226
|
+
if (m === "hover") {
|
|
227
|
+
I();
|
|
205
228
|
return;
|
|
206
229
|
}
|
|
207
|
-
|
|
230
|
+
q(e.relatedTarget);
|
|
208
231
|
}
|
|
209
232
|
}
|
|
210
233
|
)
|
|
211
|
-
}),
|
|
234
|
+
}), Te = {
|
|
212
235
|
maxHeight: o == null ? void 0 : o.maxHeight,
|
|
213
|
-
maxWidth: `calc(100vw - ${
|
|
236
|
+
maxWidth: `calc(100vw - ${Ue * 2}px)`,
|
|
214
237
|
visibility: o ? "visible" : "hidden"
|
|
215
238
|
};
|
|
216
|
-
return /* @__PURE__ */
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
/* @__PURE__ */
|
|
220
|
-
|
|
239
|
+
return /* @__PURE__ */ ye(Me, { children: [
|
|
240
|
+
xe,
|
|
241
|
+
c && be && Ae(
|
|
242
|
+
/* @__PURE__ */ O(ee.Provider, { value: ge, children: /* @__PURE__ */ O(
|
|
243
|
+
Ie,
|
|
221
244
|
{
|
|
222
|
-
hostRef:
|
|
223
|
-
hostProps:
|
|
245
|
+
hostRef: b,
|
|
246
|
+
hostProps: Pe,
|
|
224
247
|
hostStyle: {
|
|
225
248
|
position: "fixed",
|
|
226
249
|
top: (o == null ? void 0 : o.top) ?? 0,
|
|
227
250
|
left: (o == null ? void 0 : o.left) ?? 0
|
|
228
251
|
},
|
|
229
|
-
children: /* @__PURE__ */
|
|
252
|
+
children: /* @__PURE__ */ O(
|
|
230
253
|
"div",
|
|
231
254
|
{
|
|
232
|
-
ref:
|
|
233
|
-
role:
|
|
234
|
-
"aria-label":
|
|
235
|
-
"aria-labelledby":
|
|
255
|
+
ref: Ee,
|
|
256
|
+
role: G,
|
|
257
|
+
"aria-label": fe,
|
|
258
|
+
"aria-labelledby": de,
|
|
236
259
|
"data-side": o == null ? void 0 : o.side,
|
|
237
260
|
tabIndex: -1,
|
|
238
|
-
className: `${
|
|
239
|
-
style:
|
|
240
|
-
onMouseOver:
|
|
241
|
-
onMouseLeave:
|
|
242
|
-
onFocus: () => {
|
|
243
|
-
|
|
261
|
+
className: `${Xe} ${Ye[le]} ${qe[ce]} ${pe}`.trim(),
|
|
262
|
+
style: Te,
|
|
263
|
+
onMouseOver: i == null ? void 0 : i.onPanelMouseOver,
|
|
264
|
+
onMouseLeave: i == null ? void 0 : i.onMouseLeave,
|
|
265
|
+
onFocus: (e) => {
|
|
266
|
+
M.current = !0, e.target !== x.current && (x.current = null), e.target instanceof HTMLElement && (t != null && t.contains(e.target)) && (T.current = e.target), h();
|
|
244
267
|
},
|
|
245
268
|
onBlur: (e) => {
|
|
246
|
-
if (!
|
|
247
|
-
if (
|
|
248
|
-
|
|
269
|
+
if (!N(e.relatedTarget)) {
|
|
270
|
+
if (e.relatedTarget && (T.current = null), M.current = !1, m === "hover") {
|
|
271
|
+
I();
|
|
249
272
|
return;
|
|
250
273
|
}
|
|
251
|
-
|
|
274
|
+
q(e.relatedTarget);
|
|
252
275
|
}
|
|
253
276
|
},
|
|
254
|
-
children:
|
|
277
|
+
children: /* @__PURE__ */ O(je.Provider, { value: C, children: a })
|
|
255
278
|
}
|
|
256
279
|
)
|
|
257
280
|
}
|
|
@@ -259,15 +282,15 @@ const He = "font-sans box-border overflow-auto outline-none rounded-[var(--malac
|
|
|
259
282
|
document.body
|
|
260
283
|
)
|
|
261
284
|
] });
|
|
262
|
-
},
|
|
263
|
-
Header:
|
|
264
|
-
Action:
|
|
265
|
-
List:
|
|
266
|
-
Section:
|
|
267
|
-
Empty:
|
|
285
|
+
}, wr = Object.assign(or, {
|
|
286
|
+
Header: Re,
|
|
287
|
+
Action: Ke,
|
|
288
|
+
List: ke,
|
|
289
|
+
Section: Oe,
|
|
290
|
+
Empty: Ne
|
|
268
291
|
});
|
|
269
292
|
export {
|
|
270
|
-
|
|
271
|
-
|
|
293
|
+
wr as Popover,
|
|
294
|
+
wr as default
|
|
272
295
|
};
|
|
273
296
|
//# sourceMappingURL=Popover.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","sources":["../../src/components/Popover.tsx"],"sourcesContent":["import React, {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport {\n PopoverAction,\n PopoverEmpty,\n PopoverHeader,\n PopoverList,\n PopoverSection,\n} from './PopoverParts';\nimport { getDeepActiveElement } from './activeElement';\nimport { chainHandler, composeRefs, elementRef } from './composeRefs';\nimport { pushEscapeLayer } from './escapeLayers';\nimport {\n type FloatingOffset,\n type FloatingPlacement,\n MENU_VIEWPORT_PADDING_PX,\n} from './floatingMenuGeometry';\nimport { firstTabStopIn } from './overlayBehaviour';\nimport { usePopupLayer } from './overlayLayers';\nimport { PopoverTreeContext } from './popoverTree';\nimport { useHoverClose } from './useHoverClose';\nimport { useLatestRef } from './useLatestRef';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { usePopoverTree } from './usePopoverTree';\n\nexport type PopoverPlacement = FloatingPlacement;\n\ninterface PopoverBaseProps {\n trigger: React.ReactElement;\n children?: React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n placement?: PopoverPlacement;\n openOn?: 'click' | 'hover';\n width?: 'content' | 'trigger';\n padding?: 'none' | 'small' | 'medium';\n anchorRef?: React.RefObject<HTMLElement | null>;\n offset?: FloatingOffset;\n elevation?: 'default' | 'raised';\n initialFocusRef?: React.RefObject<HTMLElement | null>;\n /** A click panel also opens, focus inside, on the arrow key its placement points at. */\n openOnArrowKey?: boolean;\n role?: 'dialog' | 'menu' | 'listbox';\n className?: string;\n}\n\ntype PopoverName =\n | { 'aria-label': string; 'aria-labelledby'?: string }\n | { 'aria-label'?: string; 'aria-labelledby': string };\n\nexport type PopoverProps = PopoverBaseProps & PopoverName;\n\nconst PANEL =\n 'font-sans box-border overflow-auto outline-none rounded-[var(--malachite-radius-xl,12px)] border border-solid border-[var(--malachite-card-border,rgb(232,232,232))] bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-primary,rgb(10,10,10))]';\n\nconst ELEVATION: Record<NonNullable<PopoverBaseProps['elevation']>, string> = {\n default: '[box-shadow:0px_4px_10px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]',\n raised: '[box-shadow:0px_8px_24px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]',\n};\n\nconst PADDING: Record<NonNullable<PopoverBaseProps['padding']>, string> = {\n none: 'p-0',\n small: 'p-1',\n medium: 'p-2',\n};\n\nconst pathHits = (path: EventTarget[], nodes: Iterable<Element | null | undefined>): boolean => {\n for (const node of nodes) {\n if (node && path.includes(node)) {\n return true;\n }\n }\n return false;\n};\n\nconst KEYBOARD_OPEN_KEY: Record<string, string> = {\n bottom: 'ArrowDown',\n top: 'ArrowUp',\n right: 'ArrowRight',\n left: 'ArrowLeft',\n};\n\nconst isTextEntry = (target: EventTarget): boolean =>\n target instanceof HTMLElement &&\n (target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName));\n\nconst composedPathOf = (node: EventTarget | null): Node[] => {\n if (!(node instanceof Node)) {\n return [];\n }\n const root = node.getRootNode();\n return [node, ...(root instanceof ShadowRoot ? composedPathOf(root.host) : [])];\n};\n\nconst subscribeToNothing = () => () => undefined;\nconst onClient = () => true;\nconst onServer = () => false;\n\nconst focusTarget = (panel: HTMLElement, initial: HTMLElement | null | undefined): HTMLElement =>\n initial ?? firstTabStopIn(panel) ?? panel;\n\n/** An anchored, non-modal panel; nested Popovers count as inside their parent. */\nconst PopoverRoot: React.FC<PopoverProps> = ({\n trigger,\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n placement = 'bottom-start',\n openOn = 'click',\n width = 'content',\n padding = 'small',\n anchorRef,\n offset = 'small',\n elevation = 'default',\n initialFocusRef,\n openOnArrowKey = false,\n role = 'dialog',\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n}) => {\n const parent = useContext(PopoverTreeContext);\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isOpen = controlledOpen ?? uncontrolledOpen;\n const isClient = useSyncExternalStore(subscribeToNothing, onClient, onServer);\n\n const triggerRef = useRef<HTMLElement | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const popupIdentity = usePopupLayer('popover', isOpen, hostRef);\n const [panel, setPanel] = useState<HTMLDivElement | null>(null);\n const heldByChildren = useRef(0);\n const focusOnOpen = useRef(false);\n const returningFocus = useRef(false);\n const pointerPressedTrigger = useRef(false);\n\n const isOpenRef = useLatestRef(isOpen);\n const controlledRef = useLatestRef(controlledOpen);\n const onOpenChangeRef = useLatestRef(onOpenChange);\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (next === isOpenRef.current) {\n return;\n }\n if (controlledRef.current === undefined) {\n setUncontrolledOpen(next);\n }\n onOpenChangeRef.current?.(next);\n },\n [isOpenRef, controlledRef, onOpenChangeRef],\n );\n\n const { pointerInside, focusInside, triggerFocused, cancelClose, scheduleClose } =\n useHoverClose({\n isOpenRef,\n heldByChildren,\n setOpen,\n });\n\n const { tree, ownedSources } = usePopoverTree({\n parent,\n isOpen,\n openOn,\n isOpenRef,\n heldByChildren,\n cancelClose,\n scheduleClose,\n });\n\n const geometry = usePopoverPosition({\n isOpen,\n panel,\n hostRef,\n triggerRef,\n anchorRef,\n placement,\n width,\n offset,\n });\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n const closeOnOutsidePress = (event: MouseEvent) => {\n const path = event.composedPath();\n const inside = pathHits(path, [\n triggerRef.current,\n hostRef.current,\n ...[...ownedSources.current].map((source) => source()),\n ]);\n if (!inside) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', closeOnOutsidePress, true);\n const popEscapeLayer = pushEscapeLayer(() => setOpen(false));\n return () => {\n document.removeEventListener('mousedown', closeOnOutsidePress, true);\n popEscapeLayer();\n pointerInside.current = false;\n const active = getDeepActiveElement();\n if (focusInside.current && (!active || active === document.body)) {\n returningFocus.current = true;\n triggerRef.current?.focus({ preventScroll: true });\n returningFocus.current = false;\n }\n focusInside.current = false;\n };\n }, [isOpen, setOpen, ownedSources, pointerInside, focusInside]);\n\n const shown = isOpen && panel !== null && geometry !== null;\n\n useEffect(() => {\n const shouldFocus = openOn === 'click' || focusOnOpen.current;\n if (!shown || !panel || !shouldFocus) {\n return;\n }\n focusOnOpen.current = false;\n focusTarget(panel, initialFocusRef?.current).focus({ preventScroll: true });\n }, [shown, panel, openOn, initialFocusRef]);\n\n const openWithFocus = () => {\n cancelClose();\n if (isOpen && panel) {\n focusTarget(panel, initialFocusRef?.current).focus({ preventScroll: true });\n return;\n }\n focusOnOpen.current = true;\n setOpen(true);\n };\n\n const isInside = (node: EventTarget | null): boolean => {\n const containers = [\n triggerRef.current,\n hostRef.current,\n panel,\n ...[...ownedSources.current].map((source) => source()),\n ];\n return composedPathOf(node).some((step) =>\n containers.some((container) => container?.contains(step)),\n );\n };\n\n const closeIfFocusLeft = (next: EventTarget | null) => {\n if (!next) {\n return;\n }\n queueMicrotask(() => {\n if (!isInside(next) && !isInside(getDeepActiveElement())) {\n setOpen(false);\n }\n });\n };\n\n const hoverHandlers =\n openOn === 'hover'\n ? {\n onMouseEnter: () => {\n pointerInside.current = true;\n cancelClose();\n setOpen(true);\n },\n onMouseLeave: () => {\n pointerInside.current = false;\n scheduleClose();\n },\n onPanelMouseOver: () => {\n pointerInside.current = true;\n cancelClose();\n },\n }\n : null;\n\n const triggerProps = trigger.props as Record<string, unknown>;\n type Handler<E extends React.SyntheticEvent> = ((event: E) => void) | undefined;\n\n const ownTriggerRef = elementRef<HTMLElement>(trigger);\n const composedTriggerRef = useMemo(\n () => composeRefs(ownTriggerRef, triggerRef),\n [ownTriggerRef],\n );\n const openKey = KEYBOARD_OPEN_KEY[placement.split('-')[0]];\n\n const clonedTrigger = React.cloneElement(trigger, {\n ref: composedTriggerRef,\n 'aria-haspopup': role,\n 'aria-expanded': isOpen,\n onClick: chainHandler(\n triggerProps.onClick as Handler<React.MouseEvent>,\n (event: React.MouseEvent) => {\n if (openOn !== 'hover') {\n setOpen(!isOpen);\n return;\n }\n const fromKeyboard = event.detail === 0;\n if (fromKeyboard) {\n openWithFocus();\n return;\n }\n cancelClose();\n setOpen(true);\n },\n ),\n ...(hoverHandlers\n ? {\n onMouseEnter: chainHandler(\n triggerProps.onMouseEnter as Handler<React.MouseEvent>,\n hoverHandlers.onMouseEnter,\n ),\n onMouseLeave: chainHandler(\n triggerProps.onMouseLeave as Handler<React.MouseEvent>,\n hoverHandlers.onMouseLeave,\n ),\n onMouseDown: chainHandler(\n triggerProps.onMouseDown as Handler<React.MouseEvent>,\n () => {\n pointerPressedTrigger.current = true;\n setTimeout(() => {\n pointerPressedTrigger.current = false;\n });\n },\n ),\n onFocus: chainHandler(triggerProps.onFocus as Handler<React.FocusEvent>, () => {\n const fromPointer = pointerPressedTrigger.current;\n pointerPressedTrigger.current = false;\n triggerFocused.current = !fromPointer && !returningFocus.current;\n if (returningFocus.current) {\n return;\n }\n cancelClose();\n setOpen(true);\n }),\n onKeyDown: chainHandler(\n triggerProps.onKeyDown as Handler<React.KeyboardEvent>,\n (event: React.KeyboardEvent) => {\n if (event.key !== openKey) {\n return;\n }\n event.preventDefault();\n openWithFocus();\n },\n ),\n }\n : openOnArrowKey\n ? {\n onKeyDown: chainHandler(\n triggerProps.onKeyDown as Handler<React.KeyboardEvent>,\n (event: React.KeyboardEvent) => {\n if (event.key !== openKey || isTextEntry(event.target)) {\n return;\n }\n event.preventDefault();\n openWithFocus();\n },\n ),\n }\n : {}),\n onBlur: chainHandler(\n triggerProps.onBlur as Handler<React.FocusEvent>,\n (event: React.FocusEvent) => {\n triggerFocused.current = false;\n if (!isOpen || isInside(event.relatedTarget)) {\n return;\n }\n if (openOn === 'hover') {\n scheduleClose();\n return;\n }\n closeIfFocusLeft(event.relatedTarget);\n },\n ),\n } as Record<string, unknown>);\n\n const panelStyle: React.CSSProperties = {\n maxHeight: geometry?.maxHeight,\n maxWidth: `calc(100vw - ${MENU_VIEWPORT_PADDING_PX * 2}px)`,\n visibility: geometry ? 'visible' : 'hidden',\n };\n\n return (\n <>\n {clonedTrigger}\n {isOpen &&\n isClient &&\n createPortal(\n <PopoverTreeContext.Provider value={tree}>\n <ShadowRootWrapper\n hostRef={hostRef}\n hostProps={popupIdentity}\n hostStyle={{\n position: 'fixed',\n top: geometry?.top ?? 0,\n left: geometry?.left ?? 0,\n }}\n >\n <div\n ref={setPanel}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n data-side={geometry?.side}\n tabIndex={-1}\n className={`${PANEL} ${ELEVATION[elevation]} ${PADDING[padding]} ${className}`.trim()}\n style={panelStyle}\n // React's mouseenter stops at the shadow host, so the panel listens for mouseover.\n onMouseOver={hoverHandlers?.onPanelMouseOver}\n onMouseLeave={hoverHandlers?.onMouseLeave}\n onFocus={() => {\n focusInside.current = true;\n cancelClose();\n }}\n onBlur={(event) => {\n if (isInside(event.relatedTarget)) {\n return;\n }\n focusInside.current = false;\n if (openOn === 'hover') {\n scheduleClose();\n return;\n }\n closeIfFocusLeft(event.relatedTarget);\n }}\n >\n {children}\n </div>\n </ShadowRootWrapper>\n </PopoverTreeContext.Provider>,\n document.body,\n )}\n </>\n );\n};\n\nexport const Popover = Object.assign(PopoverRoot, {\n Header: PopoverHeader,\n Action: PopoverAction,\n List: PopoverList,\n Section: PopoverSection,\n Empty: PopoverEmpty,\n});\n\nexport default Popover;\n"],"names":["PANEL","ELEVATION","PADDING","pathHits","path","nodes","node","KEYBOARD_OPEN_KEY","isTextEntry","target","composedPathOf","root","subscribeToNothing","onClient","onServer","focusTarget","panel","initial","firstTabStopIn","PopoverRoot","trigger","children","controlledOpen","defaultOpen","onOpenChange","placement","openOn","width","padding","anchorRef","offset","elevation","initialFocusRef","openOnArrowKey","role","ariaLabel","ariaLabelledBy","className","parent","useContext","PopoverTreeContext","uncontrolledOpen","setUncontrolledOpen","useState","isOpen","isClient","useSyncExternalStore","triggerRef","useRef","hostRef","popupIdentity","usePopupLayer","setPanel","heldByChildren","focusOnOpen","returningFocus","pointerPressedTrigger","isOpenRef","useLatestRef","controlledRef","onOpenChangeRef","setOpen","useCallback","next","_a","pointerInside","focusInside","triggerFocused","cancelClose","scheduleClose","useHoverClose","tree","ownedSources","usePopoverTree","geometry","usePopoverPosition","useEffect","closeOnOutsidePress","event","source","popEscapeLayer","pushEscapeLayer","active","getDeepActiveElement","shown","shouldFocus","openWithFocus","isInside","containers","step","container","closeIfFocusLeft","hoverHandlers","triggerProps","ownTriggerRef","elementRef","composedTriggerRef","useMemo","composeRefs","openKey","clonedTrigger","React","chainHandler","fromPointer","panelStyle","MENU_VIEWPORT_PADDING_PX","jsxs","Fragment","createPortal","jsx","ShadowRootWrapper","Popover","PopoverHeader","PopoverAction","PopoverList","PopoverSection","PopoverEmpty"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover.js","sources":["../../src/components/Popover.tsx"],"sourcesContent":["import React, {\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport {\n PopoverAction,\n PopoverEmpty,\n PopoverHeader,\n PopoverList,\n PopoverSection,\n} from './PopoverParts';\nimport { getDeepActiveElement } from './activeElement';\nimport { chainHandler, composeRefs, elementRef } from './composeRefs';\nimport { pushEscapeLayer } from './escapeLayers';\nimport {\n type FloatingOffset,\n type FloatingPlacement,\n MENU_VIEWPORT_PADDING_PX,\n} from './floatingMenuGeometry';\nimport { firstTabStopIn } from './overlayBehaviour';\nimport { usePopupLayer } from './overlayLayers';\nimport { PopoverShownContext, PopoverTreeContext } from './popoverTree';\nimport { useHoverClose } from './useHoverClose';\nimport { useLatestRef } from './useLatestRef';\nimport { usePopoverPosition } from './usePopoverPosition';\nimport { usePopoverTree } from './usePopoverTree';\n\nexport type PopoverPlacement = FloatingPlacement;\n\nexport type PopoverInitialFocus =\n | React.RefObject<HTMLElement | null>\n | (() => HTMLElement | null | undefined);\n\ninterface PopoverBaseProps {\n trigger: React.ReactElement;\n children?: React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n placement?: PopoverPlacement;\n openOn?: 'click' | 'hover';\n width?: 'content' | 'trigger';\n padding?: 'none' | 'small' | 'medium';\n anchorRef?: React.RefObject<HTMLElement | null>;\n offset?: FloatingOffset;\n elevation?: 'default' | 'raised';\n /** A click panel also opens, focus inside, on the arrow key its placement points at. */\n openOnArrowKey?: boolean;\n role?: 'dialog' | 'menu' | 'listbox';\n className?: string;\n}\n\ntype PopoverName =\n | { 'aria-label': string; 'aria-labelledby'?: string }\n | { 'aria-label'?: string; 'aria-labelledby': string };\n\ntype PopoverFocusSource =\n | {\n /**\n * What takes focus when the panel is shown, in place of its first tab stop. Re-read as the\n * content changes, so focus follows late content but never leaves where the user moved it.\n */\n initialFocus?: PopoverInitialFocus;\n initialFocusRef?: never;\n }\n | {\n initialFocus?: never;\n /** @deprecated Use `initialFocus`, which takes the same ref and also follows late content. */\n initialFocusRef?: React.RefObject<HTMLElement | null>;\n };\n\nexport type PopoverProps = PopoverBaseProps & PopoverName & PopoverFocusSource;\n\nconst PANEL =\n 'font-sans box-border overflow-auto outline-none rounded-[var(--malachite-radius-xl,12px)] border border-solid border-[var(--malachite-card-border,rgb(232,232,232))] bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-primary,rgb(10,10,10))]';\n\nconst ELEVATION: Record<NonNullable<PopoverBaseProps['elevation']>, string> = {\n default: '[box-shadow:0px_4px_10px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]',\n raised: '[box-shadow:0px_8px_24px_0px_var(--malachite-card-shadow,rgba(0,0,0,0.1))]',\n};\n\nconst PADDING: Record<NonNullable<PopoverBaseProps['padding']>, string> = {\n none: 'p-0',\n small: 'p-1',\n medium: 'p-2',\n};\n\nconst pathHits = (path: EventTarget[], nodes: Iterable<Element | null | undefined>): boolean => {\n for (const node of nodes) {\n if (node && path.includes(node)) {\n return true;\n }\n }\n return false;\n};\n\nconst KEYBOARD_OPEN_KEY: Record<string, string> = {\n bottom: 'ArrowDown',\n top: 'ArrowUp',\n right: 'ArrowRight',\n left: 'ArrowLeft',\n};\n\nconst isTextEntry = (target: EventTarget): boolean =>\n target instanceof HTMLElement &&\n (target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName));\n\nconst composedPathOf = (node: EventTarget | null): Node[] => {\n if (!(node instanceof Node)) {\n return [];\n }\n const root = node.getRootNode();\n return [node, ...(root instanceof ShadowRoot ? composedPathOf(root.host) : [])];\n};\n\nconst subscribeToNothing = () => () => undefined;\nconst onClient = () => true;\nconst onServer = () => false;\n\nconst focusTarget = (panel: HTMLElement, initial: HTMLElement | null | undefined): HTMLElement =>\n initial ?? firstTabStopIn(panel) ?? panel;\n\nconst resolveFocus = (source: PopoverInitialFocus | undefined): HTMLElement | null | undefined =>\n typeof source === 'function' ? source() : source?.current;\n\n// Some engines keep a removed element as `activeElement`, and a shadow host with nothing\n// focused inside it holds focus for no one.\nconst focusIsLost = (active: HTMLElement | null, host: HTMLElement | null): boolean =>\n !active || active === document.body || !active.isConnected || active === host;\n\n/** An anchored, non-modal panel; nested Popovers count as inside their parent. */\nconst PopoverRoot: React.FC<PopoverProps> = ({\n trigger,\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n placement = 'bottom-start',\n openOn = 'click',\n width = 'content',\n padding = 'small',\n anchorRef,\n offset = 'small',\n elevation = 'default',\n initialFocus,\n initialFocusRef,\n openOnArrowKey = false,\n role = 'dialog',\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className = '',\n}) => {\n const parent = useContext(PopoverTreeContext);\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isOpen = controlledOpen ?? uncontrolledOpen;\n const isClient = useSyncExternalStore(subscribeToNothing, onClient, onServer);\n\n const triggerRef = useRef<HTMLElement | null>(null);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const popupIdentity = usePopupLayer('popover', isOpen, hostRef);\n const [panel, setPanel] = useState<HTMLDivElement | null>(null);\n const heldByChildren = useRef(0);\n const focusOnOpen = useRef(false);\n const returningFocus = useRef(false);\n const pointerPressedTrigger = useRef(false);\n const placedFocus = useRef<HTMLElement | null>(null);\n const heldFocus = useRef<HTMLElement | null>(null);\n\n const isOpenRef = useLatestRef(isOpen);\n const controlledRef = useLatestRef(controlledOpen);\n const onOpenChangeRef = useLatestRef(onOpenChange);\n const initialFocusSource = useLatestRef(initialFocus);\n const followsContent = initialFocus !== undefined;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (next === isOpenRef.current) {\n return;\n }\n if (controlledRef.current === undefined) {\n setUncontrolledOpen(next);\n }\n onOpenChangeRef.current?.(next);\n },\n [isOpenRef, controlledRef, onOpenChangeRef],\n );\n\n const { pointerInside, focusInside, triggerFocused, cancelClose, scheduleClose } =\n useHoverClose({\n isOpenRef,\n heldByChildren,\n setOpen,\n });\n\n const { tree, ownedSources } = usePopoverTree({\n parent,\n isOpen,\n openOn,\n isOpenRef,\n heldByChildren,\n cancelClose,\n scheduleClose,\n });\n\n const geometry = usePopoverPosition({\n isOpen,\n panel,\n hostRef,\n triggerRef,\n anchorRef,\n placement,\n width,\n offset,\n });\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n const closeOnOutsidePress = (event: MouseEvent) => {\n const path = event.composedPath();\n const inside = pathHits(path, [\n triggerRef.current,\n hostRef.current,\n ...[...ownedSources.current].map((source) => source()),\n ]);\n if (!inside) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', closeOnOutsidePress, true);\n const popEscapeLayer = pushEscapeLayer(() => setOpen(false));\n return () => {\n document.removeEventListener('mousedown', closeOnOutsidePress, true);\n popEscapeLayer();\n pointerInside.current = false;\n const active = getDeepActiveElement();\n if (focusInside.current && (!active || active === document.body)) {\n returningFocus.current = true;\n triggerRef.current?.focus({ preventScroll: true });\n returningFocus.current = false;\n }\n focusInside.current = false;\n placedFocus.current = null;\n heldFocus.current = null;\n };\n }, [isOpen, setOpen, ownedSources, pointerInside, focusInside]);\n\n const shown = isOpen && panel !== null && geometry !== null;\n\n const placeFocus = useCallback((target: HTMLElement) => {\n placedFocus.current = target;\n target.focus({ preventScroll: true });\n }, []);\n\n useEffect(() => {\n const shouldFocus = openOn === 'click' || focusOnOpen.current;\n if (!shown || !panel || !shouldFocus) {\n return;\n }\n focusOnOpen.current = false;\n const initial = followsContent\n ? resolveFocus(initialFocusSource.current)\n : initialFocusRef?.current;\n placeFocus(focusTarget(panel, initial));\n }, [shown, panel, openOn, followsContent, initialFocusRef, initialFocusSource, placeFocus]);\n\n useEffect(() => {\n if (!shown || !panel || !followsContent) {\n return;\n }\n const followContent = () => {\n const active = getDeepActiveElement();\n if (focusIsLost(active, hostRef.current)) {\n if (heldFocus.current && !heldFocus.current.isConnected) {\n placeFocus(focusTarget(panel, resolveFocus(initialFocusSource.current)));\n }\n return;\n }\n if (active !== placedFocus.current) {\n return;\n }\n const next =\n resolveFocus(initialFocusSource.current) ??\n (active === panel ? firstTabStopIn(panel) : null);\n if (next && next !== active && next.isConnected) {\n placeFocus(next);\n }\n };\n const observer = new MutationObserver(followContent);\n observer.observe(panel, { childList: true, subtree: true });\n return () => observer.disconnect();\n }, [shown, panel, followsContent, initialFocusSource, placeFocus]);\n\n const openWithFocus = () => {\n cancelClose();\n if (isOpen && panel) {\n const initial = followsContent\n ? resolveFocus(initialFocusSource.current)\n : initialFocusRef?.current;\n placeFocus(focusTarget(panel, initial));\n return;\n }\n focusOnOpen.current = true;\n setOpen(true);\n };\n\n const isInside = (node: EventTarget | null): boolean => {\n const containers = [\n triggerRef.current,\n hostRef.current,\n panel,\n ...[...ownedSources.current].map((source) => source()),\n ];\n return composedPathOf(node).some((step) =>\n containers.some((container) => container?.contains(step)),\n );\n };\n\n const closeIfFocusLeft = (next: EventTarget | null) => {\n if (!next) {\n return;\n }\n queueMicrotask(() => {\n if (!isInside(next) && !isInside(getDeepActiveElement())) {\n setOpen(false);\n }\n });\n };\n\n const hoverHandlers =\n openOn === 'hover'\n ? {\n onMouseEnter: () => {\n pointerInside.current = true;\n cancelClose();\n setOpen(true);\n },\n onMouseLeave: () => {\n pointerInside.current = false;\n scheduleClose();\n },\n onPanelMouseOver: () => {\n pointerInside.current = true;\n cancelClose();\n },\n }\n : null;\n\n const triggerProps = trigger.props as Record<string, unknown>;\n type Handler<E extends React.SyntheticEvent> = ((event: E) => void) | undefined;\n\n const ownTriggerRef = elementRef<HTMLElement>(trigger);\n const composedTriggerRef = useMemo(\n () => composeRefs(ownTriggerRef, triggerRef),\n [ownTriggerRef],\n );\n const openKey = KEYBOARD_OPEN_KEY[placement.split('-')[0]];\n\n const clonedTrigger = React.cloneElement(trigger, {\n ref: composedTriggerRef,\n 'aria-haspopup': role,\n 'aria-expanded': isOpen,\n onClick: chainHandler(\n triggerProps.onClick as Handler<React.MouseEvent>,\n (event: React.MouseEvent) => {\n if (openOn !== 'hover') {\n setOpen(!isOpen);\n return;\n }\n const fromKeyboard = event.detail === 0;\n if (fromKeyboard) {\n openWithFocus();\n return;\n }\n cancelClose();\n setOpen(true);\n },\n ),\n ...(hoverHandlers\n ? {\n onMouseEnter: chainHandler(\n triggerProps.onMouseEnter as Handler<React.MouseEvent>,\n hoverHandlers.onMouseEnter,\n ),\n onMouseLeave: chainHandler(\n triggerProps.onMouseLeave as Handler<React.MouseEvent>,\n hoverHandlers.onMouseLeave,\n ),\n onMouseDown: chainHandler(\n triggerProps.onMouseDown as Handler<React.MouseEvent>,\n () => {\n pointerPressedTrigger.current = true;\n setTimeout(() => {\n pointerPressedTrigger.current = false;\n });\n },\n ),\n onFocus: chainHandler(triggerProps.onFocus as Handler<React.FocusEvent>, () => {\n const fromPointer = pointerPressedTrigger.current;\n pointerPressedTrigger.current = false;\n triggerFocused.current = !fromPointer && !returningFocus.current;\n if (returningFocus.current) {\n return;\n }\n cancelClose();\n setOpen(true);\n }),\n onKeyDown: chainHandler(\n triggerProps.onKeyDown as Handler<React.KeyboardEvent>,\n (event: React.KeyboardEvent) => {\n if (event.key !== openKey) {\n return;\n }\n event.preventDefault();\n openWithFocus();\n },\n ),\n }\n : openOnArrowKey\n ? {\n onKeyDown: chainHandler(\n triggerProps.onKeyDown as Handler<React.KeyboardEvent>,\n (event: React.KeyboardEvent) => {\n if (event.key !== openKey || isTextEntry(event.target)) {\n return;\n }\n event.preventDefault();\n openWithFocus();\n },\n ),\n }\n : {}),\n onBlur: chainHandler(\n triggerProps.onBlur as Handler<React.FocusEvent>,\n (event: React.FocusEvent) => {\n triggerFocused.current = false;\n if (!isOpen || isInside(event.relatedTarget)) {\n return;\n }\n if (openOn === 'hover') {\n scheduleClose();\n return;\n }\n closeIfFocusLeft(event.relatedTarget);\n },\n ),\n } as Record<string, unknown>);\n\n const panelStyle: React.CSSProperties = {\n maxHeight: geometry?.maxHeight,\n maxWidth: `calc(100vw - ${MENU_VIEWPORT_PADDING_PX * 2}px)`,\n visibility: geometry ? 'visible' : 'hidden',\n };\n\n return (\n <>\n {clonedTrigger}\n {isOpen &&\n isClient &&\n createPortal(\n <PopoverTreeContext.Provider value={tree}>\n <ShadowRootWrapper\n hostRef={hostRef}\n hostProps={popupIdentity}\n hostStyle={{\n position: 'fixed',\n top: geometry?.top ?? 0,\n left: geometry?.left ?? 0,\n }}\n >\n <div\n ref={setPanel}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n data-side={geometry?.side}\n tabIndex={-1}\n className={`${PANEL} ${ELEVATION[elevation]} ${PADDING[padding]} ${className}`.trim()}\n style={panelStyle}\n // React's mouseenter stops at the shadow host, so the panel listens for mouseover.\n onMouseOver={hoverHandlers?.onPanelMouseOver}\n onMouseLeave={hoverHandlers?.onMouseLeave}\n onFocus={(event) => {\n focusInside.current = true;\n if (event.target !== placedFocus.current) {\n placedFocus.current = null;\n }\n if (\n event.target instanceof HTMLElement &&\n panel?.contains(event.target)\n ) {\n heldFocus.current = event.target;\n }\n cancelClose();\n }}\n onBlur={(event) => {\n if (isInside(event.relatedTarget)) {\n return;\n }\n if (event.relatedTarget) {\n heldFocus.current = null;\n }\n focusInside.current = false;\n if (openOn === 'hover') {\n scheduleClose();\n return;\n }\n closeIfFocusLeft(event.relatedTarget);\n }}\n >\n <PopoverShownContext.Provider value={shown}>\n {children}\n </PopoverShownContext.Provider>\n </div>\n </ShadowRootWrapper>\n </PopoverTreeContext.Provider>,\n document.body,\n )}\n </>\n );\n};\n\nexport const Popover = Object.assign(PopoverRoot, {\n Header: PopoverHeader,\n Action: PopoverAction,\n List: PopoverList,\n Section: PopoverSection,\n Empty: PopoverEmpty,\n});\n\nexport default Popover;\n"],"names":["PANEL","ELEVATION","PADDING","pathHits","path","nodes","node","KEYBOARD_OPEN_KEY","isTextEntry","target","composedPathOf","root","subscribeToNothing","onClient","onServer","focusTarget","panel","initial","firstTabStopIn","resolveFocus","source","focusIsLost","active","host","PopoverRoot","trigger","children","controlledOpen","defaultOpen","onOpenChange","placement","openOn","width","padding","anchorRef","offset","elevation","initialFocus","initialFocusRef","openOnArrowKey","role","ariaLabel","ariaLabelledBy","className","parent","useContext","PopoverTreeContext","uncontrolledOpen","setUncontrolledOpen","useState","isOpen","isClient","useSyncExternalStore","triggerRef","useRef","hostRef","popupIdentity","usePopupLayer","setPanel","heldByChildren","focusOnOpen","returningFocus","pointerPressedTrigger","placedFocus","heldFocus","isOpenRef","useLatestRef","controlledRef","onOpenChangeRef","initialFocusSource","followsContent","setOpen","useCallback","next","_a","pointerInside","focusInside","triggerFocused","cancelClose","scheduleClose","useHoverClose","tree","ownedSources","usePopoverTree","geometry","usePopoverPosition","useEffect","closeOnOutsidePress","event","popEscapeLayer","pushEscapeLayer","getDeepActiveElement","shown","placeFocus","shouldFocus","followContent","observer","openWithFocus","isInside","containers","step","container","closeIfFocusLeft","hoverHandlers","triggerProps","ownTriggerRef","elementRef","composedTriggerRef","useMemo","composeRefs","openKey","clonedTrigger","React","chainHandler","fromPointer","panelStyle","MENU_VIEWPORT_PADDING_PX","jsxs","Fragment","createPortal","jsx","ShadowRootWrapper","PopoverShownContext","Popover","PopoverHeader","PopoverAction","PopoverList","PopoverSection","PopoverEmpty"],"mappings":"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"}
|
|
@@ -1,60 +1,90 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as x } from "react";
|
|
3
|
-
import
|
|
4
|
-
import { BORDER as m, NO_SCROLLBAR as
|
|
5
|
-
import { FOCUS_RING_INSET as
|
|
6
|
-
import { isPlainClick as
|
|
7
|
-
import {
|
|
8
|
-
|
|
1
|
+
import { jsx as n, jsxs as u } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as f, useContext as v, useRef as x, useLayoutEffect as b } from "react";
|
|
3
|
+
import h from "./Tooltip.js";
|
|
4
|
+
import { BORDER as m, NO_SCROLLBAR as g } from "./chromeStyles.js";
|
|
5
|
+
import { FOCUS_RING_INSET as T } from "./focusRing.js";
|
|
6
|
+
import { isPlainClick as R } from "./linkClick.js";
|
|
7
|
+
import { PopoverShownContext as w } from "./popoverTree.js";
|
|
8
|
+
import { safeHref as y } from "./safeHref.js";
|
|
9
|
+
const j = ({ title: e, action: t }) => /* @__PURE__ */ u(
|
|
9
10
|
"div",
|
|
10
11
|
{
|
|
11
12
|
className: `flex items-center justify-between border-0 border-b border-solid ${m} px-5 py-4 text-[12px] leading-[15px] font-normal text-[var(--malachite-text-dimmed,rgb(161,161,161))]`,
|
|
12
13
|
children: [
|
|
13
|
-
/* @__PURE__ */
|
|
14
|
+
/* @__PURE__ */ n("span", { children: e }),
|
|
14
15
|
t
|
|
15
16
|
]
|
|
16
17
|
}
|
|
17
|
-
),
|
|
18
|
-
|
|
18
|
+
), N = '[aria-current]:not([aria-current="false"]):not([aria-current=""]), [aria-selected="true"], [role="radio"][aria-checked="true"]', E = ["aria-current", "aria-selected", "aria-checked"], d = (e) => {
|
|
19
|
+
const t = e.querySelector(N);
|
|
20
|
+
if (!t)
|
|
21
|
+
return !1;
|
|
22
|
+
const o = e.getBoundingClientRect().top + e.clientTop, { top: i, bottom: r } = t.getBoundingClientRect(), a = i - o + e.scrollTop, c = r - o + e.scrollTop;
|
|
23
|
+
return a < e.scrollTop ? e.scrollTop = a : c > e.scrollTop + e.clientHeight && (e.scrollTop = c - e.clientHeight), !0;
|
|
24
|
+
}, k = ({ children: e, scrollToSelected: t = !1 }) => {
|
|
25
|
+
const o = v(w), i = x(null);
|
|
26
|
+
return b(() => {
|
|
27
|
+
const r = i.current;
|
|
28
|
+
if (!t || !o || !r || d(r))
|
|
29
|
+
return;
|
|
30
|
+
const a = new MutationObserver(() => {
|
|
31
|
+
d(r) && a.disconnect();
|
|
32
|
+
});
|
|
33
|
+
return a.observe(r, {
|
|
34
|
+
childList: !0,
|
|
35
|
+
subtree: !0,
|
|
36
|
+
attributes: !0,
|
|
37
|
+
attributeFilter: E
|
|
38
|
+
}), () => a.disconnect();
|
|
39
|
+
}, [t, o]), /* @__PURE__ */ n(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
ref: i,
|
|
43
|
+
className: `flex max-h-80 flex-col gap-[2px] overflow-y-auto p-2 ${g}`,
|
|
44
|
+
children: e
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}, S = f(
|
|
48
|
+
({ children: e }, t) => /* @__PURE__ */ n("div", { ref: t, className: `border-0 border-t border-solid ${m} p-2`, children: e })
|
|
19
49
|
);
|
|
20
|
-
|
|
21
|
-
const
|
|
50
|
+
S.displayName = "Popover.Section";
|
|
51
|
+
const H = ({ children: e }) => /* @__PURE__ */ n("div", { className: "px-3 py-2 text-[length:var(--malachite-font-size-small,13px)] text-[var(--malachite-text-dimmed,rgb(161,161,161))] select-none", children: e }), z = ({
|
|
22
52
|
icon: e,
|
|
23
53
|
"aria-label": t,
|
|
24
|
-
onClick:
|
|
25
|
-
href:
|
|
26
|
-
disabled:
|
|
27
|
-
tooltip:
|
|
54
|
+
onClick: o,
|
|
55
|
+
href: i,
|
|
56
|
+
disabled: r = !1,
|
|
57
|
+
tooltip: a
|
|
28
58
|
}) => {
|
|
29
|
-
const
|
|
59
|
+
const c = r ? void 0 : y(i), s = `m-0 inline-flex size-5 items-center justify-center rounded-[var(--malachite-radius-sm,4px)] border-0 bg-transparent p-0 transition-colors duration-150 [&_svg]:size-3! ${r ? "cursor-not-allowed text-[var(--malachite-text-placeholder,rgb(187,187,187))] opacity-50" : "cursor-pointer text-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] hover:text-[var(--malachite-text-secondary,rgb(123,123,123))]"} ${T}`, l = c !== void 0 ? /* @__PURE__ */ n(
|
|
30
60
|
"a",
|
|
31
61
|
{
|
|
32
|
-
href:
|
|
62
|
+
href: c,
|
|
33
63
|
"aria-label": t,
|
|
34
|
-
onClick: (
|
|
35
|
-
|
|
64
|
+
onClick: (p) => {
|
|
65
|
+
R(p) && o && (p.preventDefault(), o());
|
|
36
66
|
},
|
|
37
|
-
className: `no-underline ${
|
|
67
|
+
className: `no-underline ${s}`,
|
|
38
68
|
children: e
|
|
39
69
|
}
|
|
40
|
-
) : /* @__PURE__ */
|
|
70
|
+
) : /* @__PURE__ */ n(
|
|
41
71
|
"button",
|
|
42
72
|
{
|
|
43
73
|
type: "button",
|
|
44
74
|
"aria-label": t,
|
|
45
|
-
"aria-disabled":
|
|
46
|
-
onClick:
|
|
47
|
-
className:
|
|
75
|
+
"aria-disabled": r || void 0,
|
|
76
|
+
onClick: r ? void 0 : o,
|
|
77
|
+
className: s,
|
|
48
78
|
children: e
|
|
49
79
|
}
|
|
50
80
|
);
|
|
51
|
-
return
|
|
81
|
+
return a ? /* @__PURE__ */ n(h, { text: a, children: l }) : l;
|
|
52
82
|
};
|
|
53
83
|
export {
|
|
54
84
|
z as PopoverAction,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
85
|
+
H as PopoverEmpty,
|
|
86
|
+
j as PopoverHeader,
|
|
87
|
+
k as PopoverList,
|
|
88
|
+
S as PopoverSection
|
|
59
89
|
};
|
|
60
90
|
//# sourceMappingURL=PopoverParts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopoverParts.js","sources":["../../src/components/PopoverParts.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport Tooltip from './Tooltip';\nimport { BORDER, NO_SCROLLBAR } from './chromeStyles';\nimport { FOCUS_RING_INSET } from './focusRing';\nimport { isPlainClick } from './linkClick';\nimport { safeHref } from './safeHref';\n\nexport interface PopoverHeaderProps {\n title: string;\n action?: React.ReactNode;\n}\n\nexport const PopoverHeader: React.FC<PopoverHeaderProps> = ({ title, action }) => (\n <div\n className={`flex items-center justify-between border-0 border-b border-solid ${BORDER} px-5 py-4 text-[12px] leading-[15px] font-normal text-[var(--malachite-text-dimmed,rgb(161,161,161))]`}\n >\n <span>{title}</span>\n {action}\n </div>\n);\n\
|
|
1
|
+
{"version":3,"file":"PopoverParts.js","sources":["../../src/components/PopoverParts.tsx"],"sourcesContent":["import React, { forwardRef, useContext, useLayoutEffect, useRef } from 'react';\nimport Tooltip from './Tooltip';\nimport { BORDER, NO_SCROLLBAR } from './chromeStyles';\nimport { FOCUS_RING_INSET } from './focusRing';\nimport { isPlainClick } from './linkClick';\nimport { PopoverShownContext } from './popoverTree';\nimport { safeHref } from './safeHref';\n\nexport interface PopoverHeaderProps {\n title: string;\n action?: React.ReactNode;\n}\n\nexport const PopoverHeader: React.FC<PopoverHeaderProps> = ({ title, action }) => (\n <div\n className={`flex items-center justify-between border-0 border-b border-solid ${BORDER} px-5 py-4 text-[12px] leading-[15px] font-normal text-[var(--malachite-text-dimmed,rgb(161,161,161))]`}\n >\n <span>{title}</span>\n {action}\n </div>\n);\n\nconst SELECTED_ROW =\n '[aria-current]:not([aria-current=\"false\"]):not([aria-current=\"\"]), [aria-selected=\"true\"], [role=\"radio\"][aria-checked=\"true\"]';\nconst SELECTION_ATTRIBUTES = ['aria-current', 'aria-selected', 'aria-checked'];\n\n// Not `scrollIntoView`: that also scrolls every scrollable ancestor, the page included.\nconst scrollSelectedRowIntoView = (list: HTMLElement): boolean => {\n const row = list.querySelector<HTMLElement>(SELECTED_ROW);\n if (!row) {\n return false;\n }\n const listTop = list.getBoundingClientRect().top + list.clientTop;\n const { top, bottom } = row.getBoundingClientRect();\n const rowTop = top - listTop + list.scrollTop;\n const rowBottom = bottom - listTop + list.scrollTop;\n if (rowTop < list.scrollTop) {\n list.scrollTop = rowTop;\n } else if (rowBottom > list.scrollTop + list.clientHeight) {\n list.scrollTop = rowBottom - list.clientHeight;\n }\n return true;\n};\n\nexport interface PopoverListProps {\n children: React.ReactNode;\n /**\n * Scrolls the list to its selected row (`aria-current`, `aria-selected` or a checked radio)\n * each time the popover is shown, once that row mounts. Only the list scrolls.\n */\n scrollToSelected?: boolean;\n}\n\nexport const PopoverList: React.FC<PopoverListProps> = ({ children, scrollToSelected = false }) => {\n const shown = useContext(PopoverShownContext);\n const listRef = useRef<HTMLDivElement>(null);\n\n // Before paint, so a shown panel never draws a frame at the top and then jumps.\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!scrollToSelected || !shown || !list || scrollSelectedRowIntoView(list)) {\n return;\n }\n const observer = new MutationObserver(() => {\n if (scrollSelectedRowIntoView(list)) {\n observer.disconnect();\n }\n });\n observer.observe(list, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: SELECTION_ATTRIBUTES,\n });\n return () => observer.disconnect();\n }, [scrollToSelected, shown]);\n\n return (\n <div\n ref={listRef}\n className={`flex max-h-80 flex-col gap-[2px] overflow-y-auto p-2 ${NO_SCROLLBAR}`}\n >\n {children}\n </div>\n );\n};\n\nexport const PopoverSection = forwardRef<HTMLDivElement, { children: React.ReactNode }>(\n ({ children }, ref) => (\n <div ref={ref} className={`border-0 border-t border-solid ${BORDER} p-2`}>\n {children}\n </div>\n ),\n);\nPopoverSection.displayName = 'Popover.Section';\n\nexport const PopoverEmpty: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"px-3 py-2 text-[length:var(--malachite-font-size-small,13px)] text-[var(--malachite-text-dimmed,rgb(161,161,161))] select-none\">\n {children}\n </div>\n);\n\nexport interface PopoverActionProps {\n icon: React.ReactNode;\n 'aria-label': string;\n onClick?: () => void;\n /** Renders a link; a plain click runs `onClick` instead of following it, when one is given. */\n href?: string;\n disabled?: boolean;\n tooltip?: string;\n}\n\nexport const PopoverAction: React.FC<PopoverActionProps> = ({\n icon,\n 'aria-label': ariaLabel,\n onClick,\n href: rawHref,\n disabled = false,\n tooltip,\n}) => {\n const href = disabled ? undefined : safeHref(rawHref);\n const className = `m-0 inline-flex size-5 items-center justify-center rounded-[var(--malachite-radius-sm,4px)] border-0 bg-transparent p-0 transition-colors duration-150 [&_svg]:size-3! ${disabled ? 'cursor-not-allowed text-[var(--malachite-text-placeholder,rgb(187,187,187))] opacity-50' : `cursor-pointer text-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] hover:text-[var(--malachite-text-secondary,rgb(123,123,123))]`} ${FOCUS_RING_INSET}`;\n const button =\n href !== undefined ? (\n <a\n href={href}\n aria-label={ariaLabel}\n onClick={(event) => {\n if (isPlainClick(event) && onClick) {\n event.preventDefault();\n onClick();\n }\n }}\n className={`no-underline ${className}`}\n >\n {icon}\n </a>\n ) : (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n onClick={disabled ? undefined : onClick}\n className={className}\n >\n {icon}\n </button>\n );\n return tooltip ? <Tooltip text={tooltip}>{button}</Tooltip> : button;\n};\n"],"names":["PopoverHeader","title","action","jsxs","BORDER","jsx","SELECTED_ROW","SELECTION_ATTRIBUTES","scrollSelectedRowIntoView","list","row","listTop","top","bottom","rowTop","rowBottom","PopoverList","children","scrollToSelected","shown","useContext","PopoverShownContext","listRef","useRef","useLayoutEffect","observer","NO_SCROLLBAR","PopoverSection","forwardRef","ref","PopoverEmpty","PopoverAction","icon","ariaLabel","onClick","rawHref","disabled","tooltip","href","safeHref","className","FOCUS_RING_INSET","button","event","isPlainClick","Tooltip"],"mappings":"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"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { useContext as r, useLayoutEffect as
|
|
2
|
-
const f = 150, u =
|
|
1
|
+
import { useContext as r, useLayoutEffect as s, createContext as n } from "react";
|
|
2
|
+
const f = 150, u = n(null), p = n(!1), x = (t, o) => {
|
|
3
3
|
const e = r(u);
|
|
4
|
-
|
|
4
|
+
s(() => {
|
|
5
5
|
if (!(!o || !e))
|
|
6
6
|
return e.register(t);
|
|
7
7
|
}, [o, e, t]);
|
|
8
8
|
};
|
|
9
9
|
export {
|
|
10
10
|
f as HOVER_CLOSE_DELAY_MS,
|
|
11
|
+
p as PopoverShownContext,
|
|
11
12
|
u as PopoverTreeContext,
|
|
12
|
-
|
|
13
|
+
x as useOwnedByPopover
|
|
13
14
|
};
|
|
14
15
|
//# sourceMappingURL=popoverTree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popoverTree.js","sources":["../../src/components/popoverTree.ts"],"sourcesContent":["import { createContext, useContext, useLayoutEffect } from 'react';\n\nexport type OverlaySource = () => HTMLElement | null;\n\nexport interface PopoverTree {\n register: (source: OverlaySource) => () => void;\n hold: () => () => void;\n}\n\nexport const HOVER_CLOSE_DELAY_MS = 150;\n\nexport const PopoverTreeContext = createContext<PopoverTree | null>(null);\n\nexport const useOwnedByPopover = (source: OverlaySource, active: boolean): void => {\n const tree = useContext(PopoverTreeContext);\n useLayoutEffect(() => {\n if (!active || !tree) {\n return;\n }\n return tree.register(source);\n }, [active, tree, source]);\n};\n"],"names":["HOVER_CLOSE_DELAY_MS","PopoverTreeContext","createContext","useOwnedByPopover","source","active","tree","useContext","useLayoutEffect"],"mappings":";AASO,MAAMA,IAAuB,KAEvBC,IAAqBC,EAAkC,IAAI,GAE3DC,IAAoB,CAACC,GAAuBC,MAA0B;AAC/E,QAAMC,IAAOC,
|
|
1
|
+
{"version":3,"file":"popoverTree.js","sources":["../../src/components/popoverTree.ts"],"sourcesContent":["import { createContext, useContext, useLayoutEffect } from 'react';\n\nexport type OverlaySource = () => HTMLElement | null;\n\nexport interface PopoverTree {\n register: (source: OverlaySource) => () => void;\n hold: () => () => void;\n}\n\nexport const HOVER_CLOSE_DELAY_MS = 150;\n\nexport const PopoverTreeContext = createContext<PopoverTree | null>(null);\n\nexport const PopoverShownContext = createContext(false);\n\nexport const useOwnedByPopover = (source: OverlaySource, active: boolean): void => {\n const tree = useContext(PopoverTreeContext);\n useLayoutEffect(() => {\n if (!active || !tree) {\n return;\n }\n return tree.register(source);\n }, [active, tree, source]);\n};\n"],"names":["HOVER_CLOSE_DELAY_MS","PopoverTreeContext","createContext","PopoverShownContext","useOwnedByPopover","source","active","tree","useContext","useLayoutEffect"],"mappings":";AASO,MAAMA,IAAuB,KAEvBC,IAAqBC,EAAkC,IAAI,GAE3DC,IAAsBD,EAAc,EAAK,GAEzCE,IAAoB,CAACC,GAAuBC,MAA0B;AAC/E,QAAMC,IAAOC,EAAWP,CAAkB;AAC1C,EAAAQ,EAAgB,MAAM;AAClB,QAAI,GAACH,KAAU,CAACC;AAGhB,aAAOA,EAAK,SAASF,CAAM;AAAA,EAC/B,GAAG,CAACC,GAAQC,GAAMF,CAAM,CAAC;AAC7B;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3943,9 +3943,7 @@ export declare const PlusIcon: React.FC<IconProps_85>;
|
|
|
3943
3943
|
export declare const Popover: default_2.FC<PopoverProps> & {
|
|
3944
3944
|
Header: default_2.FC< PopoverHeaderProps>;
|
|
3945
3945
|
Action: default_2.FC< PopoverActionProps>;
|
|
3946
|
-
List: default_2.FC<
|
|
3947
|
-
children: default_2.ReactNode;
|
|
3948
|
-
}>;
|
|
3946
|
+
List: default_2.FC< PopoverListProps>;
|
|
3949
3947
|
Section: default_2.ForwardRefExoticComponent<{
|
|
3950
3948
|
children: default_2.ReactNode;
|
|
3951
3949
|
} & default_2.RefAttributes<HTMLDivElement>>;
|
|
@@ -3977,18 +3975,41 @@ declare interface PopoverBaseProps {
|
|
|
3977
3975
|
anchorRef?: default_2.RefObject<HTMLElement | null>;
|
|
3978
3976
|
offset?: FloatingOffset;
|
|
3979
3977
|
elevation?: 'default' | 'raised';
|
|
3980
|
-
initialFocusRef?: default_2.RefObject<HTMLElement | null>;
|
|
3981
3978
|
/** A click panel also opens, focus inside, on the arrow key its placement points at. */
|
|
3982
3979
|
openOnArrowKey?: boolean;
|
|
3983
3980
|
role?: 'dialog' | 'menu' | 'listbox';
|
|
3984
3981
|
className?: string;
|
|
3985
3982
|
}
|
|
3986
3983
|
|
|
3984
|
+
declare type PopoverFocusSource = {
|
|
3985
|
+
/**
|
|
3986
|
+
* What takes focus when the panel is shown, in place of its first tab stop. Re-read as the
|
|
3987
|
+
* content changes, so focus follows late content but never leaves where the user moved it.
|
|
3988
|
+
*/
|
|
3989
|
+
initialFocus?: PopoverInitialFocus;
|
|
3990
|
+
initialFocusRef?: never;
|
|
3991
|
+
} | {
|
|
3992
|
+
initialFocus?: never;
|
|
3993
|
+
/** @deprecated Use `initialFocus`, which takes the same ref and also follows late content. */
|
|
3994
|
+
initialFocusRef?: default_2.RefObject<HTMLElement | null>;
|
|
3995
|
+
};
|
|
3996
|
+
|
|
3987
3997
|
export declare interface PopoverHeaderProps {
|
|
3988
3998
|
title: string;
|
|
3989
3999
|
action?: default_2.ReactNode;
|
|
3990
4000
|
}
|
|
3991
4001
|
|
|
4002
|
+
export declare type PopoverInitialFocus = default_2.RefObject<HTMLElement | null> | (() => HTMLElement | null | undefined);
|
|
4003
|
+
|
|
4004
|
+
export declare interface PopoverListProps {
|
|
4005
|
+
children: default_2.ReactNode;
|
|
4006
|
+
/**
|
|
4007
|
+
* Scrolls the list to its selected row (`aria-current`, `aria-selected` or a checked radio)
|
|
4008
|
+
* each time the popover is shown, once that row mounts. Only the list scrolls.
|
|
4009
|
+
*/
|
|
4010
|
+
scrollToSelected?: boolean;
|
|
4011
|
+
}
|
|
4012
|
+
|
|
3992
4013
|
declare type PopoverName = {
|
|
3993
4014
|
'aria-label': string;
|
|
3994
4015
|
'aria-labelledby'?: string;
|
|
@@ -3999,7 +4020,7 @@ declare type PopoverName = {
|
|
|
3999
4020
|
|
|
4000
4021
|
export declare type PopoverPlacement = FloatingPlacement;
|
|
4001
4022
|
|
|
4002
|
-
export declare type PopoverProps = PopoverBaseProps & PopoverName;
|
|
4023
|
+
export declare type PopoverProps = PopoverBaseProps & PopoverName & PopoverFocusSource;
|
|
4003
4024
|
|
|
4004
4025
|
export declare const PreviewIcon: React.FC<IconProps_86>;
|
|
4005
4026
|
|
package/package.json
CHANGED