@petrarca/sonnet-shell 0.8.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 +550 -229
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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
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";
|
|
@@ -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";
|
|
@@ -472,7 +528,7 @@ function SidebarGroup({
|
|
|
472
528
|
separator = false,
|
|
473
529
|
children
|
|
474
530
|
}) {
|
|
475
|
-
const [open, setOpen] =
|
|
531
|
+
const [open, setOpen] = useState2(defaultOpen);
|
|
476
532
|
const canCollapse = collapsible && !!heading;
|
|
477
533
|
return /* @__PURE__ */ jsxs3("div", { className: cn2(separator && "border-b border-border pb-2"), children: [
|
|
478
534
|
heading && /* @__PURE__ */ jsx5(
|
|
@@ -586,27 +642,15 @@ function SidebarItem({
|
|
|
586
642
|
|
|
587
643
|
// src/SubNavPanel.tsx
|
|
588
644
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
589
|
-
function
|
|
590
|
-
|
|
591
|
-
return useMemo2(() => {
|
|
592
|
-
if (contributions.length === 0) return service.navigation;
|
|
593
|
-
const contributed = {
|
|
594
|
-
id: `${service.id}-contributed`,
|
|
595
|
-
links: contributions.map((c) => ({
|
|
596
|
-
id: c.extensionPoint + "." + c.label.toLowerCase().replace(/\s+/g, "-"),
|
|
597
|
-
label: c.label,
|
|
598
|
-
path: c.path
|
|
599
|
-
}))
|
|
600
|
-
};
|
|
601
|
-
return [...service.navigation, contributed];
|
|
602
|
-
}, [service, contributions]);
|
|
645
|
+
function SubNavPanel(props) {
|
|
646
|
+
return /* @__PURE__ */ jsx7(ModuleSubNav, { ...props }, props.service.id);
|
|
603
647
|
}
|
|
604
|
-
function
|
|
648
|
+
function ModuleSubNav({
|
|
605
649
|
service,
|
|
606
650
|
collapsed,
|
|
607
651
|
onToggleCollapse
|
|
608
652
|
}) {
|
|
609
|
-
const mergedNavigation =
|
|
653
|
+
const mergedNavigation = useModuleNavigation(service);
|
|
610
654
|
if (collapsed) {
|
|
611
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: [
|
|
612
656
|
/* @__PURE__ */ jsx7(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
@@ -660,7 +704,7 @@ function SubNavPanel({
|
|
|
660
704
|
}
|
|
661
705
|
|
|
662
706
|
// src/shellNavigation.ts
|
|
663
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
707
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2 } from "react";
|
|
664
708
|
var ShellNavigationContext = createContext2(null);
|
|
665
709
|
function useShellNavigation() {
|
|
666
710
|
const ctx = useContext2(ShellNavigationContext);
|
|
@@ -669,6 +713,13 @@ function useShellNavigation() {
|
|
|
669
713
|
}
|
|
670
714
|
return ctx;
|
|
671
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
|
+
}
|
|
672
723
|
|
|
673
724
|
// src/shellConfig.ts
|
|
674
725
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
@@ -754,7 +805,7 @@ function ShellRail() {
|
|
|
754
805
|
onServiceSelect
|
|
755
806
|
} = useShellNavigation();
|
|
756
807
|
const isActive = (id) => activeService?.id === id || sidePaneModuleId === id;
|
|
757
|
-
const policy =
|
|
808
|
+
const policy = useMemo2(
|
|
758
809
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
759
810
|
[capabilityPolicy]
|
|
760
811
|
);
|
|
@@ -901,7 +952,7 @@ function SidePaneOpen({
|
|
|
901
952
|
}
|
|
902
953
|
|
|
903
954
|
// src/CommandMenu.tsx
|
|
904
|
-
import { useEffect as
|
|
955
|
+
import { useEffect as useEffect3, useCallback, useMemo as useMemo3 } from "react";
|
|
905
956
|
import { useNavigate } from "react-router-dom";
|
|
906
957
|
import {
|
|
907
958
|
CommandDialog,
|
|
@@ -917,7 +968,7 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
917
968
|
const navigate = useNavigate();
|
|
918
969
|
const { mainModules, bottomModules } = useShellModules();
|
|
919
970
|
const { resolveCapability, capabilityPolicy } = useShellConfig();
|
|
920
|
-
|
|
971
|
+
useEffect3(() => {
|
|
921
972
|
const handleKeyDown = (e) => {
|
|
922
973
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
923
974
|
e.preventDefault();
|
|
@@ -927,7 +978,7 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
927
978
|
document.addEventListener("keydown", handleKeyDown);
|
|
928
979
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
929
980
|
}, [open, onOpenChange]);
|
|
930
|
-
const policy =
|
|
981
|
+
const policy = useMemo3(
|
|
931
982
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
932
983
|
[capabilityPolicy]
|
|
933
984
|
);
|
|
@@ -940,27 +991,18 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
940
991
|
[navigate, onOpenChange]
|
|
941
992
|
);
|
|
942
993
|
const renderNavGroup = (service) => {
|
|
943
|
-
if (service.navigation.length === 0) return null;
|
|
944
994
|
const { effect, reason } = moduleEffect(service);
|
|
945
995
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
/* @__PURE__ */ jsx11(Icon, { className: "mr-2 h-4 w-4 text-muted-foreground" }),
|
|
957
|
-
/* @__PURE__ */ jsx11("span", { children: link.label }),
|
|
958
|
-
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 })
|
|
959
|
-
]
|
|
960
|
-
},
|
|
961
|
-
link.path
|
|
962
|
-
))
|
|
963
|
-
) }, `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
|
+
);
|
|
964
1006
|
};
|
|
965
1007
|
const renderCommandGroup = (service) => {
|
|
966
1008
|
if (!service.commands?.length) return null;
|
|
@@ -1017,12 +1059,38 @@ function CommandMenu({ open, onOpenChange }) {
|
|
|
1017
1059
|
] })
|
|
1018
1060
|
] });
|
|
1019
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
|
+
}
|
|
1020
1088
|
|
|
1021
1089
|
// src/ModuleEffects.tsx
|
|
1022
|
-
import
|
|
1090
|
+
import React5 from "react";
|
|
1023
1091
|
import { warnLog as warnLog4 } from "@petrarca/sonnet-core";
|
|
1024
1092
|
import { Fragment as Fragment3, jsx as jsx12 } from "react/jsx-runtime";
|
|
1025
|
-
var ModuleEffectBoundary = class extends
|
|
1093
|
+
var ModuleEffectBoundary = class extends React5.Component {
|
|
1026
1094
|
state = { caught: false };
|
|
1027
1095
|
static getDerivedStateFromError() {
|
|
1028
1096
|
return { caught: true };
|
|
@@ -1046,8 +1114,64 @@ function ModuleEffects({ modules }) {
|
|
|
1046
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)) });
|
|
1047
1115
|
}
|
|
1048
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
|
+
|
|
1049
1173
|
// src/AppShell.tsx
|
|
1050
|
-
import { Fragment as
|
|
1174
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1051
1175
|
var PANEL_WIDTHS = {
|
|
1052
1176
|
narrow: { css: "w-[480px]", px: 480 },
|
|
1053
1177
|
default: { css: "w-[640px]", px: 640 },
|
|
@@ -1087,10 +1211,10 @@ function selectNavModule(service, navigate, setSubNavCollapsed, closeSidePane) {
|
|
|
1087
1211
|
}
|
|
1088
1212
|
function useShellApiInit(deps) {
|
|
1089
1213
|
const latest = useRef2(deps);
|
|
1090
|
-
|
|
1214
|
+
useEffect6(() => {
|
|
1091
1215
|
latest.current = deps;
|
|
1092
1216
|
});
|
|
1093
|
-
|
|
1217
|
+
useEffect6(() => {
|
|
1094
1218
|
initNavigation(
|
|
1095
1219
|
(path) => latest.current.navigate(path),
|
|
1096
1220
|
() => latest.current.openCommandMenu()
|
|
@@ -1120,7 +1244,7 @@ function useShellApiInit(deps) {
|
|
|
1120
1244
|
}
|
|
1121
1245
|
function useActiveService(modules) {
|
|
1122
1246
|
const location = useLocation2();
|
|
1123
|
-
const prefixToService =
|
|
1247
|
+
const prefixToService = useMemo4(() => {
|
|
1124
1248
|
const pairs = [];
|
|
1125
1249
|
for (const m of modules) {
|
|
1126
1250
|
if (m.hidden) continue;
|
|
@@ -1132,7 +1256,7 @@ function useActiveService(modules) {
|
|
|
1132
1256
|
pairs.sort((a, b) => b[0].length - a[0].length);
|
|
1133
1257
|
return pairs;
|
|
1134
1258
|
}, [modules]);
|
|
1135
|
-
const resolveServiceFromPath =
|
|
1259
|
+
const resolveServiceFromPath = useCallback3(
|
|
1136
1260
|
(pathname) => {
|
|
1137
1261
|
for (const [prefix, id] of prefixToService) {
|
|
1138
1262
|
if (pathname.startsWith(prefix)) return id;
|
|
@@ -1141,10 +1265,10 @@ function useActiveService(modules) {
|
|
|
1141
1265
|
},
|
|
1142
1266
|
[prefixToService]
|
|
1143
1267
|
);
|
|
1144
|
-
const [selectedServiceId, setSelectedServiceId] =
|
|
1268
|
+
const [selectedServiceId, setSelectedServiceId] = useState4(
|
|
1145
1269
|
() => resolveServiceFromPath(location.pathname)
|
|
1146
1270
|
);
|
|
1147
|
-
|
|
1271
|
+
useEffect6(
|
|
1148
1272
|
() => setSelectedServiceId(resolveServiceFromPath(location.pathname)),
|
|
1149
1273
|
[location.pathname, resolveServiceFromPath]
|
|
1150
1274
|
);
|
|
@@ -1152,26 +1276,26 @@ function useActiveService(modules) {
|
|
|
1152
1276
|
return { activeService, selectedServiceId, setSelectedServiceId };
|
|
1153
1277
|
}
|
|
1154
1278
|
function useSidePaneState2() {
|
|
1155
|
-
const [sidePaneState, setSidePaneState] =
|
|
1279
|
+
const [sidePaneState, setSidePaneState] = useState4(
|
|
1156
1280
|
null
|
|
1157
1281
|
);
|
|
1158
|
-
const handleOpen =
|
|
1282
|
+
const handleOpen = useCallback3(
|
|
1159
1283
|
(opts) => setSidePaneState(opts),
|
|
1160
1284
|
[]
|
|
1161
1285
|
);
|
|
1162
|
-
const handleClose =
|
|
1163
|
-
const handleIsOpen =
|
|
1286
|
+
const handleClose = useCallback3(() => setSidePaneState(null), []);
|
|
1287
|
+
const handleIsOpen = useCallback3(
|
|
1164
1288
|
() => sidePaneState !== null,
|
|
1165
1289
|
[sidePaneState]
|
|
1166
1290
|
);
|
|
1167
|
-
const handleActiveModuleId =
|
|
1291
|
+
const handleActiveModuleId = useCallback3(
|
|
1168
1292
|
() => sidePaneState?.moduleId ?? null,
|
|
1169
1293
|
[sidePaneState]
|
|
1170
1294
|
);
|
|
1171
|
-
const handleSetFullWidth =
|
|
1295
|
+
const handleSetFullWidth = useCallback3((fullWidth) => {
|
|
1172
1296
|
setSidePaneState((prev) => prev ? { ...prev, fullWidth } : prev);
|
|
1173
1297
|
}, []);
|
|
1174
|
-
const handleToggle =
|
|
1298
|
+
const handleToggle = useCallback3((opts) => {
|
|
1175
1299
|
setSidePaneState(
|
|
1176
1300
|
(prev) => prev?.moduleId === opts.moduleId ? null : opts
|
|
1177
1301
|
);
|
|
@@ -1207,13 +1331,13 @@ function resizeOptionsFromPanel(state, widthEntry) {
|
|
|
1207
1331
|
};
|
|
1208
1332
|
}
|
|
1209
1333
|
function usePanelState() {
|
|
1210
|
-
const [panelState, setPanelState] =
|
|
1334
|
+
const [panelState, setPanelState] = useState4(null);
|
|
1211
1335
|
const panelOnCloseRef = useRef2(void 0);
|
|
1212
|
-
const handleOpen =
|
|
1336
|
+
const handleOpen = useCallback3(
|
|
1213
1337
|
(opts) => setPanelState(opts),
|
|
1214
1338
|
[]
|
|
1215
1339
|
);
|
|
1216
|
-
const handleClose =
|
|
1340
|
+
const handleClose = useCallback3(() => {
|
|
1217
1341
|
panelOnCloseRef.current = panelState?.onClose;
|
|
1218
1342
|
setPanelState(null);
|
|
1219
1343
|
}, [panelState]);
|
|
@@ -1231,49 +1355,57 @@ function usePanelState() {
|
|
|
1231
1355
|
};
|
|
1232
1356
|
}
|
|
1233
1357
|
function useDialogState() {
|
|
1234
|
-
const [dialogState, setDialogState] =
|
|
1235
|
-
const handleConfirm =
|
|
1358
|
+
const [dialogState, setDialogState] = useState4(null);
|
|
1359
|
+
const handleConfirm = useCallback3(() => {
|
|
1236
1360
|
dialogState?.resolve(true);
|
|
1237
1361
|
setDialogState(null);
|
|
1238
1362
|
}, [dialogState]);
|
|
1239
|
-
const handleCancel =
|
|
1363
|
+
const handleCancel = useCallback3(() => {
|
|
1240
1364
|
dialogState?.resolve(false);
|
|
1241
1365
|
setDialogState(null);
|
|
1242
1366
|
}, [dialogState]);
|
|
1243
1367
|
return { dialogState, setDialogState, handleConfirm, handleCancel };
|
|
1244
1368
|
}
|
|
1245
|
-
function useFeatureLookup(modules) {
|
|
1246
|
-
return
|
|
1247
|
-
const
|
|
1369
|
+
function useFeatureLookup(modules, record) {
|
|
1370
|
+
return useMemo4(() => {
|
|
1371
|
+
const declared = /* @__PURE__ */ new Map();
|
|
1248
1372
|
for (const m of modules) {
|
|
1249
1373
|
for (const group of m.navigation) {
|
|
1250
1374
|
for (const link of group.links) {
|
|
1251
|
-
if (link.id)
|
|
1375
|
+
if (link.id) declared.set(link.id, link.path);
|
|
1252
1376
|
}
|
|
1253
1377
|
}
|
|
1254
1378
|
}
|
|
1255
|
-
return (featureId) =>
|
|
1256
|
-
|
|
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]);
|
|
1257
1387
|
}
|
|
1258
1388
|
function AppShell({ registry, sidebar }) {
|
|
1259
1389
|
const navigate = useNavigate2();
|
|
1260
1390
|
const config = useShellConfig();
|
|
1261
1391
|
const { modules } = registry;
|
|
1262
1392
|
const { activeService, setSelectedServiceId } = useActiveService(modules);
|
|
1263
|
-
const [subNavCollapsed, setSubNavCollapsed] = useState2(false);
|
|
1264
1393
|
const isBelowTablet = useMediaQuery("(max-width: 1023px)");
|
|
1265
|
-
const
|
|
1266
|
-
const
|
|
1267
|
-
const [
|
|
1268
|
-
const
|
|
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(
|
|
1269
1400
|
(opts) => setFullscreenState(opts),
|
|
1270
1401
|
[]
|
|
1271
1402
|
);
|
|
1272
|
-
const handleFullscreenExit =
|
|
1403
|
+
const handleFullscreenExit = useCallback3(() => setFullscreenState(null), []);
|
|
1273
1404
|
const sidePane2 = useSidePaneState2();
|
|
1274
1405
|
const panel2 = usePanelState();
|
|
1275
1406
|
const dialog2 = useDialogState();
|
|
1276
|
-
const
|
|
1407
|
+
const featureRecord = useRef2(/* @__PURE__ */ new Map()).current;
|
|
1408
|
+
const featureLookup = useFeatureLookup(modules, featureRecord);
|
|
1277
1409
|
useShellApiInit({
|
|
1278
1410
|
navigate,
|
|
1279
1411
|
openCommandMenu,
|
|
@@ -1289,7 +1421,7 @@ function AppShell({ registry, sidebar }) {
|
|
|
1289
1421
|
setDialogState: dialog2.setDialogState,
|
|
1290
1422
|
featureLookup
|
|
1291
1423
|
});
|
|
1292
|
-
const handleServiceSelect =
|
|
1424
|
+
const handleServiceSelect = useCallback3(
|
|
1293
1425
|
(serviceId) => {
|
|
1294
1426
|
const service = modules.find((s) => s.id === serviceId);
|
|
1295
1427
|
if (!service) return;
|
|
@@ -1323,7 +1455,7 @@ function AppShell({ registry, sidebar }) {
|
|
|
1323
1455
|
setSubNavCollapsed
|
|
1324
1456
|
]
|
|
1325
1457
|
);
|
|
1326
|
-
const sidePaneContextValue =
|
|
1458
|
+
const sidePaneContextValue = useMemo4(
|
|
1327
1459
|
() => ({
|
|
1328
1460
|
pane: sidePane2.sidePaneState,
|
|
1329
1461
|
open: sidePane2.handleOpen,
|
|
@@ -1342,22 +1474,24 @@ function AppShell({ registry, sidebar }) {
|
|
|
1342
1474
|
const navigationValue = {
|
|
1343
1475
|
activeService,
|
|
1344
1476
|
sidePaneModuleId: sidePane2.sidePaneState?.moduleId ?? null,
|
|
1345
|
-
subNavCollapsed:
|
|
1346
|
-
onToggleSubNav:
|
|
1477
|
+
subNavCollapsed: subNav.collapsed,
|
|
1478
|
+
onToggleSubNav: subNav.toggle,
|
|
1479
|
+
requestSubNavCollapse: subNav.requestCollapse,
|
|
1347
1480
|
onServiceSelect: handleServiceSelect
|
|
1348
1481
|
};
|
|
1349
|
-
return /* @__PURE__ */
|
|
1350
|
-
/* @__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 }),
|
|
1351
1485
|
/* @__PURE__ */ jsxs9("div", { className: "flex h-screen w-screen flex-col overflow-hidden", children: [
|
|
1352
|
-
/* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
1486
|
+
/* @__PURE__ */ jsx14(TopBar, { children: config.topBar }),
|
|
1487
|
+
/* @__PURE__ */ jsx14(
|
|
1354
1488
|
CommandMenu,
|
|
1355
1489
|
{
|
|
1356
1490
|
open: commandMenuOpen,
|
|
1357
1491
|
onOpenChange: setCommandMenuOpen
|
|
1358
1492
|
}
|
|
1359
1493
|
),
|
|
1360
|
-
/* @__PURE__ */
|
|
1494
|
+
/* @__PURE__ */ jsx14(
|
|
1361
1495
|
ShellBody,
|
|
1362
1496
|
{
|
|
1363
1497
|
activeService,
|
|
@@ -1365,8 +1499,8 @@ function AppShell({ registry, sidebar }) {
|
|
|
1365
1499
|
sidebar
|
|
1366
1500
|
}
|
|
1367
1501
|
),
|
|
1368
|
-
config.footer && /* @__PURE__ */
|
|
1369
|
-
dialog2.dialogState && /* @__PURE__ */
|
|
1502
|
+
config.footer && /* @__PURE__ */ jsx14(ShellFooter, { children: config.footer }),
|
|
1503
|
+
dialog2.dialogState && /* @__PURE__ */ jsx14(
|
|
1370
1504
|
ConfirmDialog,
|
|
1371
1505
|
{
|
|
1372
1506
|
open: true,
|
|
@@ -1375,12 +1509,13 @@ function AppShell({ registry, sidebar }) {
|
|
|
1375
1509
|
confirmLabel: dialog2.dialogState.opts.confirmLabel,
|
|
1376
1510
|
cancelLabel: dialog2.dialogState.opts.cancelLabel,
|
|
1377
1511
|
variant: dialog2.dialogState.opts.variant,
|
|
1512
|
+
confirmText: dialog2.dialogState.opts.confirmText,
|
|
1378
1513
|
onConfirm: dialog2.handleConfirm,
|
|
1379
1514
|
onCancel: dialog2.handleCancel
|
|
1380
1515
|
}
|
|
1381
1516
|
),
|
|
1382
|
-
fullscreenState && /* @__PURE__ */
|
|
1383
|
-
/* @__PURE__ */
|
|
1517
|
+
fullscreenState && /* @__PURE__ */ jsx14("div", { className: "fixed inset-0 z-50 bg-background overflow-auto", children: fullscreenState.content }),
|
|
1518
|
+
/* @__PURE__ */ jsx14(
|
|
1384
1519
|
SlideOverPanel,
|
|
1385
1520
|
{
|
|
1386
1521
|
panelState: panel2.panelState,
|
|
@@ -1413,14 +1548,14 @@ function SlideOverPanel({
|
|
|
1413
1548
|
},
|
|
1414
1549
|
...!panelState?.description && { "aria-describedby": void 0 }
|
|
1415
1550
|
};
|
|
1416
|
-
return /* @__PURE__ */
|
|
1551
|
+
return /* @__PURE__ */ jsx14(
|
|
1417
1552
|
Sheet,
|
|
1418
1553
|
{
|
|
1419
1554
|
open: panelState !== null,
|
|
1420
1555
|
onOpenChange: (open) => {
|
|
1421
1556
|
if (!open) onClose();
|
|
1422
1557
|
},
|
|
1423
|
-
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 }) })
|
|
1424
1559
|
}
|
|
1425
1560
|
);
|
|
1426
1561
|
}
|
|
@@ -1447,7 +1582,7 @@ function ResizableSheetContent({
|
|
|
1447
1582
|
className: "max-w-[90vw]",
|
|
1448
1583
|
style: { width: dynWidth },
|
|
1449
1584
|
children: [
|
|
1450
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx14(
|
|
1451
1586
|
DragHandle,
|
|
1452
1587
|
{
|
|
1453
1588
|
edge: "left",
|
|
@@ -1467,24 +1602,24 @@ function ShellBody({
|
|
|
1467
1602
|
sidebar
|
|
1468
1603
|
}) {
|
|
1469
1604
|
return /* @__PURE__ */ jsxs9("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
1470
|
-
sidebar ?? /* @__PURE__ */
|
|
1471
|
-
/* @__PURE__ */
|
|
1472
|
-
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 }) })
|
|
1473
1608
|
] });
|
|
1474
1609
|
}
|
|
1475
1610
|
function ContentArea({ layout }) {
|
|
1476
1611
|
if (layout === "full") {
|
|
1477
|
-
return /* @__PURE__ */
|
|
1612
|
+
return /* @__PURE__ */ jsx14("div", { className: "h-full w-full overflow-hidden", children: /* @__PURE__ */ jsx14(Outlet, {}) });
|
|
1478
1613
|
}
|
|
1479
|
-
return /* @__PURE__ */
|
|
1614
|
+
return /* @__PURE__ */ jsx14(ScrollArea2, { className: "h-full", children: /* @__PURE__ */ jsx14("main", { className: "p-6", children: /* @__PURE__ */ jsx14(Outlet, {}) }) });
|
|
1480
1615
|
}
|
|
1481
1616
|
function PanelContent({ state }) {
|
|
1482
|
-
return /* @__PURE__ */ jsxs9(
|
|
1617
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1483
1618
|
state.title ? /* @__PURE__ */ jsxs9(SheetHeader, { children: [
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
state.description && /* @__PURE__ */
|
|
1486
|
-
] }) : /* @__PURE__ */
|
|
1487
|
-
/* @__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 })
|
|
1488
1623
|
] });
|
|
1489
1624
|
}
|
|
1490
1625
|
|
|
@@ -1492,36 +1627,36 @@ function PanelContent({ state }) {
|
|
|
1492
1627
|
import { Toaster } from "sonner";
|
|
1493
1628
|
|
|
1494
1629
|
// src/ShellConfigProvider.tsx
|
|
1495
|
-
import { jsx as
|
|
1630
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1496
1631
|
function ShellConfigProvider({
|
|
1497
1632
|
config,
|
|
1498
1633
|
children
|
|
1499
1634
|
}) {
|
|
1500
|
-
return /* @__PURE__ */
|
|
1635
|
+
return /* @__PURE__ */ jsx15(ShellConfigContext.Provider, { value: config, children });
|
|
1501
1636
|
}
|
|
1502
1637
|
|
|
1503
1638
|
// src/RootLayout.tsx
|
|
1504
|
-
import { jsx as
|
|
1639
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1505
1640
|
function RootLayout({
|
|
1506
1641
|
config,
|
|
1507
1642
|
registry,
|
|
1508
1643
|
sidebar
|
|
1509
1644
|
}) {
|
|
1510
1645
|
return /* @__PURE__ */ jsxs10(ShellConfigProvider, { config, children: [
|
|
1511
|
-
/* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsx16(Toaster, { position: "top-right", richColors: true, closeButton: true }),
|
|
1647
|
+
/* @__PURE__ */ jsx16(AppShell, { registry, sidebar })
|
|
1513
1648
|
] });
|
|
1514
1649
|
}
|
|
1515
1650
|
|
|
1516
1651
|
// src/PlaceholderPage.tsx
|
|
1517
1652
|
import { useLocation as useLocation3 } from "react-router-dom";
|
|
1518
|
-
import { jsx as
|
|
1653
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1519
1654
|
function PlaceholderPage() {
|
|
1520
1655
|
const { pathname } = useLocation3();
|
|
1521
1656
|
return /* @__PURE__ */ jsxs11("div", { children: [
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__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" }) })
|
|
1525
1660
|
] });
|
|
1526
1661
|
}
|
|
1527
1662
|
function pathToTitle(path) {
|
|
@@ -1530,46 +1665,148 @@ function pathToTitle(path) {
|
|
|
1530
1665
|
return last.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
1531
1666
|
}
|
|
1532
1667
|
|
|
1533
|
-
// 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";
|
|
1534
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";
|
|
1535
1772
|
import { ScrollArea as ScrollArea3 } from "@petrarca/sonnet-ui";
|
|
1536
|
-
import { jsx as
|
|
1773
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1537
1774
|
function Sidebar({
|
|
1538
1775
|
children,
|
|
1539
1776
|
header,
|
|
1540
1777
|
width = 260,
|
|
1541
1778
|
className
|
|
1542
1779
|
}) {
|
|
1543
|
-
return /* @__PURE__ */
|
|
1780
|
+
return /* @__PURE__ */ jsxs14(
|
|
1544
1781
|
"aside",
|
|
1545
1782
|
{
|
|
1546
1783
|
style: { width },
|
|
1547
|
-
className:
|
|
1784
|
+
className: cn8(
|
|
1548
1785
|
"shrink-0 border-r bg-muted/30 flex flex-col h-full",
|
|
1549
1786
|
className
|
|
1550
1787
|
),
|
|
1551
1788
|
children: [
|
|
1552
1789
|
header,
|
|
1553
|
-
/* @__PURE__ */
|
|
1790
|
+
/* @__PURE__ */ jsx20(ScrollArea3, { className: "flex-1", children: /* @__PURE__ */ jsx20("nav", { className: "px-1.5 py-2 space-y-3", children }) })
|
|
1554
1791
|
]
|
|
1555
1792
|
}
|
|
1556
1793
|
);
|
|
1557
1794
|
}
|
|
1558
1795
|
|
|
1559
1796
|
// src/ShellSidebar.tsx
|
|
1560
|
-
import
|
|
1561
|
-
import { jsx as
|
|
1797
|
+
import React8, { useMemo as useMemo5 } from "react";
|
|
1798
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1562
1799
|
function ShellSidebar({
|
|
1563
1800
|
bottomGroupLabel = "Tools",
|
|
1564
1801
|
...sidebarProps
|
|
1565
1802
|
}) {
|
|
1566
1803
|
const { mainModules, bottomModules } = useShellModules();
|
|
1567
1804
|
const { resolveCapability, capabilityPolicy } = useShellConfig();
|
|
1568
|
-
const policy =
|
|
1805
|
+
const policy = useMemo5(
|
|
1569
1806
|
() => resolveCapabilityPolicy(capabilityPolicy),
|
|
1570
1807
|
[capabilityPolicy]
|
|
1571
1808
|
);
|
|
1572
|
-
const effectOf =
|
|
1809
|
+
const effectOf = React8.useCallback(
|
|
1573
1810
|
(moduleId) => {
|
|
1574
1811
|
const module = [...mainModules, ...bottomModules].find(
|
|
1575
1812
|
(m) => m.id === moduleId
|
|
@@ -1590,8 +1827,8 @@ function ShellSidebar({
|
|
|
1590
1827
|
reason
|
|
1591
1828
|
}));
|
|
1592
1829
|
});
|
|
1593
|
-
return /* @__PURE__ */
|
|
1594
|
-
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(
|
|
1595
1832
|
SidebarItem,
|
|
1596
1833
|
{
|
|
1597
1834
|
icon,
|
|
@@ -1606,63 +1843,21 @@ function ShellSidebar({
|
|
|
1606
1843
|
mainModules.map((mod) => {
|
|
1607
1844
|
const { effect, reason } = effectOf(mod.id);
|
|
1608
1845
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
disabled,
|
|
1619
|
-
title
|
|
1620
|
-
},
|
|
1621
|
-
mod.id
|
|
1622
|
-
);
|
|
1623
|
-
}
|
|
1624
|
-
return /* @__PURE__ */ jsx18(SidebarGroup, { heading: mod.label, collapsible: true, children: mod.navigation.flatMap((group) => [
|
|
1625
|
-
// Render NavGroup heading if it has one
|
|
1626
|
-
...group.heading ? [
|
|
1627
|
-
/* @__PURE__ */ jsx18(
|
|
1628
|
-
SidebarGroup,
|
|
1629
|
-
{
|
|
1630
|
-
heading: group.heading,
|
|
1631
|
-
collapsible: group.collapsible,
|
|
1632
|
-
children: group.links.map((link) => /* @__PURE__ */ jsx18(
|
|
1633
|
-
SidebarItem,
|
|
1634
|
-
{
|
|
1635
|
-
icon: mod.icon,
|
|
1636
|
-
label: link.label,
|
|
1637
|
-
path: link.path,
|
|
1638
|
-
badge: link.badge,
|
|
1639
|
-
disabled,
|
|
1640
|
-
title: disabled ? reason : void 0
|
|
1641
|
-
},
|
|
1642
|
-
link.path
|
|
1643
|
-
))
|
|
1644
|
-
},
|
|
1645
|
-
group.id
|
|
1646
|
-
)
|
|
1647
|
-
] : group.links.map((link) => /* @__PURE__ */ jsx18(
|
|
1648
|
-
SidebarItem,
|
|
1649
|
-
{
|
|
1650
|
-
icon: mod.icon,
|
|
1651
|
-
label: link.label,
|
|
1652
|
-
path: link.path,
|
|
1653
|
-
badge: link.badge,
|
|
1654
|
-
disabled,
|
|
1655
|
-
title: disabled ? reason : void 0
|
|
1656
|
-
},
|
|
1657
|
-
link.path
|
|
1658
|
-
))
|
|
1659
|
-
]) }, mod.id);
|
|
1846
|
+
return /* @__PURE__ */ jsx21(
|
|
1847
|
+
ModuleSection,
|
|
1848
|
+
{
|
|
1849
|
+
mod,
|
|
1850
|
+
disabled: effect === "disabled",
|
|
1851
|
+
reason
|
|
1852
|
+
},
|
|
1853
|
+
mod.id
|
|
1854
|
+
);
|
|
1660
1855
|
}),
|
|
1661
|
-
bottomModules.length > 0 && /* @__PURE__ */
|
|
1856
|
+
bottomModules.length > 0 && /* @__PURE__ */ jsx21(SidebarGroup, { heading: bottomGroupLabel, collapsible: true, children: bottomModules.map((mod) => {
|
|
1662
1857
|
const { effect, reason } = effectOf(mod.id);
|
|
1663
1858
|
if (effect === "hidden" || effect === "redirect") return null;
|
|
1664
1859
|
const disabled = effect === "disabled";
|
|
1665
|
-
return /* @__PURE__ */
|
|
1860
|
+
return /* @__PURE__ */ jsx21(
|
|
1666
1861
|
SidebarItem,
|
|
1667
1862
|
{
|
|
1668
1863
|
icon: mod.icon,
|
|
@@ -1676,16 +1871,61 @@ function ShellSidebar({
|
|
|
1676
1871
|
}) })
|
|
1677
1872
|
] });
|
|
1678
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
|
+
}
|
|
1679
1919
|
|
|
1680
1920
|
// src/ShellVersion.tsx
|
|
1681
|
-
import { jsx as
|
|
1921
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1682
1922
|
function ShellVersion({
|
|
1683
1923
|
name,
|
|
1684
1924
|
version
|
|
1685
1925
|
}) {
|
|
1686
|
-
return /* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
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: [
|
|
1689
1929
|
"v",
|
|
1690
1930
|
version
|
|
1691
1931
|
] })
|
|
@@ -1695,9 +1935,9 @@ function ShellVersion({
|
|
|
1695
1935
|
// src/SearchTrigger.tsx
|
|
1696
1936
|
import { Search } from "lucide-react";
|
|
1697
1937
|
import { Button as Button3 } from "@petrarca/sonnet-ui";
|
|
1698
|
-
import { jsx as
|
|
1938
|
+
import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1699
1939
|
function SearchTrigger() {
|
|
1700
|
-
return /* @__PURE__ */
|
|
1940
|
+
return /* @__PURE__ */ jsxs17(
|
|
1701
1941
|
Button3,
|
|
1702
1942
|
{
|
|
1703
1943
|
variant: "outline",
|
|
@@ -1705,10 +1945,10 @@ function SearchTrigger() {
|
|
|
1705
1945
|
className: "h-8 gap-2 text-sm text-muted-foreground w-56 justify-start",
|
|
1706
1946
|
onClick: () => navigation.openCommandMenu(),
|
|
1707
1947
|
children: [
|
|
1708
|
-
/* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__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" }),
|
|
1712
1952
|
"K"
|
|
1713
1953
|
] })
|
|
1714
1954
|
]
|
|
@@ -1716,9 +1956,32 @@ function SearchTrigger() {
|
|
|
1716
1956
|
);
|
|
1717
1957
|
}
|
|
1718
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
|
+
|
|
1719
1982
|
// src/UserMenu.tsx
|
|
1720
1983
|
import { LogOut, User } from "lucide-react";
|
|
1721
|
-
import { Button as
|
|
1984
|
+
import { Button as Button5 } from "@petrarca/sonnet-ui";
|
|
1722
1985
|
import { Avatar, AvatarFallback } from "@petrarca/sonnet-ui";
|
|
1723
1986
|
import {
|
|
1724
1987
|
DropdownMenu,
|
|
@@ -1728,23 +1991,23 @@ import {
|
|
|
1728
1991
|
DropdownMenuSeparator,
|
|
1729
1992
|
DropdownMenuTrigger
|
|
1730
1993
|
} from "@petrarca/sonnet-ui";
|
|
1731
|
-
import { jsx as
|
|
1994
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1732
1995
|
function UserMenu({ user, onSignOut }) {
|
|
1733
|
-
return /* @__PURE__ */
|
|
1734
|
-
/* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
/* @__PURE__ */
|
|
1738
|
-
/* @__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 })
|
|
1739
2002
|
] }) }),
|
|
1740
|
-
/* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsx25(DropdownMenuSeparator, {}),
|
|
2004
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { children: [
|
|
2005
|
+
/* @__PURE__ */ jsx25(User, { className: "mr-2 h-4 w-4" }),
|
|
1743
2006
|
"Profile"
|
|
1744
2007
|
] }),
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
2008
|
+
/* @__PURE__ */ jsx25(DropdownMenuSeparator, {}),
|
|
2009
|
+
/* @__PURE__ */ jsxs18(DropdownMenuItem, { onSelect: onSignOut, children: [
|
|
2010
|
+
/* @__PURE__ */ jsx25(LogOut, { className: "mr-2 h-4 w-4" }),
|
|
1748
2011
|
"Sign out"
|
|
1749
2012
|
] })
|
|
1750
2013
|
] })
|
|
@@ -1756,7 +2019,6 @@ function createModuleRegistry(modules) {
|
|
|
1756
2019
|
const visible = modules.filter((m) => !m.hidden);
|
|
1757
2020
|
const mainModules = visible.filter((m) => !m.pinBottom);
|
|
1758
2021
|
const bottomModules = visible.filter((m) => m.pinBottom);
|
|
1759
|
-
const allRoutes = modules.flatMap((m) => m.routes);
|
|
1760
2022
|
const contributionsByPoint = /* @__PURE__ */ new Map();
|
|
1761
2023
|
for (const m of modules) {
|
|
1762
2024
|
for (const c of m.contributions ?? []) {
|
|
@@ -1771,17 +2033,57 @@ function createModuleRegistry(modules) {
|
|
|
1771
2033
|
function getExtensionPoint(name) {
|
|
1772
2034
|
return contributionsByPoint.get(name) ?? [];
|
|
1773
2035
|
}
|
|
2036
|
+
const allRoutes = nestContributedRoutes(
|
|
2037
|
+
modules.flatMap((m) => m.routes),
|
|
2038
|
+
contributionsByPoint
|
|
2039
|
+
);
|
|
1774
2040
|
return { modules, mainModules, bottomModules, allRoutes, getExtensionPoint };
|
|
1775
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
|
+
}
|
|
1776
2078
|
|
|
1777
2079
|
// src/OverviewCard.tsx
|
|
1778
|
-
import { cn as
|
|
1779
|
-
import { jsx as
|
|
2080
|
+
import { cn as cn9 } from "@petrarca/sonnet-core";
|
|
2081
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1780
2082
|
function FeatureLink({
|
|
1781
2083
|
feature,
|
|
1782
2084
|
children
|
|
1783
2085
|
}) {
|
|
1784
|
-
return /* @__PURE__ */
|
|
2086
|
+
return /* @__PURE__ */ jsx26(
|
|
1785
2087
|
"span",
|
|
1786
2088
|
{
|
|
1787
2089
|
role: "link",
|
|
@@ -1807,37 +2109,51 @@ function OverviewCard({
|
|
|
1807
2109
|
title,
|
|
1808
2110
|
description,
|
|
1809
2111
|
feature,
|
|
2112
|
+
path,
|
|
1810
2113
|
className
|
|
1811
2114
|
}) {
|
|
1812
|
-
|
|
2115
|
+
const go = feature ? () => navigation.goToFeature(feature) : path ? () => navigation.goTo(path) : void 0;
|
|
2116
|
+
return /* @__PURE__ */ jsxs19(
|
|
1813
2117
|
"button",
|
|
1814
2118
|
{
|
|
1815
|
-
onClick:
|
|
1816
|
-
disabled: !
|
|
1817
|
-
className:
|
|
2119
|
+
onClick: go,
|
|
2120
|
+
disabled: !go,
|
|
2121
|
+
className: cn9(
|
|
1818
2122
|
"rounded-lg border bg-card p-5 text-left flex flex-col gap-3",
|
|
1819
2123
|
"disabled:cursor-default",
|
|
1820
|
-
|
|
2124
|
+
go && "hover:bg-accent/50 transition-colors",
|
|
1821
2125
|
className
|
|
1822
2126
|
),
|
|
1823
2127
|
children: [
|
|
1824
|
-
/* @__PURE__ */
|
|
1825
|
-
/* @__PURE__ */
|
|
1826
|
-
/* @__PURE__ */
|
|
1827
|
-
/* @__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 })
|
|
1828
2132
|
] })
|
|
1829
2133
|
]
|
|
1830
2134
|
}
|
|
1831
2135
|
);
|
|
1832
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
|
+
}
|
|
1833
2146
|
export {
|
|
1834
2147
|
AppShell,
|
|
2148
|
+
Breadcrumbs,
|
|
1835
2149
|
CommandMenu,
|
|
1836
2150
|
ConfirmDialog,
|
|
1837
2151
|
DEFAULT_CAPABILITY_POLICY,
|
|
2152
|
+
DrillDownHeader,
|
|
1838
2153
|
FeatureLink,
|
|
1839
2154
|
IconRail,
|
|
1840
2155
|
OverviewCard,
|
|
2156
|
+
OverviewGroupHeading,
|
|
1841
2157
|
PlaceholderPage,
|
|
1842
2158
|
RailIcon,
|
|
1843
2159
|
RailSeparator,
|
|
@@ -1854,8 +2170,10 @@ export {
|
|
|
1854
2170
|
SidebarGroup,
|
|
1855
2171
|
SidebarItem,
|
|
1856
2172
|
SubNavPanel,
|
|
2173
|
+
ThemeToggle,
|
|
1857
2174
|
TopBar,
|
|
1858
2175
|
UserMenu,
|
|
2176
|
+
contributionPath,
|
|
1859
2177
|
createModuleRegistry,
|
|
1860
2178
|
dialog,
|
|
1861
2179
|
evaluateModule,
|
|
@@ -1872,8 +2190,11 @@ export {
|
|
|
1872
2190
|
panel,
|
|
1873
2191
|
resolveCapabilityPolicy,
|
|
1874
2192
|
sidePane,
|
|
2193
|
+
useCollapsedSubNav,
|
|
2194
|
+
useContributedComponent,
|
|
1875
2195
|
useExtensionPoint,
|
|
1876
2196
|
useMainModules,
|
|
2197
|
+
useModuleNavigation,
|
|
1877
2198
|
useShellConfig,
|
|
1878
2199
|
useShellEvent,
|
|
1879
2200
|
useShellModules,
|