@hjmds/react 1.1.0 → 1.2.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/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +12 -6
- package/dist/actions.js.map +1 -1
- package/dist/advanced-display.d.ts +21 -0
- package/dist/advanced-display.d.ts.map +1 -1
- package/dist/advanced-display.js +11 -0
- package/dist/advanced-display.js.map +1 -1
- package/dist/advanced-navigation.d.ts +2 -23
- package/dist/advanced-navigation.d.ts.map +1 -1
- package/dist/advanced-navigation.js +3 -24
- package/dist/advanced-navigation.js.map +1 -1
- package/dist/agreement.d.ts +20 -0
- package/dist/agreement.d.ts.map +1 -0
- package/dist/agreement.js +29 -0
- package/dist/agreement.js.map +1 -0
- package/dist/anchor.d.ts +24 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +110 -0
- package/dist/anchor.js.map +1 -0
- package/dist/asset.d.ts +40 -0
- package/dist/asset.d.ts.map +1 -0
- package/dist/asset.js +26 -0
- package/dist/asset.js.map +1 -0
- package/dist/bottom-cta.d.ts +32 -0
- package/dist/bottom-cta.d.ts.map +1 -0
- package/dist/bottom-cta.js +30 -0
- package/dist/bottom-cta.js.map +1 -0
- package/dist/bottom-info.d.ts +16 -0
- package/dist/bottom-info.d.ts.map +1 -0
- package/dist/bottom-info.js +12 -0
- package/dist/bottom-info.js.map +1 -0
- package/dist/breadcrumb.d.ts +9 -0
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +12 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/calendar.d.ts +30 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +69 -0
- package/dist/calendar.js.map +1 -0
- package/dist/carousel.d.ts +20 -0
- package/dist/carousel.d.ts.map +1 -0
- package/dist/carousel.js +70 -0
- package/dist/carousel.js.map +1 -0
- package/dist/clipboard.d.ts +33 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +40 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/collapsible.d.ts +11 -0
- package/dist/collapsible.d.ts.map +1 -0
- package/dist/collapsible.js +18 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/command-palette.d.ts +25 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +82 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/context-menu.d.ts +12 -0
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +111 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/data-table.d.ts +30 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +57 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +3 -1
- package/dist/date-picker.d.ts.map +1 -1
- package/dist/date-picker.js +16 -31
- package/dist/date-picker.js.map +1 -1
- package/dist/date-range.d.ts +24 -0
- package/dist/date-range.d.ts.map +1 -0
- package/dist/date-range.js +29 -0
- package/dist/date-range.js.map +1 -0
- package/dist/display.d.ts +16 -0
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +13 -1
- package/dist/display.js.map +1 -1
- package/dist/evidence.d.ts +481 -1
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +47 -2
- package/dist/evidence.js.map +1 -1
- package/dist/feedback.d.ts +18 -2
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +10 -2
- package/dist/feedback.js.map +1 -1
- package/dist/floating-action-button.d.ts +32 -0
- package/dist/floating-action-button.d.ts.map +1 -0
- package/dist/floating-action-button.js +58 -0
- package/dist/floating-action-button.js.map +1 -0
- package/dist/forms.d.ts +3 -3
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +18 -7
- package/dist/forms.js.map +1 -1
- package/dist/heading.d.ts +12 -0
- package/dist/heading.d.ts.map +1 -0
- package/dist/heading.js +25 -0
- package/dist/heading.js.map +1 -0
- package/dist/index.d.ts +35 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +1 -1
- package/dist/mentions.d.ts +28 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +84 -0
- package/dist/mentions.js.map +1 -0
- package/dist/menubar.d.ts +11 -0
- package/dist/menubar.d.ts.map +1 -0
- package/dist/menubar.js +137 -0
- package/dist/menubar.js.map +1 -0
- package/dist/modal.d.ts +67 -0
- package/dist/modal.d.ts.map +1 -0
- package/dist/modal.js +307 -0
- package/dist/modal.js.map +1 -0
- package/dist/overlay-stack.d.ts +28 -0
- package/dist/overlay-stack.d.ts.map +1 -0
- package/dist/overlay-stack.js +47 -0
- package/dist/overlay-stack.js.map +1 -0
- package/dist/overlays.d.ts +26 -43
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +62 -302
- package/dist/overlays.js.map +1 -1
- package/dist/pagination.d.ts +17 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +21 -0
- package/dist/pagination.js.map +1 -0
- package/dist/popover.d.ts +25 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +226 -0
- package/dist/popover.js.map +1 -0
- package/dist/portal.d.ts +5 -1
- package/dist/portal.d.ts.map +1 -1
- package/dist/portal.js +24 -1
- package/dist/portal.js.map +1 -1
- package/dist/provider-button.d.ts +21 -0
- package/dist/provider-button.d.ts.map +1 -0
- package/dist/provider-button.js +26 -0
- package/dist/provider-button.js.map +1 -0
- package/dist/provider.d.ts +13 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +12 -2
- package/dist/provider.js.map +1 -1
- package/dist/selection.d.ts +5 -1
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +2 -2
- package/dist/selection.js.map +1 -1
- package/dist/side-panel.d.ts +34 -0
- package/dist/side-panel.d.ts.map +1 -0
- package/dist/side-panel.js +95 -0
- package/dist/side-panel.js.map +1 -0
- package/dist/sidebar.d.ts +22 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +29 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/skip-nav.d.ts +12 -0
- package/dist/skip-nav.d.ts.map +1 -0
- package/dist/skip-nav.js +29 -0
- package/dist/skip-nav.js.map +1 -0
- package/dist/splitter.d.ts +45 -0
- package/dist/splitter.d.ts.map +1 -0
- package/dist/splitter.js +116 -0
- package/dist/splitter.js.map +1 -0
- package/dist/styles.css +1068 -26
- package/dist/supplemental-display.d.ts +12 -0
- package/dist/supplemental-display.d.ts.map +1 -1
- package/dist/supplemental-display.js +6 -2
- package/dist/supplemental-display.js.map +1 -1
- package/dist/tags-input.d.ts +60 -0
- package/dist/tags-input.d.ts.map +1 -0
- package/dist/tags-input.js +90 -0
- package/dist/tags-input.js.map +1 -0
- package/dist/text-formats.d.ts +16 -0
- package/dist/text-formats.d.ts.map +1 -0
- package/dist/text-formats.js +24 -0
- package/dist/text-formats.js.map +1 -0
- package/dist/toast.d.ts +1 -1
- package/dist/toggle-group.d.ts +13 -0
- package/dist/toggle-group.d.ts.map +1 -0
- package/dist/toggle-group.js +21 -0
- package/dist/toggle-group.js.map +1 -0
- package/dist/top-bar.d.ts +27 -0
- package/dist/top-bar.d.ts.map +1 -0
- package/dist/top-bar.js +30 -0
- package/dist/top-bar.js.map +1 -0
- package/dist/top.d.ts +15 -0
- package/dist/top.d.ts.map +1 -0
- package/dist/top.js +18 -0
- package/dist/top.js.map +1 -0
- package/dist/tour.d.ts +21 -0
- package/dist/tour.d.ts.map +1 -0
- package/dist/tour.js +122 -0
- package/dist/tour.js.map +1 -0
- package/dist/transfer-list.d.ts +24 -0
- package/dist/transfer-list.d.ts.map +1 -0
- package/dist/transfer-list.js +109 -0
- package/dist/transfer-list.js.map +1 -0
- package/dist/tree.d.ts +29 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +120 -0
- package/dist/tree.js.map +1 -0
- package/package.json +173 -3
package/dist/popover.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { cloneElement, createContext, forwardRef, useCallback, useContext, useEffect, useId, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { canDismissPopover, popoverBehaviorDefaults, popoverHoverDelay, popoverRecipe, resolvePopoverDescriptor, validatePopoverOpenState } from "@hjmds/design-contracts/components/popover";
|
|
4
|
+
import { easing } from "@hjmds/design-contracts/foundations";
|
|
5
|
+
import { Button } from "./actions.js";
|
|
6
|
+
import { classNames, composeRefs } from "./internal.js";
|
|
7
|
+
import { AnchoredPortal, getPopoverOwner, useAnchoredPopup } from "./portal.js";
|
|
8
|
+
import { useOptionalHjmTheme } from "./provider.js";
|
|
9
|
+
const ParentPopoverOpen = createContext(true);
|
|
10
|
+
const motionQuery = "(prefers-reduced-motion: reduce)";
|
|
11
|
+
function subscribeSystemMotion(notify) {
|
|
12
|
+
const media = window.matchMedia(motionQuery);
|
|
13
|
+
media.addEventListener("change", notify);
|
|
14
|
+
return () => media.removeEventListener("change", notify);
|
|
15
|
+
}
|
|
16
|
+
const readSystemMotion = () => window.matchMedia(motionQuery).matches;
|
|
17
|
+
const readServerMotion = () => false;
|
|
18
|
+
const focusable = 'a[href],button,input,select,textarea,[tabindex]';
|
|
19
|
+
function tabStops(container) {
|
|
20
|
+
return [...container.querySelectorAll(focusable)].filter((node) => node.tabIndex >= 0 && !node.matches(":disabled") && !node.closest('[inert],[hidden],[aria-hidden="true"]') && node.getClientRects().length > 0 && getComputedStyle(node).visibility !== "hidden").sort((a, b) => (a.tabIndex > 0 ? a.tabIndex : Infinity) - (b.tabIndex > 0 ? b.tabIndex : Infinity));
|
|
21
|
+
}
|
|
22
|
+
function contains(content, target) {
|
|
23
|
+
if (content.contains(target))
|
|
24
|
+
return true;
|
|
25
|
+
const visited = new Set();
|
|
26
|
+
let owner = getPopoverOwner(target);
|
|
27
|
+
while (owner && !visited.has(owner)) {
|
|
28
|
+
if (owner === content)
|
|
29
|
+
return true;
|
|
30
|
+
visited.add(owner);
|
|
31
|
+
owner = getPopoverOwner(owner.parentElement);
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
export const Popover = forwardRef(function Popover({ trigger, title, closeLabel, description, descriptor = {}, children, dismissPolicy, openOn = popoverBehaviorDefaults.openOn, initialFocusRef, portalContainer, className, open: controlledOpen, defaultOpen, onOpenChange }, ref) {
|
|
36
|
+
if (!title.trim() || !closeLabel.trim())
|
|
37
|
+
throw new TypeError("Popover title and closeLabel must not be empty");
|
|
38
|
+
const resolved = resolvePopoverDescriptor(descriptor);
|
|
39
|
+
validatePopoverOpenState({ ...(controlledOpen === undefined ? {} : { open: controlledOpen }), ...(defaultOpen === undefined ? {} : { defaultOpen }), ...(onOpenChange ? { onOpenChange } : {}) });
|
|
40
|
+
const policy = { ...popoverBehaviorDefaults, ...dismissPolicy };
|
|
41
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);
|
|
42
|
+
const parentOpen = useContext(ParentPopoverOpen);
|
|
43
|
+
const open = parentOpen && (controlledOpen ?? internalOpen);
|
|
44
|
+
const previousParentOpen = useRef(parentOpen);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!parentOpen && previousParentOpen.current && (controlledOpen ?? internalOpen)) {
|
|
47
|
+
// A closed parent ends the child's session; reopening it must not resurrect
|
|
48
|
+
// a stale uncontrolled submenu or leave a controlled owner uninformed.
|
|
49
|
+
if (controlledOpen === undefined)
|
|
50
|
+
setInternalOpen(false);
|
|
51
|
+
onOpenChange?.(false, { reason: "programmatic" });
|
|
52
|
+
}
|
|
53
|
+
previousParentOpen.current = parentOpen;
|
|
54
|
+
}, [parentOpen, controlledOpen, internalOpen, onOpenChange]);
|
|
55
|
+
const theme = useOptionalHjmTheme();
|
|
56
|
+
const systemReduced = useSyncExternalStore(subscribeSystemMotion, readSystemMotion, readServerMotion);
|
|
57
|
+
const reduced = theme?.environment.reducedMotion ?? systemReduced;
|
|
58
|
+
const [present, setPresent] = useState(open);
|
|
59
|
+
const [node, setNode] = useState(null);
|
|
60
|
+
const triggerRef = useRef(null);
|
|
61
|
+
const closeReason = useRef(undefined);
|
|
62
|
+
const focusWasInside = useRef(false);
|
|
63
|
+
const didFocus = useRef(false);
|
|
64
|
+
const requestPending = useRef(false);
|
|
65
|
+
const id = `${useId().replaceAll(":", "")}-popover`;
|
|
66
|
+
const state = useRef({ open, policy, onOpenChange, controlledOpen });
|
|
67
|
+
state.current = { open, policy, onOpenChange, controlledOpen };
|
|
68
|
+
const change = useCallback((next, reason) => {
|
|
69
|
+
const current = state.current;
|
|
70
|
+
if (next === current.open || requestPending.current)
|
|
71
|
+
return;
|
|
72
|
+
if (!next && !canDismissPopover(reason, current.policy))
|
|
73
|
+
return;
|
|
74
|
+
requestPending.current = true;
|
|
75
|
+
// Deduplicate one interaction, but let a controlled owner reject it and receive a later attempt.
|
|
76
|
+
queueMicrotask(() => { requestPending.current = false; });
|
|
77
|
+
closeReason.current = next ? undefined : reason;
|
|
78
|
+
if (current.controlledOpen === undefined)
|
|
79
|
+
setInternalOpen(next);
|
|
80
|
+
current.onOpenChange?.(next, { reason });
|
|
81
|
+
}, []);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (open) {
|
|
84
|
+
setPresent(true);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!present)
|
|
88
|
+
return;
|
|
89
|
+
// Keep only the exit surface briefly; inert/aria-hidden exclude it immediately.
|
|
90
|
+
// A parent context closes nested popovers in the same render, including their portals.
|
|
91
|
+
if (reduced) {
|
|
92
|
+
setPresent(false);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const timeout = setTimeout(() => setPresent(false), popoverRecipe.transition.exit.duration);
|
|
96
|
+
return () => clearTimeout(timeout);
|
|
97
|
+
}, [open, present, reduced]);
|
|
98
|
+
const position = useAnchoredPopup(triggerRef, open || present ? node : null, {
|
|
99
|
+
placement: resolved.placement, align: resolved.align, gap: popoverRecipe.sideOffset,
|
|
100
|
+
// Contextual forms sit above menus (900) and below tooltips (1100); a modal
|
|
101
|
+
// owner supplies its own layer through the shared positioning helper.
|
|
102
|
+
viewportPadding: popoverRecipe.collisionPadding, zIndex: 950, fallbackAxis: true,
|
|
103
|
+
});
|
|
104
|
+
const setContent = useCallback((value) => { setNode(value); }, []);
|
|
105
|
+
const contentRef = useCallback(composeRefs(setContent, ref), [setContent, ref]);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (!open) {
|
|
108
|
+
if (didFocus.current) {
|
|
109
|
+
didFocus.current = false;
|
|
110
|
+
const reason = closeReason.current;
|
|
111
|
+
if ((reason === undefined || reason === "programmatic" || reason === "escape" || reason === "close-action") && focusWasInside.current) {
|
|
112
|
+
queueMicrotask(() => {
|
|
113
|
+
const active = document.activeElement;
|
|
114
|
+
if (active === document.body || (node && active instanceof Node && contains(node, active)))
|
|
115
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
closeReason.current = undefined;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!node || position.style.visibility !== "visible" || didFocus.current)
|
|
123
|
+
return;
|
|
124
|
+
didFocus.current = true;
|
|
125
|
+
const initial = initialFocusRef?.current;
|
|
126
|
+
const target = initial && contains(node, initial) ? initial : tabStops(node.querySelector("[data-hjm-popover-body]"))[0] ?? node;
|
|
127
|
+
target.focus({ preventScroll: true });
|
|
128
|
+
focusWasInside.current = true;
|
|
129
|
+
}, [open, node, position.style.visibility, initialFocusRef]);
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!open || !node)
|
|
132
|
+
return;
|
|
133
|
+
let pointerOutside = false;
|
|
134
|
+
const inside = (target) => target instanceof Node && (contains(node, target) || triggerRef.current?.contains(target) === true);
|
|
135
|
+
const pointer = (event) => {
|
|
136
|
+
pointerOutside = !inside(event.target);
|
|
137
|
+
if (pointerOutside)
|
|
138
|
+
change(false, "outside-pointer");
|
|
139
|
+
};
|
|
140
|
+
const pointerEnd = () => { pointerOutside = false; };
|
|
141
|
+
const focus = (event) => {
|
|
142
|
+
focusWasInside.current = event.target instanceof Node && contains(node, event.target);
|
|
143
|
+
if (!inside(event.target) && !pointerOutside)
|
|
144
|
+
change(false, "outside-focus");
|
|
145
|
+
};
|
|
146
|
+
const keyboard = (event) => {
|
|
147
|
+
if (event.defaultPrevented || !inside(event.target))
|
|
148
|
+
return;
|
|
149
|
+
const owner = getPopoverOwner(event.target instanceof Node ? event.target : null);
|
|
150
|
+
if (owner && owner !== node)
|
|
151
|
+
return;
|
|
152
|
+
if (event.key === "Escape") {
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
event.stopPropagation();
|
|
155
|
+
change(false, "escape");
|
|
156
|
+
}
|
|
157
|
+
if (event.key !== "Tab" || !(event.target instanceof Node) || !contains(node, event.target))
|
|
158
|
+
return;
|
|
159
|
+
const stops = tabStops(node);
|
|
160
|
+
const first = stops[0];
|
|
161
|
+
const last = stops.at(-1);
|
|
162
|
+
if (event.shiftKey && (document.activeElement === first || document.activeElement === node)) {
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
triggerRef.current?.focus();
|
|
165
|
+
change(false, "outside-focus");
|
|
166
|
+
}
|
|
167
|
+
else if (!event.shiftKey && (document.activeElement === last || stops.length === 0)) {
|
|
168
|
+
const all = tabStops(document.body).filter((item) => !contains(node, item));
|
|
169
|
+
const index = all.indexOf(triggerRef.current);
|
|
170
|
+
const next = index >= 0 ? all[index + 1] : undefined;
|
|
171
|
+
// Portals sit at the end of body; continue after the trigger's logical position.
|
|
172
|
+
if (next) {
|
|
173
|
+
event.preventDefault();
|
|
174
|
+
next.focus();
|
|
175
|
+
change(false, "outside-focus");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
document.addEventListener("pointerdown", pointer);
|
|
180
|
+
document.addEventListener("pointerup", pointerEnd);
|
|
181
|
+
document.addEventListener("pointercancel", pointerEnd);
|
|
182
|
+
document.addEventListener("focusin", focus);
|
|
183
|
+
document.addEventListener("keydown", keyboard);
|
|
184
|
+
return () => { document.removeEventListener("pointerdown", pointer); document.removeEventListener("pointerup", pointerEnd); document.removeEventListener("pointercancel", pointerEnd); document.removeEventListener("focusin", focus); document.removeEventListener("keydown", keyboard); };
|
|
185
|
+
}, [open, node, change]);
|
|
186
|
+
const hoverTimer = useRef(undefined);
|
|
187
|
+
const cancelHover = useCallback(() => { if (hoverTimer.current !== undefined) {
|
|
188
|
+
clearTimeout(hoverTimer.current);
|
|
189
|
+
hoverTimer.current = undefined;
|
|
190
|
+
} }, []);
|
|
191
|
+
useEffect(() => cancelHover, [cancelHover]);
|
|
192
|
+
const scheduleHover = useCallback((next) => {
|
|
193
|
+
cancelHover();
|
|
194
|
+
// Delays on both edges: opening instantly turns a pass-through into a flash,
|
|
195
|
+
// and closing instantly makes the gap between trigger and panel untraversable.
|
|
196
|
+
hoverTimer.current = setTimeout(() => change(next, next ? "trigger" : "outside-pointer"), next ? popoverHoverDelay.open : popoverHoverDelay.close);
|
|
197
|
+
}, [cancelHover, change]);
|
|
198
|
+
const hoverHandlers = openOn === "hover"
|
|
199
|
+
? {
|
|
200
|
+
onPointerEnter: (event) => { if (event.pointerType !== "touch")
|
|
201
|
+
scheduleHover(true); },
|
|
202
|
+
onPointerLeave: (event) => { if (event.pointerType !== "touch")
|
|
203
|
+
scheduleHover(false); },
|
|
204
|
+
}
|
|
205
|
+
: {};
|
|
206
|
+
const triggerProps = trigger.props;
|
|
207
|
+
const renderedTrigger = cloneElement(trigger, {
|
|
208
|
+
ref: composeRefs(triggerProps.ref, triggerRef), "aria-haspopup": "dialog", "aria-expanded": open, "aria-controls": id,
|
|
209
|
+
...hoverHandlers,
|
|
210
|
+
onClick: (event) => {
|
|
211
|
+
triggerProps.onClick?.(event);
|
|
212
|
+
if (event.defaultPrevented || triggerProps.disabled || triggerProps["aria-disabled"] === true || triggerProps["aria-disabled"] === "true")
|
|
213
|
+
return;
|
|
214
|
+
change(!open, open ? "close-action" : "trigger");
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
const style = { ...position.style, "--hjm-popover-max-width": `${popoverRecipe.maxWidth}px`,
|
|
218
|
+
"--hjm-popover-duration": `${open ? popoverRecipe.transition.enter.duration : reduced ? 0 : popoverRecipe.transition.exit.duration}ms`,
|
|
219
|
+
"--hjm-popover-easing": `cubic-bezier(${easing[open ? popoverRecipe.transition.enter.easing : popoverRecipe.transition.exit.easing].join(", ")})`,
|
|
220
|
+
minWidth: Math.min(popoverRecipe.minWidth, Number(position.style.maxWidth ?? popoverRecipe.minWidth)),
|
|
221
|
+
boxShadow: `0 ${popoverRecipe.surface.shadow.offsetY}px ${popoverRecipe.surface.shadow.radius}px ${popoverRecipe.surface.shadow.color}${Math.round(popoverRecipe.surface.shadow.opacity * 255).toString(16).padStart(2, "0")}`,
|
|
222
|
+
};
|
|
223
|
+
return _jsxs(_Fragment, { children: [renderedTrigger, open || present ? _jsx(AnchoredPortal, { anchorRef: triggerRef, ssrFallback: "inline", ...(portalContainer ? { container: portalContainer } : {}), children: _jsx(ParentPopoverOpen.Provider, { value: open, children: _jsxs("div", { ref: contentRef, id: id, role: "dialog", tabIndex: -1, "data-hjm-popover-content": "", "data-state": open ? "open" : "closed", "aria-hidden": !open || undefined, inert: !open || undefined, "aria-label": resolved.accessibilityLabel, "aria-labelledby": resolved.accessibilityLabel ? undefined : `${id}-title`, "aria-describedby": description ? `${id}-description` : undefined, className: classNames("hjm-popover", className), style: style, "data-placement": position.placement, "data-align": position.align, ...hoverHandlers, onAnimationEnd: (event) => { if (!open && event.target === event.currentTarget)
|
|
224
|
+
setPresent(false); }, children: [_jsxs("div", { className: "hjm-popover__header", children: [_jsx("h2", { id: `${id}-title`, className: "hjm-popover__title", children: title }), _jsx(Button, { tone: "ghost", onClick: () => change(false, "close-action"), children: closeLabel })] }), description ? _jsx("p", { id: `${id}-description`, className: "hjm-popover__description", children: description }) : null, _jsx("div", { "data-hjm-popover-body": "", className: "hjm-popover__body", children: typeof children === "function" ? children({ close: () => change(false, "close-action") }) : children })] }) }) }) : null] });
|
|
225
|
+
});
|
|
226
|
+
//# sourceMappingURL=popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.js","sourceRoot":"","sources":["../src/popover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,EAAsD,MAAM,OAAO,CAAC;AACvM,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,wBAAwB,EAAE,wBAAwB,EAA0J,MAAM,4CAA4C,CAAC;AACtV,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAqBpD,MAAM,iBAAiB,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,kCAAkC,CAAC;AACvD,SAAS,qBAAqB,CAAC,MAAkB;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvF,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC3D,CAAC;AACD,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;AACtE,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC;AACrC,MAAM,SAAS,GAAG,iDAAiD,CAAC;AACpE,SAAS,QAAQ,CAAC,SAAsB;IACtC,OAAO,CAAC,GAAG,SAAS,CAAC,gBAAgB,CAAc,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAC7E,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,uCAAuC,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ,CACjM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxG,CAAC;AACD,SAAS,QAAQ,CAAC,OAAoB,EAAE,MAAY;IAClD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAAC,IAAI,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5E,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAAC,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAA+B,SAAS,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAC3G,WAAW,EAAE,UAAU,GAAG,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,uBAAuB,CAAC,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAC3I,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,GAAG;IACtD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IAC/G,MAAM,QAAQ,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IACtD,wBAAwB,CAAC,EAAE,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAsB,CAAC,CAAC;IACtN,MAAM,MAAM,GAAG,EAAE,GAAG,uBAAuB,EAAE,GAAG,aAAa,EAAE,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,UAAU,IAAI,CAAC,cAAc,IAAI,YAAY,CAAC,CAAC;IAC5D,MAAM,kBAAkB,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,UAAU,IAAI,kBAAkB,CAAC,OAAO,IAAI,CAAC,cAAc,IAAI,YAAY,CAAC,EAAE,CAAC;YAClF,4EAA4E;YAC5E,uEAAuE;YACvE,IAAI,cAAc,KAAK,SAAS;gBAAE,eAAe,CAAC,KAAK,CAAC,CAAC;YACzD,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,kBAAkB,CAAC,OAAO,GAAG,UAAU,CAAC;IAC1C,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,MAAM,aAAa,GAAG,oBAAoB,CAAC,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACtG,MAAM,OAAO,GAAG,KAAK,EAAE,WAAW,CAAC,aAAa,IAAI,aAAa,CAAC;IAClE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAwB,IAAI,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,MAAM,CAAmC,SAAS,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,GAAG,KAAK,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC;IACrI,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,IAAa,EAAE,MAA0C,EAAE,EAAE;QACvF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,IAAI,KAAK,OAAO,CAAC,IAAI,IAAI,cAAc,CAAC,OAAO;YAAE,OAAO;QAC5D,IAAI,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAA8B,EAAE,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO;QACxF,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,iGAAiG;QACjG,cAAc,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAA8B,CAAC;QACxE,IAAI,OAAO,CAAC,cAAc,KAAK,SAAS;YAAE,eAAe,CAAC,IAAI,CAAC,CAAC;QAChE,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,EAAE,CAAC;YAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,gFAAgF;QAChF,uFAAuF;QACvF,IAAI,OAAO,EAAE,CAAC;YAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5F,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,EAAE,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;QAC3E,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,CAAC,UAAU;QACnF,4EAA4E;QAC5E,sEAAsE;QACtE,eAAe,EAAE,aAAa,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI;KACjF,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,KAA4B,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1F,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IAChF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;gBACzB,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC;gBACnC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,cAAc,CAAC,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;oBACtI,cAAc,CAAC,GAAG,EAAE;wBAClB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC;wBACtC,IAAI,MAAM,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,YAAY,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;4BAAE,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;oBACjJ,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,WAAW,CAAC,OAAO,GAAG,SAAS,CAAC;YAAC,OAAO;QAC1C,CAAC;QACD,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO;QACjF,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,MAAM,OAAO,GAAG,eAAe,EAAE,OAAO,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAc,yBAAyB,CAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC/I,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAAC,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC;IACvE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;IAC7D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QAC3B,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,MAAM,MAAM,GAAG,CAAC,MAA0B,EAAkB,EAAE,CAAC,MAAM,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;QACnK,MAAM,OAAO,GAAG,CAAC,KAAmB,EAAE,EAAE;YACtC,cAAc,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,cAAc;gBAAE,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACvD,CAAC,CAAC;QACF,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,KAAiB,EAAE,EAAE;YAClC,cAAc,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,YAAY,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACtF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc;gBAAE,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QAC/E,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAE,EAAE;YACxC,IAAI,KAAK,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC5D,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClF,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO;YACpC,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAAC,KAAK,CAAC,cAAc,EAAE,CAAC;gBAAC,KAAK,CAAC,eAAe,EAAE,CAAC;gBAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAAC,CAAC;YACzG,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;gBAAE,OAAO;YACpG,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAAC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAAC,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAChF,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,aAAa,KAAK,KAAK,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC5F,KAAK,CAAC,cAAc,EAAE,CAAC;gBAAC,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;gBAAC,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YACtF,CAAC;iBAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,aAAa,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtF,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;gBAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,OAAQ,CAAC,CAAC;gBAAC,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACrG,iFAAiF;gBACjF,IAAI,IAAI,EAAE,CAAC;oBAAC,KAAK,CAAC,cAAc,EAAE,CAAC;oBAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAAC,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;gBAAC,CAAC;YACrF,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC9J,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC5F,OAAO,GAAG,EAAE,GAAG,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9R,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACzB,MAAM,UAAU,GAAG,MAAM,CAA4C,SAAS,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAAC,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC;IAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3J,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,IAAa,EAAE,EAAE;QAClD,WAAW,EAAE,CAAC;QACd,6EAA6E;QAC7E,+EAA+E;QAC/E,UAAU,CAAC,OAAO,GAAG,UAAU,CAC7B,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,EACxD,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CACxD,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1B,MAAM,aAAa,GAAG,MAAM,KAAK,OAAO;QACtC,CAAC,CAAC;YACE,cAAc,EAAE,CAAC,KAA+B,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,WAAW,KAAK,OAAO;gBAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChH,cAAc,EAAE,CAAC,KAA+B,EAAE,EAAE,GAAG,IAAI,KAAK,CAAC,WAAW,KAAK,OAAO;gBAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClH;QACH,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IACnC,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,EAAE;QAC5C,GAAG,EAAE,WAAW,CAAC,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE;QACrH,GAAG,aAAa;QAChB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,gBAAgB,IAAI,YAAY,CAAC,QAAQ,IAAI,YAAY,CAAC,eAAe,CAAC,KAAK,IAAI,IAAI,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM;gBAAE,OAAO;YAClJ,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,yBAAyB,EAAE,GAAG,aAAa,CAAC,QAAQ,IAAI;QACzF,wBAAwB,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,IAAI;QACtI,sBAAsB,EAAE,gBAAgB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACjJ,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrG,SAAS,EAAE,KAAK,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;KAE9M,CAAC;IACnB,OAAO,8BAAG,eAAe,EAAE,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,KAAC,cAAc,IAAC,SAAS,EAAE,UAAU,EAAE,WAAW,EAAC,QAAQ,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,YAClK,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAE,eAAK,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,CAAC,8BAA2B,EAAE,gBAAa,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,iBACpJ,CAAC,IAAI,IAAI,SAAS,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,SAAS,gBAAc,QAAQ,CAAC,kBAAkB,qBAAmB,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,sBAAoB,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,SAAS,EAC9O,SAAS,EAAE,UAAU,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,oBAAkB,QAAQ,CAAC,SAAS,gBAAc,QAAQ,CAAC,KAAK,KAAM,aAAa,EAChJ,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,aAAa;4BAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aACpG,eAAK,SAAS,EAAC,qBAAqB,aAAC,aAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAC,oBAAoB,YAAE,KAAK,GAAM,EAAA,KAAC,MAAM,IAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,YAAG,UAAU,GAAU,IAAM,EACpM,WAAW,CAAC,CAAC,CAAC,YAAG,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,SAAS,EAAC,0BAA0B,YAAE,WAAW,GAAK,CAAC,CAAC,CAAC,IAAI,EACxG,uCAA2B,EAAE,EAAC,SAAS,EAAC,mBAAmB,YAAE,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAO,IACpK,GAA6B,GACpB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC/B,CAAC,CAAC,CAAC","sourcesContent":["import { cloneElement, createContext, forwardRef, useCallback, useContext, useEffect, useId, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactNode, type RefObject } from \"react\";\nimport { canDismissPopover, popoverBehaviorDefaults, popoverHoverDelay, popoverRecipe, resolvePopoverDescriptor, validatePopoverOpenState, type PopoverDescriptor, type PopoverDismissPolicy, type PopoverDismissReason, type PopoverOpenChangeDetails, type PopoverOpenOn, type PopoverOpenState } from \"@hjmds/design-contracts/components/popover\";\nimport { easing } from \"@hjmds/design-contracts/foundations\";\nimport { Button } from \"./actions.js\";\nimport { classNames, composeRefs } from \"./internal.js\";\nimport { AnchoredPortal, getPopoverOwner, useAnchoredPopup } from \"./portal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\nimport type { OverlayTrigger } from \"./overlays.js\";\n\nexport type PopoverContentActions = Readonly<{ close(): void }>;\nexport type PopoverProps = PopoverOpenState & Readonly<{\n trigger: OverlayTrigger;\n title: string;\n closeLabel: string;\n description?: string;\n descriptor?: PopoverDescriptor;\n children?: ReactNode | ((actions: PopoverContentActions) => ReactNode);\n dismissPolicy?: Partial<PopoverDismissPolicy>;\n /**\n * `\"hover\"` adds pointer enter/leave on top of the click path; it never\n * replaces it, because hover does not exist on touch or for a keyboard.\n */\n openOn?: PopoverOpenOn;\n initialFocusRef?: RefObject<HTMLElement | null>;\n portalContainer?: HTMLElement;\n className?: string;\n}>;\nconst ParentPopoverOpen = createContext(true);\nconst motionQuery = \"(prefers-reduced-motion: reduce)\";\nfunction subscribeSystemMotion(notify: () => void) {\n const media = window.matchMedia(motionQuery); media.addEventListener(\"change\", notify);\n return () => media.removeEventListener(\"change\", notify);\n}\nconst readSystemMotion = () => window.matchMedia(motionQuery).matches;\nconst readServerMotion = () => false;\nconst focusable = 'a[href],button,input,select,textarea,[tabindex]';\nfunction tabStops(container: HTMLElement): HTMLElement[] {\n return [...container.querySelectorAll<HTMLElement>(focusable)].filter((node) =>\n node.tabIndex >= 0 && !node.matches(\":disabled\") && !node.closest('[inert],[hidden],[aria-hidden=\"true\"]') && node.getClientRects().length > 0 && getComputedStyle(node).visibility !== \"hidden\",\n ).sort((a, b) => (a.tabIndex > 0 ? a.tabIndex : Infinity) - (b.tabIndex > 0 ? b.tabIndex : Infinity));\n}\nfunction contains(content: HTMLElement, target: Node): boolean {\n if (content.contains(target)) return true;\n const visited = new Set<HTMLElement>(); let owner = getPopoverOwner(target);\n while (owner && !visited.has(owner)) {\n if (owner === content) return true;\n visited.add(owner); owner = getPopoverOwner(owner.parentElement);\n }\n return false;\n}\n\nexport const Popover = forwardRef<HTMLDivElement, PopoverProps>(function Popover({ trigger, title, closeLabel,\n description, descriptor = {}, children, dismissPolicy, openOn = popoverBehaviorDefaults.openOn, initialFocusRef, portalContainer, className,\n open: controlledOpen, defaultOpen, onOpenChange }, ref) {\n if (!title.trim() || !closeLabel.trim()) throw new TypeError(\"Popover title and closeLabel must not be empty\");\n const resolved = resolvePopoverDescriptor(descriptor);\n validatePopoverOpenState({ ...(controlledOpen === undefined ? {} : { open: controlledOpen }), ...(defaultOpen === undefined ? {} : { defaultOpen }), ...(onOpenChange ? { onOpenChange } : {}) } as PopoverOpenState);\n const policy = { ...popoverBehaviorDefaults, ...dismissPolicy };\n const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);\n const parentOpen = useContext(ParentPopoverOpen);\n const open = parentOpen && (controlledOpen ?? internalOpen);\n const previousParentOpen = useRef(parentOpen);\n useEffect(() => {\n if (!parentOpen && previousParentOpen.current && (controlledOpen ?? internalOpen)) {\n // A closed parent ends the child's session; reopening it must not resurrect\n // a stale uncontrolled submenu or leave a controlled owner uninformed.\n if (controlledOpen === undefined) setInternalOpen(false);\n onOpenChange?.(false, { reason: \"programmatic\" });\n }\n previousParentOpen.current = parentOpen;\n }, [parentOpen, controlledOpen, internalOpen, onOpenChange]);\n const theme = useOptionalHjmTheme();\n const systemReduced = useSyncExternalStore(subscribeSystemMotion, readSystemMotion, readServerMotion);\n const reduced = theme?.environment.reducedMotion ?? systemReduced;\n const [present, setPresent] = useState(open);\n const [node, setNode] = useState<HTMLDivElement | null>(null);\n const triggerRef = useRef<HTMLElement>(null);\n const closeReason = useRef<PopoverDismissReason | undefined>(undefined);\n const focusWasInside = useRef(false);\n const didFocus = useRef(false);\n const requestPending = useRef(false);\n const id = `${useId().replaceAll(\":\", \"\")}-popover`;\n const state = useRef({ open, policy, onOpenChange, controlledOpen }); state.current = { open, policy, onOpenChange, controlledOpen };\n const change = useCallback((next: boolean, reason: PopoverOpenChangeDetails[\"reason\"]) => {\n const current = state.current;\n if (next === current.open || requestPending.current) return;\n if (!next && !canDismissPopover(reason as PopoverDismissReason, current.policy)) return;\n requestPending.current = true;\n // Deduplicate one interaction, but let a controlled owner reject it and receive a later attempt.\n queueMicrotask(() => { requestPending.current = false; });\n closeReason.current = next ? undefined : reason as PopoverDismissReason;\n if (current.controlledOpen === undefined) setInternalOpen(next);\n current.onOpenChange?.(next, { reason });\n }, []);\n useEffect(() => {\n if (open) { setPresent(true); return; }\n if (!present) return;\n // Keep only the exit surface briefly; inert/aria-hidden exclude it immediately.\n // A parent context closes nested popovers in the same render, including their portals.\n if (reduced) { setPresent(false); return; }\n const timeout = setTimeout(() => setPresent(false), popoverRecipe.transition.exit.duration);\n return () => clearTimeout(timeout);\n }, [open, present, reduced]);\n const position = useAnchoredPopup(triggerRef, open || present ? node : null, {\n placement: resolved.placement, align: resolved.align, gap: popoverRecipe.sideOffset,\n // Contextual forms sit above menus (900) and below tooltips (1100); a modal\n // owner supplies its own layer through the shared positioning helper.\n viewportPadding: popoverRecipe.collisionPadding, zIndex: 950, fallbackAxis: true,\n });\n const setContent = useCallback((value: HTMLDivElement | null) => { setNode(value); }, []);\n const contentRef = useCallback(composeRefs(setContent, ref), [setContent, ref]);\n useEffect(() => {\n if (!open) {\n if (didFocus.current) {\n didFocus.current = false;\n const reason = closeReason.current;\n if ((reason === undefined || reason === \"programmatic\" || reason === \"escape\" || reason === \"close-action\") && focusWasInside.current) {\n queueMicrotask(() => {\n const active = document.activeElement;\n if (active === document.body || (node && active instanceof Node && contains(node, active))) triggerRef.current?.focus({ preventScroll: true });\n });\n }\n }\n closeReason.current = undefined; return;\n }\n if (!node || position.style.visibility !== \"visible\" || didFocus.current) return;\n didFocus.current = true;\n const initial = initialFocusRef?.current;\n const target = initial && contains(node, initial) ? initial : tabStops(node.querySelector<HTMLElement>(\"[data-hjm-popover-body]\")!)[0] ?? node;\n target.focus({ preventScroll: true }); focusWasInside.current = true;\n }, [open, node, position.style.visibility, initialFocusRef]);\n useEffect(() => {\n if (!open || !node) return;\n let pointerOutside = false;\n const inside = (target: EventTarget | null): target is Node => target instanceof Node && (contains(node, target) || triggerRef.current?.contains(target) === true);\n const pointer = (event: PointerEvent) => {\n pointerOutside = !inside(event.target);\n if (pointerOutside) change(false, \"outside-pointer\");\n };\n const pointerEnd = () => { pointerOutside = false; };\n const focus = (event: FocusEvent) => {\n focusWasInside.current = event.target instanceof Node && contains(node, event.target);\n if (!inside(event.target) && !pointerOutside) change(false, \"outside-focus\");\n };\n const keyboard = (event: KeyboardEvent) => {\n if (event.defaultPrevented || !inside(event.target)) return;\n const owner = getPopoverOwner(event.target instanceof Node ? event.target : null);\n if (owner && owner !== node) return;\n if (event.key === \"Escape\") { event.preventDefault(); event.stopPropagation(); change(false, \"escape\"); }\n if (event.key !== \"Tab\" || !(event.target instanceof Node) || !contains(node, event.target)) return;\n const stops = tabStops(node); const first = stops[0]; const last = stops.at(-1);\n if (event.shiftKey && (document.activeElement === first || document.activeElement === node)) {\n event.preventDefault(); triggerRef.current?.focus(); change(false, \"outside-focus\");\n } else if (!event.shiftKey && (document.activeElement === last || stops.length === 0)) {\n const all = tabStops(document.body).filter((item) => !contains(node, item));\n const index = all.indexOf(triggerRef.current!); const next = index >= 0 ? all[index + 1] : undefined;\n // Portals sit at the end of body; continue after the trigger's logical position.\n if (next) { event.preventDefault(); next.focus(); change(false, \"outside-focus\"); }\n }\n };\n document.addEventListener(\"pointerdown\", pointer); document.addEventListener(\"pointerup\", pointerEnd); document.addEventListener(\"pointercancel\", pointerEnd);\n document.addEventListener(\"focusin\", focus); document.addEventListener(\"keydown\", keyboard);\n return () => { document.removeEventListener(\"pointerdown\", pointer); document.removeEventListener(\"pointerup\", pointerEnd); document.removeEventListener(\"pointercancel\", pointerEnd); document.removeEventListener(\"focusin\", focus); document.removeEventListener(\"keydown\", keyboard); };\n }, [open, node, change]);\n const hoverTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const cancelHover = useCallback(() => { if (hoverTimer.current !== undefined) { clearTimeout(hoverTimer.current); hoverTimer.current = undefined; } }, []);\n useEffect(() => cancelHover, [cancelHover]);\n const scheduleHover = useCallback((next: boolean) => {\n cancelHover();\n // Delays on both edges: opening instantly turns a pass-through into a flash,\n // and closing instantly makes the gap between trigger and panel untraversable.\n hoverTimer.current = setTimeout(\n () => change(next, next ? \"trigger\" : \"outside-pointer\"),\n next ? popoverHoverDelay.open : popoverHoverDelay.close,\n );\n }, [cancelHover, change]);\n const hoverHandlers = openOn === \"hover\"\n ? {\n onPointerEnter: (event: { pointerType?: string }) => { if (event.pointerType !== \"touch\") scheduleHover(true); },\n onPointerLeave: (event: { pointerType?: string }) => { if (event.pointerType !== \"touch\") scheduleHover(false); },\n }\n : {};\n const triggerProps = trigger.props;\n const renderedTrigger = cloneElement(trigger, {\n ref: composeRefs(triggerProps.ref, triggerRef), \"aria-haspopup\": \"dialog\", \"aria-expanded\": open, \"aria-controls\": id,\n ...hoverHandlers,\n onClick: (event) => {\n triggerProps.onClick?.(event);\n if (event.defaultPrevented || triggerProps.disabled || triggerProps[\"aria-disabled\"] === true || triggerProps[\"aria-disabled\"] === \"true\") return;\n change(!open, open ? \"close-action\" : \"trigger\");\n },\n });\n const style = { ...position.style, \"--hjm-popover-max-width\": `${popoverRecipe.maxWidth}px`,\n \"--hjm-popover-duration\": `${open ? popoverRecipe.transition.enter.duration : reduced ? 0 : popoverRecipe.transition.exit.duration}ms`,\n \"--hjm-popover-easing\": `cubic-bezier(${easing[open ? popoverRecipe.transition.enter.easing : popoverRecipe.transition.exit.easing].join(\", \")})`,\n minWidth: Math.min(popoverRecipe.minWidth, Number(position.style.maxWidth ?? popoverRecipe.minWidth)),\n boxShadow: `0 ${popoverRecipe.surface.shadow.offsetY}px ${popoverRecipe.surface.shadow.radius}px ${popoverRecipe.surface.shadow.color}${Math.round(popoverRecipe.surface.shadow.opacity * 255).toString(16).padStart(2, \"0\")}`,\n\n } as CSSProperties;\n return <>{renderedTrigger}{open || present ? <AnchoredPortal anchorRef={triggerRef} ssrFallback=\"inline\" {...(portalContainer ? { container: portalContainer } : {})}>\n <ParentPopoverOpen.Provider value={open}><div ref={contentRef} id={id} role=\"dialog\" tabIndex={-1} data-hjm-popover-content=\"\" data-state={open ? \"open\" : \"closed\"}\n aria-hidden={!open || undefined} inert={!open || undefined} aria-label={resolved.accessibilityLabel} aria-labelledby={resolved.accessibilityLabel ? undefined : `${id}-title`} aria-describedby={description ? `${id}-description` : undefined}\n className={classNames(\"hjm-popover\", className)} style={style} data-placement={position.placement} data-align={position.align} {...hoverHandlers}\n onAnimationEnd={(event) => { if (!open && event.target === event.currentTarget) setPresent(false); }}>\n <div className=\"hjm-popover__header\"><h2 id={`${id}-title`} className=\"hjm-popover__title\">{title}</h2><Button tone=\"ghost\" onClick={() => change(false, \"close-action\")}>{closeLabel}</Button></div>\n {description ? <p id={`${id}-description`} className=\"hjm-popover__description\">{description}</p> : null}\n <div data-hjm-popover-body=\"\" className=\"hjm-popover__body\">{typeof children === \"function\" ? children({ close: () => change(false, \"close-action\") }) : children}</div>\n </div></ParentPopoverOpen.Provider>\n </AnchoredPortal> : null}</>;\n});\n"]}
|
package/dist/portal.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type PortalProps = Readonly<{
|
|
|
6
6
|
/** Anchored non-modal popups may render inline until hydration moves them. */
|
|
7
7
|
ssrFallback?: "none" | "inline";
|
|
8
8
|
}>;
|
|
9
|
+
/** Nearest interactive popover, including descendants rendered through another portal. */
|
|
10
|
+
export declare function getPopoverOwner(node: Node | null): HTMLElement | null;
|
|
9
11
|
export declare function AnchoredPortal({ anchorRef, children, container, ssrFallback, }: PortalProps): ReactNode;
|
|
10
12
|
export type AnchoredPopupAlign = "start" | "center" | "end";
|
|
11
13
|
export type AnchoredPopupPlacement = "bottom" | "top" | "start" | "end";
|
|
@@ -21,12 +23,14 @@ type AnchoredPopupOptions = Readonly<{
|
|
|
21
23
|
placement?: AnchoredPopupPlacement;
|
|
22
24
|
viewportPadding?: number;
|
|
23
25
|
zIndex?: number;
|
|
26
|
+
/** Wide contextual content may switch to the block axis in a narrow viewport. */
|
|
27
|
+
fallbackAxis?: boolean;
|
|
24
28
|
}>;
|
|
25
29
|
/**
|
|
26
30
|
* Positions a fixed portal popup against its anchor using logical alignment.
|
|
27
31
|
* The popup flips vertically and shifts horizontally to stay inside the visual
|
|
28
32
|
* viewport, then follows every scroll/resize source that can move either node.
|
|
29
33
|
*/
|
|
30
|
-
export declare function useAnchoredPopup(anchorRef: RefObject<HTMLElement | null>, popup: HTMLElement | null, { align, gap, matchAnchorWidth, placement: preferredPlacement, viewportPadding, zIndex, }?: AnchoredPopupOptions): AnchoredPopupPosition;
|
|
34
|
+
export declare function useAnchoredPopup(anchorRef: RefObject<HTMLElement | null>, popup: HTMLElement | null, { align, fallbackAxis, gap, matchAnchorWidth, placement: preferredPlacement, viewportPadding, zIndex, }?: AnchoredPopupOptions): AnchoredPopupPosition;
|
|
31
35
|
export {};
|
|
32
36
|
//# sourceMappingURL=portal.d.ts.map
|
package/dist/portal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../src/portal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CACjC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../src/portal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CACjC,CAAC,CAAC;AAEH,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CAMrE;AAyDD,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAoB,GACrB,EAAE,WAAW,aA8Bb;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC5D,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,CAAC;AAExE,KAAK,qBAAqB,GAAG,QAAQ,CAAC;IACpC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,SAAS,EAAE,sBAAsB,CAAC;IAClC,KAAK,EAAE,aAAa,CAAC;CACtB,CAAC,CAAC;AAEH,KAAK,oBAAoB,GAAG,QAAQ,CAAC;IACnC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC,CAAC;AA6BH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACxC,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,EACE,KAAe,EACf,YAAoB,EACpB,GAAO,EACP,gBAAwB,EACxB,SAAS,EAAE,kBAA6B,EACxC,eAAoB,EACpB,MAAY,GACb,GAAE,oBAAyB,GAC3B,qBAAqB,CA+LvB"}
|
package/dist/portal.js
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef, useState, } from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
+
/** Nearest interactive popover, including descendants rendered through another portal. */
|
|
5
|
+
export function getPopoverOwner(node) {
|
|
6
|
+
const element = node instanceof Element ? node : node?.parentElement;
|
|
7
|
+
const direct = element?.closest("[data-hjm-popover-content]");
|
|
8
|
+
if (direct)
|
|
9
|
+
return direct;
|
|
10
|
+
const ownerId = element?.closest("[data-hjm-popover-owner]")?.getAttribute("data-hjm-popover-owner");
|
|
11
|
+
return ownerId ? document.getElementById(ownerId) : null;
|
|
12
|
+
}
|
|
4
13
|
/**
|
|
5
14
|
* Copies the closest provider DOM boundary instead of importing provider
|
|
6
15
|
* runtime code, keeping granular form/overlay entry points lightweight.
|
|
7
16
|
*/
|
|
8
17
|
function synchronizePortalEnvironment(host, anchor) {
|
|
18
|
+
// Modal ownership and non-modal ownership are separate: nested selects/menus
|
|
19
|
+
// must belong to both, so outside focus does not close their parent popover.
|
|
20
|
+
const popoverOwner = getPopoverOwner(anchor);
|
|
21
|
+
if (popoverOwner?.id)
|
|
22
|
+
host.setAttribute("data-hjm-popover-owner", popoverOwner.id);
|
|
23
|
+
else
|
|
24
|
+
host.removeAttribute("data-hjm-popover-owner");
|
|
9
25
|
const source = anchor?.closest("[data-hjm-provider], [data-hjm-portal]") ?? null;
|
|
10
26
|
const directModalOwner = anchor?.closest("[data-hjm-modal-content]") ?? null;
|
|
11
27
|
const inheritedOwnerId = anchor
|
|
@@ -102,7 +118,7 @@ function samePosition(previous, next) {
|
|
|
102
118
|
* The popup flips vertically and shifts horizontally to stay inside the visual
|
|
103
119
|
* viewport, then follows every scroll/resize source that can move either node.
|
|
104
120
|
*/
|
|
105
|
-
export function useAnchoredPopup(anchorRef, popup, { align = "start", gap = 8, matchAnchorWidth = false, placement: preferredPlacement = "bottom", viewportPadding = 16, zIndex = 800, } = {}) {
|
|
121
|
+
export function useAnchoredPopup(anchorRef, popup, { align = "start", fallbackAxis = false, gap = 8, matchAnchorWidth = false, placement: preferredPlacement = "bottom", viewportPadding = 16, zIndex = 800, } = {}) {
|
|
106
122
|
const [position, setPosition] = useState(() => ({
|
|
107
123
|
...hiddenPopupPosition,
|
|
108
124
|
align,
|
|
@@ -163,6 +179,12 @@ export function useAnchoredPopup(anchorRef, popup, { align = "start", gap = 8, m
|
|
|
163
179
|
desiredPopupWidth > availableRight &&
|
|
164
180
|
availableLeft > availableRight)
|
|
165
181
|
physicalPlacement = "left";
|
|
182
|
+
// A wide form cannot fit beside a centered mobile trigger. Preserve readable
|
|
183
|
+
// content by trying the block axis; existing compact popup defaults stay unchanged.
|
|
184
|
+
if (fallbackAxis && (physicalPlacement === "left" || physicalPlacement === "right") &&
|
|
185
|
+
Math.max(availableLeft, availableRight) < desiredPopupWidth) {
|
|
186
|
+
physicalPlacement = availableBottom >= availableTop ? "bottom" : "top";
|
|
187
|
+
}
|
|
166
188
|
const placement = physicalPlacement === "left"
|
|
167
189
|
? (logicalStartAtLeft ? "start" : "end")
|
|
168
190
|
: physicalPlacement === "right"
|
|
@@ -226,6 +248,7 @@ export function useAnchoredPopup(anchorRef, popup, { align = "start", gap = 8, m
|
|
|
226
248
|
}, [
|
|
227
249
|
align,
|
|
228
250
|
anchorRef,
|
|
251
|
+
fallbackAxis,
|
|
229
252
|
gap,
|
|
230
253
|
matchAnchorWidth,
|
|
231
254
|
popup,
|
package/dist/portal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../src/portal.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport type PortalProps = Readonly<{\n anchorRef: RefObject<HTMLElement | null>;\n children: ReactNode;\n container?: HTMLElement;\n /** Anchored non-modal popups may render inline until hydration moves them. */\n ssrFallback?: \"none\" | \"inline\";\n}>;\n\n/**\n * Copies the closest provider DOM boundary instead of importing provider\n * runtime code, keeping granular form/overlay entry points lightweight.\n */\nfunction synchronizePortalEnvironment(host: HTMLDivElement, anchor: HTMLElement | null): void {\n const source = anchor?.closest<HTMLElement>(\"[data-hjm-provider], [data-hjm-portal]\") ?? null;\n const directModalOwner = anchor?.closest<HTMLElement>(\"[data-hjm-modal-content]\") ?? null;\n const inheritedOwnerId = anchor\n ?.closest<HTMLElement>(\"[data-hjm-popup-owner]\")\n ?.getAttribute(\"data-hjm-popup-owner\") ?? null;\n const modalOwner = directModalOwner ??\n (inheritedOwnerId === null ? null : document.getElementById(inheritedOwnerId));\n if (modalOwner?.id) host.setAttribute(\"data-hjm-popup-owner\", modalOwner.id);\n else host.removeAttribute(\"data-hjm-popup-owner\");\n if (source) {\n host.removeAttribute(\"style\");\n for (let index = 0; index < source.style.length; index += 1) {\n const property = source.style.item(index);\n if (\n property.startsWith(\"--hjm-\") ||\n property === \"background-color\" ||\n property === \"color\" ||\n property === \"color-scheme\" ||\n property === \"font-family\" ||\n property === \"font-size\" ||\n property === \"line-height\"\n ) {\n host.style.setProperty(\n property,\n source.style.getPropertyValue(property),\n source.style.getPropertyPriority(property),\n );\n }\n }\n for (const attribute of [\"data-motion\", \"data-theme\", \"data-text-scale\", \"data-large-text\"] as const) {\n const value = source.getAttribute(attribute);\n if (value === null) host.removeAttribute(attribute);\n else host.setAttribute(attribute, value);\n }\n host.dir = source.dir;\n return;\n }\n host.removeAttribute(\"style\");\n host.removeAttribute(\"data-motion\");\n host.removeAttribute(\"data-theme\");\n host.removeAttribute(\"data-text-scale\");\n host.removeAttribute(\"data-large-text\");\n host.dir = anchor?.closest<HTMLElement>(\"[dir]\")?.dir ?? \"\";\n}\n\nexport function AnchoredPortal({\n anchorRef,\n children,\n container,\n ssrFallback = \"none\",\n}: PortalProps) {\n const [mounted, setMounted] = useState(false);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const setHostRef = useCallback((host: HTMLDivElement | null) => {\n hostRef.current = host;\n if (host) synchronizePortalEnvironment(host, anchorRef.current);\n }, [anchorRef]);\n useEffect(() => setMounted(true), []);\n useEffect(() => {\n const host = hostRef.current;\n const source = anchorRef.current?.closest<HTMLElement>(\n \"[data-hjm-provider], [data-hjm-portal]\",\n ) ?? null;\n if (!host || !source || typeof MutationObserver === \"undefined\") return;\n const observer = new MutationObserver(() => {\n synchronizePortalEnvironment(host, anchorRef.current);\n });\n observer.observe(source, {\n attributes: true,\n attributeFilter: [\"data-motion\", \"data-theme\", \"data-text-scale\", \"data-large-text\", \"dir\", \"style\"],\n });\n return () => observer.disconnect();\n }, [anchorRef, mounted]);\n if (!mounted) return ssrFallback === \"inline\" ? children : null;\n return createPortal(\n <div ref={setHostRef} className=\"hjm-root hjm-portal\" data-hjm-portal=\"\">\n {children}\n </div>,\n container ?? document.body,\n );\n}\n\nexport type AnchoredPopupAlign = \"start\" | \"center\" | \"end\";\nexport type AnchoredPopupPlacement = \"bottom\" | \"top\" | \"start\" | \"end\";\n\ntype AnchoredPopupPosition = Readonly<{\n align: AnchoredPopupAlign;\n placement: AnchoredPopupPlacement;\n style: CSSProperties;\n}>;\n\ntype AnchoredPopupOptions = Readonly<{\n align?: AnchoredPopupAlign;\n gap?: number;\n matchAnchorWidth?: boolean;\n placement?: AnchoredPopupPlacement;\n viewportPadding?: number;\n zIndex?: number;\n}>;\n\nconst hiddenPopupPosition: AnchoredPopupPosition = {\n align: \"start\",\n placement: \"bottom\",\n style: {\n position: \"fixed\",\n inset: \"auto\",\n left: 0,\n top: 0,\n visibility: \"hidden\",\n },\n};\n\nfunction samePosition(\n previous: AnchoredPopupPosition,\n next: AnchoredPopupPosition,\n): boolean {\n return previous.align === next.align &&\n previous.placement === next.placement &&\n previous.style.left === next.style.left &&\n previous.style.top === next.style.top &&\n previous.style.minWidth === next.style.minWidth &&\n previous.style.maxWidth === next.style.maxWidth &&\n previous.style.maxHeight === next.style.maxHeight &&\n previous.style.zIndex === next.style.zIndex &&\n previous.style.visibility === next.style.visibility;\n}\n\n/**\n * Positions a fixed portal popup against its anchor using logical alignment.\n * The popup flips vertically and shifts horizontally to stay inside the visual\n * viewport, then follows every scroll/resize source that can move either node.\n */\nexport function useAnchoredPopup(\n anchorRef: RefObject<HTMLElement | null>,\n popup: HTMLElement | null,\n {\n align = \"start\",\n gap = 8,\n matchAnchorWidth = false,\n placement: preferredPlacement = \"bottom\",\n viewportPadding = 16,\n zIndex = 800,\n }: AnchoredPopupOptions = {},\n): AnchoredPopupPosition {\n const [position, setPosition] = useState<AnchoredPopupPosition>(() => ({\n ...hiddenPopupPosition,\n align,\n }));\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor || !popup || !anchor.isConnected || !popup.isConnected) return;\n\n const anchorRect = anchor.getBoundingClientRect();\n const popupRect = popup.getBoundingClientRect();\n const visualViewport = window.visualViewport;\n const viewportLeft = visualViewport?.offsetLeft ?? 0;\n const viewportTop = visualViewport?.offsetTop ?? 0;\n const viewportWidth = visualViewport?.width ?? window.innerWidth;\n const viewportHeight = visualViewport?.height ?? window.innerHeight;\n const viewportRight = viewportLeft + viewportWidth;\n const viewportBottom = viewportTop + viewportHeight;\n const availableBottom = Math.max(0, viewportBottom - viewportPadding - anchorRect.bottom - gap);\n const availableTop = Math.max(0, anchorRect.top - viewportTop - viewportPadding - gap);\n const availableLeft = Math.max(0, anchorRect.left - viewportLeft - viewportPadding - gap);\n const availableRight = Math.max(0, viewportRight - viewportPadding - anchorRect.right - gap);\n const maximumPopupHeight = Math.max(0, viewportHeight - (2 * viewportPadding));\n const maximumPopupWidth = Math.max(0, viewportWidth - (2 * viewportPadding));\n const desiredPopupHeight = Math.min(\n Math.max(popupRect.height, popup.scrollHeight),\n maximumPopupHeight,\n );\n const desiredPopupWidth = Math.min(\n Math.max(popupRect.width, popup.scrollWidth, matchAnchorWidth ? anchorRect.width : 0),\n maximumPopupWidth,\n );\n const direction = getComputedStyle(anchor).direction;\n const directModalOwner = anchor.closest<HTMLElement>(\"[data-hjm-modal-content]\");\n const inheritedOwnerId = anchor\n .closest<HTMLElement>(\"[data-hjm-popup-owner]\")\n ?.getAttribute(\"data-hjm-popup-owner\") ?? null;\n const modalOwner = directModalOwner ??\n (inheritedOwnerId === null ? null : document.getElementById(inheritedOwnerId));\n const modalLayerValue = modalOwner\n ?.closest<HTMLElement>(\".hjm-overlay\")\n ?.style.zIndex ?? \"\";\n const modalLayer = Number.parseInt(modalLayerValue, 10);\n const resolvedZIndex = Number.isFinite(modalLayer) ? modalLayer + 1 : zIndex;\n const logicalStartAtLeft = direction !== \"rtl\";\n const preferredPhysicalPlacement = preferredPlacement === \"start\"\n ? (logicalStartAtLeft ? \"left\" : \"right\")\n : preferredPlacement === \"end\"\n ? (logicalStartAtLeft ? \"right\" : \"left\")\n : preferredPlacement;\n let physicalPlacement: \"bottom\" | \"top\" | \"left\" | \"right\" =\n preferredPhysicalPlacement;\n if (\n physicalPlacement === \"bottom\" &&\n desiredPopupHeight > availableBottom &&\n availableTop > availableBottom\n ) physicalPlacement = \"top\";\n else if (\n physicalPlacement === \"top\" &&\n desiredPopupHeight > availableTop &&\n availableBottom > availableTop\n ) physicalPlacement = \"bottom\";\n else if (\n physicalPlacement === \"left\" &&\n desiredPopupWidth > availableLeft &&\n availableRight > availableLeft\n ) physicalPlacement = \"right\";\n else if (\n physicalPlacement === \"right\" &&\n desiredPopupWidth > availableRight &&\n availableLeft > availableRight\n ) physicalPlacement = \"left\";\n const placement: AnchoredPopupPlacement = physicalPlacement === \"left\"\n ? (logicalStartAtLeft ? \"start\" : \"end\")\n : physicalPlacement === \"right\"\n ? (logicalStartAtLeft ? \"end\" : \"start\")\n : physicalPlacement;\n const availableHeight = physicalPlacement === \"bottom\"\n ? availableBottom\n : physicalPlacement === \"top\"\n ? availableTop\n : maximumPopupHeight;\n const availableWidth = physicalPlacement === \"left\"\n ? availableLeft\n : physicalPlacement === \"right\"\n ? availableRight\n : maximumPopupWidth;\n const popupHeight = Math.min(desiredPopupHeight, Math.max(0, availableHeight));\n const popupWidth = Math.min(desiredPopupWidth, Math.max(0, availableWidth));\n const alignLeftEdge = align === \"start\" ? logicalStartAtLeft : !logicalStartAtLeft;\n const inlineAlignedLeft = align === \"center\"\n ? anchorRect.left + ((anchorRect.width - popupWidth) / 2)\n : alignLeftEdge\n ? anchorRect.left\n : anchorRect.right - popupWidth;\n const blockAlignedTop = align === \"center\"\n ? anchorRect.top + ((anchorRect.height - popupHeight) / 2)\n : align === \"start\"\n ? anchorRect.top\n : anchorRect.bottom - popupHeight;\n const desiredLeft = physicalPlacement === \"left\"\n ? anchorRect.left - gap - popupWidth\n : physicalPlacement === \"right\"\n ? anchorRect.right + gap\n : inlineAlignedLeft;\n const maximumLeft = Math.max(\n viewportLeft + viewportPadding,\n viewportRight - viewportPadding - popupWidth,\n );\n const left = Math.min(\n Math.max(desiredLeft, viewportLeft + viewportPadding),\n maximumLeft,\n );\n const desiredTop = physicalPlacement === \"bottom\"\n ? anchorRect.bottom + gap\n : physicalPlacement === \"top\"\n ? anchorRect.top - gap - popupHeight\n : blockAlignedTop;\n const maximumTop = Math.max(\n viewportTop + viewportPadding,\n viewportBottom - viewportPadding - popupHeight,\n );\n const top = Math.min(\n Math.max(desiredTop, viewportTop + viewportPadding),\n maximumTop,\n );\n const next: AnchoredPopupPosition = {\n align,\n placement,\n style: {\n position: \"fixed\",\n inset: \"auto\",\n left: Math.round(left),\n top: Math.round(top),\n minWidth: matchAnchorWidth\n ? Math.round(Math.min(anchorRect.width, availableWidth, maximumPopupWidth))\n : undefined,\n maxWidth: Math.max(0, availableWidth),\n maxHeight: Math.max(0, availableHeight),\n visibility: \"visible\",\n zIndex: resolvedZIndex,\n },\n };\n setPosition((previous) => samePosition(previous, next) ? previous : next);\n }, [\n align,\n anchorRef,\n gap,\n matchAnchorWidth,\n popup,\n preferredPlacement,\n viewportPadding,\n zIndex,\n ]);\n\n useEffect(() => {\n if (!popup) {\n setPosition({ ...hiddenPopupPosition, align });\n return;\n }\n update();\n const frame = requestAnimationFrame(update);\n const handleViewportChange = () => update();\n window.addEventListener(\"resize\", handleViewportChange);\n window.addEventListener(\"scroll\", handleViewportChange, true);\n window.visualViewport?.addEventListener(\"resize\", handleViewportChange);\n window.visualViewport?.addEventListener(\"scroll\", handleViewportChange);\n const resizeObserver = typeof ResizeObserver === \"undefined\"\n ? null\n : new ResizeObserver(update);\n if (anchorRef.current) resizeObserver?.observe(anchorRef.current);\n resizeObserver?.observe(popup);\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener(\"resize\", handleViewportChange);\n window.removeEventListener(\"scroll\", handleViewportChange, true);\n window.visualViewport?.removeEventListener(\"resize\", handleViewportChange);\n window.visualViewport?.removeEventListener(\"scroll\", handleViewportChange);\n resizeObserver?.disconnect();\n };\n }, [align, anchorRef, popup, update]);\n\n return position;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../src/portal.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport type PortalProps = Readonly<{\n anchorRef: RefObject<HTMLElement | null>;\n children: ReactNode;\n container?: HTMLElement;\n /** Anchored non-modal popups may render inline until hydration moves them. */\n ssrFallback?: \"none\" | \"inline\";\n}>;\n\n/** Nearest interactive popover, including descendants rendered through another portal. */\nexport function getPopoverOwner(node: Node | null): HTMLElement | null {\n const element = node instanceof Element ? node : node?.parentElement;\n const direct = element?.closest<HTMLElement>(\"[data-hjm-popover-content]\");\n if (direct) return direct;\n const ownerId = element?.closest<HTMLElement>(\"[data-hjm-popover-owner]\")?.getAttribute(\"data-hjm-popover-owner\");\n return ownerId ? document.getElementById(ownerId) : null;\n}\n\n/**\n * Copies the closest provider DOM boundary instead of importing provider\n * runtime code, keeping granular form/overlay entry points lightweight.\n */\nfunction synchronizePortalEnvironment(host: HTMLDivElement, anchor: HTMLElement | null): void {\n // Modal ownership and non-modal ownership are separate: nested selects/menus\n // must belong to both, so outside focus does not close their parent popover.\n const popoverOwner = getPopoverOwner(anchor);\n if (popoverOwner?.id) host.setAttribute(\"data-hjm-popover-owner\", popoverOwner.id);\n else host.removeAttribute(\"data-hjm-popover-owner\");\n const source = anchor?.closest<HTMLElement>(\"[data-hjm-provider], [data-hjm-portal]\") ?? null;\n const directModalOwner = anchor?.closest<HTMLElement>(\"[data-hjm-modal-content]\") ?? null;\n const inheritedOwnerId = anchor\n ?.closest<HTMLElement>(\"[data-hjm-popup-owner]\")\n ?.getAttribute(\"data-hjm-popup-owner\") ?? null;\n const modalOwner = directModalOwner ??\n (inheritedOwnerId === null ? null : document.getElementById(inheritedOwnerId));\n if (modalOwner?.id) host.setAttribute(\"data-hjm-popup-owner\", modalOwner.id);\n else host.removeAttribute(\"data-hjm-popup-owner\");\n if (source) {\n host.removeAttribute(\"style\");\n for (let index = 0; index < source.style.length; index += 1) {\n const property = source.style.item(index);\n if (\n property.startsWith(\"--hjm-\") ||\n property === \"background-color\" ||\n property === \"color\" ||\n property === \"color-scheme\" ||\n property === \"font-family\" ||\n property === \"font-size\" ||\n property === \"line-height\"\n ) {\n host.style.setProperty(\n property,\n source.style.getPropertyValue(property),\n source.style.getPropertyPriority(property),\n );\n }\n }\n for (const attribute of [\"data-motion\", \"data-theme\", \"data-text-scale\", \"data-large-text\"] as const) {\n const value = source.getAttribute(attribute);\n if (value === null) host.removeAttribute(attribute);\n else host.setAttribute(attribute, value);\n }\n host.dir = source.dir;\n return;\n }\n host.removeAttribute(\"style\");\n host.removeAttribute(\"data-motion\");\n host.removeAttribute(\"data-theme\");\n host.removeAttribute(\"data-text-scale\");\n host.removeAttribute(\"data-large-text\");\n host.dir = anchor?.closest<HTMLElement>(\"[dir]\")?.dir ?? \"\";\n}\n\nexport function AnchoredPortal({\n anchorRef,\n children,\n container,\n ssrFallback = \"none\",\n}: PortalProps) {\n const [mounted, setMounted] = useState(false);\n const hostRef = useRef<HTMLDivElement | null>(null);\n const setHostRef = useCallback((host: HTMLDivElement | null) => {\n hostRef.current = host;\n if (host) synchronizePortalEnvironment(host, anchorRef.current);\n }, [anchorRef]);\n useEffect(() => setMounted(true), []);\n useEffect(() => {\n const host = hostRef.current;\n const source = anchorRef.current?.closest<HTMLElement>(\n \"[data-hjm-provider], [data-hjm-portal]\",\n ) ?? null;\n if (!host || !source || typeof MutationObserver === \"undefined\") return;\n const observer = new MutationObserver(() => {\n synchronizePortalEnvironment(host, anchorRef.current);\n });\n observer.observe(source, {\n attributes: true,\n attributeFilter: [\"data-motion\", \"data-theme\", \"data-text-scale\", \"data-large-text\", \"dir\", \"style\"],\n });\n return () => observer.disconnect();\n }, [anchorRef, mounted]);\n if (!mounted) return ssrFallback === \"inline\" ? children : null;\n return createPortal(\n <div ref={setHostRef} className=\"hjm-root hjm-portal\" data-hjm-portal=\"\">\n {children}\n </div>,\n container ?? document.body,\n );\n}\n\nexport type AnchoredPopupAlign = \"start\" | \"center\" | \"end\";\nexport type AnchoredPopupPlacement = \"bottom\" | \"top\" | \"start\" | \"end\";\n\ntype AnchoredPopupPosition = Readonly<{\n align: AnchoredPopupAlign;\n placement: AnchoredPopupPlacement;\n style: CSSProperties;\n}>;\n\ntype AnchoredPopupOptions = Readonly<{\n align?: AnchoredPopupAlign;\n gap?: number;\n matchAnchorWidth?: boolean;\n placement?: AnchoredPopupPlacement;\n viewportPadding?: number;\n zIndex?: number;\n /** Wide contextual content may switch to the block axis in a narrow viewport. */\n fallbackAxis?: boolean;\n}>;\n\nconst hiddenPopupPosition: AnchoredPopupPosition = {\n align: \"start\",\n placement: \"bottom\",\n style: {\n position: \"fixed\",\n inset: \"auto\",\n left: 0,\n top: 0,\n visibility: \"hidden\",\n },\n};\n\nfunction samePosition(\n previous: AnchoredPopupPosition,\n next: AnchoredPopupPosition,\n): boolean {\n return previous.align === next.align &&\n previous.placement === next.placement &&\n previous.style.left === next.style.left &&\n previous.style.top === next.style.top &&\n previous.style.minWidth === next.style.minWidth &&\n previous.style.maxWidth === next.style.maxWidth &&\n previous.style.maxHeight === next.style.maxHeight &&\n previous.style.zIndex === next.style.zIndex &&\n previous.style.visibility === next.style.visibility;\n}\n\n/**\n * Positions a fixed portal popup against its anchor using logical alignment.\n * The popup flips vertically and shifts horizontally to stay inside the visual\n * viewport, then follows every scroll/resize source that can move either node.\n */\nexport function useAnchoredPopup(\n anchorRef: RefObject<HTMLElement | null>,\n popup: HTMLElement | null,\n {\n align = \"start\",\n fallbackAxis = false,\n gap = 8,\n matchAnchorWidth = false,\n placement: preferredPlacement = \"bottom\",\n viewportPadding = 16,\n zIndex = 800,\n }: AnchoredPopupOptions = {},\n): AnchoredPopupPosition {\n const [position, setPosition] = useState<AnchoredPopupPosition>(() => ({\n ...hiddenPopupPosition,\n align,\n }));\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor || !popup || !anchor.isConnected || !popup.isConnected) return;\n\n const anchorRect = anchor.getBoundingClientRect();\n const popupRect = popup.getBoundingClientRect();\n const visualViewport = window.visualViewport;\n const viewportLeft = visualViewport?.offsetLeft ?? 0;\n const viewportTop = visualViewport?.offsetTop ?? 0;\n const viewportWidth = visualViewport?.width ?? window.innerWidth;\n const viewportHeight = visualViewport?.height ?? window.innerHeight;\n const viewportRight = viewportLeft + viewportWidth;\n const viewportBottom = viewportTop + viewportHeight;\n const availableBottom = Math.max(0, viewportBottom - viewportPadding - anchorRect.bottom - gap);\n const availableTop = Math.max(0, anchorRect.top - viewportTop - viewportPadding - gap);\n const availableLeft = Math.max(0, anchorRect.left - viewportLeft - viewportPadding - gap);\n const availableRight = Math.max(0, viewportRight - viewportPadding - anchorRect.right - gap);\n const maximumPopupHeight = Math.max(0, viewportHeight - (2 * viewportPadding));\n const maximumPopupWidth = Math.max(0, viewportWidth - (2 * viewportPadding));\n const desiredPopupHeight = Math.min(\n Math.max(popupRect.height, popup.scrollHeight),\n maximumPopupHeight,\n );\n const desiredPopupWidth = Math.min(\n Math.max(popupRect.width, popup.scrollWidth, matchAnchorWidth ? anchorRect.width : 0),\n maximumPopupWidth,\n );\n const direction = getComputedStyle(anchor).direction;\n const directModalOwner = anchor.closest<HTMLElement>(\"[data-hjm-modal-content]\");\n const inheritedOwnerId = anchor\n .closest<HTMLElement>(\"[data-hjm-popup-owner]\")\n ?.getAttribute(\"data-hjm-popup-owner\") ?? null;\n const modalOwner = directModalOwner ??\n (inheritedOwnerId === null ? null : document.getElementById(inheritedOwnerId));\n const modalLayerValue = modalOwner\n ?.closest<HTMLElement>(\".hjm-overlay\")\n ?.style.zIndex ?? \"\";\n const modalLayer = Number.parseInt(modalLayerValue, 10);\n const resolvedZIndex = Number.isFinite(modalLayer) ? modalLayer + 1 : zIndex;\n const logicalStartAtLeft = direction !== \"rtl\";\n const preferredPhysicalPlacement = preferredPlacement === \"start\"\n ? (logicalStartAtLeft ? \"left\" : \"right\")\n : preferredPlacement === \"end\"\n ? (logicalStartAtLeft ? \"right\" : \"left\")\n : preferredPlacement;\n let physicalPlacement: \"bottom\" | \"top\" | \"left\" | \"right\" =\n preferredPhysicalPlacement;\n if (\n physicalPlacement === \"bottom\" &&\n desiredPopupHeight > availableBottom &&\n availableTop > availableBottom\n ) physicalPlacement = \"top\";\n else if (\n physicalPlacement === \"top\" &&\n desiredPopupHeight > availableTop &&\n availableBottom > availableTop\n ) physicalPlacement = \"bottom\";\n else if (\n physicalPlacement === \"left\" &&\n desiredPopupWidth > availableLeft &&\n availableRight > availableLeft\n ) physicalPlacement = \"right\";\n else if (\n physicalPlacement === \"right\" &&\n desiredPopupWidth > availableRight &&\n availableLeft > availableRight\n ) physicalPlacement = \"left\";\n // A wide form cannot fit beside a centered mobile trigger. Preserve readable\n // content by trying the block axis; existing compact popup defaults stay unchanged.\n if (fallbackAxis && (physicalPlacement === \"left\" || physicalPlacement === \"right\") &&\n Math.max(availableLeft, availableRight) < desiredPopupWidth) {\n physicalPlacement = availableBottom >= availableTop ? \"bottom\" : \"top\";\n }\n const placement: AnchoredPopupPlacement = physicalPlacement === \"left\"\n ? (logicalStartAtLeft ? \"start\" : \"end\")\n : physicalPlacement === \"right\"\n ? (logicalStartAtLeft ? \"end\" : \"start\")\n : physicalPlacement;\n const availableHeight = physicalPlacement === \"bottom\"\n ? availableBottom\n : physicalPlacement === \"top\"\n ? availableTop\n : maximumPopupHeight;\n const availableWidth = physicalPlacement === \"left\"\n ? availableLeft\n : physicalPlacement === \"right\"\n ? availableRight\n : maximumPopupWidth;\n const popupHeight = Math.min(desiredPopupHeight, Math.max(0, availableHeight));\n const popupWidth = Math.min(desiredPopupWidth, Math.max(0, availableWidth));\n const alignLeftEdge = align === \"start\" ? logicalStartAtLeft : !logicalStartAtLeft;\n const inlineAlignedLeft = align === \"center\"\n ? anchorRect.left + ((anchorRect.width - popupWidth) / 2)\n : alignLeftEdge\n ? anchorRect.left\n : anchorRect.right - popupWidth;\n const blockAlignedTop = align === \"center\"\n ? anchorRect.top + ((anchorRect.height - popupHeight) / 2)\n : align === \"start\"\n ? anchorRect.top\n : anchorRect.bottom - popupHeight;\n const desiredLeft = physicalPlacement === \"left\"\n ? anchorRect.left - gap - popupWidth\n : physicalPlacement === \"right\"\n ? anchorRect.right + gap\n : inlineAlignedLeft;\n const maximumLeft = Math.max(\n viewportLeft + viewportPadding,\n viewportRight - viewportPadding - popupWidth,\n );\n const left = Math.min(\n Math.max(desiredLeft, viewportLeft + viewportPadding),\n maximumLeft,\n );\n const desiredTop = physicalPlacement === \"bottom\"\n ? anchorRect.bottom + gap\n : physicalPlacement === \"top\"\n ? anchorRect.top - gap - popupHeight\n : blockAlignedTop;\n const maximumTop = Math.max(\n viewportTop + viewportPadding,\n viewportBottom - viewportPadding - popupHeight,\n );\n const top = Math.min(\n Math.max(desiredTop, viewportTop + viewportPadding),\n maximumTop,\n );\n const next: AnchoredPopupPosition = {\n align,\n placement,\n style: {\n position: \"fixed\",\n inset: \"auto\",\n left: Math.round(left),\n top: Math.round(top),\n minWidth: matchAnchorWidth\n ? Math.round(Math.min(anchorRect.width, availableWidth, maximumPopupWidth))\n : undefined,\n maxWidth: Math.max(0, availableWidth),\n maxHeight: Math.max(0, availableHeight),\n visibility: \"visible\",\n zIndex: resolvedZIndex,\n },\n };\n setPosition((previous) => samePosition(previous, next) ? previous : next);\n }, [\n align,\n anchorRef,\n fallbackAxis,\n gap,\n matchAnchorWidth,\n popup,\n preferredPlacement,\n viewportPadding,\n zIndex,\n ]);\n\n useEffect(() => {\n if (!popup) {\n setPosition({ ...hiddenPopupPosition, align });\n return;\n }\n update();\n const frame = requestAnimationFrame(update);\n const handleViewportChange = () => update();\n window.addEventListener(\"resize\", handleViewportChange);\n window.addEventListener(\"scroll\", handleViewportChange, true);\n window.visualViewport?.addEventListener(\"resize\", handleViewportChange);\n window.visualViewport?.addEventListener(\"scroll\", handleViewportChange);\n const resizeObserver = typeof ResizeObserver === \"undefined\"\n ? null\n : new ResizeObserver(update);\n if (anchorRef.current) resizeObserver?.observe(anchorRef.current);\n resizeObserver?.observe(popup);\n return () => {\n cancelAnimationFrame(frame);\n window.removeEventListener(\"resize\", handleViewportChange);\n window.removeEventListener(\"scroll\", handleViewportChange, true);\n window.visualViewport?.removeEventListener(\"resize\", handleViewportChange);\n window.visualViewport?.removeEventListener(\"scroll\", handleViewportChange);\n resizeObserver?.disconnect();\n };\n }, [align, anchorRef, popup, update]);\n\n return position;\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type AuthProviderButtonDescriptor } from "@hjmds/design-contracts/components/provider-button";
|
|
2
|
+
import { type ButtonHTMLAttributes, type ReactNode } from "react";
|
|
3
|
+
export type AuthProviderButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "disabled" | "style"> & Readonly<{
|
|
4
|
+
descriptor: AuthProviderButtonDescriptor;
|
|
5
|
+
/**
|
|
6
|
+
* The provider's own mark, supplied by the product: brand assets have
|
|
7
|
+
* per-provider redistribution terms, so the design system never bundles them.
|
|
8
|
+
*/
|
|
9
|
+
logo: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const AuthProviderButton: import("react").ForwardRefExoticComponent<Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "style" | "disabled"> & Readonly<{
|
|
13
|
+
descriptor: AuthProviderButtonDescriptor;
|
|
14
|
+
/**
|
|
15
|
+
* The provider's own mark, supplied by the product: brand assets have
|
|
16
|
+
* per-provider redistribution terms, so the design system never bundles them.
|
|
17
|
+
*/
|
|
18
|
+
logo: ReactNode;
|
|
19
|
+
className?: string;
|
|
20
|
+
}> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
21
|
+
//# sourceMappingURL=provider-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-button.d.ts","sourceRoot":"","sources":["../src/provider-button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,4BAA4B,EAClC,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EAEL,KAAK,oBAAoB,EAEzB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,UAAU,GAAG,UAAU,GAAG,OAAO,CAClC,GACC,QAAQ,CAAC;IACP,UAAU,EAAE,4BAA4B,CAAC;IACzC;;;OAGG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEL,eAAO,MAAM,kBAAkB;gBATf,4BAA4B;IACxC;;;OAGG;UACG,SAAS;gBACH,MAAM;sDA4CrB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { authProviderButtonRecipe, resolveAuthProviderSurface, validateAuthProviderButtonDescriptor, } from "@hjmds/design-contracts/components/provider-button";
|
|
3
|
+
import { forwardRef, } from "react";
|
|
4
|
+
import { classNames } from "./internal.js";
|
|
5
|
+
import { useOptionalHjmTheme } from "./provider.js";
|
|
6
|
+
export const AuthProviderButton = forwardRef(function AuthProviderButton({ descriptor, logo, className, ...props }, forwardedRef) {
|
|
7
|
+
validateAuthProviderButtonDescriptor(descriptor);
|
|
8
|
+
const theme = useOptionalHjmTheme();
|
|
9
|
+
// The theme only picks between the provider's own variants; it never mixes
|
|
10
|
+
// HJM palette values into a brand fill.
|
|
11
|
+
const surface = resolveAuthProviderSurface(descriptor.provider, theme?.environment.theme === "dark" ? "dark" : "light");
|
|
12
|
+
const busy = descriptor.busy === true;
|
|
13
|
+
return (_jsxs("button", { ...props, ref: forwardedRef, type: props.type ?? "button", "data-provider": descriptor.provider, "data-busy": busy || undefined, "aria-busy": busy || undefined, disabled: descriptor.disabled === true || busy, className: classNames("hjm-auth-provider-button", className), style: {
|
|
14
|
+
"--hjm-provider-background": surface.background,
|
|
15
|
+
"--hjm-provider-content": surface.content,
|
|
16
|
+
"--hjm-provider-border": surface.border ?? "transparent",
|
|
17
|
+
"--hjm-provider-border-width": `${surface.border === null ? 0 : authProviderButtonRecipe.borderWidth}px`,
|
|
18
|
+
"--hjm-provider-min-height": `${authProviderButtonRecipe.minHeight}px`,
|
|
19
|
+
"--hjm-provider-radius": `${authProviderButtonRecipe.radius}px`,
|
|
20
|
+
"--hjm-provider-gap": `${authProviderButtonRecipe.gap}px`,
|
|
21
|
+
"--hjm-provider-padding": `${authProviderButtonRecipe.paddingHorizontal}px`,
|
|
22
|
+
"--hjm-provider-logo-size": `${authProviderButtonRecipe.logoSize}px`,
|
|
23
|
+
"--hjm-provider-focus-offset": `${authProviderButtonRecipe.focusOutlineOffset}px`,
|
|
24
|
+
}, children: [_jsx("span", { "aria-hidden": "true", className: "hjm-auth-provider-button__logo", children: logo }), _jsx("span", { className: "hjm-auth-provider-button__label", children: descriptor.label }), busy ? _jsx("span", { "aria-hidden": "true", className: "hjm-auth-provider-button__spinner" }) : null] }));
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=provider-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-button.js","sourceRoot":"","sources":["../src/provider-button.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,oCAAoC,GAErC,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EACL,UAAU,GAIX,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAgBpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAC1C,SAAS,kBAAkB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY;IACjF,oCAAoC,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,2EAA2E;IAC3E,wCAAwC;IACxC,MAAM,OAAO,GAAG,0BAA0B,CACxC,UAAU,CAAC,QAAQ,EACnB,KAAK,EAAE,WAAW,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CACvD,CAAC;IACF,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;IACtC,OAAO,CACL,qBACM,KAAK,EACT,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ,mBACb,UAAU,CAAC,QAAQ,eACvB,IAAI,IAAI,SAAS,eACjB,IAAI,IAAI,SAAS,EAC5B,QAAQ,EAAE,UAAU,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,EAC9C,SAAS,EAAE,UAAU,CAAC,0BAA0B,EAAE,SAAS,CAAC,EAC5D,KAAK,EAAE;YACL,2BAA2B,EAAE,OAAO,CAAC,UAAU;YAC/C,wBAAwB,EAAE,OAAO,CAAC,OAAO;YACzC,uBAAuB,EAAE,OAAO,CAAC,MAAM,IAAI,aAAa;YACxD,6BAA6B,EAAE,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,WAAW,IAAI;YACxG,2BAA2B,EAAE,GAAG,wBAAwB,CAAC,SAAS,IAAI;YACtE,uBAAuB,EAAE,GAAG,wBAAwB,CAAC,MAAM,IAAI;YAC/D,oBAAoB,EAAE,GAAG,wBAAwB,CAAC,GAAG,IAAI;YACzD,wBAAwB,EAAE,GAAG,wBAAwB,CAAC,iBAAiB,IAAI;YAC3E,0BAA0B,EAAE,GAAG,wBAAwB,CAAC,QAAQ,IAAI;YACpE,6BAA6B,EAAE,GAAG,wBAAwB,CAAC,kBAAkB,IAAI;SACjE,aAElB,8BAAkB,MAAM,EAAC,SAAS,EAAC,gCAAgC,YAAE,IAAI,GAAQ,EAEjF,eAAM,SAAS,EAAC,iCAAiC,YAAE,UAAU,CAAC,KAAK,GAAQ,EAC1E,IAAI,CAAC,CAAC,CAAC,8BAAkB,MAAM,EAAC,SAAS,EAAC,mCAAmC,GAAG,CAAC,CAAC,CAAC,IAAI,IACjF,CACV,CAAC;AACJ,CAAC,CACF,CAAC","sourcesContent":["import {\n authProviderButtonRecipe,\n resolveAuthProviderSurface,\n validateAuthProviderButtonDescriptor,\n type AuthProviderButtonDescriptor,\n} from \"@hjmds/design-contracts/components/provider-button\";\nimport {\n forwardRef,\n type ButtonHTMLAttributes,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nexport type AuthProviderButtonProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\" | \"disabled\" | \"style\"\n> &\n Readonly<{\n descriptor: AuthProviderButtonDescriptor;\n /**\n * The provider's own mark, supplied by the product: brand assets have\n * per-provider redistribution terms, so the design system never bundles them.\n */\n logo: ReactNode;\n className?: string;\n }>;\n\nexport const AuthProviderButton = forwardRef<HTMLButtonElement, AuthProviderButtonProps>(\n function AuthProviderButton({ descriptor, logo, className, ...props }, forwardedRef) {\n validateAuthProviderButtonDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n // The theme only picks between the provider's own variants; it never mixes\n // HJM palette values into a brand fill.\n const surface = resolveAuthProviderSurface(\n descriptor.provider,\n theme?.environment.theme === \"dark\" ? \"dark\" : \"light\",\n );\n const busy = descriptor.busy === true;\n return (\n <button\n {...props}\n ref={forwardedRef}\n type={props.type ?? \"button\"}\n data-provider={descriptor.provider}\n data-busy={busy || undefined}\n aria-busy={busy || undefined}\n disabled={descriptor.disabled === true || busy}\n className={classNames(\"hjm-auth-provider-button\", className)}\n style={{\n \"--hjm-provider-background\": surface.background,\n \"--hjm-provider-content\": surface.content,\n \"--hjm-provider-border\": surface.border ?? \"transparent\",\n \"--hjm-provider-border-width\": `${surface.border === null ? 0 : authProviderButtonRecipe.borderWidth}px`,\n \"--hjm-provider-min-height\": `${authProviderButtonRecipe.minHeight}px`,\n \"--hjm-provider-radius\": `${authProviderButtonRecipe.radius}px`,\n \"--hjm-provider-gap\": `${authProviderButtonRecipe.gap}px`,\n \"--hjm-provider-padding\": `${authProviderButtonRecipe.paddingHorizontal}px`,\n \"--hjm-provider-logo-size\": `${authProviderButtonRecipe.logoSize}px`,\n \"--hjm-provider-focus-offset\": `${authProviderButtonRecipe.focusOutlineOffset}px`,\n } as CSSProperties}\n >\n <span aria-hidden=\"true\" className=\"hjm-auth-provider-button__logo\">{logo}</span>\n {/* Busy keeps the label and the width; only the spinner is added. */}\n <span className=\"hjm-auth-provider-button__label\">{descriptor.label}</span>\n {busy ? <span aria-hidden=\"true\" className=\"hjm-auth-provider-button__spinner\" /> : null}\n </button>\n );\n },\n);\n"]}
|