@petrarca/sonnet-shell 0.7.0 → 0.9.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/auth/index.d.ts +2 -1
- package/dist/index.d.ts +235 -22
- package/dist/index.js +562 -235
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// src/AppShell.tsx
|
|
2
2
|
import {
|
|
3
|
-
useState as
|
|
4
|
-
useEffect as
|
|
5
|
-
useCallback as
|
|
3
|
+
useState as useState4,
|
|
4
|
+
useEffect as useEffect6,
|
|
5
|
+
useCallback as useCallback3,
|
|
6
6
|
useRef as useRef2,
|
|
7
|
-
useMemo as
|
|
7
|
+
useMemo as useMemo4
|
|
8
8
|
} from "react";
|
|
9
|
-
import { useResizablePanel as useResizablePanel2 } from "@petrarca/sonnet-core/hooks";
|
|
9
|
+
import { useResizablePanel as useResizablePanel2, useMediaQuery } from "@petrarca/sonnet-core/hooks";
|
|
10
10
|
import { Outlet, useLocation as useLocation2, useNavigate as useNavigate2 } from "react-router-dom";
|
|
11
11
|
import { TooltipProvider } from "@petrarca/sonnet-ui";
|
|
12
12
|
import { ScrollArea as ScrollArea2 } from "@petrarca/sonnet-ui";
|
|
@@ -20,8 +20,9 @@ import {
|
|
|
20
20
|
} from "@petrarca/sonnet-ui";
|
|
21
21
|
|
|
22
22
|
// src/ConfirmDialog.tsx
|
|
23
|
+
import { useState } from "react";
|
|
23
24
|
import { AlertTriangle } from "lucide-react";
|
|
24
|
-
import { Button } from "@petrarca/sonnet-ui";
|
|
25
|
+
import { Button, Input } from "@petrarca/sonnet-ui";
|
|
25
26
|
import {
|
|
26
27
|
Dialog,
|
|
27
28
|
DialogContent,
|
|
@@ -38,9 +39,12 @@ function ConfirmDialog({
|
|
|
38
39
|
confirmLabel = "Confirm",
|
|
39
40
|
cancelLabel = "Cancel",
|
|
40
41
|
variant = "default",
|
|
42
|
+
confirmText,
|
|
41
43
|
onConfirm,
|
|
42
44
|
onCancel
|
|
43
45
|
}) {
|
|
46
|
+
const [typed, setTyped] = useState("");
|
|
47
|
+
const confirmed = confirmText == null || typed === confirmText;
|
|
44
48
|
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (isOpen) => !isOpen && onCancel(), children: /* @__PURE__ */ jsxs(DialogContent, { children: [
|
|
45
49
|
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
46
50
|
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
@@ -56,9 +60,28 @@ function ConfirmDialog({
|
|
|
56
60
|
),
|
|
57
61
|
/* @__PURE__ */ jsx("p", { className: "flex-1 text-sm text-muted-foreground", children: "This action cannot be undone." })
|
|
58
62
|
] }),
|
|
63
|
+
confirmText != null && /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm", children: [
|
|
64
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
65
|
+
"Type",
|
|
66
|
+
" ",
|
|
67
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium text-foreground", children: confirmText }),
|
|
68
|
+
" ",
|
|
69
|
+
"to confirm"
|
|
70
|
+
] }),
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
Input,
|
|
73
|
+
{
|
|
74
|
+
value: typed,
|
|
75
|
+
onChange: (e) => setTyped(e.target.value),
|
|
76
|
+
autoComplete: "off",
|
|
77
|
+
spellCheck: false,
|
|
78
|
+
"aria-label": `Type ${confirmText} to confirm`
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
] }),
|
|
59
82
|
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
60
83
|
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onCancel, children: cancelLabel }),
|
|
61
|
-
/* @__PURE__ */ jsx(Button, { variant, onClick: onConfirm, children: confirmLabel })
|
|
84
|
+
/* @__PURE__ */ jsx(Button, { variant, onClick: onConfirm, disabled: !confirmed, children: confirmLabel })
|
|
62
85
|
] })
|
|
63
86
|
] }) });
|
|
64
87
|
}
|
|
@@ -76,7 +99,7 @@ function ShellFooter({ children }) {
|
|
|
76
99
|
}
|
|
77
100
|
|
|
78
101
|
// src/ShellRail.tsx
|
|
79
|
-
import { useMemo as
|
|
102
|
+
import { useMemo as useMemo2 } from "react";
|
|
80
103
|
|
|
81
104
|
// src/IconRail.tsx
|
|
82
105
|
import { cn } from "@petrarca/sonnet-core";
|
|
@@ -132,7 +155,6 @@ function RailSeparator() {
|
|
|
132
155
|
}
|
|
133
156
|
|
|
134
157
|
// src/SubNavPanel.tsx
|
|
135
|
-
import { useMemo as useMemo2 } from "react";
|
|
136
158
|
import { ChevronsLeft, ChevronsRight } from "lucide-react";
|
|
137
159
|
import { ScrollArea } from "@petrarca/sonnet-ui";
|
|
138
160
|
import { Tooltip as Tooltip2, TooltipContent as TooltipContent2, TooltipTrigger as TooltipTrigger2 } from "@petrarca/sonnet-ui";
|
|
@@ -185,18 +207,25 @@ function emit(key, payload) {
|
|
|
185
207
|
}
|
|
186
208
|
|
|
187
209
|
// src/api.ts
|
|
210
|
+
var toastOptions = (options) => options && {
|
|
211
|
+
description: options.description,
|
|
212
|
+
action: options.action && {
|
|
213
|
+
label: options.action.label,
|
|
214
|
+
onClick: () => options.action?.onClick()
|
|
215
|
+
}
|
|
216
|
+
};
|
|
188
217
|
var notification = {
|
|
189
|
-
success(message) {
|
|
190
|
-
toast.success(message);
|
|
218
|
+
success(message, options) {
|
|
219
|
+
toast.success(message, toastOptions(options));
|
|
191
220
|
},
|
|
192
|
-
error(message) {
|
|
193
|
-
toast.error(message);
|
|
221
|
+
error(message, options) {
|
|
222
|
+
toast.error(message, toastOptions(options));
|
|
194
223
|
},
|
|
195
|
-
warning(message) {
|
|
196
|
-
toast.warning(message);
|
|
224
|
+
warning(message, options) {
|
|
225
|
+
toast.warning(message, toastOptions(options));
|
|
197
226
|
},
|
|
198
|
-
info(message) {
|
|
199
|
-
toast.info(message);
|
|
227
|
+
info(message, options) {
|
|
228
|
+
toast.info(message, toastOptions(options));
|
|
200
229
|
},
|
|
201
230
|
promise(promise, opts) {
|
|
202
231
|
return toast.promise(promise, opts);
|
|
@@ -419,6 +448,33 @@ function useExtensionPoint(name) {
|
|
|
419
448
|
const { getExtensionPoint } = useShellModules();
|
|
420
449
|
return useMemo(() => getExtensionPoint(name), [getExtensionPoint, name]);
|
|
421
450
|
}
|
|
451
|
+
function useContributedComponent(extensionPoint, path) {
|
|
452
|
+
const contributions = useExtensionPoint(extensionPoint);
|
|
453
|
+
return useMemo(() => {
|
|
454
|
+
const found = contributions.find((c) => c.path === path && c.component);
|
|
455
|
+
return found?.component;
|
|
456
|
+
}, [contributions, path]);
|
|
457
|
+
}
|
|
458
|
+
function noRuntimeNavigation() {
|
|
459
|
+
return [];
|
|
460
|
+
}
|
|
461
|
+
function useModuleNavigation(module) {
|
|
462
|
+
const runtime = (module.useNavigation ?? noRuntimeNavigation)();
|
|
463
|
+
const contributions = useExtensionPoint(`${module.id}.nav`);
|
|
464
|
+
return useMemo(() => {
|
|
465
|
+
const groups = [...module.navigation, ...runtime];
|
|
466
|
+
if (contributions.length === 0) return groups;
|
|
467
|
+
const contributed = {
|
|
468
|
+
id: `${module.id}-contributed`,
|
|
469
|
+
links: contributions.map((c) => ({
|
|
470
|
+
id: c.extensionPoint + "." + c.label.toLowerCase().replace(/\s+/g, "-"),
|
|
471
|
+
label: c.label,
|
|
472
|
+
path: c.path
|
|
473
|
+
}))
|
|
474
|
+
};
|
|
475
|
+
return [...groups, contributed];
|
|
476
|
+
}, [module, runtime, contributions]);
|
|
477
|
+
}
|
|
422
478
|
function useMainModules() {
|
|
423
479
|
const { mainModules } = useShellModules();
|
|
424
480
|
return mainModules;
|
|
@@ -432,7 +488,7 @@ function useShellEvent(key, handler) {
|
|
|
432
488
|
}
|
|
433
489
|
|
|
434
490
|
// src/SidebarGroup.tsx
|
|
435
|
-
import { useState } from "react";
|
|
491
|
+
import { useState as useState2 } from "react";
|
|
436
492
|
import { ChevronDown } from "lucide-react";
|
|
437
493
|
import { cn as cn2 } from "@petrarca/sonnet-core";
|
|
438
494
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -448,9 +504,10 @@ function GroupHeading({
|
|
|
448
504
|
type: "button",
|
|
449
505
|
onClick: canCollapse ? onToggle : void 0,
|
|
450
506
|
className: cn2(
|
|
451
|
-
"flex w-full items-center gap-1 px-2 py-1.5",
|
|
507
|
+
"flex w-full items-center gap-1 rounded px-2 py-1.5",
|
|
452
508
|
"text-[11px] font-semibold uppercase tracking-widest text-muted-foreground/70",
|
|
453
|
-
canCollapse ? "hover:text-foreground cursor-pointer" : "cursor-default"
|
|
509
|
+
canCollapse ? "hover:text-foreground cursor-pointer" : "cursor-default",
|
|
510
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
454
511
|
),
|
|
455
512
|
children: [
|
|
456
513
|
canCollapse && /* @__PURE__ */ jsx5(
|
|
@@ -471,7 +528,7 @@ function SidebarGroup({
|
|
|
471
528
|
separator = false,
|
|
472
529
|
children
|
|
473
530
|
}) {
|
|
474
|
-
const [open, setOpen] =
|
|
531
|
+
const [open, setOpen] = useState2(defaultOpen);
|
|
475
532
|
const canCollapse = collapsible && !!heading;
|
|
476
533
|
return /* @__PURE__ */ jsxs3("div", { className: cn2(separator && "border-b border-border pb-2"), children: [
|
|
477
534
|
heading && /* @__PURE__ */ jsx5(
|
|
@@ -511,8 +568,9 @@ function ItemTrailing({
|
|
|
511
568
|
"button",
|
|
512
569
|
{
|
|
513
570
|
type: "button",
|
|
571
|
+
"aria-label": expanded ? "Collapse" : "Expand",
|
|
514
572
|
onClick: handleClick,
|
|
515
|
-
className: "p-0.5 text-muted-foreground hover:text-foreground",
|
|
573
|
+
className: "rounded p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
516
574
|
children: /* @__PURE__ */ jsx6(
|
|
517
575
|
ChevronRight,
|
|
518
576
|
{
|
|
@@ -562,6 +620,7 @@ function SidebarItem({
|
|
|
562
620
|
style,
|
|
563
621
|
className: cn3(
|
|
564
622
|
"flex items-center gap-2 rounded px-2 py-1.5 text-[13px] font-medium transition-colors select-none",
|
|
623
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
565
624
|
itemStateClass(disabled, isActive)
|
|
566
625
|
),
|
|
567
626
|
children: [
|
|
@@ -583,34 +642,23 @@ function SidebarItem({
|
|
|
583
642
|
|
|
584
643
|
// src/SubNavPanel.tsx
|
|
585
644
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
586
|
-
function
|
|
587
|
-
|
|
588
|
-
return useMemo2(() => {
|
|
589
|
-
if (contributions.length === 0) return service.navigation;
|
|
590
|
-
const contributed = {
|
|
591
|
-
id: `${service.id}-contributed`,
|
|
592
|
-
links: contributions.map((c) => ({
|
|
593
|
-
id: c.extensionPoint + "." + c.label.toLowerCase().replace(/\s+/g, "-"),
|
|
594
|
-
label: c.label,
|
|
595
|
-
path: c.path
|
|
596
|
-
}))
|
|
597
|
-
};
|
|
598
|
-
return [...service.navigation, contributed];
|
|
599
|
-
}, [service, contributions]);
|
|
645
|
+
function SubNavPanel(props) {
|
|
646
|
+
return /* @__PURE__ */ jsx7(ModuleSubNav, { ...props }, props.service.id);
|
|
600
647
|
}
|
|
601
|
-
function
|
|
648
|
+
function ModuleSubNav({
|
|
602
649
|
service,
|
|
603
650
|
collapsed,
|
|
604
651
|
onToggleCollapse
|
|
605
652
|
}) {
|
|
606
|
-
const mergedNavigation =
|
|
653
|
+
const mergedNavigation = useModuleNavigation(service);
|
|
607
654
|
if (collapsed) {
|
|
608
655
|
return /* @__PURE__ */ jsx7("aside", { className: "shrink-0 border-r bg-background flex flex-col items-center pt-2.5", children: /* @__PURE__ */ jsxs5(Tooltip2, { children: [
|
|
609
656
|
/* @__PURE__ */ jsx7(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
610
657
|
"button",
|
|
611
658
|
{
|
|
612
659
|
type: "button",
|
|
613
|
-
|
|
660
|
+
"aria-label": "Expand navigation",
|
|
661
|
+
className: "rounded text-muted-foreground/50 hover:text-muted-foreground transition-colors p-1 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
614
662
|
onClick: onToggleCollapse,
|
|
615
663
|
children: /* @__PURE__ */ jsx7(ChevronsRight, { className: "h-4 w-4" })
|
|
616
664
|
}
|
|
@@ -626,7 +674,8 @@ function SubNavPanel({
|
|
|
626
674
|
"button",
|
|
627
675
|
{
|
|
628
676
|
type: "button",
|
|
629
|
-
|
|
677
|
+
"aria-label": "Collapse navigation",
|
|
678
|
+
className: "rounded text-muted-foreground/40 hover:text-muted-foreground transition-colors p-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
630
679
|
onClick: onToggleCollapse,
|
|
631
680
|
children: /* @__PURE__ */ jsx7(ChevronsLeft, { className: "h-3.5 w-3.5" })
|
|
632
681
|
}
|
|
@@ -655,7 +704,7 @@ function SubNavPanel({
|
|
|
655
704
|
}
|
|
656
705
|
|
|
657
706
|
// src/shellNavigation.ts
|
|
658
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
707
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2 } from "react";
|
|
659
708
|
var ShellNavigationContext = createContext2(null);
|
|
660
709
|
function useShellNavigation() {
|
|
661
710
|
const ctx = useContext2(ShellNavigationContext);
|
|
@@ -664,6 +713,13 @@ function useShellNavigation() {
|
|
|
664
713
|
}
|
|
665
714
|
return ctx;
|
|
666
715
|
}
|
|
716
|
+
function useCollapsedSubNav(active = true) {
|
|
717
|
+
const request = useContext2(ShellNavigationContext)?.requestSubNavCollapse;
|
|
718
|
+
useEffect2(
|
|
719
|
+
() => active && request ? request() : void 0,
|
|
720
|
+
[active, request]
|
|
721
|
+
);
|
|
722
|
+
}
|
|
667
723
|
|
|
668
724
|
// src/shellConfig.ts
|
|
669
725
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
@@ -749,7 +805,7 @@ function ShellRail() {
|
|
|
749
805
|
onServiceSelect
|
|
750
806
|
} = useShellNavigation();
|
|
751
807
|
const isActive = (id) => activeService?.id === id || sidePaneModuleId === id;
|
|
752
|
-
const policy =
|
|
808
|
+
const policy = useMemo2(
|
|
753
809
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
754
810
|
[capabilityPolicy]
|
|
755
811
|
);
|
|
@@ -896,7 +952,7 @@ function SidePaneOpen({
|
|
|
896
952
|
}
|
|
897
953
|
|
|
898
954
|
// src/CommandMenu.tsx
|
|
899
|
-
import { useEffect as
|
|
955
|
+
import { useEffect as useEffect3, useCallback, useMemo as useMemo3 } from "react";
|
|
900
956
|
import { useNavigate } from "react-router-dom";
|
|
901
957
|
import {
|
|
902
958
|
CommandDialog,
|
|
@@ -912,7 +968,7 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
912
968
|
const navigate = useNavigate();
|
|
913
969
|
const { mainModules, bottomModules } = useShellModules();
|
|
914
970
|
const { resolveCapability, capabilityPolicy } = useShellConfig();
|
|
915
|
-
|
|
971
|
+
useEffect3(() => {
|
|
916
972
|
const handleKeyDown = (e) => {
|
|
917
973
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
918
974
|
e.preventDefault();
|
|
@@ -922,7 +978,7 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
922
978
|
document.addEventListener("keydown", handleKeyDown);
|
|
923
979
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
924
980
|
}, [open, onOpenChange]);
|
|
925
|
-
const policy =
|
|
981
|
+
const policy = useMemo3(
|
|
926
982
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
927
983
|
[capabilityPolicy]
|
|
928
984
|
);
|
|
@@ -935,27 +991,18 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
935
991
|
[navigate, onOpenChange]
|
|
936
992
|
);
|
|
937
993
|
const renderNavGroup = (service) => {
|
|
938
|
-
if (service.navigation.length === 0) return null;
|
|
939
994
|
const { effect, reason } = moduleEffect(service);
|
|
940
995
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
/* @__PURE__ */ jsx11(Icon, { className: "mr-2 h-4 w-4 text-muted-foreground" }),
|
|
952
|
-
/* @__PURE__ */ jsx11("span", { children: link.label }),
|
|
953
|
-
disabled && reason ? /* @__PURE__ */ jsx11("span", { className: "ml-auto text-xs text-muted-foreground", children: reason }) : group.heading && /* @__PURE__ */ jsx11("span", { className: "ml-auto text-xs text-muted-foreground", children: group.heading })
|
|
954
|
-
]
|
|
955
|
-
},
|
|
956
|
-
link.path
|
|
957
|
-
))
|
|
958
|
-
) }, `nav-${service.id}`);
|
|
996
|
+
return /* @__PURE__ */ jsx11(
|
|
997
|
+
ModuleNavCommands,
|
|
998
|
+
{
|
|
999
|
+
service,
|
|
1000
|
+
disabled: effect === "disabled",
|
|
1001
|
+
reason,
|
|
1002
|
+
onSelect: handleSelect
|
|
1003
|
+
},
|
|
1004
|
+
`nav-${service.id}`
|
|
1005
|
+
);
|
|
959
1006
|
};
|
|
960
1007
|
const renderCommandGroup = (service) => {
|
|
961
1008
|
if (!service.commands?.length) return null;
|
|
@@ -1012,12 +1059,38 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
1012
1059
|
] })
|
|
1013
1060
|
] });
|
|
1014
1061
|
}
|
|
1062
|
+
function ModuleNavCommands({
|
|
1063
|
+
service,
|
|
1064
|
+
disabled,
|
|
1065
|
+
reason,
|
|
1066
|
+
onSelect
|
|
1067
|
+
}) {
|
|
1068
|
+
const navigation2 = useModuleNavigation(service);
|
|
1069
|
+
if (navigation2.length === 0) return null;
|
|
1070
|
+
const Icon = service.icon;
|
|
1071
|
+
return /* @__PURE__ */ jsx11(CommandGroup, { heading: service.label, children: navigation2.flatMap(
|
|
1072
|
+
(group) => group.links.map((link) => /* @__PURE__ */ jsxs8(
|
|
1073
|
+
CommandItem,
|
|
1074
|
+
{
|
|
1075
|
+
value: `${service.label} ${group.heading ?? ""} ${link.label}`,
|
|
1076
|
+
disabled,
|
|
1077
|
+
onSelect: disabled ? void 0 : () => onSelect(link.path),
|
|
1078
|
+
children: [
|
|
1079
|
+
/* @__PURE__ */ jsx11(Icon, { className: "mr-2 h-4 w-4 text-muted-foreground" }),
|
|
1080
|
+
/* @__PURE__ */ jsx11("span", { children: link.label }),
|
|
1081
|
+
disabled && reason ? /* @__PURE__ */ jsx11("span", { className: "ml-auto text-xs text-muted-foreground", children: reason }) : group.heading && /* @__PURE__ */ jsx11("span", { className: "ml-auto text-xs text-muted-foreground", children: group.heading })
|
|
1082
|
+
]
|
|
1083
|
+
},
|
|
1084
|
+
link.path
|
|
1085
|
+
))
|
|
1086
|
+
) });
|
|
1087
|
+
}
|
|
1015
1088
|
|
|
1016
1089
|
// src/ModuleEffects.tsx
|
|
1017
|
-
import
|
|
1090
|
+
import React5 from "react";
|
|
1018
1091
|
import { warnLog as warnLog4 } from "@petrarca/sonnet-core";
|
|
1019
1092
|
import { Fragment as Fragment3, jsx as jsx12 } from "react/jsx-runtime";
|
|
1020
|
-
var ModuleEffectBoundary = class extends
|
|
1093
|
+
var ModuleEffectBoundary = class extends React5.Component {
|
|
1021
1094
|
state = { caught: false };
|
|
1022
1095
|
static getDerivedStateFromError() {
|
|
1023
1096
|
return { caught: true };
|
|
@@ -1041,8 +1114,64 @@ function ModuleEffects({ modules }) {
|
|
|
1041
1114
|
return /* @__PURE__ */ jsx12(Fragment3, { children: modules.filter((m) => typeof m.useEffects === "function").map((m) => /* @__PURE__ */ jsx12(ModuleEffectBoundary, { moduleId: m.id, children: /* @__PURE__ */ jsx12(ModuleEffectHost, { module: m }) }, m.id)) });
|
|
1042
1115
|
}
|
|
1043
1116
|
|
|
1117
|
+
// src/ModuleFeatures.tsx
|
|
1118
|
+
import { useEffect as useEffect4 } from "react";
|
|
1119
|
+
import { Fragment as Fragment4, jsx as jsx13 } from "react/jsx-runtime";
|
|
1120
|
+
function ModuleFeatureHost({
|
|
1121
|
+
module,
|
|
1122
|
+
record
|
|
1123
|
+
}) {
|
|
1124
|
+
const navigation2 = useModuleNavigation(module);
|
|
1125
|
+
useEffect4(() => {
|
|
1126
|
+
const links = /* @__PURE__ */ new Map();
|
|
1127
|
+
for (const group of navigation2) {
|
|
1128
|
+
for (const link of group.links) {
|
|
1129
|
+
if (link.id) links.set(link.id, link.path);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
record.set(module.id, links);
|
|
1133
|
+
}, [module.id, navigation2, record]);
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
function ModuleFeatures({
|
|
1137
|
+
modules,
|
|
1138
|
+
record
|
|
1139
|
+
}) {
|
|
1140
|
+
return /* @__PURE__ */ jsx13(Fragment4, { children: modules.map((m) => /* @__PURE__ */ jsx13(ModuleFeatureHost, { module: m, record }, m.id)) });
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// src/subNavCollapse.ts
|
|
1144
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useState as useState3 } from "react";
|
|
1145
|
+
function useSubNavCollapse(isBelowTablet) {
|
|
1146
|
+
const [preference, setPreference] = useState3(false);
|
|
1147
|
+
const [requests, setRequests] = useState3(0);
|
|
1148
|
+
const [overridden, setOverridden] = useState3(false);
|
|
1149
|
+
useEffect5(() => {
|
|
1150
|
+
if (requests === 0) setOverridden(false);
|
|
1151
|
+
}, [requests]);
|
|
1152
|
+
const requested = requests > 0 && !overridden;
|
|
1153
|
+
const toggle = useCallback2(() => {
|
|
1154
|
+
if (requested) {
|
|
1155
|
+
setOverridden(true);
|
|
1156
|
+
setPreference(false);
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
setPreference((c) => !c);
|
|
1160
|
+
}, [requested]);
|
|
1161
|
+
const requestCollapse = useCallback2(() => {
|
|
1162
|
+
setRequests((n) => n + 1);
|
|
1163
|
+
return () => setRequests((n) => n - 1);
|
|
1164
|
+
}, []);
|
|
1165
|
+
return {
|
|
1166
|
+
collapsed: preference || isBelowTablet || requested,
|
|
1167
|
+
toggle,
|
|
1168
|
+
setCollapsed: setPreference,
|
|
1169
|
+
requestCollapse
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1044
1173
|
// src/AppShell.tsx
|
|
1045
|
-
import { Fragment as
|
|
1174
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1046
1175
|
var PANEL_WIDTHS = {
|
|
1047
1176
|
narrow: { css: "w-[480px]", px: 480 },
|
|
1048
1177
|
default: { css: "w-[640px]", px: 640 },
|
|
@@ -1082,10 +1211,10 @@ function selectNavModule(service, navigate, setSubNavCollapsed, closeSidePane) {
|
|
|
1082
1211
|
}
|
|
1083
1212
|
function useShellApiInit(deps) {
|
|
1084
1213
|
const latest = useRef2(deps);
|
|
1085
|
-
|
|
1214
|
+
useEffect6(() => {
|
|
1086
1215
|
latest.current = deps;
|
|
1087
1216
|
});
|
|
1088
|
-
|
|
1217
|
+
useEffect6(() => {
|
|
1089
1218
|
initNavigation(
|
|
1090
1219
|
(path) => latest.current.navigate(path),
|
|
1091
1220
|
() => latest.current.openCommandMenu()
|
|
@@ -1115,7 +1244,7 @@ function useShellApiInit(deps) {
|
|
|
1115
1244
|
}
|
|
1116
1245
|
function useActiveService(modules) {
|
|
1117
1246
|
const location = useLocation2();
|
|
1118
|
-
const prefixToService =
|
|
1247
|
+
const prefixToService = useMemo4(() => {
|
|
1119
1248
|
const pairs = [];
|
|
1120
1249
|
for (const m of modules) {
|
|
1121
1250
|
if (m.hidden) continue;
|
|
@@ -1127,7 +1256,7 @@ function useActiveService(modules) {
|
|
|
1127
1256
|
pairs.sort((a, b) => b[0].length - a[0].length);
|
|
1128
1257
|
return pairs;
|
|
1129
1258
|
}, [modules]);
|
|
1130
|
-
const resolveServiceFromPath =
|
|
1259
|
+
const resolveServiceFromPath = useCallback3(
|
|
1131
1260
|
(pathname) => {
|
|
1132
1261
|
for (const [prefix, id] of prefixToService) {
|
|
1133
1262
|
if (pathname.startsWith(prefix)) return id;
|
|
@@ -1136,10 +1265,10 @@ function useActiveService(modules) {
|
|
|
1136
1265
|
},
|
|
1137
1266
|
[prefixToService]
|
|
1138
1267
|
);
|
|
1139
|
-
const [selectedServiceId, setSelectedServiceId] =
|
|
1268
|
+
const [selectedServiceId, setSelectedServiceId] = useState4(
|
|
1140
1269
|
() => resolveServiceFromPath(location.pathname)
|
|
1141
1270
|
);
|
|
1142
|
-
|
|
1271
|
+
useEffect6(
|
|
1143
1272
|
() => setSelectedServiceId(resolveServiceFromPath(location.pathname)),
|
|
1144
1273
|
[location.pathname, resolveServiceFromPath]
|
|
1145
1274
|
);
|
|
@@ -1147,26 +1276,26 @@ function useActiveService(modules) {
|
|
|
1147
1276
|
return { activeService, selectedServiceId, setSelectedServiceId };
|
|
1148
1277
|
}
|
|
1149
1278
|
function useSidePaneState2() {
|
|
1150
|
-
const [sidePaneState, setSidePaneState] =
|
|
1279
|
+
const [sidePaneState, setSidePaneState] = useState4(
|
|
1151
1280
|
null
|
|
1152
1281
|
);
|
|
1153
|
-
const handleOpen =
|
|
1282
|
+
const handleOpen = useCallback3(
|
|
1154
1283
|
(opts) => setSidePaneState(opts),
|
|
1155
1284
|
[]
|
|
1156
1285
|
);
|
|
1157
|
-
const handleClose =
|
|
1158
|
-
const handleIsOpen =
|
|
1286
|
+
const handleClose = useCallback3(() => setSidePaneState(null), []);
|
|
1287
|
+
const handleIsOpen = useCallback3(
|
|
1159
1288
|
() => sidePaneState !== null,
|
|
1160
1289
|
[sidePaneState]
|
|
1161
1290
|
);
|
|
1162
|
-
const handleActiveModuleId =
|
|
1291
|
+
const handleActiveModuleId = useCallback3(
|
|
1163
1292
|
() => sidePaneState?.moduleId ?? null,
|
|
1164
1293
|
[sidePaneState]
|
|
1165
1294
|
);
|
|
1166
|
-
const handleSetFullWidth =
|
|
1295
|
+
const handleSetFullWidth = useCallback3((fullWidth) => {
|
|
1167
1296
|
setSidePaneState((prev) => prev ? { ...prev, fullWidth } : prev);
|
|
1168
1297
|
}, []);
|
|
1169
|
-
const handleToggle =
|
|
1298
|
+
const handleToggle = useCallback3((opts) => {
|
|
1170
1299
|
setSidePaneState(
|
|
1171
1300
|
(prev) => prev?.moduleId === opts.moduleId ? null : opts
|
|
1172
1301
|
);
|
|
@@ -1202,13 +1331,13 @@ function resizeOptionsFromPanel(state, widthEntry) {
|
|
|
1202
1331
|
};
|
|
1203
1332
|
}
|
|
1204
1333
|
function usePanelState() {
|
|
1205
|
-
const [panelState, setPanelState] =
|
|
1334
|
+
const [panelState, setPanelState] = useState4(null);
|
|
1206
1335
|
const panelOnCloseRef = useRef2(void 0);
|
|
1207
|
-
const handleOpen =
|
|
1336
|
+
const handleOpen = useCallback3(
|
|
1208
1337
|
(opts) => setPanelState(opts),
|
|
1209
1338
|
[]
|
|
1210
1339
|
);
|
|
1211
|
-
const handleClose =
|
|
1340
|
+
const handleClose = useCallback3(() => {
|
|
1212
1341
|
panelOnCloseRef.current = panelState?.onClose;
|
|
1213
1342
|
setPanelState(null);
|
|
1214
1343
|
}, [panelState]);
|
|
@@ -1226,48 +1355,57 @@ function usePanelState() {
|
|
|
1226
1355
|
};
|
|
1227
1356
|
}
|
|
1228
1357
|
function useDialogState() {
|
|
1229
|
-
const [dialogState, setDialogState] =
|
|
1230
|
-
const handleConfirm =
|
|
1358
|
+
const [dialogState, setDialogState] = useState4(null);
|
|
1359
|
+
const handleConfirm = useCallback3(() => {
|
|
1231
1360
|
dialogState?.resolve(true);
|
|
1232
1361
|
setDialogState(null);
|
|
1233
1362
|
}, [dialogState]);
|
|
1234
|
-
const handleCancel =
|
|
1363
|
+
const handleCancel = useCallback3(() => {
|
|
1235
1364
|
dialogState?.resolve(false);
|
|
1236
1365
|
setDialogState(null);
|
|
1237
1366
|
}, [dialogState]);
|
|
1238
1367
|
return { dialogState, setDialogState, handleConfirm, handleCancel };
|
|
1239
1368
|
}
|
|
1240
|
-
function useFeatureLookup(modules) {
|
|
1241
|
-
return
|
|
1242
|
-
const
|
|
1369
|
+
function useFeatureLookup(modules, record) {
|
|
1370
|
+
return useMemo4(() => {
|
|
1371
|
+
const declared = /* @__PURE__ */ new Map();
|
|
1243
1372
|
for (const m of modules) {
|
|
1244
1373
|
for (const group of m.navigation) {
|
|
1245
1374
|
for (const link of group.links) {
|
|
1246
|
-
if (link.id)
|
|
1375
|
+
if (link.id) declared.set(link.id, link.path);
|
|
1247
1376
|
}
|
|
1248
1377
|
}
|
|
1249
1378
|
}
|
|
1250
|
-
return (featureId) =>
|
|
1251
|
-
|
|
1379
|
+
return (featureId) => {
|
|
1380
|
+
for (const links of record.values()) {
|
|
1381
|
+
const path = links.get(featureId);
|
|
1382
|
+
if (path) return path;
|
|
1383
|
+
}
|
|
1384
|
+
return declared.get(featureId) ?? null;
|
|
1385
|
+
};
|
|
1386
|
+
}, [modules, record]);
|
|
1252
1387
|
}
|
|
1253
1388
|
function AppShell({ registry, sidebar }) {
|
|
1254
1389
|
const navigate = useNavigate2();
|
|
1255
1390
|
const config = useShellConfig();
|
|
1256
1391
|
const { modules } = registry;
|
|
1257
1392
|
const { activeService, setSelectedServiceId } = useActiveService(modules);
|
|
1258
|
-
const
|
|
1259
|
-
const
|
|
1260
|
-
const
|
|
1261
|
-
const [
|
|
1262
|
-
const
|
|
1393
|
+
const isBelowTablet = useMediaQuery("(max-width: 1023px)");
|
|
1394
|
+
const subNav = useSubNavCollapse(isBelowTablet);
|
|
1395
|
+
const setSubNavCollapsed = subNav.setCollapsed;
|
|
1396
|
+
const [commandMenuOpen, setCommandMenuOpen] = useState4(false);
|
|
1397
|
+
const openCommandMenu = useCallback3(() => setCommandMenuOpen(true), []);
|
|
1398
|
+
const [fullscreenState, setFullscreenState] = useState4(null);
|
|
1399
|
+
const handleFullscreenEnter = useCallback3(
|
|
1263
1400
|
(opts) => setFullscreenState(opts),
|
|
1264
1401
|
[]
|
|
1265
1402
|
);
|
|
1266
|
-
const handleFullscreenExit =
|
|
1403
|
+
const handleFullscreenExit = useCallback3(() => setFullscreenState(null), []);
|
|
1267
1404
|
const sidePane2 = useSidePaneState2();
|
|
1268
1405
|
const panel2 = usePanelState();
|
|
1269
1406
|
const dialog2 = useDialogState();
|
|
1270
|
-
const
|
|
1407
|
+
const featureRecord = useRef2(/* @__PURE__ */ new Map()).current;
|
|
1408
|
+
const featureLookup = useFeatureLookup(modules, featureRecord);
|
|
1271
1409
|
useShellApiInit({
|
|
1272
1410
|
navigate,
|
|
1273
1411
|
openCommandMenu,
|
|
@@ -1283,7 +1421,7 @@ function AppShell({ registry, sidebar }) {
|
|
|
1283
1421
|
setDialogState: dialog2.setDialogState,
|
|
1284
1422
|
featureLookup
|
|
1285
1423
|
});
|
|
1286
|
-
const handleServiceSelect =
|
|
1424
|
+
const handleServiceSelect = useCallback3(
|
|
1287
1425
|
(serviceId) => {
|
|
1288
1426
|
const service = modules.find((s) => s.id === serviceId);
|
|
1289
1427
|
if (!service) return;
|
|
@@ -1317,7 +1455,7 @@ function AppShell({ registry, sidebar }) {
|
|
|
1317
1455
|
setSubNavCollapsed
|
|
1318
1456
|
]
|
|
1319
1457
|
);
|
|
1320
|
-
const sidePaneContextValue =
|
|
1458
|
+
const sidePaneContextValue = useMemo4(
|
|
1321
1459
|
() => ({
|
|
1322
1460
|
pane: sidePane2.sidePaneState,
|
|
1323
1461
|
open: sidePane2.handleOpen,
|
|
@@ -1336,22 +1474,24 @@ function AppShell({ registry, sidebar }) {
|
|
|
1336
1474
|
const navigationValue = {
|
|
1337
1475
|
activeService,
|
|
1338
1476
|
sidePaneModuleId: sidePane2.sidePaneState?.moduleId ?? null,
|
|
1339
|
-
subNavCollapsed,
|
|
1340
|
-
onToggleSubNav:
|
|
1477
|
+
subNavCollapsed: subNav.collapsed,
|
|
1478
|
+
onToggleSubNav: subNav.toggle,
|
|
1479
|
+
requestSubNavCollapse: subNav.requestCollapse,
|
|
1341
1480
|
onServiceSelect: handleServiceSelect
|
|
1342
1481
|
};
|
|
1343
|
-
return /* @__PURE__ */
|
|
1344
|
-
/* @__PURE__ */
|
|
1482
|
+
return /* @__PURE__ */ jsx14(ShellModulesContext.Provider, { value: registry, children: /* @__PURE__ */ jsx14(SidePaneContext.Provider, { value: sidePaneContextValue, children: /* @__PURE__ */ jsx14(ShellNavigationContext.Provider, { value: navigationValue, children: /* @__PURE__ */ jsxs9(TooltipProvider, { children: [
|
|
1483
|
+
/* @__PURE__ */ jsx14(ModuleEffects, { modules }),
|
|
1484
|
+
/* @__PURE__ */ jsx14(ModuleFeatures, { modules, record: featureRecord }),
|
|
1345
1485
|
/* @__PURE__ */ jsxs9("div", { className: "flex h-screen w-screen flex-col overflow-hidden", children: [
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1486
|
+
/* @__PURE__ */ jsx14(TopBar, { children: config.topBar }),
|
|
1487
|
+
/* @__PURE__ */ jsx14(
|
|
1348
1488
|
CommandMenu,
|
|
1349
1489
|
{
|
|
1350
1490
|
open: commandMenuOpen,
|
|
1351
1491
|
onOpenChange: setCommandMenuOpen
|
|
1352
1492
|
}
|
|
1353
1493
|
),
|
|
1354
|
-
/* @__PURE__ */
|
|
1494
|
+
/* @__PURE__ */ jsx14(
|
|
1355
1495
|
ShellBody,
|
|
1356
1496
|
{
|
|
1357
1497
|
activeService,
|
|
@@ -1359,8 +1499,8 @@ function AppShell({ registry, sidebar }) {
|
|
|
1359
1499
|
sidebar
|
|
1360
1500
|
}
|
|
1361
1501
|
),
|
|
1362
|
-
config.footer && /* @__PURE__ */
|
|
1363
|
-
dialog2.dialogState && /* @__PURE__ */
|
|
1502
|
+
config.footer && /* @__PURE__ */ jsx14(ShellFooter, { children: config.footer }),
|
|
1503
|
+
dialog2.dialogState && /* @__PURE__ */ jsx14(
|
|
1364
1504
|
ConfirmDialog,
|
|
1365
1505
|
{
|
|
1366
1506
|
open: true,
|
|
@@ -1369,12 +1509,13 @@ function AppShell({ registry, sidebar }) {
|
|
|
1369
1509
|
confirmLabel: dialog2.dialogState.opts.confirmLabel,
|
|
1370
1510
|
cancelLabel: dialog2.dialogState.opts.cancelLabel,
|
|
1371
1511
|
variant: dialog2.dialogState.opts.variant,
|
|
1512
|
+
confirmText: dialog2.dialogState.opts.confirmText,
|
|
1372
1513
|
onConfirm: dialog2.handleConfirm,
|
|
1373
1514
|
onCancel: dialog2.handleCancel
|
|
1374
1515
|
}
|
|
1375
1516
|
),
|
|
1376
|
-
fullscreenState && /* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1517
|
+
fullscreenState && /* @__PURE__ */ jsx14("div", { className: "fixed inset-0 z-50 bg-background overflow-auto", children: fullscreenState.content }),
|
|
1518
|
+
/* @__PURE__ */ jsx14(
|
|
1378
1519
|
SlideOverPanel,
|
|
1379
1520
|
{
|
|
1380
1521
|
panelState: panel2.panelState,
|
|
@@ -1407,14 +1548,14 @@ function SlideOverPanel({
|
|
|
1407
1548
|
},
|
|
1408
1549
|
...!panelState?.description && { "aria-describedby": void 0 }
|
|
1409
1550
|
};
|
|
1410
|
-
return /* @__PURE__ */
|
|
1551
|
+
return /* @__PURE__ */ jsx14(
|
|
1411
1552
|
Sheet,
|
|
1412
1553
|
{
|
|
1413
1554
|
open: panelState !== null,
|
|
1414
1555
|
onOpenChange: (open) => {
|
|
1415
1556
|
if (!open) onClose();
|
|
1416
1557
|
},
|
|
1417
|
-
children: resize.enabled ? /* @__PURE__ */
|
|
1558
|
+
children: resize.enabled ? /* @__PURE__ */ jsx14(ResizableSheetContent, { ...sheetProps, resize, children: panelState && /* @__PURE__ */ jsx14(PanelContent, { state: panelState }) }) : /* @__PURE__ */ jsx14(SheetContent, { ...sheetProps, className: `${panelWidth} max-w-[90vw]`, children: panelState && /* @__PURE__ */ jsx14(PanelContent, { state: panelState }) })
|
|
1418
1559
|
}
|
|
1419
1560
|
);
|
|
1420
1561
|
}
|
|
@@ -1441,7 +1582,7 @@ function ResizableSheetContent({
|
|
|
1441
1582
|
className: "max-w-[90vw]",
|
|
1442
1583
|
style: { width: dynWidth },
|
|
1443
1584
|
children: [
|
|
1444
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx14(
|
|
1445
1586
|
DragHandle,
|
|
1446
1587
|
{
|
|
1447
1588
|
edge: "left",
|
|
@@ -1461,24 +1602,24 @@ function ShellBody({
|
|
|
1461
1602
|
sidebar
|
|
1462
1603
|
}) {
|
|
1463
1604
|
return /* @__PURE__ */ jsxs9("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
1464
|
-
sidebar ?? /* @__PURE__ */
|
|
1465
|
-
/* @__PURE__ */
|
|
1466
|
-
sidePaneFullWidth !== true && /* @__PURE__ */
|
|
1605
|
+
sidebar ?? /* @__PURE__ */ jsx14(ShellRail, {}),
|
|
1606
|
+
/* @__PURE__ */ jsx14(SidePane, {}),
|
|
1607
|
+
sidePaneFullWidth !== true && /* @__PURE__ */ jsx14("div", { className: "flex-1 min-w-0 h-full overflow-hidden", children: /* @__PURE__ */ jsx14(ContentArea, { layout: activeService?.layout }) })
|
|
1467
1608
|
] });
|
|
1468
1609
|
}
|
|
1469
1610
|
function ContentArea({ layout }) {
|
|
1470
1611
|
if (layout === "full") {
|
|
1471
|
-
return /* @__PURE__ */
|
|
1612
|
+
return /* @__PURE__ */ jsx14("div", { className: "h-full w-full overflow-hidden", children: /* @__PURE__ */ jsx14(Outlet, {}) });
|
|
1472
1613
|
}
|
|
1473
|
-
return /* @__PURE__ */
|
|
1614
|
+
return /* @__PURE__ */ jsx14(ScrollArea2, { className: "h-full", children: /* @__PURE__ */ jsx14("main", { className: "p-6", children: /* @__PURE__ */ jsx14(Outlet, {}) }) });
|
|
1474
1615
|
}
|
|
1475
1616
|
function PanelContent({ state }) {
|
|
1476
|
-
return /* @__PURE__ */ jsxs9(
|
|
1617
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1477
1618
|
state.title ? /* @__PURE__ */ jsxs9(SheetHeader, { children: [
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
state.description && /* @__PURE__ */
|
|
1480
|
-
] }) : /* @__PURE__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1619
|
+
/* @__PURE__ */ jsx14(SheetTitle, { children: state.title }),
|
|
1620
|
+
state.description && /* @__PURE__ */ jsx14(SheetDescription, { children: state.description })
|
|
1621
|
+
] }) : /* @__PURE__ */ jsx14(SheetTitle, { className: "sr-only", children: "Panel" }),
|
|
1622
|
+
/* @__PURE__ */ jsx14(SheetBody, { children: state.content })
|
|
1482
1623
|
] });
|
|
1483
1624
|
}
|
|
1484
1625
|
|
|
@@ -1486,36 +1627,36 @@ function PanelContent({ state }) {
|
|
|
1486
1627
|
import { Toaster } from "sonner";
|
|
1487
1628
|
|
|
1488
1629
|
// src/ShellConfigProvider.tsx
|
|
1489
|
-
import { jsx as
|
|
1630
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1490
1631
|
function ShellConfigProvider({
|
|
1491
1632
|
config,
|
|
1492
1633
|
children
|
|
1493
1634
|
}) {
|
|
1494
|
-
return /* @__PURE__ */
|
|
1635
|
+
return /* @__PURE__ */ jsx15(ShellConfigContext.Provider, { value: config, children });
|
|
1495
1636
|
}
|
|
1496
1637
|
|
|
1497
1638
|
// src/RootLayout.tsx
|
|
1498
|
-
import { jsx as
|
|
1639
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1499
1640
|
function RootLayout({
|
|
1500
1641
|
config,
|
|
1501
1642
|
registry,
|
|
1502
1643
|
sidebar
|
|
1503
1644
|
}) {
|
|
1504
1645
|
return /* @__PURE__ */ jsxs10(ShellConfigProvider, { config, children: [
|
|
1505
|
-
/* @__PURE__ */
|
|
1506
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsx16(Toaster, { position: "top-right", richColors: true, closeButton: true }),
|
|
1647
|
+
/* @__PURE__ */ jsx16(AppShell, { registry, sidebar })
|
|
1507
1648
|
] });
|
|
1508
1649
|
}
|
|
1509
1650
|
|
|
1510
1651
|
// src/PlaceholderPage.tsx
|
|
1511
1652
|
import { useLocation as useLocation3 } from "react-router-dom";
|
|
1512
|
-
import { jsx as
|
|
1653
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1513
1654
|
function PlaceholderPage() {
|
|
1514
1655
|
const { pathname } = useLocation3();
|
|
1515
1656
|
return /* @__PURE__ */ jsxs11("div", { children: [
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1657
|
+
/* @__PURE__ */ jsx17("h1", { className: "mb-1", children: pathToTitle(pathname) }),
|
|
1658
|
+
/* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground mb-6", children: pathname }),
|
|
1659
|
+
/* @__PURE__ */ jsx17("div", { className: "rounded-lg border-2 border-dashed border-border p-12 flex items-center justify-center", children: /* @__PURE__ */ jsx17("span", { className: "text-sm text-muted-foreground", children: "Content area \u2014 not yet implemented" }) })
|
|
1519
1660
|
] });
|
|
1520
1661
|
}
|
|
1521
1662
|
function pathToTitle(path) {
|
|
@@ -1524,46 +1665,148 @@ function pathToTitle(path) {
|
|
|
1524
1665
|
return last.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
1525
1666
|
}
|
|
1526
1667
|
|
|
1527
|
-
// src/
|
|
1668
|
+
// src/Breadcrumbs.tsx
|
|
1669
|
+
import { useContext as useContext5 } from "react";
|
|
1670
|
+
import { Link as Link2 } from "react-router-dom";
|
|
1671
|
+
import { ChevronRight as ChevronRight2 } from "lucide-react";
|
|
1528
1672
|
import { cn as cn6 } from "@petrarca/sonnet-core";
|
|
1673
|
+
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1674
|
+
var ELLIPSIS = { label: "\u2026" };
|
|
1675
|
+
function useTrail({
|
|
1676
|
+
items,
|
|
1677
|
+
omitModule,
|
|
1678
|
+
maxItems
|
|
1679
|
+
}) {
|
|
1680
|
+
const navigation2 = useContext5(ShellNavigationContext);
|
|
1681
|
+
const module = navigation2?.activeService;
|
|
1682
|
+
const root = !omitModule && module ? [{ label: module.label, to: module.basePath }] : [];
|
|
1683
|
+
const trail = [...root, ...items];
|
|
1684
|
+
if (trail.length <= maxItems || maxItems < 3) return trail;
|
|
1685
|
+
return [trail[0], ELLIPSIS, ...trail.slice(trail.length - 2)];
|
|
1686
|
+
}
|
|
1687
|
+
function titleOf(label) {
|
|
1688
|
+
return typeof label === "string" ? label : void 0;
|
|
1689
|
+
}
|
|
1690
|
+
function Crumb({
|
|
1691
|
+
item,
|
|
1692
|
+
current
|
|
1693
|
+
}) {
|
|
1694
|
+
const text = /* @__PURE__ */ jsx18("span", { className: "truncate max-w-[18rem]", children: item.label });
|
|
1695
|
+
if (current || !item.to) {
|
|
1696
|
+
return /* @__PURE__ */ jsx18(
|
|
1697
|
+
"span",
|
|
1698
|
+
{
|
|
1699
|
+
className: cn6(
|
|
1700
|
+
"inline-flex min-w-0",
|
|
1701
|
+
current ? "text-foreground font-medium" : "text-muted-foreground"
|
|
1702
|
+
),
|
|
1703
|
+
"aria-current": current ? "page" : void 0,
|
|
1704
|
+
title: titleOf(item.label),
|
|
1705
|
+
children: text
|
|
1706
|
+
}
|
|
1707
|
+
);
|
|
1708
|
+
}
|
|
1709
|
+
return /* @__PURE__ */ jsx18(
|
|
1710
|
+
Link2,
|
|
1711
|
+
{
|
|
1712
|
+
to: item.to,
|
|
1713
|
+
className: "inline-flex min-w-0 text-muted-foreground hover:text-foreground transition-colors",
|
|
1714
|
+
title: titleOf(item.label),
|
|
1715
|
+
children: text
|
|
1716
|
+
}
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
function Breadcrumbs({
|
|
1720
|
+
items,
|
|
1721
|
+
omitModule = false,
|
|
1722
|
+
maxItems = 5,
|
|
1723
|
+
className
|
|
1724
|
+
}) {
|
|
1725
|
+
const trail = useTrail({ items, omitModule, maxItems });
|
|
1726
|
+
return /* @__PURE__ */ jsx18("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx18("ol", { className: "flex items-center gap-1.5 text-sm min-w-0", children: trail.map((item, index) => {
|
|
1727
|
+
const current = index === trail.length - 1;
|
|
1728
|
+
return /* @__PURE__ */ jsxs12(
|
|
1729
|
+
"li",
|
|
1730
|
+
{
|
|
1731
|
+
className: "inline-flex items-center gap-1.5 min-w-0",
|
|
1732
|
+
children: [
|
|
1733
|
+
/* @__PURE__ */ jsx18(Crumb, { item, current }),
|
|
1734
|
+
!current && /* @__PURE__ */ jsx18(
|
|
1735
|
+
ChevronRight2,
|
|
1736
|
+
{
|
|
1737
|
+
className: "h-3.5 w-3.5 shrink-0 text-muted-foreground",
|
|
1738
|
+
"aria-hidden": true
|
|
1739
|
+
}
|
|
1740
|
+
)
|
|
1741
|
+
]
|
|
1742
|
+
},
|
|
1743
|
+
index
|
|
1744
|
+
);
|
|
1745
|
+
}) }) });
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
// src/DrillDownHeader.tsx
|
|
1749
|
+
import { cn as cn7 } from "@petrarca/sonnet-core";
|
|
1750
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1751
|
+
function DrillDownHeader({
|
|
1752
|
+
breadcrumbs,
|
|
1753
|
+
title,
|
|
1754
|
+
adornment,
|
|
1755
|
+
actions,
|
|
1756
|
+
subtitle,
|
|
1757
|
+
className
|
|
1758
|
+
}) {
|
|
1759
|
+
return /* @__PURE__ */ jsxs13("header", { className: cn7("mb-4", className), children: [
|
|
1760
|
+
/* @__PURE__ */ jsx19(Breadcrumbs, { items: breadcrumbs, className: "mb-3" }),
|
|
1761
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3 mb-1 min-w-0", children: [
|
|
1762
|
+
/* @__PURE__ */ jsx19("h1", { className: "truncate", children: title }),
|
|
1763
|
+
adornment,
|
|
1764
|
+
actions && /* @__PURE__ */ jsx19("div", { className: "ml-auto flex items-center gap-2 shrink-0", children: actions })
|
|
1765
|
+
] }),
|
|
1766
|
+
subtitle && /* @__PURE__ */ jsx19("p", { className: "text-xs text-muted-foreground", children: subtitle })
|
|
1767
|
+
] });
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// src/Sidebar.tsx
|
|
1771
|
+
import { cn as cn8 } from "@petrarca/sonnet-core";
|
|
1529
1772
|
import { ScrollArea as ScrollArea3 } from "@petrarca/sonnet-ui";
|
|
1530
|
-
import { jsx as
|
|
1773
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1531
1774
|
function Sidebar({
|
|
1532
1775
|
children,
|
|
1533
1776
|
header,
|
|
1534
1777
|
width = 260,
|
|
1535
1778
|
className
|
|
1536
1779
|
}) {
|
|
1537
|
-
return /* @__PURE__ */
|
|
1780
|
+
return /* @__PURE__ */ jsxs14(
|
|
1538
1781
|
"aside",
|
|
1539
1782
|
{
|
|
1540
1783
|
style: { width },
|
|
1541
|
-
className:
|
|
1784
|
+
className: cn8(
|
|
1542
1785
|
"shrink-0 border-r bg-muted/30 flex flex-col h-full",
|
|
1543
1786
|
className
|
|
1544
1787
|
),
|
|
1545
1788
|
children: [
|
|
1546
1789
|
header,
|
|
1547
|
-
/* @__PURE__ */
|
|
1790
|
+
/* @__PURE__ */ jsx20(ScrollArea3, { className: "flex-1", children: /* @__PURE__ */ jsx20("nav", { className: "px-1.5 py-2 space-y-3", children }) })
|
|
1548
1791
|
]
|
|
1549
1792
|
}
|
|
1550
1793
|
);
|
|
1551
1794
|
}
|
|
1552
1795
|
|
|
1553
1796
|
// src/ShellSidebar.tsx
|
|
1554
|
-
import
|
|
1555
|
-
import { jsx as
|
|
1797
|
+
import React8, { useMemo as useMemo5 } from "react";
|
|
1798
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1556
1799
|
function ShellSidebar({
|
|
1557
1800
|
bottomGroupLabel = "Tools",
|
|
1558
1801
|
...sidebarProps
|
|
1559
1802
|
}) {
|
|
1560
1803
|
const { mainModules, bottomModules } = useShellModules();
|
|
1561
1804
|
const { resolveCapability, capabilityPolicy } = useShellConfig();
|
|
1562
|
-
const policy =
|
|
1805
|
+
const policy = useMemo5(
|
|
1563
1806
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
1564
1807
|
[capabilityPolicy]
|
|
1565
1808
|
);
|
|
1566
|
-
const effectOf =
|
|
1809
|
+
const effectOf = React8.useCallback(
|
|
1567
1810
|
(moduleId) => {
|
|
1568
1811
|
const module = [...mainModules, ...bottomModules].find(
|
|
1569
1812
|
(m) => m.id === moduleId
|
|
@@ -1584,8 +1827,8 @@ function ShellSidebar({
|
|
|
1584
1827
|
reason
|
|
1585
1828
|
}));
|
|
1586
1829
|
});
|
|
1587
|
-
return /* @__PURE__ */
|
|
1588
|
-
topNavItems.length > 0 && /* @__PURE__ */
|
|
1830
|
+
return /* @__PURE__ */ jsxs15(Sidebar, { ...sidebarProps, children: [
|
|
1831
|
+
topNavItems.length > 0 && /* @__PURE__ */ jsx21(SidebarGroup, { separator: true, children: topNavItems.map(({ link, icon, disabled, reason }) => /* @__PURE__ */ jsx21(
|
|
1589
1832
|
SidebarItem,
|
|
1590
1833
|
{
|
|
1591
1834
|
icon,
|
|
@@ -1600,63 +1843,21 @@ function ShellSidebar({
|
|
|
1600
1843
|
mainModules.map((mod) => {
|
|
1601
1844
|
const { effect, reason } = effectOf(mod.id);
|
|
1602
1845
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
disabled,
|
|
1613
|
-
title
|
|
1614
|
-
},
|
|
1615
|
-
mod.id
|
|
1616
|
-
);
|
|
1617
|
-
}
|
|
1618
|
-
return /* @__PURE__ */ jsx18(SidebarGroup, { heading: mod.label, collapsible: true, children: mod.navigation.flatMap((group) => [
|
|
1619
|
-
// Render NavGroup heading if it has one
|
|
1620
|
-
...group.heading ? [
|
|
1621
|
-
/* @__PURE__ */ jsx18(
|
|
1622
|
-
SidebarGroup,
|
|
1623
|
-
{
|
|
1624
|
-
heading: group.heading,
|
|
1625
|
-
collapsible: group.collapsible,
|
|
1626
|
-
children: group.links.map((link) => /* @__PURE__ */ jsx18(
|
|
1627
|
-
SidebarItem,
|
|
1628
|
-
{
|
|
1629
|
-
icon: mod.icon,
|
|
1630
|
-
label: link.label,
|
|
1631
|
-
path: link.path,
|
|
1632
|
-
badge: link.badge,
|
|
1633
|
-
disabled,
|
|
1634
|
-
title: disabled ? reason : void 0
|
|
1635
|
-
},
|
|
1636
|
-
link.path
|
|
1637
|
-
))
|
|
1638
|
-
},
|
|
1639
|
-
group.id
|
|
1640
|
-
)
|
|
1641
|
-
] : group.links.map((link) => /* @__PURE__ */ jsx18(
|
|
1642
|
-
SidebarItem,
|
|
1643
|
-
{
|
|
1644
|
-
icon: mod.icon,
|
|
1645
|
-
label: link.label,
|
|
1646
|
-
path: link.path,
|
|
1647
|
-
badge: link.badge,
|
|
1648
|
-
disabled,
|
|
1649
|
-
title: disabled ? reason : void 0
|
|
1650
|
-
},
|
|
1651
|
-
link.path
|
|
1652
|
-
))
|
|
1653
|
-
]) }, mod.id);
|
|
1846
|
+
return /* @__PURE__ */ jsx21(
|
|
1847
|
+
ModuleSection,
|
|
1848
|
+
{
|
|
1849
|
+
mod,
|
|
1850
|
+
disabled: effect === "disabled",
|
|
1851
|
+
reason
|
|
1852
|
+
},
|
|
1853
|
+
mod.id
|
|
1854
|
+
);
|
|
1654
1855
|
}),
|
|
1655
|
-
bottomModules.length > 0 && /* @__PURE__ */
|
|
1856
|
+
bottomModules.length > 0 && /* @__PURE__ */ jsx21(SidebarGroup, { heading: bottomGroupLabel, collapsible: true, children: bottomModules.map((mod) => {
|
|
1656
1857
|
const { effect, reason } = effectOf(mod.id);
|
|
1657
1858
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
1658
1859
|
const disabled = effect === "disabled";
|
|
1659
|
-
return /* @__PURE__ */
|
|
1860
|
+
return /* @__PURE__ */ jsx21(
|
|
1660
1861
|
SidebarItem,
|
|
1661
1862
|
{
|
|
1662
1863
|
icon: mod.icon,
|
|
@@ -1670,16 +1871,61 @@ function ShellSidebar({
|
|
|
1670
1871
|
}) })
|
|
1671
1872
|
] });
|
|
1672
1873
|
}
|
|
1874
|
+
function ModuleSection({
|
|
1875
|
+
mod,
|
|
1876
|
+
disabled,
|
|
1877
|
+
reason
|
|
1878
|
+
}) {
|
|
1879
|
+
const navigation2 = useModuleNavigation(mod);
|
|
1880
|
+
const title = disabled ? reason : void 0;
|
|
1881
|
+
if (navigation2.length === 0) {
|
|
1882
|
+
return /* @__PURE__ */ jsx21(
|
|
1883
|
+
SidebarItem,
|
|
1884
|
+
{
|
|
1885
|
+
icon: mod.icon,
|
|
1886
|
+
label: mod.label,
|
|
1887
|
+
path: mod.basePath,
|
|
1888
|
+
disabled,
|
|
1889
|
+
title
|
|
1890
|
+
}
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
return /* @__PURE__ */ jsx21(SidebarGroup, { heading: mod.label, collapsible: true, children: navigation2.flatMap((group) => {
|
|
1894
|
+
const items = group.links.map((link) => /* @__PURE__ */ jsx21(
|
|
1895
|
+
SidebarItem,
|
|
1896
|
+
{
|
|
1897
|
+
icon: mod.icon,
|
|
1898
|
+
label: link.label,
|
|
1899
|
+
path: link.path,
|
|
1900
|
+
badge: link.badge,
|
|
1901
|
+
disabled,
|
|
1902
|
+
title
|
|
1903
|
+
},
|
|
1904
|
+
link.path
|
|
1905
|
+
));
|
|
1906
|
+
return group.heading ? [
|
|
1907
|
+
/* @__PURE__ */ jsx21(
|
|
1908
|
+
SidebarGroup,
|
|
1909
|
+
{
|
|
1910
|
+
heading: group.heading,
|
|
1911
|
+
collapsible: group.collapsible,
|
|
1912
|
+
children: items
|
|
1913
|
+
},
|
|
1914
|
+
group.id
|
|
1915
|
+
)
|
|
1916
|
+
] : items;
|
|
1917
|
+
}) });
|
|
1918
|
+
}
|
|
1673
1919
|
|
|
1674
1920
|
// src/ShellVersion.tsx
|
|
1675
|
-
import { jsx as
|
|
1921
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1676
1922
|
function ShellVersion({
|
|
1677
1923
|
name,
|
|
1678
1924
|
version
|
|
1679
1925
|
}) {
|
|
1680
|
-
return /* @__PURE__ */
|
|
1681
|
-
/* @__PURE__ */
|
|
1682
|
-
version && /* @__PURE__ */
|
|
1926
|
+
return /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
1927
|
+
/* @__PURE__ */ jsx22("span", { children: name }),
|
|
1928
|
+
version && /* @__PURE__ */ jsxs16("span", { className: "text-tertiary-foreground", children: [
|
|
1683
1929
|
"v",
|
|
1684
1930
|
version
|
|
1685
1931
|
] })
|
|
@@ -1689,9 +1935,9 @@ function ShellVersion({
|
|
|
1689
1935
|
// src/SearchTrigger.tsx
|
|
1690
1936
|
import { Search } from "lucide-react";
|
|
1691
1937
|
import { Button as Button3 } from "@petrarca/sonnet-ui";
|
|
1692
|
-
import { jsx as
|
|
1938
|
+
import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1693
1939
|
function SearchTrigger() {
|
|
1694
|
-
return /* @__PURE__ */
|
|
1940
|
+
return /* @__PURE__ */ jsxs17(
|
|
1695
1941
|
Button3,
|
|
1696
1942
|
{
|
|
1697
1943
|
variant: "outline",
|
|
@@ -1699,10 +1945,10 @@ function SearchTrigger() {
|
|
|
1699
1945
|
className: "h-8 gap-2 text-sm text-muted-foreground w-56 justify-start",
|
|
1700
1946
|
onClick: () => navigation.openCommandMenu(),
|
|
1701
1947
|
children: [
|
|
1702
|
-
/* @__PURE__ */
|
|
1703
|
-
/* @__PURE__ */
|
|
1704
|
-
/* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1948
|
+
/* @__PURE__ */ jsx23(Search, { className: "h-4 w-4" }),
|
|
1949
|
+
/* @__PURE__ */ jsx23("span", { children: "Search..." }),
|
|
1950
|
+
/* @__PURE__ */ jsxs17("kbd", { className: "ml-auto pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground", children: [
|
|
1951
|
+
/* @__PURE__ */ jsx23("span", { className: "text-xs", children: "\u2318" }),
|
|
1706
1952
|
"K"
|
|
1707
1953
|
] })
|
|
1708
1954
|
]
|
|
@@ -1710,9 +1956,32 @@ function SearchTrigger() {
|
|
|
1710
1956
|
);
|
|
1711
1957
|
}
|
|
1712
1958
|
|
|
1959
|
+
// src/ThemeToggle.tsx
|
|
1960
|
+
import { Moon, Sun } from "lucide-react";
|
|
1961
|
+
import { Button as Button4 } from "@petrarca/sonnet-ui";
|
|
1962
|
+
import { useTheme } from "@petrarca/sonnet-core/hooks";
|
|
1963
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1964
|
+
function ThemeToggle() {
|
|
1965
|
+
const { theme, setTheme } = useTheme();
|
|
1966
|
+
const dark = theme === "dark";
|
|
1967
|
+
const label = dark ? "Switch to light mode" : "Switch to dark mode";
|
|
1968
|
+
return /* @__PURE__ */ jsx24(
|
|
1969
|
+
Button4,
|
|
1970
|
+
{
|
|
1971
|
+
variant: "ghost",
|
|
1972
|
+
size: "icon",
|
|
1973
|
+
className: "h-8 w-8",
|
|
1974
|
+
"aria-label": label,
|
|
1975
|
+
title: label,
|
|
1976
|
+
onClick: () => setTheme(dark ? "light" : "dark"),
|
|
1977
|
+
children: dark ? /* @__PURE__ */ jsx24(Sun, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx24(Moon, { className: "h-4 w-4" })
|
|
1978
|
+
}
|
|
1979
|
+
);
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1713
1982
|
// src/UserMenu.tsx
|
|
1714
1983
|
import { LogOut, User } from "lucide-react";
|
|
1715
|
-
import { Button as
|
|
1984
|
+
import { Button as Button5 } from "@petrarca/sonnet-ui";
|
|
1716
1985
|
import { Avatar, AvatarFallback } from "@petrarca/sonnet-ui";
|
|
1717
1986
|
import {
|
|
1718
1987
|
DropdownMenu,
|
|
@@ -1722,23 +1991,23 @@ import {
|
|
|
1722
1991
|
DropdownMenuSeparator,
|
|
1723
1992
|
DropdownMenuTrigger
|
|
1724
1993
|
} from "@petrarca/sonnet-ui";
|
|
1725
|
-
import { jsx as
|
|
1994
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1726
1995
|
function UserMenu({ user, onSignOut }) {
|
|
1727
|
-
return /* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
1731
|
-
/* @__PURE__ */
|
|
1732
|
-
/* @__PURE__ */
|
|
1996
|
+
return /* @__PURE__ */ jsxs18(DropdownMenu, { children: [
|
|
1997
|
+
/* @__PURE__ */ jsx25(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(Button5, { variant: "ghost", size: "compact", className: "rounded-full", children: /* @__PURE__ */ jsx25(Avatar, { className: "h-7 w-7", children: /* @__PURE__ */ jsx25(AvatarFallback, { className: "text-xs", children: user.initials }) }) }) }),
|
|
1998
|
+
/* @__PURE__ */ jsxs18(DropdownMenuContent, { align: "end", className: "w-48", children: [
|
|
1999
|
+
/* @__PURE__ */ jsx25(DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1", children: [
|
|
2000
|
+
/* @__PURE__ */ jsx25("p", { className: "text-sm font-medium", children: user.name }),
|
|
2001
|
+
/* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: user.email })
|
|
1733
2002
|
] }) }),
|
|
1734
|
-
/* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsx25(DropdownMenuSeparator, {}),
|
|
2004
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { children: [
|
|
2005
|
+
/* @__PURE__ */ jsx25(User, { className: "mr-2 h-4 w-4" }),
|
|
1737
2006
|
"Profile"
|
|
1738
2007
|
] }),
|
|
1739
|
-
/* @__PURE__ */
|
|
1740
|
-
/* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
2008
|
+
/* @__PURE__ */ jsx25(DropdownMenuSeparator, {}),
|
|
2009
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { onSelect: onSignOut, children: [
|
|
2010
|
+
/* @__PURE__ */ jsx25(LogOut, { className: "mr-2 h-4 w-4" }),
|
|
1742
2011
|
"Sign out"
|
|
1743
2012
|
] })
|
|
1744
2013
|
] })
|
|
@@ -1750,7 +2019,6 @@ function createModuleRegistry(modules) {
|
|
|
1750
2019
|
const visible = modules.filter((m) => !m.hidden);
|
|
1751
2020
|
const mainModules = visible.filter((m) => !m.pinBottom);
|
|
1752
2021
|
const bottomModules = visible.filter((m) => m.pinBottom);
|
|
1753
|
-
const allRoutes = modules.flatMap((m) => m.routes);
|
|
1754
2022
|
const contributionsByPoint = /* @__PURE__ */ new Map();
|
|
1755
2023
|
for (const m of modules) {
|
|
1756
2024
|
for (const c of m.contributions ?? []) {
|
|
@@ -1765,17 +2033,57 @@ function createModuleRegistry(modules) {
|
|
|
1765
2033
|
function getExtensionPoint(name) {
|
|
1766
2034
|
return contributionsByPoint.get(name) ?? [];
|
|
1767
2035
|
}
|
|
2036
|
+
const allRoutes = nestContributedRoutes(
|
|
2037
|
+
modules.flatMap((m) => m.routes),
|
|
2038
|
+
contributionsByPoint
|
|
2039
|
+
);
|
|
1768
2040
|
return { modules, mainModules, bottomModules, allRoutes, getExtensionPoint };
|
|
1769
2041
|
}
|
|
2042
|
+
function nestContributedRoutes(routes, contributionsByPoint) {
|
|
2043
|
+
const hosted = /* @__PURE__ */ new Set();
|
|
2044
|
+
function nest(route) {
|
|
2045
|
+
if (route.index) return route;
|
|
2046
|
+
const pages = (contributionsByPoint.get(route.id ?? "") ?? []).filter(
|
|
2047
|
+
(c) => c.element !== void 0
|
|
2048
|
+
);
|
|
2049
|
+
const children = route.children?.map(nest);
|
|
2050
|
+
if (pages.length === 0) {
|
|
2051
|
+
return children ? { ...route, children } : route;
|
|
2052
|
+
}
|
|
2053
|
+
hosted.add(route.id);
|
|
2054
|
+
const contributed = pages.map((c) => ({
|
|
2055
|
+
path: c.path,
|
|
2056
|
+
element: c.element
|
|
2057
|
+
}));
|
|
2058
|
+
return { ...route, children: [...children ?? [], ...contributed] };
|
|
2059
|
+
}
|
|
2060
|
+
const nested = routes.map(nest);
|
|
2061
|
+
for (const [point, list] of contributionsByPoint) {
|
|
2062
|
+
if (!hosted.has(point) && list.some((c) => c.element !== void 0)) {
|
|
2063
|
+
throw new Error(
|
|
2064
|
+
`Pages are contributed to extension point "${point}", but no route has id "${point}" to host them.`
|
|
2065
|
+
);
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
return nested;
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
// src/contributionPath.ts
|
|
2072
|
+
function contributionPath(path, params) {
|
|
2073
|
+
return path.replace(
|
|
2074
|
+
/:([A-Za-z_][A-Za-z0-9_]*)/g,
|
|
2075
|
+
(token, name) => name in params ? encodeURIComponent(params[name]) : token
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
1770
2078
|
|
|
1771
2079
|
// src/OverviewCard.tsx
|
|
1772
|
-
import { cn as
|
|
1773
|
-
import { jsx as
|
|
2080
|
+
import { cn as cn9 } from "@petrarca/sonnet-core";
|
|
2081
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1774
2082
|
function FeatureLink({
|
|
1775
2083
|
feature,
|
|
1776
2084
|
children
|
|
1777
2085
|
}) {
|
|
1778
|
-
return /* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsx26(
|
|
1779
2087
|
"span",
|
|
1780
2088
|
{
|
|
1781
2089
|
role: "link",
|
|
@@ -1801,37 +2109,51 @@ function OverviewCard({
|
|
|
1801
2109
|
title,
|
|
1802
2110
|
description,
|
|
1803
2111
|
feature,
|
|
2112
|
+
path,
|
|
1804
2113
|
className
|
|
1805
2114
|
}) {
|
|
1806
|
-
|
|
2115
|
+
const go = feature ? () => navigation.goToFeature(feature) : path ? () => navigation.goTo(path) : void 0;
|
|
2116
|
+
return /* @__PURE__ */ jsxs19(
|
|
1807
2117
|
"button",
|
|
1808
2118
|
{
|
|
1809
|
-
onClick:
|
|
1810
|
-
disabled: !
|
|
1811
|
-
className:
|
|
2119
|
+
onClick: go,
|
|
2120
|
+
disabled: !go,
|
|
2121
|
+
className: cn9(
|
|
1812
2122
|
"rounded-lg border bg-card p-5 text-left flex flex-col gap-3",
|
|
1813
2123
|
"disabled:cursor-default",
|
|
1814
|
-
|
|
2124
|
+
go && "hover:bg-accent/50 transition-colors",
|
|
1815
2125
|
className
|
|
1816
2126
|
),
|
|
1817
2127
|
children: [
|
|
1818
|
-
/* @__PURE__ */
|
|
1819
|
-
/* @__PURE__ */
|
|
1820
|
-
/* @__PURE__ */
|
|
1821
|
-
/* @__PURE__ */
|
|
2128
|
+
/* @__PURE__ */ jsx26("div", { className: "h-9 w-9 rounded-md bg-blue-50 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx26(Icon, { className: "h-5 w-5 text-blue-600" }) }),
|
|
2129
|
+
/* @__PURE__ */ jsxs19("div", { children: [
|
|
2130
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm font-medium mb-1", children: title }),
|
|
2131
|
+
/* @__PURE__ */ jsx26("p", { className: "text-xs text-muted-foreground leading-relaxed", children: description })
|
|
1822
2132
|
] })
|
|
1823
2133
|
]
|
|
1824
2134
|
}
|
|
1825
2135
|
);
|
|
1826
2136
|
}
|
|
2137
|
+
function OverviewGroupHeading({
|
|
2138
|
+
heading,
|
|
2139
|
+
description
|
|
2140
|
+
}) {
|
|
2141
|
+
return /* @__PURE__ */ jsxs19("div", { className: "mb-3", children: [
|
|
2142
|
+
/* @__PURE__ */ jsx26("h2", { className: "text-sm font-semibold text-foreground", children: heading }),
|
|
2143
|
+
description && /* @__PURE__ */ jsx26("p", { className: "text-sm text-muted-foreground", children: description })
|
|
2144
|
+
] });
|
|
2145
|
+
}
|
|
1827
2146
|
export {
|
|
1828
2147
|
AppShell,
|
|
2148
|
+
Breadcrumbs,
|
|
1829
2149
|
CommandMenu,
|
|
1830
2150
|
ConfirmDialog,
|
|
1831
2151
|
DEFAULT_CAPABILITY_POLICY,
|
|
2152
|
+
DrillDownHeader,
|
|
1832
2153
|
FeatureLink,
|
|
1833
2154
|
IconRail,
|
|
1834
2155
|
OverviewCard,
|
|
2156
|
+
OverviewGroupHeading,
|
|
1835
2157
|
PlaceholderPage,
|
|
1836
2158
|
RailIcon,
|
|
1837
2159
|
RailSeparator,
|
|
@@ -1848,8 +2170,10 @@ export {
|
|
|
1848
2170
|
SidebarGroup,
|
|
1849
2171
|
SidebarItem,
|
|
1850
2172
|
SubNavPanel,
|
|
2173
|
+
ThemeToggle,
|
|
1851
2174
|
TopBar,
|
|
1852
2175
|
UserMenu,
|
|
2176
|
+
contributionPath,
|
|
1853
2177
|
createModuleRegistry,
|
|
1854
2178
|
dialog,
|
|
1855
2179
|
evaluateModule,
|
|
@@ -1866,8 +2190,11 @@ export {
|
|
|
1866
2190
|
panel,
|
|
1867
2191
|
resolveCapabilityPolicy,
|
|
1868
2192
|
sidePane,
|
|
2193
|
+
useCollapsedSubNav,
|
|
2194
|
+
useContributedComponent,
|
|
1869
2195
|
useExtensionPoint,
|
|
1870
2196
|
useMainModules,
|
|
2197
|
+
useModuleNavigation,
|
|
1871
2198
|
useShellConfig,
|
|
1872
2199
|
useShellEvent,
|
|
1873
2200
|
useShellModules,
|