@stll/ui 0.44.1 → 0.46.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/README.md +2 -1
- package/dist/components/accordion.d.ts +6 -2
- package/dist/components/accordion.js +4 -4
- package/dist/components/ai-label.d.ts +33 -0
- package/dist/components/ai-label.js +42 -0
- package/dist/components/alert-dialog.js +3 -2
- package/dist/components/animated-count.d.ts +13 -0
- package/dist/components/animated-count.js +63 -0
- package/dist/components/application-rail.js +1 -1
- package/dist/components/brand-icons.d.ts +1 -0
- package/dist/components/brand-icons.js +8 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js +12 -2
- package/dist/components/command.js +1 -1
- 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/dialog.js +3 -2
- 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/input-group.d.ts +1 -1
- package/dist/components/input-otp.js +1 -1
- package/dist/components/landing.d.ts +1 -1
- package/dist/components/landing.js +2 -2
- package/dist/components/list.d.ts +8 -2
- package/dist/components/list.js +10 -4
- 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/popover.js +1 -1
- package/dist/components/search-field.js +30 -34
- package/dist/components/select.js +1 -1
- package/dist/components/sheet.js +22 -4
- package/dist/components/sidebar.d.ts +1 -1
- package/dist/components/sidebar.js +8 -8
- package/dist/components/status-mark.d.ts +17 -0
- package/dist/components/status-mark.js +74 -0
- package/dist/components/swap-text.d.ts +16 -0
- package/dist/components/swap-text.js +52 -0
- package/dist/components/switch.d.ts +5 -0
- package/dist/components/switch.js +16 -0
- package/dist/components/table-chart.d.ts +20 -0
- package/dist/components/table-chart.js +274 -0
- package/dist/components/tabs.js +1 -1
- package/dist/components/toast.js +42 -25
- package/dist/components/workspace-shell.js +5 -4
- package/dist/icons.js +1 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/inspector/dock.js +1 -1
- package/dist/inspector/entity-tab.js +1 -2
- package/dist/kanban/virtual-cell.js +1 -1
- 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/lib/safe-area.d.ts +11 -0
- package/dist/lib/safe-area.js +12 -0
- package/dist/review/review-word-diff.d.ts +13 -0
- package/dist/review/review-word-diff.js +78 -0
- package/dist/styles/theme.css +79 -0
- package/package.json +64 -8
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { DatePickerPopover } from "./date-picker-popover.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { useId, useRef, useState } from "react";
|
|
6
|
+
//#region src/components/date-range-filter.tsx
|
|
7
|
+
/** Both calendar bounds and the focus handoff belong to the range. */
|
|
8
|
+
const DateRangeFilter = ({ from, to, onFromChange, onToChange, fromLabel, toLabel, className, maxDate, ...pickerProps }) => {
|
|
9
|
+
const id = useId();
|
|
10
|
+
const toRef = useRef(null);
|
|
11
|
+
const [picker, setPicker] = useState({ type: "closed" });
|
|
12
|
+
const fromMax = to && (!maxDate || to < maxDate) ? to : maxDate;
|
|
13
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
14
|
+
className: cn("flex flex-col gap-1.5", className),
|
|
15
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
16
|
+
className: "flex min-w-0 flex-col gap-1.5",
|
|
17
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
18
|
+
id: `${id}-from-label`,
|
|
19
|
+
className: "text-muted-foreground text-xs font-medium",
|
|
20
|
+
children: fromLabel
|
|
21
|
+
}), /* @__PURE__ */ jsx(DatePickerPopover, {
|
|
22
|
+
...pickerProps,
|
|
23
|
+
mode: "date",
|
|
24
|
+
id: `${id}-from`,
|
|
25
|
+
defaultOpen: false,
|
|
26
|
+
labelledBy: `${id}-from-label`,
|
|
27
|
+
dateInputLabel: fromLabel,
|
|
28
|
+
value: from,
|
|
29
|
+
maxDate: fromMax,
|
|
30
|
+
minDate: void 0,
|
|
31
|
+
triggerRef: void 0,
|
|
32
|
+
focusTriggerOnOpen: false,
|
|
33
|
+
open: picker.type === "from",
|
|
34
|
+
onOpenChange: (open) => setPicker(open ? { type: "from" } : { type: "closed" }),
|
|
35
|
+
onChange: (next) => {
|
|
36
|
+
onFromChange(next);
|
|
37
|
+
if (!next) return;
|
|
38
|
+
setPicker({
|
|
39
|
+
type: "to",
|
|
40
|
+
focus: "trigger"
|
|
41
|
+
});
|
|
42
|
+
toRef.current?.focus();
|
|
43
|
+
}
|
|
44
|
+
})]
|
|
45
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
46
|
+
className: "flex min-w-0 flex-col gap-1.5",
|
|
47
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
48
|
+
id: `${id}-to-label`,
|
|
49
|
+
className: "text-muted-foreground text-xs font-medium",
|
|
50
|
+
children: toLabel
|
|
51
|
+
}), /* @__PURE__ */ jsx(DatePickerPopover, {
|
|
52
|
+
...pickerProps,
|
|
53
|
+
mode: "date",
|
|
54
|
+
id: `${id}-to`,
|
|
55
|
+
defaultOpen: false,
|
|
56
|
+
labelledBy: `${id}-to-label`,
|
|
57
|
+
dateInputLabel: toLabel,
|
|
58
|
+
value: to,
|
|
59
|
+
minDate: from ?? void 0,
|
|
60
|
+
maxDate,
|
|
61
|
+
open: picker.type === "to",
|
|
62
|
+
triggerRef: toRef,
|
|
63
|
+
focusTriggerOnOpen: picker.type === "to" && picker.focus === "trigger",
|
|
64
|
+
onOpenChange: (open) => setPicker(open ? {
|
|
65
|
+
type: "to",
|
|
66
|
+
focus: "calendar"
|
|
67
|
+
} : { type: "closed" }),
|
|
68
|
+
onChange: onToChange
|
|
69
|
+
})]
|
|
70
|
+
})]
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
export { DateRangeFilter };
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { XIcon } from "../icons.js";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { OVERLAY_LAYER_CLASS_NAMES } from "../lib/overlay-layer.js";
|
|
5
|
+
import { SAFE_AREA_OVERLAY_GUTTER_CLASS_NAME } from "../lib/safe-area.js";
|
|
5
6
|
import { renderTooltipTrigger } from "./tooltip-trigger-helper.js";
|
|
6
7
|
import { Button } from "./button.js";
|
|
7
8
|
import { ScrollArea } from "./scroll-area.js";
|
|
@@ -86,7 +87,7 @@ const DialogBackdrop = ({ className, layer = "default", ...props }) => /* @__PUR
|
|
|
86
87
|
...props
|
|
87
88
|
});
|
|
88
89
|
const DialogViewport = ({ className, layer = "default", ...props }) => /* @__PURE__ */ jsx(Dialog$1.Viewport, {
|
|
89
|
-
className: cn("fixed inset-0 grid grid-rows-[1fr_auto_3fr] justify-items-center
|
|
90
|
+
className: cn("fixed inset-0 grid grid-rows-[1fr_auto_3fr] justify-items-center", SAFE_AREA_OVERLAY_GUTTER_CLASS_NAME, OVERLAY_LAYER_CLASS_NAMES[layer], className),
|
|
90
91
|
"data-slot": "dialog-viewport",
|
|
91
92
|
...props
|
|
92
93
|
});
|
|
@@ -100,7 +101,7 @@ const DialogPopup = ({ backdropClassName, className, children, showCloseButton =
|
|
|
100
101
|
className: cn(bottomStickOnMobile && "max-sm:grid-rows-[1fr_auto] max-sm:p-0 max-sm:pt-12", viewportClassName),
|
|
101
102
|
layer,
|
|
102
103
|
children: /* @__PURE__ */ jsxs(Dialog$1.Popup, {
|
|
103
|
-
className: cn("bg-popover text-popover-foreground relative row-start-2 flex max-h-full min-h-0 w-full max-w-lg min-w-0 -translate-y-[calc(1.25rem*var(--nested-dialogs))] scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-
|
|
104
|
+
className: cn("bg-popover text-popover-foreground relative row-start-2 flex max-h-full min-h-0 w-full max-w-lg min-w-0 -translate-y-[calc(1.25rem*var(--nested-dialogs))] scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 transition-[scale,opacity,translate] duration-200 ease-out will-change-transform not-dark:bg-clip-padding before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-ending-style:scale-98 data-ending-style:opacity-0 data-ending-style:duration-150 data-nested:data-ending-style:translate-y-8 data-nested-dialog-open:origin-top data-starting-style:scale-98 data-starting-style:opacity-0 data-nested:data-starting-style:translate-y-8 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", bottomStickOnMobile && "max-sm:max-w-none max-sm:rounded-none max-sm:border-x-0 max-sm:border-t max-sm:border-b-0 max-sm:pb-(--safe-area-bottom) max-sm:opacity-[calc(1-min(var(--nested-dialogs),1))] max-sm:before:hidden max-sm:before:rounded-none max-sm:data-ending-style:translate-y-4 max-sm:data-starting-style:translate-y-4", className),
|
|
104
105
|
"data-slot": "dialog-popup",
|
|
105
106
|
...props,
|
|
106
107
|
children: [
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CourtBadgeSize } from "./court-badge.js";
|
|
2
|
+
import { DocumentIdentity } from "./document-identity-badge.logic.js";
|
|
3
|
+
//#region src/components/document-identity-badge.d.ts
|
|
4
|
+
export declare const DocumentIdentityBadge: ({ identity, size, title }: DocumentIdentityBadgeProps) => import("react").JSX.Element;
|
|
5
|
+
type DocumentIdentityBadgeProps = {
|
|
6
|
+
identity: DocumentIdentity;
|
|
7
|
+
/** Court chip size; statute labels follow their container width. */
|
|
8
|
+
size?: CourtBadgeSize | undefined;
|
|
9
|
+
/** Omit when the enclosing tab already supplies the full-title tooltip. */
|
|
10
|
+
title?: string | undefined;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { FileTextIcon } from "../icons.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { Tooltip, TooltipContent as TooltipPopup, TooltipTrigger } from "./tooltip.js";
|
|
4
|
+
import { CourtBadge } from "./court-badge.js";
|
|
5
|
+
import { COURT_TIER_WEIGHT, statuteIdentityLabels } from "./document-identity-badge.logic.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { panic } from "better-result";
|
|
8
|
+
//#region src/components/document-identity-badge.tsx
|
|
9
|
+
const DocumentIdentityBadge = ({ identity, size, title }) => {
|
|
10
|
+
const content = documentIdentityMark(identity, size);
|
|
11
|
+
if (title === void 0) return content;
|
|
12
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
13
|
+
render: /* @__PURE__ */ jsx("span", { className: "inline-flex max-w-full min-w-0" }),
|
|
14
|
+
children: content
|
|
15
|
+
}), /* @__PURE__ */ jsx(TooltipPopup, { children: title })] });
|
|
16
|
+
};
|
|
17
|
+
function documentIdentityMark(identity, size) {
|
|
18
|
+
switch (identity.kind) {
|
|
19
|
+
case "statute": {
|
|
20
|
+
const labels = statuteIdentityLabels(identity);
|
|
21
|
+
if (labels === null) return unknownDocumentMark();
|
|
22
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
23
|
+
className: cn("@container/document-identity inline-flex max-w-full shrink-0 items-center justify-center font-mono leading-4 font-semibold tabular-nums", labels.short.length > 7 ? "text-[9px]" : "text-[10px]"),
|
|
24
|
+
style: { width: `${labels.long.length + .25}ch` },
|
|
25
|
+
"data-slot": "document-identity-badge",
|
|
26
|
+
"data-kind": "statute",
|
|
27
|
+
dir: "ltr",
|
|
28
|
+
children: [/* @__PURE__ */ jsx("bdi", {
|
|
29
|
+
className: statuteLabelClasses(labels.long.length).short,
|
|
30
|
+
children: labels.short
|
|
31
|
+
}), /* @__PURE__ */ jsx("bdi", {
|
|
32
|
+
className: statuteLabelClasses(labels.long.length).long,
|
|
33
|
+
children: labels.long
|
|
34
|
+
})]
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
case "decision": {
|
|
38
|
+
const abbreviation = identity.courtAbbreviation?.trim();
|
|
39
|
+
if (!abbreviation) return unknownDocumentMark();
|
|
40
|
+
return /* @__PURE__ */ jsx("span", {
|
|
41
|
+
className: "inline-flex max-w-full min-w-0",
|
|
42
|
+
"data-slot": "document-identity-badge",
|
|
43
|
+
"data-kind": "decision",
|
|
44
|
+
children: /* @__PURE__ */ jsx(CourtBadge, {
|
|
45
|
+
abbreviation,
|
|
46
|
+
size,
|
|
47
|
+
weight: identity.courtTier === void 0 ? "outline" : COURT_TIER_WEIGHT[identity.courtTier],
|
|
48
|
+
className: cn("max-w-full overflow-hidden", abbreviation.length > 4 && "px-0.5 text-[9px] tracking-normal")
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
case "unknown": return unknownDocumentMark();
|
|
53
|
+
default: return panic("Unhandled document identity");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function unknownDocumentMark() {
|
|
57
|
+
return /* @__PURE__ */ jsx(FileTextIcon, {
|
|
58
|
+
"aria-hidden": "true",
|
|
59
|
+
className: "size-3.5 shrink-0",
|
|
60
|
+
"data-slot": "document-identity-badge",
|
|
61
|
+
"data-kind": "unknown"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const STATUTE_LABEL_CLASSES = {
|
|
65
|
+
6: {
|
|
66
|
+
short: "@[6ch]/document-identity:hidden",
|
|
67
|
+
long: "hidden @[6ch]/document-identity:inline"
|
|
68
|
+
},
|
|
69
|
+
7: {
|
|
70
|
+
short: "@[7ch]/document-identity:hidden",
|
|
71
|
+
long: "hidden @[7ch]/document-identity:inline"
|
|
72
|
+
},
|
|
73
|
+
8: {
|
|
74
|
+
short: "@[8ch]/document-identity:hidden",
|
|
75
|
+
long: "hidden @[8ch]/document-identity:inline"
|
|
76
|
+
},
|
|
77
|
+
9: {
|
|
78
|
+
short: "@[9ch]/document-identity:hidden",
|
|
79
|
+
long: "hidden @[9ch]/document-identity:inline"
|
|
80
|
+
},
|
|
81
|
+
10: {
|
|
82
|
+
short: "@[10ch]/document-identity:hidden",
|
|
83
|
+
long: "hidden @[10ch]/document-identity:inline"
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
function statuteLabelClasses(length) {
|
|
87
|
+
if (length <= 6) return STATUTE_LABEL_CLASSES[6];
|
|
88
|
+
if (length === 7) return STATUTE_LABEL_CLASSES[7];
|
|
89
|
+
if (length === 8) return STATUTE_LABEL_CLASSES[8];
|
|
90
|
+
if (length === 9) return STATUTE_LABEL_CLASSES[9];
|
|
91
|
+
return STATUTE_LABEL_CLASSES[10];
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { DocumentIdentityBadge };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/components/document-identity-badge.logic.d.ts
|
|
2
|
+
export declare const COURT_TIER_WEIGHT: {
|
|
3
|
+
readonly constitutional: "solid";
|
|
4
|
+
readonly supreme: "tinted";
|
|
5
|
+
readonly regional: "outline";
|
|
6
|
+
readonly other: "dashed";
|
|
7
|
+
};
|
|
8
|
+
export type DocumentIdentity = {
|
|
9
|
+
kind: "statute";
|
|
10
|
+
number: string | null;
|
|
11
|
+
year: string | null;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "decision";
|
|
14
|
+
courtAbbreviation: string | null | undefined;
|
|
15
|
+
courtTier?: keyof typeof COURT_TIER_WEIGHT | undefined;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "unknown";
|
|
18
|
+
};
|
|
19
|
+
export declare const statuteIdentityLabels: ({ number, year }: Extract<DocumentIdentity, {
|
|
20
|
+
kind: "statute";
|
|
21
|
+
}>) => {
|
|
22
|
+
short: string;
|
|
23
|
+
long: string;
|
|
24
|
+
} | null;
|
|
25
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/components/document-identity-badge.logic.ts
|
|
2
|
+
const COURT_TIER_WEIGHT = {
|
|
3
|
+
constitutional: "solid",
|
|
4
|
+
supreme: "tinted",
|
|
5
|
+
regional: "outline",
|
|
6
|
+
other: "dashed"
|
|
7
|
+
};
|
|
8
|
+
const statuteIdentityLabels = ({ number, year }) => {
|
|
9
|
+
const ordinal = number?.trim() || null;
|
|
10
|
+
const fullYear = year?.trim() || null;
|
|
11
|
+
if (ordinal === null) return fullYear === null ? null : {
|
|
12
|
+
short: fullYear,
|
|
13
|
+
long: fullYear
|
|
14
|
+
};
|
|
15
|
+
if (fullYear === null) return {
|
|
16
|
+
short: ordinal,
|
|
17
|
+
long: ordinal
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
short: `${ordinal}/${fullYear.slice(-2)}`,
|
|
21
|
+
long: `${ordinal}/${fullYear}`
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { COURT_TIER_WEIGHT, statuteIdentityLabels };
|
|
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
|
|
|
5
5
|
//#region src/components/input-group.d.ts
|
|
6
6
|
declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
|
7
7
|
declare const inputGroupAddonVariants: (props?: ({
|
|
8
|
-
align?: "inline-end" | "inline-start" | "block-
|
|
8
|
+
align?: "inline-end" | "inline-start" | "block-start" | "block-end" | null | undefined;
|
|
9
9
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
10
|
declare const InputGroupAddon: ({ className, align, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) => React$1.JSX.Element;
|
|
11
11
|
declare const InputGroupText: ({ className, ...props }: React$1.ComponentProps<"span">) => React$1.JSX.Element;
|
|
@@ -25,7 +25,7 @@ const InputOTPSlot = ({ index, className, ...props }) => {
|
|
|
25
25
|
...props,
|
|
26
26
|
children: [char, hasFakeCaret && /* @__PURE__ */ jsx("div", {
|
|
27
27
|
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
28
|
-
children: /* @__PURE__ */ jsx("div", { className: "animate-caret-blink bg-foreground h-4 w-px
|
|
28
|
+
children: /* @__PURE__ */ jsx("div", { className: "animate-caret-blink bg-foreground h-4 w-px" })
|
|
29
29
|
})]
|
|
30
30
|
});
|
|
31
31
|
};
|
|
@@ -25,7 +25,7 @@ type LandingGreetingProps = {
|
|
|
25
25
|
};
|
|
26
26
|
export declare const LandingGreeting: ({ icon, children }: LandingGreetingProps) => import("react").JSX.Element;
|
|
27
27
|
/** A column's heading: an icon and a sentence-case label, as a link or a trigger. */
|
|
28
|
-
export declare const LANDING_SECTION_HEADING_CLASS = "text-
|
|
28
|
+
export declare const LANDING_SECTION_HEADING_CLASS = "text-foreground hover:bg-accent/50 focus-visible:ring-ring [&>svg]:text-muted-foreground flex items-center gap-2 rounded-md px-2 py-0.5 text-sm font-semibold outline-none focus-visible:ring-2";
|
|
29
29
|
/** A row of a column, as a link or a button. Its text lines up with the
|
|
30
30
|
* heading's label; the icon slot under the heading icon stays empty unless
|
|
31
31
|
* the icon identifies the row (a matter's colour). */
|
|
@@ -22,7 +22,7 @@ const LandingLayout = ({ actions, hero, children, footer }) => /* @__PURE__ */ j
|
|
|
22
22
|
children
|
|
23
23
|
}),
|
|
24
24
|
footer !== void 0 && /* @__PURE__ */ jsx(ScrollArea, {
|
|
25
|
-
className: "h-auto max-h-[
|
|
25
|
+
className: "h-auto max-h-[40dvh] w-full shrink-0",
|
|
26
26
|
scrollFade: true,
|
|
27
27
|
children: footer
|
|
28
28
|
})
|
|
@@ -40,7 +40,7 @@ const LandingGreeting = ({ icon, children }) => /* @__PURE__ */ jsxs("div", {
|
|
|
40
40
|
})]
|
|
41
41
|
});
|
|
42
42
|
/** A column's heading: an icon and a sentence-case label, as a link or a trigger. */
|
|
43
|
-
const LANDING_SECTION_HEADING_CLASS = "text-
|
|
43
|
+
const LANDING_SECTION_HEADING_CLASS = "text-foreground hover:bg-accent/50 focus-visible:ring-ring [&>svg]:text-muted-foreground flex items-center gap-2 rounded-md px-2 py-0.5 text-sm font-semibold outline-none focus-visible:ring-2";
|
|
44
44
|
/** A row of a column, as a link or a button. Its text lines up with the
|
|
45
45
|
* heading's label; the icon slot under the heading icon stays empty unless
|
|
46
46
|
* the icon identifies the row (a matter's colour). */
|
|
@@ -15,8 +15,14 @@ declare const ListGroupHeader: ({ className, ...props }: React$1.ComponentProps<
|
|
|
15
15
|
/** Title and description stack; takes the space the header action leaves. */
|
|
16
16
|
declare const ListGroupHeading: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
|
17
17
|
declare const ListGroupTitle: ({ className, children, ...props }: React$1.ComponentProps<"h2">) => React$1.JSX.Element;
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Quiet item count after the title; shows matches while a search filters,
|
|
20
|
+
* and a changed digit fades in rather than snapping. `count` arrives
|
|
21
|
+
* formatted in the caller's locale.
|
|
22
|
+
*/
|
|
23
|
+
declare const ListGroupCount: ({ className, count, ...props }: Omit<React$1.ComponentProps<"span">, "children"> & {
|
|
24
|
+
count: string;
|
|
25
|
+
}) => React$1.JSX.Element;
|
|
20
26
|
declare const ListGroupDescription: ({ className, ...props }: React$1.ComponentProps<"p">) => React$1.JSX.Element;
|
|
21
27
|
/** Quiet trailing affordance on the header row (a link or ghost button). */
|
|
22
28
|
declare const ListGroupAction: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
package/dist/components/list.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { AnimatedCount } from "./animated-count.js";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import { mergeProps } from "@base-ui/react/merge-props";
|
|
5
6
|
import { useRender } from "@base-ui/react/use-render";
|
|
@@ -35,11 +36,16 @@ const ListGroupTitle = ({ className, children, ...props }) => /* @__PURE__ */ js
|
|
|
35
36
|
...props,
|
|
36
37
|
children
|
|
37
38
|
});
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Quiet item count after the title; shows matches while a search filters,
|
|
41
|
+
* and a changed digit fades in rather than snapping. `count` arrives
|
|
42
|
+
* formatted in the caller's locale.
|
|
43
|
+
*/
|
|
44
|
+
const ListGroupCount = ({ className, count, ...props }) => /* @__PURE__ */ jsx("span", {
|
|
45
|
+
className: cn("text-muted-foreground ms-1.5 font-normal", className),
|
|
41
46
|
"data-slot": "list-group-count",
|
|
42
|
-
...props
|
|
47
|
+
...props,
|
|
48
|
+
children: /* @__PURE__ */ jsx(AnimatedCount, { value: count })
|
|
43
49
|
});
|
|
44
50
|
const ListGroupDescription = ({ className, ...props }) => /* @__PURE__ */ jsx("p", {
|
|
45
51
|
className: cn("text-muted-foreground text-xs text-pretty", className),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/components/matter-icon.d.ts
|
|
2
|
+
type MatterIconProps = {
|
|
3
|
+
className?: string | undefined;
|
|
4
|
+
} & ({
|
|
5
|
+
matter: {
|
|
6
|
+
id: string;
|
|
7
|
+
color: string | null;
|
|
8
|
+
};
|
|
9
|
+
} | {
|
|
10
|
+
variant: "none" | "all";
|
|
11
|
+
});
|
|
12
|
+
export declare const MatterIcon: (props: MatterIconProps) => import("react").JSX.Element;
|
|
13
|
+
export declare const MattersNavIcon: ({ className }: {
|
|
14
|
+
className?: string | undefined;
|
|
15
|
+
}) => import("react").JSX.Element;
|
|
16
|
+
//#endregion
|
|
@@ -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 overscroll-contain 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
|