@stll/ui 0.44.1 → 0.45.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/components/accordion.d.ts +6 -2
- package/dist/components/accordion.js +4 -4
- package/dist/components/button.d.ts +2 -2
- package/dist/components/court-badge.d.ts +7 -1
- package/dist/components/court-badge.js +13 -3
- package/dist/components/date-picker-popover.d.ts +12 -2
- package/dist/components/date-picker-popover.js +105 -9
- package/dist/components/date-range-filter.d.ts +14 -0
- package/dist/components/date-range-filter.js +74 -0
- package/dist/components/document-identity-badge.d.ts +12 -0
- package/dist/components/document-identity-badge.js +94 -0
- package/dist/components/document-identity-badge.logic.d.ts +25 -0
- package/dist/components/document-identity-badge.logic.js +25 -0
- package/dist/components/landing.d.ts +1 -1
- package/dist/components/landing.js +1 -1
- package/dist/components/matter-icon.d.ts +16 -0
- package/dist/components/matter-icon.js +56 -0
- package/dist/components/menu.d.ts +9 -1
- package/dist/components/menu.js +6 -6
- package/dist/components/outline-rail.d.ts +8 -1
- package/dist/components/outline-rail.js +95 -48
- package/dist/components/search-field.js +30 -34
- package/dist/components/sheet.js +3 -2
- package/dist/components/sidebar.d.ts +1 -1
- package/dist/components/switch.d.ts +5 -0
- package/dist/components/switch.js +16 -0
- package/dist/components/toast.js +39 -23
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/inspector/entity-tab.js +1 -2
- package/dist/lib/control-size.d.ts +1 -1
- package/dist/lib/matter-colors.d.ts +38 -0
- package/dist/lib/matter-colors.js +65 -0
- package/dist/lib/panel-inset.d.ts +11 -0
- package/dist/lib/panel-inset.js +33 -0
- package/dist/review/review-word-diff.d.ts +13 -0
- package/dist/review/review-word-diff.js +78 -0
- package/package.json +37 -5
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { LayersIcon } from "../icons.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { resolveMatterColor } from "../lib/matter-colors.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/matter-icon.tsx
|
|
6
|
+
const ALL_MATTERS_STACK_COLORS = [
|
|
7
|
+
"var(--option-red)",
|
|
8
|
+
"var(--option-blue)",
|
|
9
|
+
"var(--option-green)"
|
|
10
|
+
];
|
|
11
|
+
const MatterIcon = (props) => {
|
|
12
|
+
if ("matter" in props) return /* @__PURE__ */ jsx(LayersIcon, {
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
className: cn(props.className),
|
|
15
|
+
style: { color: resolveMatterColor(props.matter.id, props.matter.color) }
|
|
16
|
+
});
|
|
17
|
+
if (props.variant === "all") return /* @__PURE__ */ jsxs("svg", {
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
className: cn(props.className),
|
|
20
|
+
fill: "none",
|
|
21
|
+
viewBox: "0 0 24 24",
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsx("path", {
|
|
24
|
+
d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",
|
|
25
|
+
stroke: ALL_MATTERS_STACK_COLORS[0],
|
|
26
|
+
strokeLinecap: "round",
|
|
27
|
+
strokeLinejoin: "round",
|
|
28
|
+
strokeWidth: "2"
|
|
29
|
+
}),
|
|
30
|
+
/* @__PURE__ */ jsx("path", {
|
|
31
|
+
d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
|
|
32
|
+
stroke: ALL_MATTERS_STACK_COLORS[1],
|
|
33
|
+
strokeLinecap: "round",
|
|
34
|
+
strokeLinejoin: "round",
|
|
35
|
+
strokeWidth: "2"
|
|
36
|
+
}),
|
|
37
|
+
/* @__PURE__ */ jsx("path", {
|
|
38
|
+
d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",
|
|
39
|
+
stroke: ALL_MATTERS_STACK_COLORS[2],
|
|
40
|
+
strokeLinecap: "round",
|
|
41
|
+
strokeLinejoin: "round",
|
|
42
|
+
strokeWidth: "2"
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
return /* @__PURE__ */ jsx(LayersIcon, {
|
|
47
|
+
"aria-hidden": "true",
|
|
48
|
+
className: cn(props.className)
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const MattersNavIcon = ({ className }) => /* @__PURE__ */ jsx(MatterIcon, {
|
|
52
|
+
className,
|
|
53
|
+
variant: "none"
|
|
54
|
+
});
|
|
55
|
+
//#endregion
|
|
56
|
+
export { MatterIcon, MattersNavIcon };
|
|
@@ -7,7 +7,13 @@ declare const MenuPortal: React$1.ForwardRefExoticComponent<Omit<import("@base-u
|
|
|
7
7
|
declare function MenuTrigger({ tooltip, ...props }: Menu$1.Trigger.Props & {
|
|
8
8
|
tooltip?: React$1.ReactNode;
|
|
9
9
|
}): React$1.JSX.Element;
|
|
10
|
-
declare const MenuPopup: ({ children, className, sideOffset, align, alignOffset, side, anchor, collisionAvoidance, ...props }: Menu$1.Popup.Props & {
|
|
10
|
+
declare const MenuPopup: ({ children, className, sideOffset, align, alignOffset, side, anchor, collisionAvoidance, header, viewportClassName, ...props }: Menu$1.Popup.Props & {
|
|
11
|
+
/** Content pinned above the scrolling list, such as a search field. It sits
|
|
12
|
+
* outside the list, so a row scrolled into view can never hide under it. */
|
|
13
|
+
header?: React$1.ReactNode;
|
|
14
|
+
/** Classes for the scrolling list inside the popup, e.g. a lower height
|
|
15
|
+
* cap for a long searchable list. */
|
|
16
|
+
viewportClassName?: string;
|
|
11
17
|
align?: Menu$1.Positioner.Props["align"];
|
|
12
18
|
sideOffset?: Menu$1.Positioner.Props["sideOffset"];
|
|
13
19
|
alignOffset?: Menu$1.Positioner.Props["alignOffset"];
|
|
@@ -37,6 +43,8 @@ declare const MenuSubTrigger: ({ className, inset, children, ...props }: Menu$1.
|
|
|
37
43
|
inset?: boolean;
|
|
38
44
|
}) => React$1.JSX.Element;
|
|
39
45
|
declare const MenuSubPopup: ({ className, sideOffset, alignOffset, align, ...props }: Menu$1.Popup.Props & {
|
|
46
|
+
header?: React$1.ReactNode;
|
|
47
|
+
viewportClassName?: string;
|
|
40
48
|
align?: Menu$1.Positioner.Props["align"];
|
|
41
49
|
sideOffset?: Menu$1.Positioner.Props["sideOffset"];
|
|
42
50
|
alignOffset?: Menu$1.Positioner.Props["alignOffset"];
|
package/dist/components/menu.js
CHANGED
|
@@ -20,7 +20,7 @@ function MenuTrigger({ tooltip, ...props }) {
|
|
|
20
20
|
})
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
const MenuPopup = ({ children, className, sideOffset = 4, align, alignOffset, side = "bottom", anchor, collisionAvoidance, ...props }) => /* @__PURE__ */ jsx(Menu$1.Portal, { children: /* @__PURE__ */ jsx(Menu$1.Positioner, {
|
|
23
|
+
const MenuPopup = ({ children, className, sideOffset = 4, align, alignOffset, side = "bottom", anchor, collisionAvoidance, header, viewportClassName, ...props }) => /* @__PURE__ */ jsx(Menu$1.Portal, { children: /* @__PURE__ */ jsx(Menu$1.Positioner, {
|
|
24
24
|
align: align ?? (anchor ? "start" : "center"),
|
|
25
25
|
alignOffset,
|
|
26
26
|
anchor,
|
|
@@ -29,14 +29,14 @@ const MenuPopup = ({ children, className, sideOffset = 4, align, alignOffset, si
|
|
|
29
29
|
"data-slot": "menu-positioner",
|
|
30
30
|
side,
|
|
31
31
|
sideOffset,
|
|
32
|
-
children: /* @__PURE__ */
|
|
33
|
-
className: cn("bg-popover relative flex origin-(--transform-origin) rounded-lg border shadow-lg/5 outline-none not-dark:bg-clip-padding not-[class*='w-']:min-w-32 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] focus:outline-none dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", className),
|
|
32
|
+
children: /* @__PURE__ */ jsxs(Menu$1.Popup, {
|
|
33
|
+
className: cn("bg-popover relative flex max-h-(--available-height) origin-(--transform-origin) flex-col rounded-lg border shadow-lg/5 outline-none not-dark:bg-clip-padding not-[class*='w-']:min-w-32 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] focus:outline-none dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", className),
|
|
34
34
|
"data-slot": "menu-popup",
|
|
35
35
|
...props,
|
|
36
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
37
|
-
className: "
|
|
36
|
+
children: [header, /* @__PURE__ */ jsx("div", {
|
|
37
|
+
className: cn("min-h-0 w-full flex-1 overflow-y-auto p-1", viewportClassName),
|
|
38
38
|
children
|
|
39
|
-
})
|
|
39
|
+
})]
|
|
40
40
|
})
|
|
41
41
|
}) });
|
|
42
42
|
const MenuGroup = (props) => /* @__PURE__ */ jsx(Menu$1.Group, {
|
|
@@ -41,16 +41,23 @@ export type OutlineRailProps = {
|
|
|
41
41
|
* filter that narrows the tree to nothing cannot take its own control
|
|
42
42
|
* away; the caller decides whether the document has an outline at all. */
|
|
43
43
|
header?: ReactNode;
|
|
44
|
+
/** Name a trailing annotation for assistive technology and its tooltip. */
|
|
45
|
+
formatMetaLabel?: (meta: string) => string;
|
|
44
46
|
/** Depth from which entries start collapsed. Their ancestors still open on
|
|
45
47
|
* their own while one of their descendants is active, so a deep outline
|
|
46
48
|
* reads as the chain down to where the reader is rather than as every
|
|
47
49
|
* branch at once. Omitted: everything starts expanded. */
|
|
48
50
|
collapsedFromLevel?: number;
|
|
51
|
+
/** `panel` and `rail` fill a host-owned track; `popover` owns its disclosure. */
|
|
52
|
+
presentation?: "panel" | "rail" | "popover";
|
|
53
|
+
/** A host that already reserves docked chrome passes zero. */
|
|
54
|
+
bottomInset?: number;
|
|
49
55
|
topOffset?: number;
|
|
50
56
|
panelWidth?: number;
|
|
51
57
|
ariaLabel?: string;
|
|
52
58
|
};
|
|
59
|
+
export declare const OUTLINE_CONTROL_MIN_SIZE = 32;
|
|
53
60
|
/** The entry as one line of text: label, then its title when it has one. */
|
|
54
61
|
export declare const outlineEntryText: (item: OutlineItem) => string;
|
|
55
|
-
export declare const OutlineRail: ({ items, scrollContainerRef, resolvePct, onJump, activeId, header, collapsedFromLevel, topOffset, panelWidth, ariaLabel }: OutlineRailProps) => import("react").JSX.Element | null;
|
|
62
|
+
export declare const OutlineRail: ({ items, scrollContainerRef, resolvePct, onJump, activeId, header, formatMetaLabel, collapsedFromLevel, presentation, bottomInset, topOffset, panelWidth, ariaLabel }: OutlineRailProps) => import("react").JSX.Element | null;
|
|
56
63
|
//#endregion
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { ChevronRightIcon } from "../icons.js";
|
|
2
|
+
import { ChevronRightIcon, PanelLeftIcon } from "../icons.js";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { Tooltip, TooltipContent as TooltipPopup, TooltipTrigger } from "./tooltip.js";
|
|
5
|
+
import { ScrollArea } from "./scroll-area.js";
|
|
5
6
|
import { DirectionalIcon } from "./directional-icon.js";
|
|
7
|
+
import "../lib/panel-inset.js";
|
|
6
8
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
9
|
import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
8
10
|
import { Temporal } from "temporal-polyfill/full";
|
|
9
11
|
//#region src/components/outline-rail.tsx
|
|
10
12
|
/**
|
|
11
|
-
* Outline
|
|
13
|
+
* Outline navigation: an embedded panel, a host-owned rail, or a disclosure.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* jump.
|
|
15
|
+
* Embedded presentations fill their host track. The standalone disclosure
|
|
16
|
+
* owns a toggle above a thin column of ticks; hovering or pressing it reveals
|
|
17
|
+
* the collapsible tree. Click a tick or a row to jump.
|
|
17
18
|
*
|
|
18
19
|
* Generic over the position source: callers supply `resolvePct` (vertical % for
|
|
19
20
|
* a tick) and `onJump`. Active tracking is derived from `resolvePct` by default,
|
|
@@ -29,8 +30,9 @@ const OUTLINE_EMPHASIS = {
|
|
|
29
30
|
primary: "primary",
|
|
30
31
|
secondary: "secondary"
|
|
31
32
|
};
|
|
32
|
-
const
|
|
33
|
-
const
|
|
33
|
+
const OUTLINE_CONTROL_MIN_SIZE = 32;
|
|
34
|
+
const OUTLINE_CONTROL_TARGET_CLASS = "relative pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11";
|
|
35
|
+
const RAIL_WIDTH = 32;
|
|
34
36
|
const TICK_BASE_WIDTH = 6;
|
|
35
37
|
const TICK_LEVEL_STEP = 2;
|
|
36
38
|
const TICK_MAX_LEVEL = 5;
|
|
@@ -87,7 +89,7 @@ const Chevron = ({ open }) => /* @__PURE__ */ jsx(DirectionalIcon, {
|
|
|
87
89
|
flip: !open,
|
|
88
90
|
icon: ChevronRightIcon
|
|
89
91
|
});
|
|
90
|
-
const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId, header, collapsedFromLevel, topOffset = 0, panelWidth = 300, ariaLabel = "Outline" }) => {
|
|
92
|
+
const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId, header, formatMetaLabel, collapsedFromLevel, presentation = "popover", bottomInset, topOffset = 0, panelWidth = 300, ariaLabel = "Outline" }) => {
|
|
91
93
|
const [pctById, setPctById] = useState(/* @__PURE__ */ new Map());
|
|
92
94
|
const [derivedActive, setDerivedActive] = useState(null);
|
|
93
95
|
const [hovered, setHovered] = useState(false);
|
|
@@ -97,7 +99,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
97
99
|
const [hoveredId, setHoveredId] = useState(null);
|
|
98
100
|
const panelId = useId();
|
|
99
101
|
const triggerId = useId();
|
|
100
|
-
const panelOpen = hovered || pinned;
|
|
102
|
+
const panelOpen = presentation === "panel" || hovered || pinned;
|
|
101
103
|
const closeTimer = useRef(null);
|
|
102
104
|
const manualLockUntil = useRef(0);
|
|
103
105
|
const panelRef = useRef(null);
|
|
@@ -232,7 +234,13 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
232
234
|
const activeIndex = items.findIndex((item) => item.id === activeId);
|
|
233
235
|
useLayoutEffect(() => {
|
|
234
236
|
if (activeIndex === -1 || !panelOpen) return;
|
|
235
|
-
panelRef.current
|
|
237
|
+
const panel = panelRef.current;
|
|
238
|
+
const row = panel?.querySelector(`[${ACTIVE_ROW_ATTRIBUTE}]`);
|
|
239
|
+
if (!panel || !(row instanceof HTMLElement)) return;
|
|
240
|
+
const panelBox = panel.getBoundingClientRect();
|
|
241
|
+
const rowBox = row.getBoundingClientRect();
|
|
242
|
+
if (rowBox.top < panelBox.top) panel.scrollTop += rowBox.top - panelBox.top;
|
|
243
|
+
else if (rowBox.bottom > panelBox.bottom) panel.scrollTop += rowBox.bottom - panelBox.bottom;
|
|
236
244
|
}, [activeIndex, panelOpen]);
|
|
237
245
|
const openPanel = useCallback(() => {
|
|
238
246
|
if (closeTimer.current !== null) {
|
|
@@ -246,7 +254,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
246
254
|
closeTimer.current = setTimeout(() => setHovered(false), 120);
|
|
247
255
|
}, []);
|
|
248
256
|
useEffect(() => {
|
|
249
|
-
if (pinned) panelRef.current?.focus();
|
|
257
|
+
if (pinned) panelRef.current?.closest("nav")?.focus();
|
|
250
258
|
}, [pinned]);
|
|
251
259
|
const closePanel = useCallback(() => {
|
|
252
260
|
if (closeTimer.current !== null) {
|
|
@@ -267,23 +275,21 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
267
275
|
const highlighted = isActive || isHovered;
|
|
268
276
|
const indent = 8 + Math.min(node.item.level, maxLevel) * 12;
|
|
269
277
|
return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsxs("div", {
|
|
270
|
-
className: cn("flex items-center rounded-md pe-2.5",
|
|
278
|
+
className: cn("flex items-center rounded-md pe-2.5", highlighted && "bg-accent"),
|
|
271
279
|
...isActive ? { [ACTIVE_ROW_ATTRIBUTE]: "" } : {},
|
|
272
280
|
onMouseEnter: () => setHoveredId(node.item.id),
|
|
273
281
|
onMouseLeave: () => setHoveredId(null),
|
|
274
|
-
style: hasChildren ? {
|
|
275
|
-
position: "sticky",
|
|
276
|
-
top: node.item.level * ROW_H,
|
|
277
|
-
zIndex: 40 - node.item.level,
|
|
278
|
-
background: highlighted ? "linear-gradient(var(--color-accent), var(--color-accent)), var(--color-popover)" : "var(--color-popover)"
|
|
279
|
-
} : void 0,
|
|
280
282
|
children: [
|
|
281
283
|
hasChildren ? /* @__PURE__ */ jsx("button", {
|
|
282
284
|
"aria-expanded": !isCollapsed,
|
|
283
285
|
"aria-label": isCollapsed ? "Expand" : "Collapse",
|
|
284
|
-
className: "text-muted-foreground hover:text-foreground flex
|
|
286
|
+
className: cn("text-muted-foreground hover:text-foreground flex shrink-0 items-center justify-center", OUTLINE_CONTROL_TARGET_CLASS),
|
|
287
|
+
style: {
|
|
288
|
+
minWidth: 32,
|
|
289
|
+
minHeight: 32,
|
|
290
|
+
marginInlineStart: indent - 4
|
|
291
|
+
},
|
|
285
292
|
onClick: (event) => toggleCollapse(node.item.id, event.currentTarget.parentElement),
|
|
286
|
-
style: { marginInlineStart: indent - 4 },
|
|
287
293
|
type: "button",
|
|
288
294
|
children: /* @__PURE__ */ jsx(Chevron, { open: !isCollapsed })
|
|
289
295
|
}) : /* @__PURE__ */ jsx("span", {
|
|
@@ -314,10 +320,22 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
314
320
|
children: node.item.title
|
|
315
321
|
})] })
|
|
316
322
|
}), /* @__PURE__ */ jsx(TooltipPopup, { children: outlineEntryText(node.item) })] }),
|
|
317
|
-
node.item.meta !== void 0 && /* @__PURE__ */ jsx(
|
|
323
|
+
node.item.meta !== void 0 && (formatMetaLabel ? /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
324
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
325
|
+
"aria-label": formatMetaLabel(node.item.meta),
|
|
326
|
+
className: cn("text-foreground-placeholder text-2xs shrink-0 tabular-nums", OUTLINE_CONTROL_TARGET_CLASS),
|
|
327
|
+
style: {
|
|
328
|
+
minWidth: 32,
|
|
329
|
+
minHeight: 32
|
|
330
|
+
},
|
|
331
|
+
onClick: () => jumpTo(node.item.id),
|
|
332
|
+
type: "button"
|
|
333
|
+
}),
|
|
334
|
+
children: node.item.meta
|
|
335
|
+
}), /* @__PURE__ */ jsx(TooltipPopup, { children: formatMetaLabel(node.item.meta) })] }) : /* @__PURE__ */ jsx("span", {
|
|
318
336
|
className: "text-foreground-placeholder text-2xs shrink-0 ps-2 tabular-nums",
|
|
319
337
|
children: node.item.meta
|
|
320
|
-
})
|
|
338
|
+
}))
|
|
321
339
|
]
|
|
322
340
|
}), hasChildren && !isCollapsed && /* @__PURE__ */ jsx("ul", {
|
|
323
341
|
className: "m-0 list-none p-0",
|
|
@@ -337,18 +355,26 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
337
355
|
const ghostItem = ghostPct === void 0 ? void 0 : items.find((item) => item.id === hoveredId);
|
|
338
356
|
return /* @__PURE__ */ jsxs("div", {
|
|
339
357
|
"aria-label": ariaLabel,
|
|
340
|
-
className:
|
|
358
|
+
className: OUTLINE_PRESENTATION_CLASS[presentation],
|
|
341
359
|
role: "group",
|
|
342
360
|
style: {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
361
|
+
marginBlockEnd: bottomInset ?? "max(env(safe-area-inset-bottom, 0px), var(--document-panel-bottom-inset, 0px))",
|
|
362
|
+
...presentation === "popover" ? {
|
|
363
|
+
top: topOffset,
|
|
364
|
+
bottom: 0,
|
|
365
|
+
width: RAIL_WIDTH
|
|
366
|
+
} : {}
|
|
346
367
|
},
|
|
347
368
|
children: [
|
|
348
|
-
/* @__PURE__ */ jsx("button", {
|
|
369
|
+
presentation === "popover" && /* @__PURE__ */ jsx("button", {
|
|
349
370
|
"aria-controls": panelId,
|
|
350
371
|
"aria-expanded": panelOpen,
|
|
351
|
-
className: "focus-visible:ring-ring bg-popover text-popover-foreground
|
|
372
|
+
className: cn("focus-visible:ring-ring bg-popover text-popover-foreground flex shrink-0 items-center justify-center self-start rounded-md focus-visible:ring-2 focus-visible:outline-none", "pointer-coarse:my-1.5", OUTLINE_CONTROL_TARGET_CLASS),
|
|
373
|
+
"aria-label": ariaLabel,
|
|
374
|
+
style: {
|
|
375
|
+
minWidth: 32,
|
|
376
|
+
minHeight: 32
|
|
377
|
+
},
|
|
352
378
|
id: triggerId,
|
|
353
379
|
onClick: () => {
|
|
354
380
|
if (pinned) {
|
|
@@ -359,10 +385,15 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
359
385
|
openPanel();
|
|
360
386
|
},
|
|
361
387
|
type: "button",
|
|
362
|
-
children:
|
|
388
|
+
children: /* @__PURE__ */ jsx(PanelLeftIcon, {
|
|
389
|
+
"aria-hidden": true,
|
|
390
|
+
className: "size-4 rtl:-scale-x-100"
|
|
391
|
+
})
|
|
363
392
|
}),
|
|
364
|
-
/* @__PURE__ */ jsxs("div", {
|
|
365
|
-
className: "relative h-
|
|
393
|
+
presentation !== "panel" && /* @__PURE__ */ jsxs("div", {
|
|
394
|
+
className: "relative min-h-0 flex-1",
|
|
395
|
+
"data-outline-ticks": true,
|
|
396
|
+
style: presentation === "popover" ? { height: `calc(100% - 32px)` } : void 0,
|
|
366
397
|
onMouseEnter: openPanel,
|
|
367
398
|
onMouseLeave: scheduleClose,
|
|
368
399
|
onWheel: (event) => {
|
|
@@ -379,7 +410,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
379
410
|
onMouseEnter: () => setHoveredId(item.id),
|
|
380
411
|
onMouseLeave: () => setHoveredId(null),
|
|
381
412
|
style: {
|
|
382
|
-
top:
|
|
413
|
+
top: `clamp(2px, ${pct}%, calc(100% - 2px))`,
|
|
383
414
|
transform: "translateY(-50%)",
|
|
384
415
|
width: isHovered ? tickWidth(item.level) + 8 : tickWidth(item.level),
|
|
385
416
|
height: tickHeight(isHovered, isActive),
|
|
@@ -391,7 +422,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
391
422
|
"aria-hidden": true,
|
|
392
423
|
className: "absolute end-0 rounded-full opacity-100",
|
|
393
424
|
style: {
|
|
394
|
-
top:
|
|
425
|
+
top: `clamp(2px, ${ghostPct}%, calc(100% - 2px))`,
|
|
395
426
|
transform: "translateY(-50%)",
|
|
396
427
|
width: tickWidth(ghostItem.level) + 8,
|
|
397
428
|
height: 4,
|
|
@@ -399,13 +430,15 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
399
430
|
}
|
|
400
431
|
})]
|
|
401
432
|
}),
|
|
402
|
-
/* @__PURE__ */ jsxs("nav", {
|
|
433
|
+
presentation !== "rail" && /* @__PURE__ */ jsxs("nav", {
|
|
434
|
+
"aria-label": ariaLabel,
|
|
403
435
|
"aria-hidden": !panelOpen,
|
|
404
436
|
id: panelId,
|
|
405
437
|
inert: panelOpen ? void 0 : true,
|
|
406
438
|
tabIndex: -1,
|
|
407
|
-
className: cn("
|
|
439
|
+
className: cn("bg-popover text-popover-foreground flex min-h-0 flex-col", presentation === "popover" && "border-border absolute rounded-xl border shadow-lg transition-[opacity,transform] duration-150", outlinePanelVisibilityClass(presentation, panelOpen)),
|
|
408
440
|
onBlurCapture: (event) => {
|
|
441
|
+
if (event.relatedTarget instanceof HTMLElement && event.relatedTarget.id === triggerId) return;
|
|
409
442
|
if (pinned && !event.currentTarget.contains(event.relatedTarget)) {
|
|
410
443
|
closePanel();
|
|
411
444
|
return;
|
|
@@ -422,28 +455,42 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
|
|
|
422
455
|
onMouseEnter: openPanel,
|
|
423
456
|
onMouseLeave: scheduleClose,
|
|
424
457
|
onWheel: (event) => {
|
|
425
|
-
const panel =
|
|
458
|
+
const panel = panelRef.current;
|
|
459
|
+
if (!panel) return;
|
|
426
460
|
const room = panel.scrollHeight - panel.clientHeight;
|
|
427
461
|
if (room > WHEEL_EDGE_TOLERANCE && (event.deltaY < 0 ? panel.scrollTop > WHEEL_EDGE_TOLERANCE : panel.scrollTop < room - WHEEL_EDGE_TOLERANCE)) return;
|
|
428
462
|
scrollContainerRef.current?.scrollBy(0, event.deltaY);
|
|
429
463
|
},
|
|
430
|
-
|
|
431
|
-
style: {
|
|
464
|
+
style: presentation === "popover" ? {
|
|
432
465
|
top: 0,
|
|
433
|
-
insetInlineEnd:
|
|
434
|
-
width: panelWidth,
|
|
435
|
-
|
|
436
|
-
},
|
|
466
|
+
insetInlineEnd: 38,
|
|
467
|
+
width: `min(${panelWidth}px, calc(100vw - 54px))`,
|
|
468
|
+
height: "calc(100% - 24px)"
|
|
469
|
+
} : void 0,
|
|
437
470
|
children: [header !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
438
|
-
className: "bg-popover
|
|
471
|
+
className: "bg-popover z-50 shrink-0 border-b p-2",
|
|
439
472
|
children: header
|
|
440
|
-
}), /* @__PURE__ */ jsx(
|
|
441
|
-
|
|
442
|
-
|
|
473
|
+
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
474
|
+
axis: "vertical",
|
|
475
|
+
className: "min-h-0 flex-1",
|
|
476
|
+
viewportRef: panelRef,
|
|
477
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
478
|
+
className: "m-0 list-none p-0 pb-2",
|
|
479
|
+
children: tree.map(renderNode)
|
|
480
|
+
})
|
|
443
481
|
})]
|
|
444
482
|
})
|
|
445
483
|
]
|
|
446
484
|
});
|
|
447
485
|
};
|
|
486
|
+
const OUTLINE_PRESENTATION_CLASS = {
|
|
487
|
+
popover: "absolute end-0 z-20 flex flex-col pointer-coarse:min-w-11",
|
|
488
|
+
panel: "relative flex min-h-0 w-full flex-1 flex-col",
|
|
489
|
+
rail: "relative flex min-h-0 w-full flex-1 flex-col"
|
|
490
|
+
};
|
|
491
|
+
function outlinePanelVisibilityClass(presentation, open) {
|
|
492
|
+
if (presentation === "panel") return "flex-1";
|
|
493
|
+
return open ? "translate-x-0 opacity-100" : "pointer-events-none translate-x-2 opacity-0";
|
|
494
|
+
}
|
|
448
495
|
//#endregion
|
|
449
|
-
export { OUTLINE_EMPHASIS, OutlineRail, outlineEntryText };
|
|
496
|
+
export { OUTLINE_CONTROL_MIN_SIZE, OUTLINE_EMPHASIS, OutlineRail, outlineEntryText };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { XIcon } from "../icons.js";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { Button } from "./button.js";
|
|
5
5
|
import { InputGroup, InputGroupAddon, InputGroupInput } from "./input-group.js";
|
|
@@ -13,41 +13,37 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
13
13
|
*/
|
|
14
14
|
const SearchField = ({ value, onValueChange, clearLabel, groupClassName, className, onKeyDown, ...props }) => /* @__PURE__ */ jsxs(InputGroup, {
|
|
15
15
|
className: cn("min-h-11 sm:min-h-0", groupClassName),
|
|
16
|
-
children: [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
children: [/* @__PURE__ */ jsx(InputGroupInput, {
|
|
17
|
+
autoComplete: "off",
|
|
18
|
+
spellCheck: false,
|
|
19
|
+
...props,
|
|
20
|
+
className: cn("max-sm:h-11 max-sm:leading-11", className),
|
|
21
|
+
onChange: (event) => {
|
|
22
|
+
onValueChange(event.target.value);
|
|
23
|
+
},
|
|
24
|
+
onKeyDown: (event) => {
|
|
25
|
+
if (event.key === "Escape" && value.length > 0) {
|
|
26
|
+
event.preventDefault();
|
|
27
|
+
event.stopPropagation();
|
|
28
|
+
onValueChange("");
|
|
29
|
+
}
|
|
30
|
+
onKeyDown?.(event);
|
|
31
|
+
},
|
|
32
|
+
type: "search",
|
|
33
|
+
value
|
|
34
|
+
}), value.length > 0 && /* @__PURE__ */ jsx(InputGroupAddon, {
|
|
35
|
+
align: "inline-end",
|
|
36
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
37
|
+
"aria-label": clearLabel,
|
|
38
|
+
onClick: () => {
|
|
39
|
+
onValueChange("");
|
|
25
40
|
},
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
onValueChange("");
|
|
31
|
-
}
|
|
32
|
-
onKeyDown?.(event);
|
|
33
|
-
},
|
|
34
|
-
type: "search",
|
|
35
|
-
value
|
|
36
|
-
}),
|
|
37
|
-
value.length > 0 && /* @__PURE__ */ jsx(InputGroupAddon, {
|
|
38
|
-
align: "inline-end",
|
|
39
|
-
children: /* @__PURE__ */ jsx(Button, {
|
|
40
|
-
"aria-label": clearLabel,
|
|
41
|
-
onClick: () => {
|
|
42
|
-
onValueChange("");
|
|
43
|
-
},
|
|
44
|
-
size: "icon-xs",
|
|
45
|
-
type: "button",
|
|
46
|
-
variant: "ghost",
|
|
47
|
-
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
48
|
-
})
|
|
41
|
+
size: "icon-xs",
|
|
42
|
+
type: "button",
|
|
43
|
+
variant: "ghost",
|
|
44
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
49
45
|
})
|
|
50
|
-
]
|
|
46
|
+
})]
|
|
51
47
|
});
|
|
52
48
|
//#endregion
|
|
53
49
|
export { SearchField };
|
package/dist/components/sheet.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { XIcon } from "../icons.js";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { OVERLAY_LAYER_CLASS_NAMES } from "../lib/overlay-layer.js";
|
|
4
5
|
import { renderTooltipTrigger } from "./tooltip-trigger-helper.js";
|
|
5
6
|
import { Button } from "./button.js";
|
|
6
7
|
import { ScrollArea } from "./scroll-area.js";
|
|
@@ -28,12 +29,12 @@ function SheetClose({ tooltip, ...props }) {
|
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
const SheetBackdrop = ({ className, ...props }) => /* @__PURE__ */ jsx(Dialog.Backdrop, {
|
|
31
|
-
className: cn("fixed inset-0
|
|
32
|
+
className: cn("fixed inset-0 bg-black/32 backdrop-blur-sm transition-opacity duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0", OVERLAY_LAYER_CLASS_NAMES.default, className),
|
|
32
33
|
"data-slot": "sheet-backdrop",
|
|
33
34
|
...props
|
|
34
35
|
});
|
|
35
36
|
const SheetViewport = ({ className: _className, side, variant = "default", ...props }) => /* @__PURE__ */ jsx(Dialog.Viewport, {
|
|
36
|
-
className: cn("fixed inset-0
|
|
37
|
+
className: cn("fixed inset-0", OVERLAY_LAYER_CLASS_NAMES.default, side === "block-end" && "grid grid-rows-[1fr_auto] pt-12", side === "block-start" && "grid grid-rows-[auto_1fr] pb-12", side === "inline-start" && "flex justify-start", side === "inline-end" && "flex justify-end", variant === "inset" && "sm:p-4"),
|
|
37
38
|
"data-slot": "sheet-viewport",
|
|
38
39
|
...props
|
|
39
40
|
});
|
|
@@ -86,7 +86,7 @@ declare const SidebarMenu: ({ className, ...props }: React.ComponentProps<"ul">)
|
|
|
86
86
|
declare const SidebarMenuItem: ({ className, ...props }: React.ComponentProps<"li">) => import("react").JSX.Element;
|
|
87
87
|
declare const sidebarMenuButtonVariants: (props?: ({
|
|
88
88
|
variant?: "default" | "outline" | null | undefined;
|
|
89
|
-
size?: "
|
|
89
|
+
size?: "default" | "lg" | "sm" | "rail" | null | undefined;
|
|
90
90
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
91
91
|
/**
|
|
92
92
|
* The footer's avatar trigger, signed in (user menu) or not (sign-in): a
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Switch as Switch$1 } from "@base-ui/react/switch";
|
|
5
|
+
//#region src/components/switch.tsx
|
|
6
|
+
const Switch = ({ className, ...props }) => /* @__PURE__ */ jsx(Switch$1.Root, {
|
|
7
|
+
className: cn("focus-visible:ring-ring focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input relative inline-flex h-5 w-9 shrink-0 items-center rounded-full outline-none focus-visible:ring-2 focus-visible:ring-offset-1 data-disabled:opacity-64", className),
|
|
8
|
+
"data-slot": "switch",
|
|
9
|
+
...props,
|
|
10
|
+
children: /* @__PURE__ */ jsx(Switch$1.Thumb, {
|
|
11
|
+
className: "bg-background pointer-events-none block size-4 rounded-full shadow-xs transition-transform ltr:data-checked:translate-x-4.5 ltr:data-unchecked:translate-x-0.5 rtl:data-checked:-translate-x-4.5 rtl:data-unchecked:-translate-x-0.5",
|
|
12
|
+
"data-slot": "switch-thumb"
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Switch };
|
package/dist/components/toast.js
CHANGED
|
@@ -3,6 +3,7 @@ import { CircleAlertIcon, CircleCheckIcon, InfoIcon, TriangleAlertIcon, XIcon }
|
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { Loader } from "./loader.js";
|
|
5
5
|
import { buttonVariants } from "./button.js";
|
|
6
|
+
import { ScrollArea } from "./scroll-area.js";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import * as React$1 from "react";
|
|
8
9
|
import { Toast } from "@base-ui/react/toast";
|
|
@@ -74,18 +75,22 @@ const Toasts = ({ position }) => {
|
|
|
74
75
|
})(),
|
|
75
76
|
toast: toastItem,
|
|
76
77
|
children: /* @__PURE__ */ jsxs(Toast.Content, {
|
|
77
|
-
className: "pointer-events-auto flex items-center gap-3
|
|
78
|
+
className: "pointer-events-auto flex items-center gap-3 px-3.5 py-3 text-sm transition-opacity duration-250 select-text data-behind:opacity-0 data-behind:not-data-expanded:pointer-events-none data-expanded:opacity-100",
|
|
78
79
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
79
80
|
className: "flex min-w-0 flex-1 gap-2",
|
|
80
|
-
children: [/* @__PURE__ */ jsx(ToastIcon, { type: toastItem.type }), /* @__PURE__ */
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
children: [/* @__PURE__ */ jsx(ToastIcon, { type: toastItem.type }), /* @__PURE__ */ jsx(ScrollArea, {
|
|
82
|
+
axis: "vertical",
|
|
83
|
+
className: "h-auto min-w-0 flex-1 [&_[data-slot=scroll-area-viewport]]:max-h-[60dvh]",
|
|
84
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
85
|
+
className: "flex min-w-0 flex-col gap-0.5 select-text",
|
|
86
|
+
children: [/* @__PURE__ */ jsx(Toast.Title, {
|
|
87
|
+
className: "font-medium wrap-anywhere whitespace-pre-wrap",
|
|
88
|
+
"data-slot": "toast-title"
|
|
89
|
+
}), /* @__PURE__ */ jsx(Toast.Description, {
|
|
90
|
+
className: "text-muted-foreground wrap-anywhere whitespace-pre-wrap",
|
|
91
|
+
"data-slot": "toast-description"
|
|
92
|
+
})]
|
|
93
|
+
})
|
|
89
94
|
})]
|
|
90
95
|
}), /* @__PURE__ */ jsxs("div", {
|
|
91
96
|
className: "ms-auto flex shrink-0 items-center gap-2",
|
|
@@ -132,20 +137,31 @@ const AnchoredToasts = () => {
|
|
|
132
137
|
toast: toastItem,
|
|
133
138
|
children: tooltipStyle ? /* @__PURE__ */ jsx(Toast.Content, {
|
|
134
139
|
className: "pointer-events-auto px-2 py-1 select-text",
|
|
135
|
-
children: /* @__PURE__ */ jsx(
|
|
140
|
+
children: /* @__PURE__ */ jsx(ScrollArea, {
|
|
141
|
+
axis: "vertical",
|
|
142
|
+
className: "h-auto [&_[data-slot=scroll-area-viewport]]:max-h-[60dvh]",
|
|
143
|
+
children: /* @__PURE__ */ jsx(Toast.Title, {
|
|
144
|
+
className: "wrap-anywhere whitespace-pre-wrap",
|
|
145
|
+
"data-slot": "toast-title"
|
|
146
|
+
})
|
|
147
|
+
})
|
|
136
148
|
}) : /* @__PURE__ */ jsxs(Toast.Content, {
|
|
137
|
-
className: "pointer-events-auto flex items-center gap-3
|
|
149
|
+
className: "pointer-events-auto flex items-center gap-3 px-3.5 py-3 text-sm select-text",
|
|
138
150
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
139
151
|
className: "flex min-w-0 flex-1 gap-2",
|
|
140
|
-
children: [/* @__PURE__ */ jsx(ToastIcon, { type: toastItem.type }), /* @__PURE__ */
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
children: [/* @__PURE__ */ jsx(ToastIcon, { type: toastItem.type }), /* @__PURE__ */ jsx(ScrollArea, {
|
|
153
|
+
axis: "vertical",
|
|
154
|
+
className: "h-auto min-w-0 flex-1 [&_[data-slot=scroll-area-viewport]]:max-h-[60dvh]",
|
|
155
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
156
|
+
className: "flex min-w-0 flex-col gap-0.5 select-text",
|
|
157
|
+
children: [/* @__PURE__ */ jsx(Toast.Title, {
|
|
158
|
+
className: "font-medium wrap-anywhere whitespace-pre-wrap",
|
|
159
|
+
"data-slot": "toast-title"
|
|
160
|
+
}), /* @__PURE__ */ jsx(Toast.Description, {
|
|
161
|
+
className: "text-muted-foreground wrap-anywhere whitespace-pre-wrap",
|
|
162
|
+
"data-slot": "toast-description"
|
|
163
|
+
})]
|
|
164
|
+
})
|
|
149
165
|
})]
|
|
150
166
|
}), toastItem.actionProps && /* @__PURE__ */ jsx(Toast.Action, {
|
|
151
167
|
className: cn(buttonVariants({ size: "xs" }), "ms-auto shrink-0 select-none"),
|
|
@@ -204,8 +220,8 @@ function normalizeToastActionProps({ action, actionProps, includeEmptyActionProp
|
|
|
204
220
|
} };
|
|
205
221
|
}
|
|
206
222
|
function getDefaultToastTimeout(type) {
|
|
207
|
-
if (type === "loading") return 0;
|
|
208
|
-
if (type === "
|
|
223
|
+
if (type === "loading" || type === "error") return 0;
|
|
224
|
+
if (type === "warning") return 6e3;
|
|
209
225
|
return 4e3;
|
|
210
226
|
}
|
|
211
227
|
function normalizeToastTimeout(timeout) {
|