@botiverse/raft-ui 0.83.0 → 0.85.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/CHANGELOG.md +125 -0
- package/dist/cn.d.mts +2 -0
- package/dist/cn.mjs +21 -1
- package/dist/components/alert-dialog/alert-dialog.mjs +2 -2
- package/dist/components/app-link-card/app-link-card.mjs +19 -37
- package/dist/components/app-shell/app-shell.mjs +2 -2
- package/dist/components/avatar/avatar.mjs +1 -1
- package/dist/components/banner/banner.mjs +15 -2
- package/dist/components/button/button-split.mjs +2 -2
- package/dist/components/button/button.mjs +2 -2
- package/dist/components/choice-list/choice-list.recipe.mjs +1 -1
- package/dist/components/code-block/code-block.recipe.mjs +2 -2
- package/dist/components/combobox/combobox.mjs +1 -1
- package/dist/components/combobox-select/combobox-select.css +1 -1
- package/dist/components/comment/comment.recipe.mjs +2 -2
- package/dist/components/composer/composer-attachment.recipe.mjs +5 -5
- package/dist/components/composer/composer-drop-overlay.mjs +2 -2
- package/dist/components/composer/composer-drop-overlay.recipe.mjs +1 -1
- package/dist/components/composer/sortable-composer-attachments.mjs +1 -1
- package/dist/components/context-menu/context-menu.mjs +1 -1
- package/dist/components/conversation-panel/conversation-panel-empty-state.mjs +1 -1
- package/dist/components/dialog/dialog.mjs +4 -4
- package/dist/components/drag/drag-lift.d.mts +3 -2
- package/dist/components/drag/drag-lift.mjs +3 -2
- package/dist/components/drag/drag.recipe.mjs +1 -1
- package/dist/components/drawer/drawer.recipe.mjs +4 -4
- package/dist/components/dropdown-menu/dropdown-menu.mjs +1 -1
- package/dist/components/file-preview/file-preview.recipe.mjs +1 -1
- package/dist/components/fit-toolbar/fit-toolbar.d.mts +63 -8
- package/dist/components/fit-toolbar/fit-toolbar.mjs +310 -43
- package/dist/components/fit-toolbar/fit-toolbar.recipe.mjs +21 -7
- package/dist/components/fit-toolbar/index.d.mts +2 -2
- package/dist/components/inbox-item/inbox-item.recipe.mjs +7 -7
- package/dist/components/lightbox/index.d.mts +2 -2
- package/dist/components/lightbox/lightbox.d.mts +70 -4
- package/dist/components/lightbox/lightbox.mjs +285 -91
- package/dist/components/list-row/list-row.d.mts +14 -1
- package/dist/components/list-row/list-row.mjs +4 -2
- package/dist/components/list-row/list-row.recipe.d.mts +12 -0
- package/dist/components/list-row/list-row.recipe.mjs +19 -7
- package/dist/components/message-action-card/message-action-card-content.recipe.mjs +3 -3
- package/dist/components/message-action-card/message-action-card.mjs +7 -3
- package/dist/components/message-action-card/message-action-card.recipe.mjs +2 -6
- package/dist/components/message-attachment/message-image-gallery.recipe.mjs +1 -1
- package/dist/components/message-embed/index.d.mts +2 -1
- package/dist/components/message-embed/message-embed.d.mts +8 -1
- package/dist/components/message-embed/message-embed.mjs +2 -2
- package/dist/components/message-embed/message-embed.recipe.d.mts +160 -0
- package/dist/components/message-embed/message-embed.recipe.mjs +49 -10
- package/dist/components/message-forwarded-bundle/message-forwarded-bundle.mjs +1 -0
- package/dist/components/message-forwarded-bundle/message-forwarded-bundle.recipe.mjs +1 -1
- package/dist/components/message-item/message-item.recipe.mjs +2 -2
- package/dist/components/message-list/message-list.recipe.mjs +2 -2
- package/dist/components/message-quoted-preview/message-quoted-preview.mjs +2 -0
- package/dist/components/message-replies/message-replies.mjs +1 -1
- package/dist/components/message-replies/message-replies.recipe.mjs +1 -1
- package/dist/components/mobile-nav/mobile-nav.mjs +2 -2
- package/dist/components/notification-center/notification-center.mjs +1 -1
- package/dist/components/panel/panel-header.recipe.mjs +1 -1
- package/dist/components/panel/panel-split-action.recipe.mjs +2 -2
- package/dist/components/popover/popover.d.mts +11 -2
- package/dist/components/popover/popover.mjs +51 -38
- package/dist/components/preview-card/preview-card.d.mts +5 -1
- package/dist/components/preview-card/preview-card.mjs +25 -28
- package/dist/components/pull-to-refresh/pull-to-refresh-indicator.mjs +1 -1
- package/dist/components/resizable/resizable.recipe.mjs +1 -1
- package/dist/components/save-status/save-status.d.mts +16 -9
- package/dist/components/save-status/save-status.mjs +19 -30
- package/dist/components/scroll-area/scroll-area.css +1 -0
- package/dist/components/segmented-control/segmented-control.mjs +45 -8
- package/dist/components/select/select.mjs +2 -2
- package/dist/components/selection-toolbar/selection-toolbar.recipe.mjs +1 -1
- package/dist/components/sidebar/sidebar.recipe.mjs +1 -1
- package/dist/components/tabs/tabs.mjs +4 -4
- package/dist/components/task-board/task-board.d.mts +5 -0
- package/dist/components/task-board/task-board.mjs +8 -1
- package/dist/components/task-dnd/task-dnd.d.mts +10 -1
- package/dist/components/task-dnd/task-dnd.mjs +2 -1
- package/dist/components/task-dnd/task-dnd.recipe.mjs +2 -2
- package/dist/components/thread-panel/thread-panel.recipe.mjs +1 -1
- package/dist/components/toast/toast.mjs +5 -5
- package/dist/components/tooltip/tooltip.mjs +2 -2
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/dist/lib/laid-out-children.mjs +32 -0
- package/dist/lib/list-cell.mjs +1 -1
- package/dist/lib/stacked-actions.mjs +7 -4
- package/dist/lint/no-raw-z-index.mjs +142 -0
- package/dist/lint/prefer-scroll-area.mjs +1 -1
- package/dist/lint/recommended.json +2 -1
- package/dist/lint.d.mts +8 -2
- package/dist/lint.mjs +16 -3
- package/dist/styles.css +28 -0
- package/dist/wip.d.mts +4 -2
- package/dist/wip.mjs +3 -2
- package/package.json +1 -1
- package/skills/raft-ui-guide/SKILL.md +1 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { laidOutChildren } from "../../lib/laid-out-children.mjs";
|
|
1
2
|
import { Button } from "../button/button.mjs";
|
|
2
3
|
import { useMergedRef } from "../../lib/use-merged-ref.mjs";
|
|
3
4
|
import { ScrollArea } from "../scroll-area/scroll-area.mjs";
|
|
4
5
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip/tooltip.mjs";
|
|
6
|
+
import { PickerTriggerButton } from "../picker-trigger-button/picker-trigger-button.mjs";
|
|
5
7
|
import { fitToolbar } from "./fit-toolbar.recipe.mjs";
|
|
6
|
-
import {
|
|
8
|
+
import { ChevronDown, Plus } from "lucide-react";
|
|
9
|
+
import { Fragment, cloneElement, createContext, useCallback, useContext, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
7
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
11
|
import { Toolbar } from "@base-ui/react/toolbar";
|
|
9
12
|
//#region src/components/fit-toolbar/fit-toolbar.tsx
|
|
@@ -16,7 +19,8 @@ const STEPS = [
|
|
|
16
19
|
"label",
|
|
17
20
|
"more",
|
|
18
21
|
"collapse",
|
|
19
|
-
"wrap"
|
|
22
|
+
"wrap",
|
|
23
|
+
"plus"
|
|
20
24
|
];
|
|
21
25
|
const ID = "data-fit-id";
|
|
22
26
|
const DECLARED = "data-fit-steps";
|
|
@@ -27,39 +31,46 @@ const ROW = "data-fit-row";
|
|
|
27
31
|
const NO_WRAP = "data-fit-first-line";
|
|
28
32
|
const WRAP_LINE = "data-fit-wrap-line";
|
|
29
33
|
const BREAK = "data-fit-break";
|
|
34
|
+
const NEEDS_ICON = "data-fit-needs-icon";
|
|
30
35
|
const stepAttribute = (step) => `data-fit-${step}`;
|
|
36
|
+
const hasIcon = (item) => item.querySelector("svg, img") !== null;
|
|
37
|
+
/** The group has a `wrap` step it may take: the toolbar wraps and the page lets it. */
|
|
38
|
+
function canWrap(group, allowWrap) {
|
|
39
|
+
return allowWrap && !group.hasAttribute(NO_WRAP) && / wrap:/.test(` ${group.getAttribute(DECLARED) ?? ""}`);
|
|
40
|
+
}
|
|
31
41
|
function declare(steps) {
|
|
32
42
|
return STEPS.filter((step) => steps[step] !== void 0).map((step) => `${step}:${steps[step]}`).join(" ");
|
|
33
43
|
}
|
|
34
|
-
/** What a row holds, looking through `display: contents` wrappers. */
|
|
35
|
-
function boxes(element) {
|
|
36
|
-
return Array.from(element.children).flatMap((child) => getComputedStyle(child).display === "contents" ? boxes(child) : [child]);
|
|
37
|
-
}
|
|
38
44
|
/**
|
|
39
45
|
* Nothing pokes out of the toolbar or out of any of its rows, and no line has
|
|
40
46
|
* broken by itself: while groups wrap, each line (one `order`) stays one line.
|
|
41
47
|
*/
|
|
42
|
-
function fits(root) {
|
|
48
|
+
function fits(root, allowWrap) {
|
|
43
49
|
if (![root, ...root.querySelectorAll(`[${ROW}]`)].every((row) => {
|
|
44
50
|
if (row.getClientRects().length === 0) return true;
|
|
45
51
|
const style = getComputedStyle(row);
|
|
46
52
|
const end = row.getBoundingClientRect().right - parseFloat(style.borderRightWidth) - parseFloat(style.paddingRight);
|
|
47
|
-
return
|
|
53
|
+
return laidOutChildren(row).every((box) => box.getBoundingClientRect().right <= end + .5);
|
|
48
54
|
})) return false;
|
|
49
|
-
for (const
|
|
50
|
-
if (
|
|
51
|
-
const
|
|
52
|
-
|
|
55
|
+
for (const group of root.querySelectorAll("[data-fit-scroll]")) {
|
|
56
|
+
if (group.getClientRects().length === 0) continue;
|
|
57
|
+
const content = group.querySelector("[data-slot=scroll-area-content]") ?? group;
|
|
58
|
+
const [first] = laidOutChildren(content);
|
|
59
|
+
if (first && group.clientWidth + .5 < first.getBoundingClientRect().width) return false;
|
|
60
|
+
if (canWrap(group, allowWrap) && !group.hasAttribute(stepAttribute("wrap"))) {
|
|
61
|
+
const scroller = group.querySelector("[data-fit-scroller]") ?? group;
|
|
62
|
+
if (scroller.scrollWidth > scroller.clientWidth + .5) return false;
|
|
63
|
+
}
|
|
53
64
|
}
|
|
54
65
|
if (!root.hasAttribute(WRAPPING)) return true;
|
|
55
|
-
const
|
|
56
|
-
for (const child of
|
|
57
|
-
if (child.hasAttribute(BREAK)
|
|
66
|
+
const lines = /* @__PURE__ */ new Map();
|
|
67
|
+
for (const child of laidOutChildren(root)) {
|
|
68
|
+
if (child.hasAttribute(BREAK)) continue;
|
|
58
69
|
const line = getComputedStyle(child).order;
|
|
59
|
-
const
|
|
60
|
-
const first =
|
|
61
|
-
if (first === void 0)
|
|
62
|
-
else if (
|
|
70
|
+
const rect = child.getBoundingClientRect();
|
|
71
|
+
const first = lines.get(line);
|
|
72
|
+
if (first === void 0) lines.set(line, rect);
|
|
73
|
+
else if (rect.top >= first.bottom - .5 || rect.bottom <= first.top + .5) return false;
|
|
63
74
|
}
|
|
64
75
|
return true;
|
|
65
76
|
}
|
|
@@ -71,6 +82,7 @@ function fits(root) {
|
|
|
71
82
|
*/
|
|
72
83
|
function measure(root, allowWrap) {
|
|
73
84
|
const elements = Array.from(root.querySelectorAll(`[${ID}]`));
|
|
85
|
+
const scrolled = Array.from(root.querySelectorAll("[data-fit-scroller]"), (scroller) => [scroller, scroller.scrollLeft]);
|
|
74
86
|
const triggers = Array.from(root.querySelectorAll(`[${MORE_TRIGGER}]`));
|
|
75
87
|
for (const element of elements) {
|
|
76
88
|
for (const step of STEPS) element.removeAttribute(stepAttribute(step));
|
|
@@ -90,10 +102,28 @@ function measure(root, allowWrap) {
|
|
|
90
102
|
};
|
|
91
103
|
}).filter(({ step, element: item }) => {
|
|
92
104
|
if (step === "more") return triggers.length > 0;
|
|
93
|
-
if (step === "wrap") return allowWrap
|
|
105
|
+
if (step === "wrap") return canWrap(item, allowWrap);
|
|
106
|
+
if (step === "label") return !item.hasAttribute(NEEDS_ICON) || hasIcon(item);
|
|
94
107
|
return true;
|
|
95
108
|
}));
|
|
96
109
|
queue.sort((a, b) => a.order - b.order || b.index - a.index);
|
|
110
|
+
const batches = [];
|
|
111
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
112
|
+
for (const { element, step, order } of queue) {
|
|
113
|
+
const group = step === "label" || step === "plus" ? element.parentElement?.closest("[data-slot=fit-toolbar-group]") : null;
|
|
114
|
+
const kind = group ? `${group.getAttribute(ID)}|${step}|${order}` : void 0;
|
|
115
|
+
const existing = kind === void 0 ? void 0 : byKind.get(kind);
|
|
116
|
+
if (existing) {
|
|
117
|
+
existing.members.push(element);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const batch = {
|
|
121
|
+
members: [element],
|
|
122
|
+
step
|
|
123
|
+
};
|
|
124
|
+
batches.push(batch);
|
|
125
|
+
if (kind !== void 0) byKind.set(kind, batch);
|
|
126
|
+
}
|
|
97
127
|
const taken = /* @__PURE__ */ new Map();
|
|
98
128
|
const history = [];
|
|
99
129
|
const showMore = () => {
|
|
@@ -113,23 +143,24 @@ function measure(root, allowWrap) {
|
|
|
113
143
|
element.removeAttribute(stepAttribute(step));
|
|
114
144
|
if (step === "more") showMore();
|
|
115
145
|
};
|
|
116
|
-
for (const {
|
|
117
|
-
if (fits(root)) break;
|
|
118
|
-
|
|
119
|
-
|
|
146
|
+
for (const { members, step } of batches) {
|
|
147
|
+
if (fits(root, allowWrap)) break;
|
|
148
|
+
const giving = members.filter((element) => !taken.get(element)?.has("more"));
|
|
149
|
+
if (giving.length === 0) continue;
|
|
150
|
+
for (const element of giving) take(element, step);
|
|
120
151
|
history.push({
|
|
121
|
-
|
|
152
|
+
members: giving,
|
|
122
153
|
step
|
|
123
154
|
});
|
|
124
155
|
}
|
|
125
156
|
for (let index = history.length - 1; index >= 0; index -= 1) {
|
|
126
|
-
const {
|
|
157
|
+
const { members, step } = history[index];
|
|
127
158
|
if (step === "wrap") continue;
|
|
128
|
-
const group =
|
|
159
|
+
const group = members[0].closest(`[${stepAttribute("wrap")}]`);
|
|
129
160
|
if (!group || !root.contains(group)) continue;
|
|
130
|
-
if (history.findIndex((entry) => entry.
|
|
131
|
-
undo(element, step);
|
|
132
|
-
if (!fits(root)) take(element, step);
|
|
161
|
+
if (history.findIndex((entry) => entry.members.includes(group) && entry.step === "wrap") < index) continue;
|
|
162
|
+
for (const element of members) undo(element, step);
|
|
163
|
+
if (!fits(root, allowWrap)) for (const element of members) take(element, step);
|
|
133
164
|
}
|
|
134
165
|
const items = /* @__PURE__ */ new Map();
|
|
135
166
|
const more = [];
|
|
@@ -142,6 +173,7 @@ function measure(root, allowWrap) {
|
|
|
142
173
|
if (steps.has("more")) more.push(id);
|
|
143
174
|
if (steps.has("wrap")) wrapping = true;
|
|
144
175
|
}
|
|
176
|
+
for (const [scroller, left] of scrolled) scroller.scrollLeft = left;
|
|
145
177
|
return {
|
|
146
178
|
items,
|
|
147
179
|
more,
|
|
@@ -172,6 +204,54 @@ function layOutLines(root, elements) {
|
|
|
172
204
|
group.style.order = String(2 * number + 2);
|
|
173
205
|
}
|
|
174
206
|
}
|
|
207
|
+
/** What the arrow keys stop on: every control a person can reach, a segment each. */
|
|
208
|
+
const STOP = [
|
|
209
|
+
"button",
|
|
210
|
+
"a[href]",
|
|
211
|
+
"input",
|
|
212
|
+
"select",
|
|
213
|
+
"textarea",
|
|
214
|
+
"[role=button]",
|
|
215
|
+
"[role=radio]",
|
|
216
|
+
"[role=checkbox]",
|
|
217
|
+
"[role=switch]",
|
|
218
|
+
"[role=combobox]"
|
|
219
|
+
].join(", ");
|
|
220
|
+
/** The line an element is on: the CSS `order` of the toolbar's flex item that holds it. */
|
|
221
|
+
function lineOf(element, root) {
|
|
222
|
+
const chain = [];
|
|
223
|
+
for (let node = element; node && node !== root; node = node.parentElement) chain.unshift(node);
|
|
224
|
+
const item = chain.find((node) => getComputedStyle(node).display !== "contents") ?? element;
|
|
225
|
+
return Number(getComputedStyle(item).order) || 0;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* The toolbar's controls in reading order: line by line as they show, in the
|
|
229
|
+
* order of the DOM on each line. Wrapped groups move with CSS `order`, which
|
|
230
|
+
* neither the browser's focus order nor Base UI's list follows (WCAG 2.4.3).
|
|
231
|
+
* Leaves out what isn't shown (in More, a collapsed group's items), what is
|
|
232
|
+
* disabled natively, hidden from assistive technology, or a popup's focus guard.
|
|
233
|
+
*/
|
|
234
|
+
function readingOrder(root) {
|
|
235
|
+
const controls = Array.from(root.querySelectorAll(STOP)).filter((control) => !control.matches(":disabled") && control.closest("[aria-hidden=true]") === null && !control.hasAttribute("data-base-ui-focus-guard") && control.getClientRects().length > 0);
|
|
236
|
+
const lines = new Map(controls.map((control) => [control, lineOf(control, root)]));
|
|
237
|
+
return controls.sort((a, b) => lines.get(a) - lines.get(b));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* A text field keeps the arrow keys while its caret has somewhere to go, as
|
|
241
|
+
* in Base UI's composite: only at its start or end does an arrow leave it.
|
|
242
|
+
*/
|
|
243
|
+
function keepsArrow(target, forward) {
|
|
244
|
+
if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return false;
|
|
245
|
+
let start;
|
|
246
|
+
try {
|
|
247
|
+
start = target.selectionStart;
|
|
248
|
+
} catch {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (start === null) return false;
|
|
252
|
+
if (start !== target.selectionEnd) return true;
|
|
253
|
+
return forward ? start < target.value.length : start > 0;
|
|
254
|
+
}
|
|
175
255
|
const keyOf = (applied) => `${applied.wrapping}|${Array.from(applied.items, ([id, steps]) => `${id}:${[...steps].join(",")}`).join(";")}`;
|
|
176
256
|
/**
|
|
177
257
|
* What each item shows in More while it is there, outside React state: the
|
|
@@ -248,6 +328,100 @@ function FitToolbar({ className, wrap = false, ref, ...props }) {
|
|
|
248
328
|
fonts?.removeEventListener?.("loadingdone", update);
|
|
249
329
|
};
|
|
250
330
|
}, [element, update]);
|
|
331
|
+
const tabbing = useRef(false);
|
|
332
|
+
const entered = useRef(false);
|
|
333
|
+
useLayoutEffect(() => {
|
|
334
|
+
const onKey = (event) => {
|
|
335
|
+
tabbing.current = event.key === "Tab";
|
|
336
|
+
};
|
|
337
|
+
const off = () => {
|
|
338
|
+
tabbing.current = false;
|
|
339
|
+
};
|
|
340
|
+
document.addEventListener("keydown", onKey, true);
|
|
341
|
+
document.addEventListener("keyup", off, true);
|
|
342
|
+
document.addEventListener("pointerdown", off, true);
|
|
343
|
+
return () => {
|
|
344
|
+
document.removeEventListener("keydown", onKey, true);
|
|
345
|
+
document.removeEventListener("keyup", off, true);
|
|
346
|
+
document.removeEventListener("pointerdown", off, true);
|
|
347
|
+
};
|
|
348
|
+
}, []);
|
|
349
|
+
const horizontal = (props.orientation ?? "horizontal") === "horizontal";
|
|
350
|
+
const { onKeyDownCapture, onFocus, loopFocus = true } = props;
|
|
351
|
+
const handleKeyDown = useCallback((event) => {
|
|
352
|
+
onKeyDownCapture?.(event);
|
|
353
|
+
const current = rootRef.current;
|
|
354
|
+
if (!current || !horizontal || event.defaultPrevented) return;
|
|
355
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
356
|
+
const target = event.target;
|
|
357
|
+
if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
358
|
+
if (target.closest("[role=radiogroup]") && current.contains(target)) {
|
|
359
|
+
event.preventDefault();
|
|
360
|
+
event.stopPropagation();
|
|
361
|
+
}
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
365
|
+
const rtl = getComputedStyle(current).direction === "rtl";
|
|
366
|
+
const forward = event.key === "ArrowRight" !== rtl;
|
|
367
|
+
if (keepsArrow(target, forward)) return;
|
|
368
|
+
const order = readingOrder(current);
|
|
369
|
+
const index = order.findIndex((control) => control === target || control.contains(target));
|
|
370
|
+
if (index < 0) return;
|
|
371
|
+
let next = index + (forward ? 1 : -1);
|
|
372
|
+
if (next < 0 || next >= order.length) {
|
|
373
|
+
if (!loopFocus) return;
|
|
374
|
+
next = (next + order.length) % order.length;
|
|
375
|
+
}
|
|
376
|
+
event.preventDefault();
|
|
377
|
+
event.stopPropagation();
|
|
378
|
+
if (next !== index) order[next].focus();
|
|
379
|
+
}, [
|
|
380
|
+
horizontal,
|
|
381
|
+
loopFocus,
|
|
382
|
+
onKeyDownCapture
|
|
383
|
+
]);
|
|
384
|
+
const handleFocus = useCallback((event) => {
|
|
385
|
+
onFocus?.(event);
|
|
386
|
+
const current = rootRef.current;
|
|
387
|
+
if (!current) return;
|
|
388
|
+
const from = event.relatedTarget;
|
|
389
|
+
if (!(from instanceof Node && current.contains(from)) && tabbing.current && !entered.current) {
|
|
390
|
+
entered.current = true;
|
|
391
|
+
const [first] = readingOrder(current);
|
|
392
|
+
if (first && first !== event.target) {
|
|
393
|
+
first.focus();
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
entered.current = true;
|
|
398
|
+
}, [onFocus]);
|
|
399
|
+
const lastFocused = useRef(null);
|
|
400
|
+
useLayoutEffect(() => {
|
|
401
|
+
if (!element) return;
|
|
402
|
+
const onFocusIn = (event) => {
|
|
403
|
+
lastFocused.current = event.target;
|
|
404
|
+
};
|
|
405
|
+
const onFocusOut = (event) => {
|
|
406
|
+
if (event.target.getClientRects().length > 0) lastFocused.current = null;
|
|
407
|
+
};
|
|
408
|
+
element.addEventListener("focusin", onFocusIn);
|
|
409
|
+
element.addEventListener("focusout", onFocusOut);
|
|
410
|
+
return () => {
|
|
411
|
+
element.removeEventListener("focusin", onFocusIn);
|
|
412
|
+
element.removeEventListener("focusout", onFocusOut);
|
|
413
|
+
};
|
|
414
|
+
}, [element]);
|
|
415
|
+
useLayoutEffect(() => {
|
|
416
|
+
const current = rootRef.current;
|
|
417
|
+
const last = lastFocused.current;
|
|
418
|
+
if (!current || !last || last.getClientRects().length > 0) return;
|
|
419
|
+
const active = document.activeElement;
|
|
420
|
+
if (active !== last && active !== document.body && active !== null) return;
|
|
421
|
+
const more = Array.from(current.querySelectorAll(`[${MORE_TRIGGER}]`)).find((trigger) => trigger.getClientRects().length > 0);
|
|
422
|
+
lastFocused.current = null;
|
|
423
|
+
more?.focus();
|
|
424
|
+
}, [applied]);
|
|
251
425
|
const context = useMemo(() => ({
|
|
252
426
|
applied,
|
|
253
427
|
store
|
|
@@ -259,7 +433,9 @@ function FitToolbar({ className, wrap = false, ref, ...props }) {
|
|
|
259
433
|
"data-slot": "fit-toolbar",
|
|
260
434
|
"data-fit-wrapping": applied.wrapping ? "" : void 0,
|
|
261
435
|
className: root({ className }),
|
|
262
|
-
...props
|
|
436
|
+
...props,
|
|
437
|
+
onKeyDownCapture: handleKeyDown,
|
|
438
|
+
onFocus: handleFocus
|
|
263
439
|
})
|
|
264
440
|
});
|
|
265
441
|
}
|
|
@@ -338,6 +514,12 @@ function useScrollGroup(group) {
|
|
|
338
514
|
if (next) group.setAttribute("data-overflow", next);
|
|
339
515
|
else group.removeAttribute("data-overflow");
|
|
340
516
|
};
|
|
517
|
+
let placed = group.scrollLeft;
|
|
518
|
+
let scrolledByPerson = false;
|
|
519
|
+
const onScroll = () => {
|
|
520
|
+
if (Math.abs(group.scrollLeft - placed) > 1) scrolledByPerson = true;
|
|
521
|
+
edges();
|
|
522
|
+
};
|
|
341
523
|
const reveal = (item) => {
|
|
342
524
|
if (!(item instanceof HTMLElement) || !group.contains(item)) return;
|
|
343
525
|
const fade = parseFloat(getComputedStyle(group).getPropertyValue("--fade-edge")) || 24;
|
|
@@ -345,11 +527,13 @@ function useScrollGroup(group) {
|
|
|
345
527
|
const end = start + item.offsetWidth;
|
|
346
528
|
if (start - fade < group.scrollLeft) group.scrollLeft = Math.max(0, start - fade);
|
|
347
529
|
else if (end + fade > group.scrollLeft + group.clientWidth) group.scrollLeft = end + fade - group.clientWidth;
|
|
530
|
+
placed = group.scrollLeft;
|
|
348
531
|
edges();
|
|
349
532
|
};
|
|
533
|
+
let target = group.querySelector("[data-active]");
|
|
350
534
|
const revealActive = () => {
|
|
351
|
-
|
|
352
|
-
|
|
535
|
+
if (!target || !group.contains(target) || !target.hasAttribute("data-active")) target = group.querySelector("[data-active]");
|
|
536
|
+
reveal(target);
|
|
353
537
|
};
|
|
354
538
|
const onWheel = (event) => {
|
|
355
539
|
if (group.scrollWidth <= group.clientWidth) return;
|
|
@@ -361,16 +545,22 @@ function useScrollGroup(group) {
|
|
|
361
545
|
const onFocus = (event) => reveal(event.target);
|
|
362
546
|
revealActive();
|
|
363
547
|
edges();
|
|
364
|
-
group.addEventListener("scroll",
|
|
548
|
+
group.addEventListener("scroll", onScroll, { passive: true });
|
|
365
549
|
group.addEventListener("wheel", onWheel, { passive: false });
|
|
366
550
|
group.addEventListener("focusin", onFocus);
|
|
367
551
|
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
|
|
368
|
-
revealActive();
|
|
552
|
+
if (!scrolledByPerson) revealActive();
|
|
369
553
|
edges();
|
|
370
554
|
});
|
|
371
555
|
resize?.observe(group);
|
|
556
|
+
const activated = (node) => node instanceof Element ? node.hasAttribute("data-active") ? node : node.querySelector("[data-active]") : null;
|
|
372
557
|
const changes = new MutationObserver((records) => {
|
|
373
|
-
|
|
558
|
+
const newly = records.flatMap((record) => record.type === "attributes" ? [record.target instanceof Element && record.target.hasAttribute("data-active") ? record.target : null] : Array.from(record.addedNodes, activated)).filter((node) => node !== null).at(-1);
|
|
559
|
+
if (newly) {
|
|
560
|
+
target = newly;
|
|
561
|
+
scrolledByPerson = false;
|
|
562
|
+
revealActive();
|
|
563
|
+
}
|
|
374
564
|
edges();
|
|
375
565
|
});
|
|
376
566
|
changes.observe(group, {
|
|
@@ -381,7 +571,7 @@ function useScrollGroup(group) {
|
|
|
381
571
|
attributeFilter: ["data-active"]
|
|
382
572
|
});
|
|
383
573
|
return () => {
|
|
384
|
-
group.removeEventListener("scroll",
|
|
574
|
+
group.removeEventListener("scroll", onScroll);
|
|
385
575
|
group.removeEventListener("wheel", onWheel);
|
|
386
576
|
group.removeEventListener("focusin", onFocus);
|
|
387
577
|
resize?.disconnect();
|
|
@@ -437,27 +627,47 @@ function FitToolbarGroup({ className, wrapOrder = 0, firstLine = false, wrapLine
|
|
|
437
627
|
/**
|
|
438
628
|
* A toolbar button that can give way: an `md` Button (ghost unless you say)
|
|
439
629
|
* with an icon and a label, an icon square with its label as a tooltip from
|
|
440
|
-
* `labelOrder` on,
|
|
630
|
+
* `labelOrder` on, a + square with its label as a tooltip from `plusOrder`
|
|
631
|
+
* on, and hidden from `moreOrder` on.
|
|
441
632
|
*/
|
|
442
|
-
function FitToolbarButton({ icon, children, labelOrder, moreOrder, moreItem, variant = "ghost", className, ...props }) {
|
|
443
|
-
const { button, label } = fitToolbar();
|
|
633
|
+
function FitToolbarButton({ icon, collapsedIcon, children, labelOrder, plusOrder, moreOrder, moreItem, variant = "ghost", className, ...props }) {
|
|
634
|
+
const { button, label, icon: iconSlot, plus, fullIcon, collapsedIcon: collapsedSlot } = fitToolbar();
|
|
444
635
|
const item = useFitItem({
|
|
445
636
|
label: labelOrder,
|
|
446
637
|
more: moreOrder,
|
|
638
|
+
plus: plusOrder,
|
|
447
639
|
moreItem
|
|
448
640
|
});
|
|
641
|
+
const icons = collapsedIcon === void 0 ? icon : /* @__PURE__ */ jsxs(Fragment$1, { children: [icon === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
642
|
+
"data-slot": "fit-toolbar-button-full-icon",
|
|
643
|
+
className: fullIcon(),
|
|
644
|
+
children: icon
|
|
645
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
646
|
+
"data-slot": "fit-toolbar-button-collapsed-icon",
|
|
647
|
+
className: collapsedSlot(),
|
|
648
|
+
children: collapsedIcon
|
|
649
|
+
})] });
|
|
449
650
|
return /* @__PURE__ */ jsxs(Tooltip, {
|
|
450
|
-
disabled: !item.taken("label"),
|
|
651
|
+
disabled: !item.taken("label") && !item.taken("plus"),
|
|
451
652
|
children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
|
|
452
653
|
"data-slot": "button",
|
|
453
654
|
render: /* @__PURE__ */ jsx(Toolbar.Button, { render: /* @__PURE__ */ jsx(Button, {
|
|
454
655
|
variant,
|
|
455
656
|
size: "md",
|
|
456
657
|
className: button({ className }),
|
|
658
|
+
"data-fit-needs-icon": "",
|
|
457
659
|
...item.props,
|
|
458
660
|
...props
|
|
459
661
|
}) }),
|
|
460
|
-
children: [
|
|
662
|
+
children: [plusOrder === void 0 ? icons : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
663
|
+
"data-slot": "fit-toolbar-button-icon",
|
|
664
|
+
className: iconSlot(),
|
|
665
|
+
children: icons
|
|
666
|
+
}), /* @__PURE__ */ jsx(Plus, {
|
|
667
|
+
"data-slot": "fit-toolbar-button-plus",
|
|
668
|
+
"aria-hidden": true,
|
|
669
|
+
className: plus()
|
|
670
|
+
})] }), /* @__PURE__ */ jsx("span", {
|
|
461
671
|
"data-slot": "fit-toolbar-button-label",
|
|
462
672
|
className: label(),
|
|
463
673
|
children
|
|
@@ -465,5 +675,62 @@ function FitToolbarButton({ icon, children, labelOrder, moreOrder, moreItem, var
|
|
|
465
675
|
}), /* @__PURE__ */ jsx(TooltipContent, { children })]
|
|
466
676
|
});
|
|
467
677
|
}
|
|
678
|
+
/** A count: a number, or a string of digits. Space Mono is for machine-written text only. */
|
|
679
|
+
const isCount = (node) => typeof node === "number" || typeof node === "string" && /^\d+$/.test(node.trim());
|
|
680
|
+
const text = (node) => typeof node === "string" || typeof node === "number" ? String(node) : void 0;
|
|
681
|
+
/**
|
|
682
|
+
* A picker's trigger as one toolbar item (a filter: Assignee, Channel): a
|
|
683
|
+
* PickerTriggerButton with an icon, a label, what is chosen and a chevron,
|
|
684
|
+
* filled `info-soft` once a value is chosen, as an applied filter is
|
|
685
|
+
* (Select › Filters). From `labelOrder` on its label gives way, while its
|
|
686
|
+
* icon, what is chosen and the chevron stay ("# ⌄", "👤 1 ⌄"); its label
|
|
687
|
+
* stays its accessible name, read before the value ("Assignee 1"), and shows
|
|
688
|
+
* as its tooltip.
|
|
689
|
+
*/
|
|
690
|
+
function FitToolbarPicker({ trigger, icon, children, value, labelOrder, moreOrder, moreItem, className, ...props }) {
|
|
691
|
+
const { picker, label, pickerValue, chevron } = fitToolbar({ count: isCount(value) });
|
|
692
|
+
const item = useFitItem({
|
|
693
|
+
label: labelOrder,
|
|
694
|
+
more: moreOrder,
|
|
695
|
+
moreItem
|
|
696
|
+
});
|
|
697
|
+
const hasValue = value !== void 0 && value !== null && value !== false && value !== "";
|
|
698
|
+
const name = text(children) !== void 0 && (!hasValue || text(value) !== void 0) ? [text(children), hasValue ? text(value) : void 0].filter(Boolean).join(" ") : void 0;
|
|
699
|
+
const ownTrigger = cloneElement(trigger, { render: /* @__PURE__ */ jsx(PickerTriggerButton, {
|
|
700
|
+
className: picker({ className }),
|
|
701
|
+
"aria-label": name,
|
|
702
|
+
"data-has-value": hasValue ? "" : void 0,
|
|
703
|
+
"data-fit-needs-icon": "",
|
|
704
|
+
...item.props,
|
|
705
|
+
...props
|
|
706
|
+
}) });
|
|
707
|
+
return /* @__PURE__ */ jsxs(Tooltip, {
|
|
708
|
+
disabled: !item.taken("label"),
|
|
709
|
+
children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
|
|
710
|
+
"data-slot": "button",
|
|
711
|
+
render: /* @__PURE__ */ jsx(Toolbar.Button, { render: ownTrigger }),
|
|
712
|
+
children: [
|
|
713
|
+
icon,
|
|
714
|
+
/* @__PURE__ */ jsxs("span", {
|
|
715
|
+
"data-slot": "fit-toolbar-picker-label",
|
|
716
|
+
className: label(),
|
|
717
|
+
children: [children, hasValue && name === void 0 ? " " : null]
|
|
718
|
+
}),
|
|
719
|
+
hasValue ? /* @__PURE__ */ jsx("span", {
|
|
720
|
+
"data-slot": "fit-toolbar-picker-value",
|
|
721
|
+
className: pickerValue(),
|
|
722
|
+
children: value
|
|
723
|
+
}) : null,
|
|
724
|
+
/* @__PURE__ */ jsx("span", {
|
|
725
|
+
"data-slot": "fit-toolbar-picker-chevron",
|
|
726
|
+
"data-picker-trigger-indicator": "",
|
|
727
|
+
"aria-hidden": true,
|
|
728
|
+
className: chevron(),
|
|
729
|
+
children: /* @__PURE__ */ jsx(ChevronDown, {})
|
|
730
|
+
})
|
|
731
|
+
]
|
|
732
|
+
}), /* @__PURE__ */ jsx(TooltipContent, { children })]
|
|
733
|
+
});
|
|
734
|
+
}
|
|
468
735
|
//#endregion
|
|
469
|
-
export { FitToolbar, FitToolbarButton, FitToolbarGroup, FitToolbarMoreItems, useFitItem, useFitMore, useInFitToolbar };
|
|
736
|
+
export { FitToolbar, FitToolbarButton, FitToolbarGroup, FitToolbarMoreItems, FitToolbarPicker, useFitItem, useFitMore, useInFitToolbar };
|
|
@@ -6,16 +6,30 @@ const fitToolbar = tv({
|
|
|
6
6
|
group: ["group/fit-group flex shrink-0 flex-nowrap items-center", "data-fit-wrap:mt-(--fit-gap)"],
|
|
7
7
|
full: ["contents group-data-fit-collapse/fit-group:hidden"],
|
|
8
8
|
short: ["hidden group-data-fit-collapse/fit-group:contents"],
|
|
9
|
-
button: [
|
|
10
|
-
|
|
9
|
+
button: [
|
|
10
|
+
"data-fit-label:w-8 data-fit-label:px-0 md:pointer-fine:data-fit-label:w-(--control-height)",
|
|
11
|
+
"data-fit-plus:w-8 data-fit-plus:px-0 md:pointer-fine:data-fit-plus:w-(--control-height)",
|
|
12
|
+
"data-fit-more:hidden"
|
|
13
|
+
],
|
|
14
|
+
label: ["in-data-fit-label:sr-only in-data-fit-plus:sr-only"],
|
|
15
|
+
icon: ["contents in-data-fit-plus:hidden"],
|
|
16
|
+
fullIcon: ["contents in-data-fit-label:hidden"],
|
|
17
|
+
collapsedIcon: ["hidden in-data-fit-label:contents"],
|
|
18
|
+
picker: ["data-fit-label:gap-1 data-fit-label:px-2", "data-fit-more:hidden"],
|
|
19
|
+
pickerValue: [],
|
|
20
|
+
chevron: ["inline-flex"],
|
|
21
|
+
plus: ["hidden in-data-fit-plus:block"],
|
|
11
22
|
scroller: [],
|
|
12
23
|
scrollContent: []
|
|
13
24
|
},
|
|
14
|
-
variants: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
variants: {
|
|
26
|
+
count: { true: { pickerValue: ["font-mono text-mono-meta"] } },
|
|
27
|
+
scroll: { true: {
|
|
28
|
+
group: ["block min-w-0 flex-1 shrink basis-0"],
|
|
29
|
+
scroller: ["-my-1.5 w-full gap-[inherit] scroll-px-6 mask-fade-x"],
|
|
30
|
+
scrollContent: ["flex w-max items-center gap-[inherit] py-1.5"]
|
|
31
|
+
} }
|
|
32
|
+
}
|
|
19
33
|
});
|
|
20
34
|
//#endregion
|
|
21
35
|
export { fitToolbar };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { FitItemOptions, FitStep, FitSteps, FitToolbar, FitToolbarButton, FitToolbarButtonProps, FitToolbarGroup, FitToolbarGroupProps, FitToolbarMoreItems, FitToolbarProps, useFitItem, useFitMore, useInFitToolbar } from "./fit-toolbar.mjs";
|
|
2
|
-
export { type FitItemOptions, type FitStep, type FitSteps, FitToolbar, FitToolbarButton, type FitToolbarButtonProps, FitToolbarGroup, type FitToolbarGroupProps, FitToolbarMoreItems, type FitToolbarProps, useFitItem, useFitMore, useInFitToolbar };
|
|
1
|
+
import { FitItemOptions, FitStep, FitSteps, FitToolbar, FitToolbarButton, FitToolbarButtonProps, FitToolbarGroup, FitToolbarGroupProps, FitToolbarMoreItems, FitToolbarPicker, FitToolbarPickerProps, FitToolbarProps, useFitItem, useFitMore, useInFitToolbar } from "./fit-toolbar.mjs";
|
|
2
|
+
export { type FitItemOptions, type FitStep, type FitSteps, FitToolbar, FitToolbarButton, type FitToolbarButtonProps, FitToolbarGroup, type FitToolbarGroupProps, FitToolbarMoreItems, FitToolbarPicker, type FitToolbarPickerProps, type FitToolbarProps, useFitItem, useFitMore, useInFitToolbar };
|
|
@@ -18,17 +18,17 @@ const inboxItem = tv({
|
|
|
18
18
|
"has-[[data-slot=inbox-item-open]:focus-visible]:keyboard:before:inset-ring-2 has-[[data-slot=inbox-item-open]:focus-visible]:keyboard:before:inset-ring-foreground",
|
|
19
19
|
"not-data-[density=compact]:has-data-[slot=inbox-item-trailing]:[--inbox-item-content-display:grid] not-data-[density=compact]:has-data-[slot=inbox-item-trailing]:[--inbox-item-content-end:-1]"
|
|
20
20
|
],
|
|
21
|
-
itemTrigger: ["absolute inset-0 z-
|
|
22
|
-
itemLeading: ["pointer-events-none relative z-
|
|
21
|
+
itemTrigger: ["absolute inset-0 z-base outline-none"],
|
|
22
|
+
itemLeading: ["pointer-events-none relative z-raised flex size-9 shrink-0 items-center justify-center"],
|
|
23
23
|
itemLeadingBadge: [
|
|
24
|
-
"absolute -right-0.5 -bottom-0.5 z-
|
|
24
|
+
"absolute -right-0.5 -bottom-0.5 z-raised inline-flex size-3.5 items-center justify-center",
|
|
25
25
|
"rounded-[3px] border border-sticker-ink outline-2 outline-layer-canvas outline-solid",
|
|
26
26
|
"bg-layer-canvas bg-[linear-gradient(var(--info-soft),var(--info-soft))] text-foreground",
|
|
27
27
|
"[&_svg]:size-2.5 [&_svg]:shrink-0"
|
|
28
28
|
],
|
|
29
|
-
itemSelection: ["relative z-
|
|
29
|
+
itemSelection: ["relative z-raised flex size-5 shrink-0 items-center justify-center"],
|
|
30
30
|
itemContent: [
|
|
31
|
-
"pointer-events-none relative z-
|
|
31
|
+
"pointer-events-none relative z-raised min-w-0 flex-1 text-left",
|
|
32
32
|
"-col-start-3 col-end-(--inbox-item-content-end) row-start-1",
|
|
33
33
|
"[display:var(--inbox-item-content-display,block)] grid-cols-subgrid"
|
|
34
34
|
],
|
|
@@ -57,7 +57,7 @@ const inboxItem = tv({
|
|
|
57
57
|
"[&>svg]:text-foreground-hint"
|
|
58
58
|
],
|
|
59
59
|
itemTrailing: [
|
|
60
|
-
"pointer-events-none relative z-
|
|
60
|
+
"pointer-events-none relative z-raised col-[-2/-1] row-start-1",
|
|
61
61
|
"flex shrink-0",
|
|
62
62
|
"mt-0 flex-col items-end gap-2 pt-px",
|
|
63
63
|
"max-md:flex-col max-md:items-end max-md:gap-2",
|
|
@@ -138,7 +138,7 @@ const inboxItem = tv({
|
|
|
138
138
|
} },
|
|
139
139
|
reveal: { hover: {
|
|
140
140
|
itemActions: [
|
|
141
|
-
"absolute top-0 right-0 z-
|
|
141
|
+
"absolute top-0 right-0 z-raised",
|
|
142
142
|
"pointer-events-none opacity-0 transition-opacity",
|
|
143
143
|
"group-hover/inbox-item:pointer-events-auto group-hover/inbox-item:opacity-100",
|
|
144
144
|
"group-focus-within/inbox-item:pointer-events-auto group-focus-within/inbox-item:opacity-100",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Lightbox, LightboxActions, LightboxActionsProps, LightboxClose, LightboxCloseProps, LightboxContent, LightboxContentProps, LightboxHeader, LightboxHeaderLabel, LightboxHeaderLabelProps, LightboxHeaderMeta, LightboxHeaderMetaProps, LightboxHeaderProps, LightboxInfoActions, LightboxInfoActionsProps, LightboxInfoBar, LightboxInfoBarProps, LightboxInfoDock, LightboxInfoDockProps, LightboxInfoTitle, LightboxInfoTitleProps, LightboxMedia, LightboxMediaProps, LightboxNavigationButton, LightboxNavigationButtonProps, LightboxPortal, LightboxPortalProps, LightboxProps, LightboxStage, LightboxStageProps, LightboxThumbnail, LightboxThumbnailProps, LightboxThumbnailStrip, LightboxThumbnailStripProps, LightboxTitle, LightboxTitleProps, LightboxToolbar, LightboxToolbarProps, LightboxTrigger, LightboxTriggerProps } from "./lightbox.mjs";
|
|
2
|
-
export { Lightbox, LightboxActions, type LightboxActionsProps, LightboxClose, type LightboxCloseProps, LightboxContent, type LightboxContentProps, LightboxHeader, LightboxHeaderLabel, type LightboxHeaderLabelProps, LightboxHeaderMeta, type LightboxHeaderMetaProps, type LightboxHeaderProps, LightboxInfoActions, type LightboxInfoActionsProps, LightboxInfoBar, type LightboxInfoBarProps, LightboxInfoDock, type LightboxInfoDockProps, LightboxInfoTitle, type LightboxInfoTitleProps, LightboxMedia, type LightboxMediaProps, LightboxNavigationButton, type LightboxNavigationButtonProps, LightboxPortal, type LightboxPortalProps, type LightboxProps, LightboxStage, type LightboxStageProps, LightboxThumbnail, type LightboxThumbnailProps, LightboxThumbnailStrip, type LightboxThumbnailStripProps, LightboxTitle, type LightboxTitleProps, LightboxToolbar, type LightboxToolbarProps, LightboxTrigger, type LightboxTriggerProps };
|
|
1
|
+
import { Lightbox, LightboxActions, LightboxActionsProps, LightboxBody, LightboxBodyProps, LightboxClose, LightboxCloseProps, LightboxContent, LightboxContentProps, LightboxHeader, LightboxHeaderLabel, LightboxHeaderLabelProps, LightboxHeaderMeta, LightboxHeaderMetaProps, LightboxHeaderProps, LightboxInfoActions, LightboxInfoActionsProps, LightboxInfoBar, LightboxInfoBarProps, LightboxInfoDock, LightboxInfoDockProps, LightboxInfoTitle, LightboxInfoTitleProps, LightboxMedia, LightboxMediaProps, LightboxNavigationButton, LightboxNavigationButtonProps, LightboxPortal, LightboxPortalProps, LightboxProps, LightboxStage, LightboxStageProps, LightboxThumbnail, LightboxThumbnailProps, LightboxThumbnailStrip, LightboxThumbnailStripProps, LightboxTitle, LightboxTitleProps, LightboxToolbar, LightboxToolbarProps, LightboxTrigger, LightboxTriggerProps } from "./lightbox.mjs";
|
|
2
|
+
export { Lightbox, LightboxActions, type LightboxActionsProps, LightboxBody, type LightboxBodyProps, LightboxClose, type LightboxCloseProps, LightboxContent, type LightboxContentProps, LightboxHeader, LightboxHeaderLabel, type LightboxHeaderLabelProps, LightboxHeaderMeta, type LightboxHeaderMetaProps, type LightboxHeaderProps, LightboxInfoActions, type LightboxInfoActionsProps, LightboxInfoBar, type LightboxInfoBarProps, LightboxInfoDock, type LightboxInfoDockProps, LightboxInfoTitle, type LightboxInfoTitleProps, LightboxMedia, type LightboxMediaProps, LightboxNavigationButton, type LightboxNavigationButtonProps, LightboxPortal, type LightboxPortalProps, type LightboxProps, LightboxStage, type LightboxStageProps, LightboxThumbnail, type LightboxThumbnailProps, LightboxThumbnailStrip, type LightboxThumbnailStripProps, LightboxTitle, type LightboxTitleProps, LightboxToolbar, type LightboxToolbarProps, LightboxTrigger, type LightboxTriggerProps };
|