@estiva-app/ui 0.53.0 → 0.54.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/NavItem.d.ts +14 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/NavTree.d.ts +93 -13
- package/dist/NavTree.d.ts.map +1 -1
- package/dist/UnreadDot.d.ts +12 -0
- package/dist/UnreadDot.d.ts.map +1 -0
- package/dist/eslint/index.js +1 -1
- package/dist/eslint/index.js.map +2 -2
- package/dist/eslint/no-native-title.d.ts +1 -1
- package/dist/eslint/no-native-title.d.ts.map +1 -1
- package/dist/gates/{chunk-FIBZLYQI.js → chunk-SNYYAFZS.js} +8 -1
- package/dist/gates/chunk-SNYYAFZS.js.map +7 -0
- package/dist/gates/create-app.d.ts.map +1 -1
- package/dist/gates/create-app.js +1 -1
- package/dist/gates/index.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +215 -141
- package/dist/index.js.map +4 -4
- package/dist/looks.d.ts +1 -1
- package/dist/looks.d.ts.map +1 -1
- package/package.json +1 -1
- package/registry.json +154 -11
- package/src/NavItem.mdx +14 -1
- package/src/NavItem.stories.tsx +15 -0
- package/src/NavItem.test.tsx +31 -0
- package/src/NavItem.tsx +49 -12
- package/src/NavTree.mdx +25 -0
- package/src/NavTree.stories.tsx +57 -1
- package/src/NavTree.test.tsx +78 -1
- package/src/NavTree.tsx +175 -40
- package/src/SectionLabel.stories.tsx +2 -3
- package/src/UnreadDot.mdx +57 -0
- package/src/UnreadDot.stories.tsx +22 -0
- package/src/UnreadDot.test.tsx +17 -0
- package/src/UnreadDot.tsx +17 -0
- package/src/eslint/no-native-title.ts +1 -1
- package/src/gates/create-app.test.ts +8 -0
- package/src/gates/create-app.ts +7 -0
- package/src/index.ts +2 -1
- package/src/looks.ts +2 -1
- package/src/registry/registry.test.ts +5 -5
- package/stories/Choosing.mdx +1 -0
- package/tailwind-preset.js +1 -0
- package/tokens.css +5 -0
- package/dist/gates/chunk-FIBZLYQI.js.map +0 -7
package/dist/index.js
CHANGED
|
@@ -319,7 +319,7 @@ var FIELD_SHELL_CLASSES = "bg-bg-field border border-border-field shadow-field h
|
|
|
319
319
|
var FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
|
|
320
320
|
var CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
|
|
321
321
|
var BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
|
|
322
|
-
var SIDEBAR_ROW_CLASSES = "rounded-
|
|
322
|
+
var SIDEBAR_ROW_CLASSES = "rounded-lg transition-colors";
|
|
323
323
|
var SIDEBAR_ROW_TEXT_CLASSES = "text-text-secondary hover:text-text-primary";
|
|
324
324
|
var COLLAPSIBLE_PANEL_CLASSES = "h-[var(--collapsible-panel-height)] overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0";
|
|
325
325
|
|
|
@@ -2799,8 +2799,16 @@ function Breadcrumb({ items, className }) {
|
|
|
2799
2799
|
// src/NavItem.tsx
|
|
2800
2800
|
import { useId, useState as useState7 } from "react";
|
|
2801
2801
|
import { Collapsible } from "@base-ui/react/collapsible";
|
|
2802
|
-
import { IconChevronRight as IconChevronRight2, IconDotsVertical } from "@tabler/icons-react";
|
|
2803
|
-
|
|
2802
|
+
import { IconAlertSquareRounded, IconChevronRight as IconChevronRight2, IconDotsVertical } from "@tabler/icons-react";
|
|
2803
|
+
|
|
2804
|
+
// src/UnreadDot.tsx
|
|
2805
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
2806
|
+
function UnreadDot({ className }) {
|
|
2807
|
+
return /* @__PURE__ */ jsx43("div", { className: cn("flex h-6 w-6 shrink-0 items-center justify-center", className), "data-unread": true, children: /* @__PURE__ */ jsx43("div", { className: "h-1.5 w-1.5 rounded-full bg-accent-primary" }) });
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
// src/NavItem.tsx
|
|
2811
|
+
import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2804
2812
|
function NavItem({
|
|
2805
2813
|
label,
|
|
2806
2814
|
href,
|
|
@@ -2811,6 +2819,8 @@ function NavItem({
|
|
|
2811
2819
|
menu,
|
|
2812
2820
|
menuLabel,
|
|
2813
2821
|
hint,
|
|
2822
|
+
unread = false,
|
|
2823
|
+
urgent = false,
|
|
2814
2824
|
children,
|
|
2815
2825
|
defaultOpen = true,
|
|
2816
2826
|
open: openProp,
|
|
@@ -2827,6 +2837,8 @@ function NavItem({
|
|
|
2827
2837
|
onOpenChange?.(next);
|
|
2828
2838
|
};
|
|
2829
2839
|
const besides = menu != null || hasRows;
|
|
2840
|
+
const mark = unread ? urgent ? /* @__PURE__ */ jsx44(UrgentMark, {}) : /* @__PURE__ */ jsx44(UnreadDot, {}) : null;
|
|
2841
|
+
const stepsAside = menu != null && "transition-opacity group-hover/nav:opacity-0 group-focus-within/nav:opacity-0 group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:opacity-0";
|
|
2830
2842
|
const row = /* @__PURE__ */ jsxs29(
|
|
2831
2843
|
"a",
|
|
2832
2844
|
{
|
|
@@ -2838,7 +2850,7 @@ function NavItem({
|
|
|
2838
2850
|
// shrink-0 family; Katerina, 2026-09-02).
|
|
2839
2851
|
"flex h-8 min-w-0 shrink-0 items-center gap-2 px-2 text-body-2",
|
|
2840
2852
|
SIDEBAR_ROW_CLASSES,
|
|
2841
|
-
active ? "bg-bg-active text-text-primary" : cn(SIDEBAR_ROW_TEXT_CLASSES, "hover:bg-bg-hover"),
|
|
2853
|
+
active ? "bg-bg-nav-active text-text-primary" : cn(unread ? "text-text-primary" : SIDEBAR_ROW_TEXT_CLASSES, "hover:bg-bg-hover"),
|
|
2842
2854
|
// With a menu the ⋮ sits beside the link, so the row keeps its hover
|
|
2843
2855
|
// look while the ⋮ is pointed at and while its menu is open. The same
|
|
2844
2856
|
// for the arrow.
|
|
@@ -2848,7 +2860,7 @@ function NavItem({
|
|
|
2848
2860
|
),
|
|
2849
2861
|
...props,
|
|
2850
2862
|
children: [
|
|
2851
|
-
(icon || hasRows) && /* @__PURE__ */
|
|
2863
|
+
(icon || hasRows) && /* @__PURE__ */ jsx44(
|
|
2852
2864
|
"span",
|
|
2853
2865
|
{
|
|
2854
2866
|
className: cn(
|
|
@@ -2859,23 +2871,25 @@ function NavItem({
|
|
|
2859
2871
|
children: icon
|
|
2860
2872
|
}
|
|
2861
2873
|
),
|
|
2862
|
-
/* @__PURE__ */
|
|
2874
|
+
/* @__PURE__ */ jsx44("span", { className: cn("flex-1 truncate", unread && "font-medium"), children: label }),
|
|
2863
2875
|
hint != null && // Takes room only while it shows, so the label gives way to it.
|
|
2864
|
-
/* @__PURE__ */
|
|
2865
|
-
count ? /* @__PURE__ */
|
|
2876
|
+
/* @__PURE__ */ jsx44("span", { className: "hidden shrink-0 items-center group-hover/nav:flex group-focus-within/nav:flex", children: hint }),
|
|
2877
|
+
count ? /* @__PURE__ */ jsx44(WithTooltip, { label: countLabel ?? `${count} open`, children: /* @__PURE__ */ jsx44(
|
|
2866
2878
|
"span",
|
|
2867
2879
|
{
|
|
2868
2880
|
className: cn(
|
|
2869
2881
|
"min-w-4 shrink-0 text-center font-mono text-caption tabular-nums text-text-muted",
|
|
2870
|
-
// With a menu, the ⋮ takes this place while it shows.
|
|
2871
|
-
|
|
2882
|
+
// With a menu and no mark after it, the ⋮ takes this place while it shows.
|
|
2883
|
+
!mark && stepsAside
|
|
2872
2884
|
),
|
|
2873
2885
|
children: count
|
|
2874
2886
|
}
|
|
2875
|
-
) }) :
|
|
2876
|
-
|
|
2877
|
-
//
|
|
2878
|
-
|
|
2887
|
+
) }) : null,
|
|
2888
|
+
mark ? /* @__PURE__ */ jsx44("span", { className: cn("flex shrink-0", stepsAside), children: mark }) : menu != null && !count ? (
|
|
2889
|
+
// Nothing at the right, but a menu: no room is kept at rest, so the
|
|
2890
|
+
// label has the row's whole width; while the ⋮ shows, its 24px slot
|
|
2891
|
+
// is kept, so a long label ends before it instead of running under it.
|
|
2892
|
+
/* @__PURE__ */ jsx44("span", { "aria-hidden": "true", className: "hidden w-6 shrink-0 group-hover/nav:block group-focus-within/nav:block group-has-[[data-nav-menu]_[aria-expanded=true]]/nav:block" })
|
|
2879
2893
|
) : null
|
|
2880
2894
|
]
|
|
2881
2895
|
}
|
|
@@ -2886,7 +2900,7 @@ function NavItem({
|
|
|
2886
2900
|
row,
|
|
2887
2901
|
hasRows && // `left-1`: the 24px button's 16px arrow then sits where the icon
|
|
2888
2902
|
// sits (the row's px-2), so the icon turns into the arrow in place.
|
|
2889
|
-
/* @__PURE__ */
|
|
2903
|
+
/* @__PURE__ */ jsx44("div", { className: "absolute inset-y-0 left-1 flex items-center opacity-0 transition-opacity focus-within:opacity-100 group-hover/nav:opacity-100", children: /* @__PURE__ */ jsx44(
|
|
2890
2904
|
IconButton,
|
|
2891
2905
|
{
|
|
2892
2906
|
tooltip: open ? "Collapse" : "Expand",
|
|
@@ -2894,16 +2908,18 @@ function NavItem({
|
|
|
2894
2908
|
"aria-expanded": open,
|
|
2895
2909
|
"aria-controls": panelId,
|
|
2896
2910
|
onClick: () => setOpen(!open),
|
|
2897
|
-
children: /* @__PURE__ */
|
|
2911
|
+
children: /* @__PURE__ */ jsx44(IconChevronRight2, { size: 16, stroke: 1.5, className: cn("transition-transform duration-150", open && "rotate-90") })
|
|
2898
2912
|
}
|
|
2899
2913
|
) }),
|
|
2900
|
-
menu != null && // `right-1`: the 24px button's 16px icon then ends 8px
|
|
2901
|
-
// edge, where the count ends (px-2), so the ⋮ lands on
|
|
2902
|
-
|
|
2914
|
+
menu != null && // On a count, `right-1`: the 24px button's 16px icon then ends 8px
|
|
2915
|
+
// from the row's edge, where the count ends (px-2), so the ⋮ lands on
|
|
2916
|
+
// the number. On the mark or the empty slot, `right-2`: the button
|
|
2917
|
+
// sits in the 24px slot itself.
|
|
2918
|
+
/* @__PURE__ */ jsx44("div", { "data-nav-menu": true, className: cn("absolute inset-y-0 flex items-center", count && !mark ? "right-1" : "right-2", "opacity-0 transition-opacity focus-within:opacity-100 group-hover/nav:opacity-100 has-[[aria-expanded=true]]:opacity-100"), children: /* @__PURE__ */ jsx44(
|
|
2903
2919
|
Menu,
|
|
2904
2920
|
{
|
|
2905
2921
|
align: "right",
|
|
2906
|
-
trigger: /* @__PURE__ */
|
|
2922
|
+
trigger: /* @__PURE__ */ jsx44(IconButton, { tooltip: "More options", "aria-label": name, children: /* @__PURE__ */ jsx44(IconDotsVertical, { size: 16, stroke: 1.5 }) }),
|
|
2907
2923
|
children: menu
|
|
2908
2924
|
}
|
|
2909
2925
|
) })
|
|
@@ -2911,17 +2927,23 @@ function NavItem({
|
|
|
2911
2927
|
if (!hasRows) return line;
|
|
2912
2928
|
return /* @__PURE__ */ jsxs29(Collapsible.Root, { open, onOpenChange: setOpen, className: "flex shrink-0 flex-col", children: [
|
|
2913
2929
|
line,
|
|
2914
|
-
/* @__PURE__ */
|
|
2930
|
+
/* @__PURE__ */ jsx44(
|
|
2915
2931
|
Collapsible.Panel,
|
|
2916
2932
|
{
|
|
2917
2933
|
id: panelId,
|
|
2918
2934
|
hiddenUntilFound: true,
|
|
2919
2935
|
className: COLLAPSIBLE_PANEL_CLASSES,
|
|
2920
|
-
children: /* @__PURE__ */
|
|
2936
|
+
children: /* @__PURE__ */ jsx44("div", { className: "flex flex-col gap-px pl-6", children })
|
|
2921
2937
|
}
|
|
2922
2938
|
)
|
|
2923
2939
|
] });
|
|
2924
2940
|
}
|
|
2941
|
+
function UrgentMark() {
|
|
2942
|
+
return /* @__PURE__ */ jsx44("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center", "data-urgent": true, children: /* @__PURE__ */ jsx44("div", { className: "flex items-center rounded-full bg-warning-muted p-0.5 signal:shadow-glow-warning", children: /* @__PURE__ */ jsx44(IconAlertSquareRounded, { size: 12, stroke: 2.5, className: "text-warning-default" }) }) });
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
// src/NavTree.tsx
|
|
2946
|
+
import { useEffect as useEffect4, useRef as useRef9 } from "react";
|
|
2925
2947
|
|
|
2926
2948
|
// src/CollapsibleSection.tsx
|
|
2927
2949
|
import { useState as useState8 } from "react";
|
|
@@ -2930,18 +2952,18 @@ import { Collapsible as Collapsible2 } from "@base-ui/react/collapsible";
|
|
|
2930
2952
|
// src/SectionHeader.tsx
|
|
2931
2953
|
import { IconChevronRight as IconChevronRight3 } from "@tabler/icons-react";
|
|
2932
2954
|
import { useRender } from "@base-ui/react/use-render";
|
|
2933
|
-
import { Fragment as Fragment11, jsx as
|
|
2955
|
+
import { Fragment as Fragment11, jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2934
2956
|
function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, trailing, actions, showActions = "hover", hover = "fill", look = "heading", render, className }) {
|
|
2935
2957
|
const row = look === "row";
|
|
2936
2958
|
const titleElement = useRender({
|
|
2937
|
-
render: render ?? (chevron ? /* @__PURE__ */
|
|
2959
|
+
render: render ?? (chevron ? /* @__PURE__ */ jsx45("button", { type: "button", onClick: onToggle, "aria-expanded": isExpanded }) : /* @__PURE__ */ jsx45("span", {})),
|
|
2938
2960
|
props: {
|
|
2939
2961
|
// `text-left`: a button centres its text. `h-full` and `flex-1`: the
|
|
2940
2962
|
// whole row up to the actions is the hit target, as it was when the
|
|
2941
2963
|
// row itself carried the click.
|
|
2942
2964
|
className: cn("flex h-full min-w-0 flex-1 items-center text-left", row ? "gap-2" : "gap-1"),
|
|
2943
2965
|
children: /* @__PURE__ */ jsxs30(Fragment11, { children: [
|
|
2944
|
-
chevron && /* @__PURE__ */
|
|
2966
|
+
chevron && /* @__PURE__ */ jsx45(
|
|
2945
2967
|
IconChevronRight3,
|
|
2946
2968
|
{
|
|
2947
2969
|
size: row ? 16 : 12,
|
|
@@ -2949,10 +2971,10 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2949
2971
|
className: cn("shrink-0 transition-transform duration-150", !row && "text-text-secondary", isExpanded && "rotate-90")
|
|
2950
2972
|
}
|
|
2951
2973
|
),
|
|
2952
|
-
look === "quiet" ? /* @__PURE__ */
|
|
2974
|
+
look === "quiet" ? /* @__PURE__ */ jsx45("span", { className: "min-w-0 truncate text-caption text-text-muted", children: title }) : row ? (
|
|
2953
2975
|
// A row's words: NavItem's size and colour, brightening under the pointer with the row.
|
|
2954
|
-
/* @__PURE__ */
|
|
2955
|
-
) : /* @__PURE__ */
|
|
2976
|
+
/* @__PURE__ */ jsx45("span", { className: "min-w-0 flex-1 truncate text-body-2", children: title })
|
|
2977
|
+
) : /* @__PURE__ */ jsx45(SectionLabel, { folds: chevron, children: title })
|
|
2956
2978
|
] })
|
|
2957
2979
|
}
|
|
2958
2980
|
});
|
|
@@ -2973,15 +2995,15 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2973
2995
|
),
|
|
2974
2996
|
children: [
|
|
2975
2997
|
titleElement,
|
|
2976
|
-
trailing != null && /* @__PURE__ */
|
|
2977
|
-
actions && actions.length > 0 && /* @__PURE__ */
|
|
2998
|
+
trailing != null && /* @__PURE__ */ jsx45("div", { className: "flex shrink-0 items-center", children: trailing }),
|
|
2999
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx45(
|
|
2978
3000
|
"div",
|
|
2979
3001
|
{
|
|
2980
3002
|
className: cn(
|
|
2981
3003
|
"-mr-1 flex shrink-0 items-center gap-1",
|
|
2982
3004
|
showActions === "hover" && "opacity-0 transition-opacity focus-within:opacity-100 group-hover:opacity-100"
|
|
2983
3005
|
),
|
|
2984
|
-
children: actions.map((action) => /* @__PURE__ */
|
|
3006
|
+
children: actions.map((action) => /* @__PURE__ */ jsx45(IconButton, { tooltip: action.tooltip, "aria-label": action.tooltip, onClick: action.onClick, children: action.icon }, action.tooltip))
|
|
2985
3007
|
}
|
|
2986
3008
|
)
|
|
2987
3009
|
]
|
|
@@ -2990,7 +3012,7 @@ function SectionHeader({ title, chevron = false, isExpanded = true, onToggle, tr
|
|
|
2990
3012
|
}
|
|
2991
3013
|
|
|
2992
3014
|
// src/CollapsibleSection.tsx
|
|
2993
|
-
import { jsx as
|
|
3015
|
+
import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2994
3016
|
var OPEN = "open";
|
|
2995
3017
|
var CLOSED = "closed";
|
|
2996
3018
|
function readStored(key) {
|
|
@@ -3018,25 +3040,30 @@ function CollapsibleSection({ title, defaultOpen = true, open: openProp, onOpenC
|
|
|
3018
3040
|
onOpenChange?.(next);
|
|
3019
3041
|
};
|
|
3020
3042
|
return /* @__PURE__ */ jsxs31(Collapsible2.Root, { open, onOpenChange: setOpen, className: cn("flex flex-col", className), children: [
|
|
3021
|
-
/* @__PURE__ */
|
|
3022
|
-
/* @__PURE__ */
|
|
3043
|
+
/* @__PURE__ */ jsx46(SectionHeader, { title, chevron: true, isExpanded: open, trailing, actions, showActions, look, className: "shrink-0", render: /* @__PURE__ */ jsx46(Collapsible2.Trigger, {}) }),
|
|
3044
|
+
/* @__PURE__ */ jsx46(
|
|
3023
3045
|
Collapsible2.Panel,
|
|
3024
3046
|
{
|
|
3025
3047
|
hiddenUntilFound: true,
|
|
3026
3048
|
className: COLLAPSIBLE_PANEL_CLASSES,
|
|
3027
|
-
children: /* @__PURE__ */
|
|
3049
|
+
children: /* @__PURE__ */ jsx46("div", { className: cn("flex flex-col", look === "row" ? "pl-6" : indent && "pl-4", contentClassName), children })
|
|
3028
3050
|
}
|
|
3029
3051
|
)
|
|
3030
3052
|
] });
|
|
3031
3053
|
}
|
|
3032
3054
|
|
|
3033
3055
|
// src/NavTree.tsx
|
|
3034
|
-
import { Fragment as Fragment12, jsx as
|
|
3056
|
+
import { Fragment as Fragment12, jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3057
|
+
var NAV_TREE_INTENT_MS = 150;
|
|
3035
3058
|
function holds(nodes, id) {
|
|
3036
|
-
return id !== void 0 && nodes.some((node) => node.id === id || holds(node.children ??
|
|
3059
|
+
return !!nodes && id !== void 0 && nodes.some((node) => node.id === id || holds(node.children ?? null, id));
|
|
3060
|
+
}
|
|
3061
|
+
function Line({ message }) {
|
|
3062
|
+
return /* @__PURE__ */ jsx47("div", { className: "px-2 py-1", children: /* @__PURE__ */ jsx47(EmptyState, { scope: "section", message }) });
|
|
3037
3063
|
}
|
|
3038
3064
|
function Row({ node, selected, onSelect }) {
|
|
3039
|
-
|
|
3065
|
+
const under = node.childrenMessage !== void 0 ? /* @__PURE__ */ jsx47(Line, { message: node.childrenMessage }) : node.children?.length ? node.children.map((child) => /* @__PURE__ */ jsx47(Row, { node: child, selected, onSelect }, child.id)) : node.children === null || node.hasChildren && node.children === void 0 ? /* @__PURE__ */ jsx47(SkeletonList, { rows: 2 }) : void 0;
|
|
3066
|
+
return /* @__PURE__ */ jsx47(
|
|
3040
3067
|
NavItem,
|
|
3041
3068
|
{
|
|
3042
3069
|
href: node.href,
|
|
@@ -3045,40 +3072,85 @@ function Row({ node, selected, onSelect }) {
|
|
|
3045
3072
|
count: node.count,
|
|
3046
3073
|
countLabel: node.countLabel,
|
|
3047
3074
|
hint: node.hint,
|
|
3075
|
+
unread: node.unread,
|
|
3076
|
+
urgent: node.urgent,
|
|
3048
3077
|
menu: node.menu,
|
|
3049
3078
|
active: node.id === selected,
|
|
3050
3079
|
defaultOpen: node.defaultOpen ?? true,
|
|
3080
|
+
open: node.open,
|
|
3081
|
+
onOpenChange: node.onOpenChange,
|
|
3051
3082
|
onClick: onSelect ? (event) => onSelect(node, event) : void 0,
|
|
3052
|
-
children:
|
|
3083
|
+
children: under
|
|
3084
|
+
}
|
|
3085
|
+
);
|
|
3086
|
+
}
|
|
3087
|
+
function Group({ group, selected, onSelect, storageKey }) {
|
|
3088
|
+
return /* @__PURE__ */ jsx47(
|
|
3089
|
+
NavTreeSection,
|
|
3090
|
+
{
|
|
3091
|
+
id: group.id,
|
|
3092
|
+
title: group.title,
|
|
3093
|
+
message: group.message,
|
|
3094
|
+
loading: group.nodes === null,
|
|
3095
|
+
trailing: group.trailing,
|
|
3096
|
+
actions: group.actions,
|
|
3097
|
+
defaultOpen: group.defaultOpen ?? holds(group.nodes, selected),
|
|
3098
|
+
open: group.open,
|
|
3099
|
+
onOpenChange: group.onOpenChange,
|
|
3100
|
+
storageKey: storageKey ? `${storageKey}.${group.id}` : void 0,
|
|
3101
|
+
onIntent: group.onIntent,
|
|
3102
|
+
children: group.nodes?.map((node) => /* @__PURE__ */ jsx47(Row, { node, selected, onSelect }, node.id))
|
|
3103
|
+
}
|
|
3104
|
+
);
|
|
3105
|
+
}
|
|
3106
|
+
function NavTreeSection({ id, title, message, loading = false, trailing, actions, defaultOpen = true, open, onOpenChange, storageKey, onIntent, children }) {
|
|
3107
|
+
const timer = useRef9(void 0);
|
|
3108
|
+
useEffect4(() => () => clearTimeout(timer.current), []);
|
|
3109
|
+
const intent = onIntent;
|
|
3110
|
+
return /* @__PURE__ */ jsx47(
|
|
3111
|
+
"div",
|
|
3112
|
+
{
|
|
3113
|
+
className: "shrink-0",
|
|
3114
|
+
"data-nav-group": id,
|
|
3115
|
+
onPointerEnter: intent ? () => {
|
|
3116
|
+
clearTimeout(timer.current);
|
|
3117
|
+
timer.current = setTimeout(intent, NAV_TREE_INTENT_MS);
|
|
3118
|
+
} : void 0,
|
|
3119
|
+
onPointerLeave: intent ? () => clearTimeout(timer.current) : void 0,
|
|
3120
|
+
onFocus: intent,
|
|
3121
|
+
children: /* @__PURE__ */ jsx47(
|
|
3122
|
+
CollapsibleSection,
|
|
3123
|
+
{
|
|
3124
|
+
title,
|
|
3125
|
+
indent: true,
|
|
3126
|
+
defaultOpen,
|
|
3127
|
+
open,
|
|
3128
|
+
onOpenChange,
|
|
3129
|
+
storageKey,
|
|
3130
|
+
trailing,
|
|
3131
|
+
actions,
|
|
3132
|
+
className: "mt-2 shrink-0",
|
|
3133
|
+
contentClassName: "gap-px",
|
|
3134
|
+
children: message !== void 0 ? /* @__PURE__ */ jsx47(Line, { message }) : loading ? /* @__PURE__ */ jsx47(SkeletonList, { rows: 3 }) : children
|
|
3135
|
+
}
|
|
3136
|
+
)
|
|
3053
3137
|
}
|
|
3054
3138
|
);
|
|
3055
3139
|
}
|
|
3056
|
-
function NavTree({ title, groups, selected, onSelect, emptyMessage, storageKey }) {
|
|
3140
|
+
function NavTree({ title, titleActions, groups, children, selected, onSelect, emptyMessage = "", storageKey }) {
|
|
3057
3141
|
return /* @__PURE__ */ jsxs32(Fragment12, { children: [
|
|
3058
|
-
title && /* @__PURE__ */
|
|
3059
|
-
groups === null ? /* @__PURE__ */
|
|
3060
|
-
//
|
|
3061
|
-
|
|
3062
|
-
) : groups.map((group) => /* @__PURE__ */
|
|
3063
|
-
CollapsibleSection,
|
|
3064
|
-
{
|
|
3065
|
-
title: group.title,
|
|
3066
|
-
indent: true,
|
|
3067
|
-
defaultOpen: holds(group.nodes, selected),
|
|
3068
|
-
storageKey: storageKey ? `${storageKey}.${group.id}` : void 0,
|
|
3069
|
-
className: "mt-2 shrink-0",
|
|
3070
|
-
contentClassName: "gap-px",
|
|
3071
|
-
children: group.nodes.map((node) => /* @__PURE__ */ jsx46(Row, { node, selected, onSelect }, node.id))
|
|
3072
|
-
},
|
|
3073
|
-
group.id
|
|
3074
|
-
))
|
|
3142
|
+
title && /* @__PURE__ */ jsx47(SectionHeader, { title, look: "quiet", showActions: "always", actions: titleActions, className: "mt-4 shrink-0" }),
|
|
3143
|
+
groups === void 0 ? children : groups === null ? /* @__PURE__ */ jsx47(SkeletonList, { rows: 5 }) : groups.length === 0 ? (
|
|
3144
|
+
// No words, no line: an app that says nothing when it has no groups.
|
|
3145
|
+
emptyMessage ? /* @__PURE__ */ jsx47(Line, { message: emptyMessage }) : null
|
|
3146
|
+
) : groups.map((group) => /* @__PURE__ */ jsx47(Group, { group, selected, onSelect, storageKey }, group.id))
|
|
3075
3147
|
] });
|
|
3076
3148
|
}
|
|
3077
3149
|
|
|
3078
3150
|
// src/Popover.tsx
|
|
3079
3151
|
import { useMemo as useMemo3 } from "react";
|
|
3080
3152
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
3081
|
-
import { jsx as
|
|
3153
|
+
import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3082
3154
|
var GAP5 = 4;
|
|
3083
3155
|
var VIEWPORT_PAD5 = 8;
|
|
3084
3156
|
function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpenChange, finalFocus, actionsRef, ariaLabel, children, className, contentClassName, maxHeight }) {
|
|
@@ -3095,8 +3167,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3095
3167
|
actionsRef,
|
|
3096
3168
|
modal: false,
|
|
3097
3169
|
children: [
|
|
3098
|
-
trigger && /* @__PURE__ */
|
|
3099
|
-
/* @__PURE__ */
|
|
3170
|
+
trigger && /* @__PURE__ */ jsx48(BasePopover.Trigger, { render: trigger, disabled: triggerDisabled(trigger) }),
|
|
3171
|
+
/* @__PURE__ */ jsx48(BasePopover.Portal, { children: /* @__PURE__ */ jsx48(
|
|
3100
3172
|
BasePopover.Positioner,
|
|
3101
3173
|
{
|
|
3102
3174
|
anchor: anchorTarget,
|
|
@@ -3105,20 +3177,20 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3105
3177
|
sideOffset: GAP5,
|
|
3106
3178
|
collisionPadding: VIEWPORT_PAD5,
|
|
3107
3179
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
3108
|
-
children: /* @__PURE__ */
|
|
3180
|
+
children: /* @__PURE__ */ jsx48(
|
|
3109
3181
|
BasePopover.Popup,
|
|
3110
3182
|
{
|
|
3111
3183
|
"aria-label": ariaLabel,
|
|
3112
3184
|
initialFocus: trigger ? void 0 : false,
|
|
3113
3185
|
finalFocus,
|
|
3114
3186
|
className: cn("min-w-[180px] outline-none p-0", className),
|
|
3115
|
-
render: /* @__PURE__ */
|
|
3116
|
-
children: /* @__PURE__ */
|
|
3187
|
+
render: /* @__PURE__ */ jsx48(MenuPanel, {}),
|
|
3188
|
+
children: /* @__PURE__ */ jsx48(
|
|
3117
3189
|
ScrollArea,
|
|
3118
3190
|
{
|
|
3119
3191
|
viewportClassName: maxHeight ?? "max-h-[var(--available-height)]",
|
|
3120
3192
|
contentClassName: cn("flex flex-col p-2", contentClassName),
|
|
3121
|
-
children: /* @__PURE__ */
|
|
3193
|
+
children: /* @__PURE__ */ jsx48(DividerInPanel.Provider, { value: true, children })
|
|
3122
3194
|
}
|
|
3123
3195
|
)
|
|
3124
3196
|
}
|
|
@@ -3131,8 +3203,8 @@ function Popover({ trigger, anchor, align = "left", side = "bottom", open, onOpe
|
|
|
3131
3203
|
}
|
|
3132
3204
|
|
|
3133
3205
|
// src/SuggestionMenu.tsx
|
|
3134
|
-
import { useCallback as useCallback3, useEffect as
|
|
3135
|
-
import { jsx as
|
|
3206
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useId as useId2, useImperativeHandle, useMemo as useMemo4, useRef as useRef10, useState as useState9 } from "react";
|
|
3207
|
+
import { jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3136
3208
|
function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sections, itemKey, row, onSelect, handle }) {
|
|
3137
3209
|
const shown = useMemo4(() => sections.filter((section) => section.items.length > 0), [sections]);
|
|
3138
3210
|
const items = useMemo4(() => shown.flatMap((section) => section.items), [shown]);
|
|
@@ -3140,9 +3212,9 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3140
3212
|
const [highlight, setHighlight] = useState9(0);
|
|
3141
3213
|
const base = useId2();
|
|
3142
3214
|
const listboxId = `${base}-list`;
|
|
3143
|
-
const chosen =
|
|
3144
|
-
|
|
3145
|
-
|
|
3215
|
+
const chosen = useRef10(null);
|
|
3216
|
+
useEffect5(() => void (chosen.current = highlight > 0 ? keys.split("\n")[highlight] ?? null : null), [highlight]);
|
|
3217
|
+
useEffect5(() => {
|
|
3146
3218
|
const at = chosen.current ? keys.split("\n").indexOf(chosen.current) : -1;
|
|
3147
3219
|
setHighlight(at > 0 ? at : 0);
|
|
3148
3220
|
}, [keys]);
|
|
@@ -3167,7 +3239,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3167
3239
|
}
|
|
3168
3240
|
}), [items, highlight, onSelect]);
|
|
3169
3241
|
const open = rect !== null && items.length > 0;
|
|
3170
|
-
|
|
3242
|
+
useEffect5(() => {
|
|
3171
3243
|
if (!editorElement || !open) return;
|
|
3172
3244
|
editorElement.setAttribute("aria-autocomplete", "list");
|
|
3173
3245
|
editorElement.setAttribute("aria-haspopup", "listbox");
|
|
@@ -3176,7 +3248,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3176
3248
|
for (const name of ["aria-autocomplete", "aria-haspopup", "aria-controls", "aria-activedescendant"]) editorElement.removeAttribute(name);
|
|
3177
3249
|
};
|
|
3178
3250
|
}, [editorElement, open, listboxId]);
|
|
3179
|
-
|
|
3251
|
+
useEffect5(() => {
|
|
3180
3252
|
if (!editorElement || !open) return;
|
|
3181
3253
|
editorElement.setAttribute("aria-activedescendant", `${base}-${highlight}`);
|
|
3182
3254
|
}, [editorElement, open, base, highlight]);
|
|
@@ -3190,7 +3262,7 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3190
3262
|
const { label, description, leading, shortcut, hint, size } = row(item);
|
|
3191
3263
|
return (
|
|
3192
3264
|
// A row of a list the editor drives from its caret: focus stays in the text, so the row is no Tab stop.
|
|
3193
|
-
/* @__PURE__ */
|
|
3265
|
+
/* @__PURE__ */ jsx49(
|
|
3194
3266
|
MenuItem,
|
|
3195
3267
|
{
|
|
3196
3268
|
role: "option",
|
|
@@ -3215,17 +3287,17 @@ function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sect
|
|
|
3215
3287
|
)
|
|
3216
3288
|
);
|
|
3217
3289
|
};
|
|
3218
|
-
return /* @__PURE__ */
|
|
3219
|
-
i > 0 && /* @__PURE__ */
|
|
3220
|
-
section.label ? /* @__PURE__ */
|
|
3290
|
+
return /* @__PURE__ */ jsx49(Popover, { anchor: rect, open: rect !== null, side: "top", align: "left", className: width, maxHeight, ariaLabel, children: /* @__PURE__ */ jsx49("div", { id: listboxId, role: "listbox", "aria-label": ariaLabel, className: "flex flex-col", children: shown.map((section, i) => /* @__PURE__ */ jsxs34("div", { className: "contents", children: [
|
|
3291
|
+
i > 0 && /* @__PURE__ */ jsx49(MenuSeparator, {}),
|
|
3292
|
+
section.label ? /* @__PURE__ */ jsx49("div", { role: "group", "aria-label": section.label, children: /* @__PURE__ */ jsx49(MenuSection, { label: section.label, className: section.className, children: section.items.map(drawRow) }) }) : section.items.map(drawRow)
|
|
3221
3293
|
] }, section.label ?? i)) }) });
|
|
3222
3294
|
}
|
|
3223
3295
|
|
|
3224
3296
|
// src/Toolbar.tsx
|
|
3225
3297
|
import { Toolbar as BaseToolbar } from "@base-ui/react/toolbar";
|
|
3226
|
-
import { jsx as
|
|
3298
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
3227
3299
|
function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocus = true, surface = true, children, className }) {
|
|
3228
|
-
const strip = /* @__PURE__ */
|
|
3300
|
+
const strip = /* @__PURE__ */ jsx50(
|
|
3229
3301
|
BaseToolbar.Root,
|
|
3230
3302
|
{
|
|
3231
3303
|
"aria-label": ariaLabel,
|
|
@@ -3236,27 +3308,27 @@ function Toolbar({ "aria-label": ariaLabel, orientation = "horizontal", loopFocu
|
|
|
3236
3308
|
}
|
|
3237
3309
|
);
|
|
3238
3310
|
if (!surface) return strip;
|
|
3239
|
-
return /* @__PURE__ */
|
|
3311
|
+
return /* @__PURE__ */ jsx50(MenuPanel, { className: "w-fit p-1", children: strip });
|
|
3240
3312
|
}
|
|
3241
3313
|
function ToolbarButton({ ref, disabled, disabledReason, ...props }) {
|
|
3242
|
-
return /* @__PURE__ */
|
|
3314
|
+
return /* @__PURE__ */ jsx50(
|
|
3243
3315
|
BaseToolbar.Button,
|
|
3244
3316
|
{
|
|
3245
3317
|
ref,
|
|
3246
3318
|
disabled: disabled || !!disabledReason,
|
|
3247
3319
|
focusableWhenDisabled: true,
|
|
3248
|
-
render: /* @__PURE__ */
|
|
3320
|
+
render: /* @__PURE__ */ jsx50(IconButton, { disabled, disabledReason, ...props })
|
|
3249
3321
|
}
|
|
3250
3322
|
);
|
|
3251
3323
|
}
|
|
3252
3324
|
function ToolbarLink({ ref, href, ...props }) {
|
|
3253
|
-
return /* @__PURE__ */
|
|
3325
|
+
return /* @__PURE__ */ jsx50(BaseToolbar.Link, { ref, render: /* @__PURE__ */ jsx50(IconButton, { href, ...props }) });
|
|
3254
3326
|
}
|
|
3255
3327
|
function ToolbarInput({ size, ...props }) {
|
|
3256
|
-
return /* @__PURE__ */
|
|
3328
|
+
return /* @__PURE__ */ jsx50(BaseToolbar.Input, { render: /* @__PURE__ */ jsx50(TextInput, { size }), ...props });
|
|
3257
3329
|
}
|
|
3258
3330
|
function ToolbarSeparator({ className }) {
|
|
3259
|
-
return /* @__PURE__ */
|
|
3331
|
+
return /* @__PURE__ */ jsx50(
|
|
3260
3332
|
BaseToolbar.Separator,
|
|
3261
3333
|
{
|
|
3262
3334
|
orientation: "vertical",
|
|
@@ -3266,9 +3338,9 @@ function ToolbarSeparator({ className }) {
|
|
|
3266
3338
|
}
|
|
3267
3339
|
|
|
3268
3340
|
// src/ReactionPicker.tsx
|
|
3269
|
-
import { jsx as
|
|
3341
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
3270
3342
|
function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reactions", surface = true, className }) {
|
|
3271
|
-
return /* @__PURE__ */
|
|
3343
|
+
return /* @__PURE__ */ jsx51(Toolbar, { "aria-label": ariaLabel, surface, className: cn("gap-0.5", className), children: options.map((option) => (
|
|
3272
3344
|
/*
|
|
3273
3345
|
A `ToolbarButton`, not a button in a tooltip wrapper. The wrapper
|
|
3274
3346
|
would become the toolbar's item and the button inside it would never
|
|
@@ -3278,14 +3350,14 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
3278
3350
|
The tooltip names it for a pointer, `aria-label` for everything else,
|
|
3279
3351
|
and both say the meaning rather than the glyph.
|
|
3280
3352
|
*/
|
|
3281
|
-
/* @__PURE__ */
|
|
3353
|
+
/* @__PURE__ */ jsx51(
|
|
3282
3354
|
ToolbarButton,
|
|
3283
3355
|
{
|
|
3284
3356
|
"aria-label": option.label,
|
|
3285
3357
|
tooltip: option.label,
|
|
3286
3358
|
onClick: () => onSelect(option.emoji),
|
|
3287
3359
|
className: "size-7",
|
|
3288
|
-
children: /* @__PURE__ */
|
|
3360
|
+
children: /* @__PURE__ */ jsx51("span", { "aria-hidden": "true", className: "text-h3 leading-none", children: option.emoji })
|
|
3289
3361
|
},
|
|
3290
3362
|
option.emoji
|
|
3291
3363
|
)
|
|
@@ -3294,23 +3366,23 @@ function ReactionPicker({ options, onSelect, "aria-label": ariaLabel = "Reaction
|
|
|
3294
3366
|
|
|
3295
3367
|
// src/PreviewCard.tsx
|
|
3296
3368
|
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
3297
|
-
import { jsx as
|
|
3369
|
+
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3298
3370
|
var GAP6 = 12;
|
|
3299
3371
|
var VIEWPORT_PAD6 = 8;
|
|
3300
3372
|
var OPEN_DELAY2 = 350;
|
|
3301
3373
|
var CLOSE_DELAY = 200;
|
|
3302
3374
|
function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, closeDelay = CLOSE_DELAY, className, contentClassName, wrapperClassName }) {
|
|
3303
3375
|
return /* @__PURE__ */ jsxs35(BasePreviewCard.Root, { children: [
|
|
3304
|
-
/* @__PURE__ */
|
|
3376
|
+
/* @__PURE__ */ jsx52(
|
|
3305
3377
|
BasePreviewCard.Trigger,
|
|
3306
3378
|
{
|
|
3307
3379
|
delay,
|
|
3308
3380
|
closeDelay,
|
|
3309
|
-
render: /* @__PURE__ */
|
|
3381
|
+
render: /* @__PURE__ */ jsx52("span", { className: cn("inline-flex", wrapperClassName) }),
|
|
3310
3382
|
children
|
|
3311
3383
|
}
|
|
3312
3384
|
),
|
|
3313
|
-
/* @__PURE__ */
|
|
3385
|
+
/* @__PURE__ */ jsx52(BasePreviewCard.Portal, { children: /* @__PURE__ */ jsx52(
|
|
3314
3386
|
BasePreviewCard.Positioner,
|
|
3315
3387
|
{
|
|
3316
3388
|
side,
|
|
@@ -3318,12 +3390,12 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
3318
3390
|
sideOffset: GAP6,
|
|
3319
3391
|
collisionPadding: VIEWPORT_PAD6,
|
|
3320
3392
|
className: "z-50 data-[anchor-hidden]:hidden",
|
|
3321
|
-
children: /* @__PURE__ */
|
|
3393
|
+
children: /* @__PURE__ */ jsx52(
|
|
3322
3394
|
BasePreviewCard.Popup,
|
|
3323
3395
|
{
|
|
3324
3396
|
className: cn("w-[360px] p-0 outline-none", className),
|
|
3325
|
-
render: /* @__PURE__ */
|
|
3326
|
-
children: /* @__PURE__ */
|
|
3397
|
+
render: /* @__PURE__ */ jsx52(MenuPanel, {}),
|
|
3398
|
+
children: /* @__PURE__ */ jsx52(ScrollArea, { viewportClassName: "max-h-[min(300px,var(--available-height))]", contentClassName: cn("flex flex-col gap-3 p-3", contentClassName), children: content })
|
|
3327
3399
|
}
|
|
3328
3400
|
)
|
|
3329
3401
|
}
|
|
@@ -3332,13 +3404,13 @@ function PreviewCard({ content, children, side = "right", delay = OPEN_DELAY2, c
|
|
|
3332
3404
|
}
|
|
3333
3405
|
|
|
3334
3406
|
// src/Rail.tsx
|
|
3335
|
-
import { jsx as
|
|
3407
|
+
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
3336
3408
|
function Rail({ "aria-label": ariaLabel = "Navigation", children, className }) {
|
|
3337
|
-
return /* @__PURE__ */
|
|
3409
|
+
return /* @__PURE__ */ jsx53("nav", { "aria-label": ariaLabel, className: cn("flex w-16 shrink-0 flex-col items-start gap-2 px-2 py-3", className), children });
|
|
3338
3410
|
}
|
|
3339
3411
|
|
|
3340
3412
|
// src/RailItem.tsx
|
|
3341
|
-
import { jsx as
|
|
3413
|
+
import { jsx as jsx54, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3342
3414
|
function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
3343
3415
|
return /* @__PURE__ */ jsxs36(
|
|
3344
3416
|
"a",
|
|
@@ -3348,14 +3420,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3348
3420
|
className: cn("group flex h-12 w-full shrink-0 flex-col items-center gap-0.5 px-2 py-0.5", className),
|
|
3349
3421
|
...props,
|
|
3350
3422
|
children: [
|
|
3351
|
-
/* @__PURE__ */
|
|
3423
|
+
/* @__PURE__ */ jsx54(
|
|
3352
3424
|
"div",
|
|
3353
3425
|
{
|
|
3354
3426
|
className: cn(
|
|
3355
3427
|
"flex items-center justify-center rounded-lg p-2 transition-colors",
|
|
3356
3428
|
active ? "bg-bg-selected" : "group-hover:bg-bg-hover"
|
|
3357
3429
|
),
|
|
3358
|
-
children: /* @__PURE__ */
|
|
3430
|
+
children: /* @__PURE__ */ jsx54(
|
|
3359
3431
|
"span",
|
|
3360
3432
|
{
|
|
3361
3433
|
className: cn(
|
|
@@ -3367,14 +3439,14 @@ function RailItem({ href, icon, label, active = false, className, ...props }) {
|
|
|
3367
3439
|
)
|
|
3368
3440
|
}
|
|
3369
3441
|
),
|
|
3370
|
-
/* @__PURE__ */
|
|
3442
|
+
/* @__PURE__ */ jsx54("span", { className: cn("text-center text-menu", active ? "text-text-primary" : "text-text-secondary"), children: label })
|
|
3371
3443
|
]
|
|
3372
3444
|
}
|
|
3373
3445
|
);
|
|
3374
3446
|
}
|
|
3375
3447
|
|
|
3376
3448
|
// src/Property.tsx
|
|
3377
|
-
import { jsx as
|
|
3449
|
+
import { jsx as jsx55, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3378
3450
|
var VALUE_CLASSES = "contents";
|
|
3379
3451
|
function Property({ label, layout = "row", children, className }) {
|
|
3380
3452
|
if (layout === "stacked") {
|
|
@@ -3383,20 +3455,20 @@ function Property({ label, layout = "row", children, className }) {
|
|
|
3383
3455
|
// Peek's topic-details sections already sit at 12px, Ship's rail was
|
|
3384
3456
|
// 6px, and unifying means the bigger, calmer one.
|
|
3385
3457
|
/* @__PURE__ */ jsxs37("dl", { className: cn("flex flex-col gap-3", className), children: [
|
|
3386
|
-
/* @__PURE__ */
|
|
3387
|
-
/* @__PURE__ */
|
|
3458
|
+
/* @__PURE__ */ jsx55("dt", { className: "text-menu uppercase tracking-widest text-text-secondary", children: label }),
|
|
3459
|
+
/* @__PURE__ */ jsx55("dd", { className: VALUE_CLASSES, children })
|
|
3388
3460
|
] })
|
|
3389
3461
|
);
|
|
3390
3462
|
}
|
|
3391
3463
|
return /* @__PURE__ */ jsxs37("dl", { className: cn("flex items-center gap-2", className), children: [
|
|
3392
|
-
/* @__PURE__ */
|
|
3393
|
-
/* @__PURE__ */
|
|
3464
|
+
/* @__PURE__ */ jsx55("dt", { className: "w-[68px] shrink-0 text-caption text-text-secondary", children: label }),
|
|
3465
|
+
/* @__PURE__ */ jsx55("dd", { className: VALUE_CLASSES, children })
|
|
3394
3466
|
] });
|
|
3395
3467
|
}
|
|
3396
3468
|
|
|
3397
3469
|
// src/Reaction.tsx
|
|
3398
3470
|
import { Toggle } from "@base-ui/react/toggle";
|
|
3399
|
-
import { jsx as
|
|
3471
|
+
import { jsx as jsx56, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3400
3472
|
function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
3401
3473
|
return (
|
|
3402
3474
|
// @estiva-escape(no-copied-look): W1 (Katerina, 24 September: leave alone): a reaction pill shares four words with a field's box by coincidence
|
|
@@ -3422,8 +3494,8 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3422
3494
|
),
|
|
3423
3495
|
...props,
|
|
3424
3496
|
children: [
|
|
3425
|
-
/* @__PURE__ */
|
|
3426
|
-
/* @__PURE__ */
|
|
3497
|
+
/* @__PURE__ */ jsx56("span", { "aria-hidden": "true", className: "shrink-0 text-body-1 leading-none", children: emoji }),
|
|
3498
|
+
/* @__PURE__ */ jsx56("span", { className: CHIP_TEXT_CLASSES, children: count })
|
|
3427
3499
|
]
|
|
3428
3500
|
}
|
|
3429
3501
|
)
|
|
@@ -3433,7 +3505,7 @@ function Reaction({ emoji, count, pressed = false, className, ...props }) {
|
|
|
3433
3505
|
// src/SearchInput.tsx
|
|
3434
3506
|
import "react";
|
|
3435
3507
|
import { Input as Input3 } from "@base-ui/react/input";
|
|
3436
|
-
import { jsx as
|
|
3508
|
+
import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3437
3509
|
function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...props }) {
|
|
3438
3510
|
return /* @__PURE__ */ jsxs39(
|
|
3439
3511
|
"div",
|
|
@@ -3447,7 +3519,7 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3447
3519
|
className
|
|
3448
3520
|
),
|
|
3449
3521
|
children: [
|
|
3450
|
-
/* @__PURE__ */
|
|
3522
|
+
/* @__PURE__ */ jsx57(
|
|
3451
3523
|
Input3,
|
|
3452
3524
|
{
|
|
3453
3525
|
className: cn("flex-1 min-w-0 text-input-value", BARE_INPUT_CLASSES),
|
|
@@ -3455,40 +3527,40 @@ function SearchInput({ shortcut, className, placeholder = "Search\u2026", ...pro
|
|
|
3455
3527
|
...props
|
|
3456
3528
|
}
|
|
3457
3529
|
),
|
|
3458
|
-
shortcut && /* @__PURE__ */
|
|
3530
|
+
shortcut && /* @__PURE__ */ jsx57(Kbd, { children: shortcut })
|
|
3459
3531
|
]
|
|
3460
3532
|
}
|
|
3461
3533
|
);
|
|
3462
3534
|
}
|
|
3463
3535
|
|
|
3464
3536
|
// src/Panel.tsx
|
|
3465
|
-
import { jsx as
|
|
3537
|
+
import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3466
3538
|
function Frame({ title, chevron = false, actions, children, footer, bodyClassName, bodyRef, onBodyScroll, className, broken = false }) {
|
|
3467
3539
|
return /* @__PURE__ */ jsxs40("div", { className: cn("flex h-full min-h-0 flex-1 flex-col", className), children: [
|
|
3468
|
-
/* @__PURE__ */
|
|
3540
|
+
/* @__PURE__ */ jsx58(ContainerHeader, { title, chevron, actions }),
|
|
3469
3541
|
broken ? (
|
|
3470
3542
|
// The message takes the room the body had and centres itself in it.
|
|
3471
|
-
/* @__PURE__ */
|
|
3472
|
-
) : /* @__PURE__ */
|
|
3473
|
-
!broken && footer && /* @__PURE__ */
|
|
3543
|
+
/* @__PURE__ */ jsx58("div", { className: "flex min-h-0 flex-1 flex-col px-4", children })
|
|
3544
|
+
) : /* @__PURE__ */ jsx58(ScrollArea, { className: "min-h-0 flex-1", contentClassName: bodyClassName, viewportRef: bodyRef, onScroll: onBodyScroll, children }),
|
|
3545
|
+
!broken && footer && /* @__PURE__ */ jsx58("div", { className: "shrink-0", children: footer })
|
|
3474
3546
|
] });
|
|
3475
3547
|
}
|
|
3476
3548
|
function Panel(props) {
|
|
3477
|
-
return /* @__PURE__ */
|
|
3549
|
+
return /* @__PURE__ */ jsx58(
|
|
3478
3550
|
ErrorBoundary,
|
|
3479
3551
|
{
|
|
3480
3552
|
label: "panel",
|
|
3481
3553
|
frame: (message) => (
|
|
3482
3554
|
// Only the name comes back with the message: the actions and the footer may be what threw.
|
|
3483
|
-
/* @__PURE__ */
|
|
3555
|
+
/* @__PURE__ */ jsx58(Frame, { title: props.title, chevron: props.chevron, className: props.className, broken: true, children: message })
|
|
3484
3556
|
),
|
|
3485
|
-
children: /* @__PURE__ */
|
|
3557
|
+
children: /* @__PURE__ */ jsx58(Frame, { ...props })
|
|
3486
3558
|
}
|
|
3487
3559
|
);
|
|
3488
3560
|
}
|
|
3489
3561
|
|
|
3490
3562
|
// src/ListColumn.tsx
|
|
3491
|
-
import { jsx as
|
|
3563
|
+
import { jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3492
3564
|
function Column({ title, chevron = false, actions, above, collapsed = false, children, className, broken = false }) {
|
|
3493
3565
|
return /* @__PURE__ */ jsxs41(
|
|
3494
3566
|
"div",
|
|
@@ -3501,35 +3573,35 @@ function Column({ title, chevron = false, actions, above, collapsed = false, chi
|
|
|
3501
3573
|
),
|
|
3502
3574
|
"data-collapsed": collapsed || void 0,
|
|
3503
3575
|
children: [
|
|
3504
|
-
/* @__PURE__ */
|
|
3576
|
+
/* @__PURE__ */ jsx59(ContainerHeader, { title, chevron, actions }),
|
|
3505
3577
|
above,
|
|
3506
3578
|
broken ? (
|
|
3507
3579
|
// The message takes the room the list had and centres itself in it (Katerina, 19 September).
|
|
3508
|
-
/* @__PURE__ */
|
|
3509
|
-
) : /* @__PURE__ */
|
|
3580
|
+
/* @__PURE__ */ jsx59("div", { className: "flex min-h-0 flex-1 flex-col px-3", children })
|
|
3581
|
+
) : /* @__PURE__ */ jsx59(ScrollArea, { className: "flex-1", contentClassName: "flex flex-col gap-0.5 px-3 pt-4 pb-3", children })
|
|
3510
3582
|
]
|
|
3511
3583
|
}
|
|
3512
3584
|
);
|
|
3513
3585
|
}
|
|
3514
3586
|
function ListColumn(props) {
|
|
3515
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsx59(
|
|
3516
3588
|
ErrorBoundary,
|
|
3517
3589
|
{
|
|
3518
3590
|
label: "list panel",
|
|
3519
3591
|
frame: (message) => (
|
|
3520
3592
|
// Only the name comes back with the message: the actions and the row above may be what threw.
|
|
3521
|
-
/* @__PURE__ */
|
|
3593
|
+
/* @__PURE__ */ jsx59(Column, { title: props.title, chevron: props.chevron, collapsed: props.collapsed, className: props.className, broken: true, children: message })
|
|
3522
3594
|
),
|
|
3523
|
-
children: /* @__PURE__ */
|
|
3595
|
+
children: /* @__PURE__ */ jsx59(Column, { ...props })
|
|
3524
3596
|
}
|
|
3525
3597
|
);
|
|
3526
3598
|
}
|
|
3527
3599
|
|
|
3528
3600
|
// src/Tabs.tsx
|
|
3529
3601
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
3530
|
-
import { jsx as
|
|
3602
|
+
import { jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3531
3603
|
function Tabs({ tabs, active, onChange, size = "default", className, ...aria }) {
|
|
3532
|
-
return /* @__PURE__ */
|
|
3604
|
+
return /* @__PURE__ */ jsx60(
|
|
3533
3605
|
BaseTabs.Root,
|
|
3534
3606
|
{
|
|
3535
3607
|
value: active,
|
|
@@ -3537,7 +3609,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3537
3609
|
if (details.reason === "none") onChange(value);
|
|
3538
3610
|
},
|
|
3539
3611
|
className,
|
|
3540
|
-
children: /* @__PURE__ */
|
|
3612
|
+
children: /* @__PURE__ */ jsx60(
|
|
3541
3613
|
BaseTabs.List,
|
|
3542
3614
|
{
|
|
3543
3615
|
activateOnFocus: true,
|
|
@@ -3559,7 +3631,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3559
3631
|
tab.icon,
|
|
3560
3632
|
/* @__PURE__ */ jsxs42("span", { className: "flex items-baseline", children: [
|
|
3561
3633
|
tab.label,
|
|
3562
|
-
tab.count !== void 0 ? /* @__PURE__ */
|
|
3634
|
+
tab.count !== void 0 ? /* @__PURE__ */ jsx60("span", { className: "ml-2.5 font-mono text-caption tabular-nums text-text-secondary", children: tab.count }) : null
|
|
3563
3635
|
] })
|
|
3564
3636
|
]
|
|
3565
3637
|
},
|
|
@@ -3575,7 +3647,7 @@ function Tabs({ tabs, active, onChange, size = "default", className, ...aria })
|
|
|
3575
3647
|
import { createContext as createContext6, useContext as useContext6, useMemo as useMemo5 } from "react";
|
|
3576
3648
|
import { Toast as BaseToast } from "@base-ui/react/toast";
|
|
3577
3649
|
import { IconAlertCircle as IconAlertCircle2, IconCircleCheck, IconCircleX } from "@tabler/icons-react";
|
|
3578
|
-
import { jsx as
|
|
3650
|
+
import { jsx as jsx61, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
3579
3651
|
var SURFACE_STYLES = {
|
|
3580
3652
|
success: "bg-success-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
3581
3653
|
brand: "bg-accent-muted signal:bg-bg-inset signal:border signal:border-border-default signal:shadow-md leaf:bg-bg-inset leaf:border leaf:border-border-default leaf:shadow-md",
|
|
@@ -3611,16 +3683,16 @@ var pillClassName = (type, hasAction, className) => cn(
|
|
|
3611
3683
|
);
|
|
3612
3684
|
function LeadingIcon({ type }) {
|
|
3613
3685
|
const Icon = ICONS[type];
|
|
3614
|
-
return /* @__PURE__ */
|
|
3686
|
+
return /* @__PURE__ */ jsx61(Icon, { size: 16, stroke: 1.5, className: cn("text-text-primary shrink-0", ICON_STYLES[type]) });
|
|
3615
3687
|
}
|
|
3616
3688
|
function Toast({ label, type = "neutral", leadingIcon = true, actionLabel, onAction, className }) {
|
|
3617
3689
|
const hasAction = !!(actionLabel && onAction);
|
|
3618
3690
|
return /* @__PURE__ */ jsxs43("div", { className: pillClassName(type, hasAction, className), children: [
|
|
3619
3691
|
/* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3620
|
-
leadingIcon && /* @__PURE__ */
|
|
3621
|
-
/* @__PURE__ */
|
|
3692
|
+
leadingIcon && /* @__PURE__ */ jsx61(LeadingIcon, { type }),
|
|
3693
|
+
/* @__PURE__ */ jsx61("span", { className: LABEL_CLASSES, children: label })
|
|
3622
3694
|
] }),
|
|
3623
|
-
hasAction && /* @__PURE__ */
|
|
3695
|
+
hasAction && /* @__PURE__ */ jsx61(Button, { variant: "outlined", size: "small", onClick: onAction, children: actionLabel })
|
|
3624
3696
|
] });
|
|
3625
3697
|
}
|
|
3626
3698
|
var ToastContext = createContext6(null);
|
|
@@ -3641,9 +3713,9 @@ function ToastProvider({ children }) {
|
|
|
3641
3713
|
}),
|
|
3642
3714
|
[manager]
|
|
3643
3715
|
);
|
|
3644
|
-
return /* @__PURE__ */
|
|
3716
|
+
return /* @__PURE__ */ jsx61(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs43(BaseToast.Provider, { toastManager: manager, limit: VISIBLE_TOASTS, children: [
|
|
3645
3717
|
children,
|
|
3646
|
-
/* @__PURE__ */
|
|
3718
|
+
/* @__PURE__ */ jsx61(BaseToast.Portal, { children: /* @__PURE__ */ jsx61(BaseToast.Viewport, { className: "fixed bottom-4 left-4 z-[100] flex flex-col-reverse items-start gap-2 pointer-events-none", children: /* @__PURE__ */ jsx61(ToastList, {}) }) })
|
|
3647
3719
|
] }) });
|
|
3648
3720
|
}
|
|
3649
3721
|
function ToastList() {
|
|
@@ -3659,17 +3731,17 @@ function ToastList() {
|
|
|
3659
3731
|
className: pillClassName(type, !!actionLabel, "pointer-events-auto data-[limited]:hidden"),
|
|
3660
3732
|
children: [
|
|
3661
3733
|
/* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3662
|
-
leadingIcon && /* @__PURE__ */
|
|
3663
|
-
/* @__PURE__ */
|
|
3734
|
+
leadingIcon && /* @__PURE__ */ jsx61(LeadingIcon, { type }),
|
|
3735
|
+
/* @__PURE__ */ jsx61(BaseToast.Title, { render: /* @__PURE__ */ jsx61("span", {}), className: LABEL_CLASSES })
|
|
3664
3736
|
] }),
|
|
3665
|
-
actionLabel && /* @__PURE__ */
|
|
3737
|
+
actionLabel && /* @__PURE__ */ jsx61(
|
|
3666
3738
|
BaseToast.Action,
|
|
3667
3739
|
{
|
|
3668
3740
|
onClick: () => {
|
|
3669
3741
|
onAction?.();
|
|
3670
3742
|
close(toast.id);
|
|
3671
3743
|
},
|
|
3672
|
-
render: /* @__PURE__ */
|
|
3744
|
+
render: /* @__PURE__ */ jsx61(Button, { variant: "outlined", size: "small", children: actionLabel })
|
|
3673
3745
|
}
|
|
3674
3746
|
)
|
|
3675
3747
|
]
|
|
@@ -3748,6 +3820,7 @@ export {
|
|
|
3748
3820
|
MenuSub,
|
|
3749
3821
|
NavItem,
|
|
3750
3822
|
NavTree,
|
|
3823
|
+
NavTreeSection,
|
|
3751
3824
|
Panel,
|
|
3752
3825
|
Person,
|
|
3753
3826
|
PersonTrigger,
|
|
@@ -3783,6 +3856,7 @@ export {
|
|
|
3783
3856
|
Tooltip,
|
|
3784
3857
|
TooltipProvider,
|
|
3785
3858
|
TopBar,
|
|
3859
|
+
UnreadDot,
|
|
3786
3860
|
WithTooltip,
|
|
3787
3861
|
cn,
|
|
3788
3862
|
hueFor,
|