@comitor/ui 0.1.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/LICENSE +21 -0
- package/README.md +458 -0
- package/dist/chart/chart.d.ts +88 -0
- package/dist/chart/chart.js +199 -0
- package/dist/chart/chart.js.map +1 -0
- package/dist/chart/comitor-chart.d.ts +109 -0
- package/dist/chart/comitor-chart.js +189 -0
- package/dist/chart/comitor-chart.js.map +1 -0
- package/dist/chart/index.d.ts +4 -0
- package/dist/chart/index.js +3 -0
- package/dist/chart/index.js.map +1 -0
- package/dist/components/composite/avatar-group.d.ts +33 -0
- package/dist/components/composite/avatar-group.js +86 -0
- package/dist/components/composite/avatar-group.js.map +1 -0
- package/dist/components/composite/combobox.d.ts +70 -0
- package/dist/components/composite/combobox.js +291 -0
- package/dist/components/composite/combobox.js.map +1 -0
- package/dist/components/composite/command-palette.d.ts +56 -0
- package/dist/components/composite/command-palette.js +131 -0
- package/dist/components/composite/command-palette.js.map +1 -0
- package/dist/components/composite/confirm-dialog.d.ts +40 -0
- package/dist/components/composite/confirm-dialog.js +96 -0
- package/dist/components/composite/confirm-dialog.js.map +1 -0
- package/dist/components/composite/copy-button.d.ts +27 -0
- package/dist/components/composite/copy-button.js +80 -0
- package/dist/components/composite/copy-button.js.map +1 -0
- package/dist/components/composite/data-table.d.ts +136 -0
- package/dist/components/composite/data-table.js +300 -0
- package/dist/components/composite/data-table.js.map +1 -0
- package/dist/components/composite/date-picker.d.ts +77 -0
- package/dist/components/composite/date-picker.js +268 -0
- package/dist/components/composite/date-picker.js.map +1 -0
- package/dist/components/composite/empty-state.d.ts +38 -0
- package/dist/components/composite/empty-state.js +35 -0
- package/dist/components/composite/empty-state.js.map +1 -0
- package/dist/components/composite/filter-chips.d.ts +39 -0
- package/dist/components/composite/filter-chips.js +79 -0
- package/dist/components/composite/filter-chips.js.map +1 -0
- package/dist/components/composite/form-field.d.ts +58 -0
- package/dist/components/composite/form-field.js +81 -0
- package/dist/components/composite/form-field.js.map +1 -0
- package/dist/components/composite/form-section.d.ts +33 -0
- package/dist/components/composite/form-section.js +85 -0
- package/dist/components/composite/form-section.js.map +1 -0
- package/dist/components/composite/inline-edit.d.ts +38 -0
- package/dist/components/composite/inline-edit.js +165 -0
- package/dist/components/composite/inline-edit.js.map +1 -0
- package/dist/components/composite/keyboard-hint.d.ts +31 -0
- package/dist/components/composite/keyboard-hint.js +72 -0
- package/dist/components/composite/keyboard-hint.js.map +1 -0
- package/dist/components/composite/letter-avatar.d.ts +47 -0
- package/dist/components/composite/letter-avatar.js +66 -0
- package/dist/components/composite/letter-avatar.js.map +1 -0
- package/dist/components/composite/page-container.d.ts +25 -0
- package/dist/components/composite/page-container.js +23 -0
- package/dist/components/composite/page-container.js.map +1 -0
- package/dist/components/composite/page-header.d.ts +49 -0
- package/dist/components/composite/page-header.js +75 -0
- package/dist/components/composite/page-header.js.map +1 -0
- package/dist/components/composite/relative-time.d.ts +28 -0
- package/dist/components/composite/relative-time.js +44 -0
- package/dist/components/composite/relative-time.js.map +1 -0
- package/dist/components/composite/search-filter-bar.d.ts +38 -0
- package/dist/components/composite/search-filter-bar.js +135 -0
- package/dist/components/composite/search-filter-bar.js.map +1 -0
- package/dist/components/composite/stat-card.d.ts +48 -0
- package/dist/components/composite/stat-card.js +76 -0
- package/dist/components/composite/stat-card.js.map +1 -0
- package/dist/components/composite/status-config.d.ts +85 -0
- package/dist/components/composite/status-config.js +41 -0
- package/dist/components/composite/status-config.js.map +1 -0
- package/dist/components/composite/status-pill.d.ts +26 -0
- package/dist/components/composite/status-pill.js +59 -0
- package/dist/components/composite/status-pill.js.map +1 -0
- package/dist/components/composite/table-pagination.d.ts +31 -0
- package/dist/components/composite/table-pagination.js +103 -0
- package/dist/components/composite/table-pagination.js.map +1 -0
- package/dist/components/composite/text-utils.d.ts +38 -0
- package/dist/components/composite/text-utils.js +40 -0
- package/dist/components/composite/text-utils.js.map +1 -0
- package/dist/components/composite/toast.d.ts +56 -0
- package/dist/components/composite/toast.js +63 -0
- package/dist/components/composite/toast.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +17 -0
- package/dist/components/ui/accordion.js +53 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +34 -0
- package/dist/components/ui/alert-dialog.js +103 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/alert.d.ts +16 -0
- package/dist/components/ui/alert.js +50 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +7 -0
- package/dist/components/ui/aspect-ratio.js +10 -0
- package/dist/components/ui/aspect-ratio.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +33 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +15 -0
- package/dist/components/ui/badge.js +37 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +30 -0
- package/dist/components/ui/breadcrumb.js +89 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button-group.d.ts +21 -0
- package/dist/components/ui/button-group.js +62 -0
- package/dist/components/ui/button-group.js.map +1 -0
- package/dist/components/ui/button.d.ts +21 -0
- package/dist/components/ui/button.js +70 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +26 -0
- package/dist/components/ui/calendar.js +148 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +33 -0
- package/dist/components/ui/card.js +70 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/carousel.d.ts +46 -0
- package/dist/components/ui/carousel.js +173 -0
- package/dist/components/ui/carousel.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +17 -0
- package/dist/components/ui/checkbox.js +67 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +17 -0
- package/dist/components/ui/collapsible.js +18 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/command.d.ts +41 -0
- package/dist/components/ui/command.js +122 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +51 -0
- package/dist/components/ui/context-menu.js +166 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +48 -0
- package/dist/components/ui/dialog.js +131 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +32 -0
- package/dist/components/ui/drawer.js +102 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +52 -0
- package/dist/components/ui/dropdown-menu.js +167 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/empty.d.ts +22 -0
- package/dist/components/ui/empty.js +87 -0
- package/dist/components/ui/empty.js.map +1 -0
- package/dist/components/ui/field.d.ts +46 -0
- package/dist/components/ui/field.js +197 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/form.d.ts +50 -0
- package/dist/components/ui/form.js +100 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +17 -0
- package/dist/components/ui/hover-card.js +31 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +26 -0
- package/dist/components/ui/input-group.js +148 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-otp.d.ts +23 -0
- package/dist/components/ui/input-otp.js +54 -0
- package/dist/components/ui/input-otp.js.map +1 -0
- package/dist/components/ui/input.d.ts +21 -0
- package/dist/components/ui/input.js +62 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/item.d.ts +39 -0
- package/dist/components/ui/item.js +142 -0
- package/dist/components/ui/item.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +8 -0
- package/dist/components/ui/kbd.js +25 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/label.d.ts +7 -0
- package/dist/components/ui/label.js +21 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/menubar.d.ts +51 -0
- package/dist/components/ui/menubar.js +196 -0
- package/dist/components/ui/menubar.js.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +39 -0
- package/dist/components/ui/navigation-menu.js +123 -0
- package/dist/components/ui/navigation-menu.js.map +1 -0
- package/dist/components/ui/pagination.d.ts +40 -0
- package/dist/components/ui/pagination.js +95 -0
- package/dist/components/ui/pagination.js.map +1 -0
- package/dist/components/ui/popover.d.ts +19 -0
- package/dist/components/ui/popover.js +35 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +12 -0
- package/dist/components/ui/progress.js +27 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +9 -0
- package/dist/components/ui/radio-group.js +34 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +19 -0
- package/dist/components/ui/resizable.js +38 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +13 -0
- package/dist/components/ui/scroll-area.js +46 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +33 -0
- package/dist/components/ui/select.js +133 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/separator.d.ts +7 -0
- package/dist/components/ui/separator.js +23 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +38 -0
- package/dist/components/ui/sheet.js +96 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +6 -0
- package/dist/components/ui/skeleton.js +9 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +12 -0
- package/dist/components/ui/slider.js +54 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +9 -0
- package/dist/components/ui/sonner.js +25 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/spinner.d.ts +6 -0
- package/dist/components/ui/spinner.js +10 -0
- package/dist/components/ui/spinner.js.map +1 -0
- package/dist/components/ui/switch.d.ts +14 -0
- package/dist/components/ui/switch.js +65 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.d.ts +30 -0
- package/dist/components/ui/table.js +87 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +35 -0
- package/dist/components/ui/tabs.js +54 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +6 -0
- package/dist/components/ui/textarea.js +19 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +18 -0
- package/dist/components/ui/toggle-group.js +52 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +15 -0
- package/dist/components/ui/toggle.js +33 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +21 -0
- package/dist/components/ui/tooltip.js +38 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/form.d.ts +5 -0
- package/dist/form.js +2 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cn.d.ts +16 -0
- package/dist/lib/cn.js +9 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/shell/app-header.d.ts +41 -0
- package/dist/shell/app-header.js +136 -0
- package/dist/shell/app-header.js.map +1 -0
- package/dist/shell/app-launcher.d.ts +33 -0
- package/dist/shell/app-launcher.js +189 -0
- package/dist/shell/app-launcher.js.map +1 -0
- package/dist/shell/app-shell.d.ts +44 -0
- package/dist/shell/app-shell.js +99 -0
- package/dist/shell/app-shell.js.map +1 -0
- package/dist/shell/comitor-lockup.d.ts +33 -0
- package/dist/shell/comitor-lockup.js +112 -0
- package/dist/shell/comitor-lockup.js.map +1 -0
- package/dist/shell/comitor-logo.d.ts +28 -0
- package/dist/shell/comitor-logo.js +92 -0
- package/dist/shell/comitor-logo.js.map +1 -0
- package/dist/shell/index.d.ts +24 -0
- package/dist/shell/index.js +23 -0
- package/dist/shell/index.js.map +1 -0
- package/dist/shell/mobile-menu.d.ts +26 -0
- package/dist/shell/mobile-menu.js +56 -0
- package/dist/shell/mobile-menu.js.map +1 -0
- package/dist/shell/notifications-button.d.ts +22 -0
- package/dist/shell/notifications-button.js +39 -0
- package/dist/shell/notifications-button.js.map +1 -0
- package/dist/shell/shell-context.d.ts +91 -0
- package/dist/shell/shell-context.js +233 -0
- package/dist/shell/shell-context.js.map +1 -0
- package/dist/shell/shell-link.d.ts +19 -0
- package/dist/shell/shell-link.js +18 -0
- package/dist/shell/shell-link.js.map +1 -0
- package/dist/shell/sidebar-group.d.ts +21 -0
- package/dist/shell/sidebar-group.js +43 -0
- package/dist/shell/sidebar-group.js.map +1 -0
- package/dist/shell/sidebar-menu-item.d.ts +27 -0
- package/dist/shell/sidebar-menu-item.js +152 -0
- package/dist/shell/sidebar-menu-item.js.map +1 -0
- package/dist/shell/sidebar.d.ts +26 -0
- package/dist/shell/sidebar.js +92 -0
- package/dist/shell/sidebar.js.map +1 -0
- package/dist/shell/theme-provider.d.ts +18 -0
- package/dist/shell/theme-provider.js +29 -0
- package/dist/shell/theme-provider.js.map +1 -0
- package/dist/shell/theme-toggle.d.ts +28 -0
- package/dist/shell/theme-toggle.js +67 -0
- package/dist/shell/theme-toggle.js.map +1 -0
- package/dist/shell/types.d.ts +168 -0
- package/dist/shell/types.js +38 -0
- package/dist/shell/types.js.map +1 -0
- package/dist/shell/user-menu.d.ts +42 -0
- package/dist/shell/user-menu.js +132 -0
- package/dist/shell/user-menu.js.map +1 -0
- package/dist/shell/utils.d.ts +62 -0
- package/dist/shell/utils.js +73 -0
- package/dist/shell/utils.js.map +1 -0
- package/dist/shell/workspace-switcher.d.ts +24 -0
- package/dist/shell/workspace-switcher.js +219 -0
- package/dist/shell/workspace-switcher.js.map +1 -0
- package/dist/tokens.d.ts +173 -0
- package/dist/tokens.js +161 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +151 -0
- package/styles.css +357 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function ComitorLogo({ className, variant = "light", title = "Comitor", style }) {
|
|
3
|
+
const dark = variant === "dark";
|
|
4
|
+
const c = dark ? {
|
|
5
|
+
accent: "#8A6800",
|
|
6
|
+
bright: "#F0CC50",
|
|
7
|
+
rich: "#D4A820",
|
|
8
|
+
topFace: "#FFFFFF",
|
|
9
|
+
sphereHi: "#F0CC50",
|
|
10
|
+
sphereLo: "#D4A820"
|
|
11
|
+
} : {
|
|
12
|
+
accent: "#7A5800",
|
|
13
|
+
bright: "#E8B824",
|
|
14
|
+
rich: "#B88A00",
|
|
15
|
+
topFace: "#F5D060",
|
|
16
|
+
sphereHi: "#E8B824",
|
|
17
|
+
sphereLo: "#B88A00"
|
|
18
|
+
};
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
"svg",
|
|
21
|
+
{
|
|
22
|
+
viewBox: "0 0 256 256",
|
|
23
|
+
fill: "none",
|
|
24
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
25
|
+
className,
|
|
26
|
+
style,
|
|
27
|
+
role: "img",
|
|
28
|
+
"aria-label": title,
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ jsx("title", { children: title }),
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
"path",
|
|
33
|
+
{
|
|
34
|
+
fillRule: "evenodd",
|
|
35
|
+
clipRule: "evenodd",
|
|
36
|
+
d: "M128 142.059L78.5642 170.543L128 209.32L177.344 170.543L128 142.059Z",
|
|
37
|
+
fill: c.accent
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"path",
|
|
42
|
+
{
|
|
43
|
+
fillRule: "evenodd",
|
|
44
|
+
clipRule: "evenodd",
|
|
45
|
+
d: "M56.6951 86.8339L66.4352 149.502L91.1528 135.259L115.779 121.016V92.5315V64.0459L56.6951 86.8339Z",
|
|
46
|
+
fill: c.bright
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
"path",
|
|
51
|
+
{
|
|
52
|
+
fillRule: "evenodd",
|
|
53
|
+
clipRule: "evenodd",
|
|
54
|
+
d: "M189.473 149.502L196.733 88.3046L140.13 64.0459V92.5315V121.016L164.755 135.259L189.473 149.502Z",
|
|
55
|
+
fill: c.rich
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
/* @__PURE__ */ jsx(
|
|
59
|
+
"path",
|
|
60
|
+
{
|
|
61
|
+
fillRule: "evenodd",
|
|
62
|
+
clipRule: "evenodd",
|
|
63
|
+
d: "M128 0C182.857 0 229.629 34.5499 247.822 82.975C223.747 95.6553 162.917 112.195 128 128C104.569 118.811 28.3934 89.4991 9.74011 78.9317C28.9448 32.6203 74.7053 0 128 0ZM170.544 81.5968L128 106.131L85.3639 81.5968L115.779 64.046L101.445 55.7761V55.6842L80.4941 43.6468L58.9921 31.15C61.2894 29.588 63.6785 28.0259 66.1594 26.4638L88.6719 39.5118C100.709 34.1824 113.941 31.2419 128 31.2419C145.183 31.2419 161.356 35.7445 175.415 43.6468L140.13 64.046L170.544 81.5968Z",
|
|
64
|
+
fill: c.topFace
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
"path",
|
|
69
|
+
{
|
|
70
|
+
fillRule: "evenodd",
|
|
71
|
+
clipRule: "evenodd",
|
|
72
|
+
d: "M238.817 63.9541C249.752 82.7915 256 104.66 256 128C256 198.662 198.662 256 128 256L120.557 199.03L128 128C164.939 106.682 201.878 85.3641 238.817 63.9541ZM146.929 188.095L177.344 170.544V211.251C202.981 196.089 220.991 169.35 224.207 138.2L246.811 125.152C246.72 122.303 246.536 119.455 246.26 116.698L207.207 139.211L189.473 149.502V114.401L146.929 138.935V188.095Z",
|
|
73
|
+
fill: c.sphereHi
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
"path",
|
|
78
|
+
{
|
|
79
|
+
fillRule: "evenodd",
|
|
80
|
+
clipRule: "evenodd",
|
|
81
|
+
d: "M128 256C57.2464 256 0 198.662 0 128C0 104.66 6.15656 82.7915 17.0912 63.9541C54.0302 85.3641 90.9691 106.682 128 128V256ZM108.979 188.095V138.935L66.4352 114.401V149.502L31.1501 129.103C31.5176 160.804 47.1387 188.83 70.9376 206.289V232.293C73.4184 233.672 75.9917 234.958 78.5644 236.152V211.251V170.544L108.979 188.095Z",
|
|
82
|
+
fill: c.sphereLo
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
ComitorLogo
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=comitor-logo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shell/comitor-logo.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\n\n/**\n * Dấu hiệu nhận diện chính thức của Comitor (khối lập phương vàng + 3 hình người đồng hành).\n *\n * Hai biến thể:\n * • `variant=\"light\"` — mặt trên vàng nhạt; dùng trên nền sáng (mặc định)\n * • `variant=\"dark\"` — mặt trên trắng; dùng trên nền tối / nền ấm\n *\n * ⚠ **Ngoại lệ duy nhất của quy tắc \"không hardcode màu\"**: mã hex dưới đây là vector\n * lấy nguyên từ file nguồn Figma của brand book. KHÔNG tokenize, KHÔNG đổi màu,\n * KHÔNG đơn giản hoá path — logo phải giống hệt nhau ở mọi sản phẩm.\n *\n * File này KHÔNG có \"use client\": logo là SVG tĩnh, để RSC render thẳng, không tốn JS phía client.\n */\nexport type ComitorLogoVariant = \"light\" | \"dark\";\n\nexport interface ComitorLogoProps {\n className?: string;\n /** Nền sáng dùng \"light\", nền tối/ấm dùng \"dark\". */\n variant?: ComitorLogoVariant;\n /** Nội dung <title> của SVG — cũng là aria-label. */\n title?: string;\n style?: CSSProperties;\n}\n\nexport function ComitorLogo({ className, variant = \"light\", title = \"Comitor\", style }: ComitorLogoProps) {\n const dark = variant === \"dark\";\n const c = dark\n ? {\n accent: \"#8A6800\",\n bright: \"#F0CC50\",\n rich: \"#D4A820\",\n topFace: \"#FFFFFF\",\n sphereHi: \"#F0CC50\",\n sphereLo: \"#D4A820\"\n }\n : {\n accent: \"#7A5800\",\n bright: \"#E8B824\",\n rich: \"#B88A00\",\n topFace: \"#F5D060\",\n sphereHi: \"#E8B824\",\n sphereLo: \"#B88A00\"\n };\n\n return (\n <svg\n viewBox=\"0 0 256 256\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n style={style}\n role=\"img\"\n aria-label={title}\n >\n <title>{title}</title>\n {/* Bottom interior diamond */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M128 142.059L78.5642 170.543L128 209.32L177.344 170.543L128 142.059Z\"\n fill={c.accent}\n />\n {/* Left-front face */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M56.6951 86.8339L66.4352 149.502L91.1528 135.259L115.779 121.016V92.5315V64.0459L56.6951 86.8339Z\"\n fill={c.bright}\n />\n {/* Right-front face */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M189.473 149.502L196.733 88.3046L140.13 64.0459V92.5315V121.016L164.755 135.259L189.473 149.502Z\"\n fill={c.rich}\n />\n {/* Top face / outer sphere highlight */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M128 0C182.857 0 229.629 34.5499 247.822 82.975C223.747 95.6553 162.917 112.195 128 128C104.569 118.811 28.3934 89.4991 9.74011 78.9317C28.9448 32.6203 74.7053 0 128 0ZM170.544 81.5968L128 106.131L85.3639 81.5968L115.779 64.046L101.445 55.7761V55.6842L80.4941 43.6468L58.9921 31.15C61.2894 29.588 63.6785 28.0259 66.1594 26.4638L88.6719 39.5118C100.709 34.1824 113.941 31.2419 128 31.2419C145.183 31.2419 161.356 35.7445 175.415 43.6468L140.13 64.046L170.544 81.5968Z\"\n fill={c.topFace}\n />\n {/* Right sphere half */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M238.817 63.9541C249.752 82.7915 256 104.66 256 128C256 198.662 198.662 256 128 256L120.557 199.03L128 128C164.939 106.682 201.878 85.3641 238.817 63.9541ZM146.929 188.095L177.344 170.544V211.251C202.981 196.089 220.991 169.35 224.207 138.2L246.811 125.152C246.72 122.303 246.536 119.455 246.26 116.698L207.207 139.211L189.473 149.502V114.401L146.929 138.935V188.095Z\"\n fill={c.sphereHi}\n />\n {/* Left sphere half */}\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M128 256C57.2464 256 0 198.662 0 128C0 104.66 6.15656 82.7915 17.0912 63.9541C54.0302 85.3641 90.9691 106.682 128 128V256ZM108.979 188.095V138.935L66.4352 114.401V149.502L31.1501 129.103C31.5176 160.804 47.1387 188.83 70.9376 206.289V232.293C73.4184 233.672 75.9917 234.958 78.5644 236.152V211.251V170.544L108.979 188.095Z\"\n fill={c.sphereLo}\n />\n </svg>\n );\n}\n"],"mappings":"AA+CI,SASE,KATF;AArBG,SAAS,YAAY,EAAE,WAAW,UAAU,SAAS,QAAQ,WAAW,MAAM,GAAqB;AACxG,QAAM,OAAO,YAAY;AACzB,QAAM,IAAI,OACN;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,IACA;AAAA,IACE,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAEJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,MAAK;AAAA,MACL,cAAY;AAAA,MAEZ;AAAA,4BAAC,WAAO,iBAAM;AAAA,QAEd;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAS;AAAA,YACT,UAAS;AAAA,YACT,GAAE;AAAA,YACF,MAAM,EAAE;AAAA;AAAA,QACV;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export { SonnerToaster, SonnerToasterProps } from '../components/ui/sonner.js';
|
|
2
|
+
export { AppHeader, AppHeaderProps } from './app-header.js';
|
|
3
|
+
export { AppLauncher, AppLauncherPanel, AppLauncherPanelProps, AppLauncherProps } from './app-launcher.js';
|
|
4
|
+
export { AppShell, AppShellLayout, AppShellProps } from './app-shell.js';
|
|
5
|
+
export { ComitorLockup, ComitorLockupProps, ComitorLockupSize, ComitorLockupVariant } from './comitor-lockup.js';
|
|
6
|
+
export { ComitorLogo, ComitorLogoProps, ComitorLogoVariant } from './comitor-logo.js';
|
|
7
|
+
export { MobileMenu, MobileMenuProps } from './mobile-menu.js';
|
|
8
|
+
export { NotificationsButton, NotificationsButtonProps } from './notifications-button.js';
|
|
9
|
+
export { ShellContextValue, ShellProvider, ShellProviderProps, useIsMac, useShell } from './shell-context.js';
|
|
10
|
+
export { ShellNavLink, ShellNavLinkProps } from './shell-link.js';
|
|
11
|
+
export { Sidebar, SidebarProps } from './sidebar.js';
|
|
12
|
+
export { SidebarGroup, SidebarGroupProps } from './sidebar-group.js';
|
|
13
|
+
export { SidebarMenuItem, SidebarMenuItemProps } from './sidebar-menu-item.js';
|
|
14
|
+
export { ThemeProvider, ThemeProviderProps } from './theme-provider.js';
|
|
15
|
+
export { ThemeToggle, ThemeToggleLabels, ThemeToggleProps } from './theme-toggle.js';
|
|
16
|
+
export { AppDescriptor, DEFAULT_SHELL_LABELS, NavBadgeVariant, NavGroup, NavItem, ShellIcon, ShellLabels, ShellLinkComponent, ShellLinkProps, ShellNav, ShellUser, UserMenuItem, Workspace } from './types.js';
|
|
17
|
+
export { UserAvatar, UserAvatarProps, UserMenu, UserMenuProps } from './user-menu.js';
|
|
18
|
+
export { appAccentStyle, flattenNavItems, getAvatarToneClass, getEntitledApps, getLockedApps, isNavBranchActive, isNavItemActive, normalizeVi, resolveCurrentApp, toNavGroups } from './utils.js';
|
|
19
|
+
export { WorkspaceSwitcher, WorkspaceSwitcherProps } from './workspace-switcher.js';
|
|
20
|
+
export { getVietnameseInitials } from '../components/composite/text-utils.js';
|
|
21
|
+
import 'react';
|
|
22
|
+
import 'sonner';
|
|
23
|
+
import 'next-themes';
|
|
24
|
+
import 'lucide-react';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SonnerToaster } from "../components/ui/sonner.js";
|
|
2
|
+
export * from "./app-header.js";
|
|
3
|
+
export * from "./app-launcher.js";
|
|
4
|
+
export * from "./app-shell.js";
|
|
5
|
+
export * from "./comitor-lockup.js";
|
|
6
|
+
export * from "./comitor-logo.js";
|
|
7
|
+
export * from "./mobile-menu.js";
|
|
8
|
+
export * from "./notifications-button.js";
|
|
9
|
+
export * from "./shell-context.js";
|
|
10
|
+
export * from "./shell-link.js";
|
|
11
|
+
export * from "./sidebar.js";
|
|
12
|
+
export * from "./sidebar-group.js";
|
|
13
|
+
export * from "./sidebar-menu-item.js";
|
|
14
|
+
export * from "./theme-provider.js";
|
|
15
|
+
export * from "./theme-toggle.js";
|
|
16
|
+
export * from "./types.js";
|
|
17
|
+
export * from "./user-menu.js";
|
|
18
|
+
export * from "./utils.js";
|
|
19
|
+
export * from "./workspace-switcher.js";
|
|
20
|
+
export {
|
|
21
|
+
SonnerToaster
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shell/index.ts"],"sourcesContent":["/**\n * Entry \"@comitor/ui/shell\" — Tier 3: khung ứng dụng (AppShell, Sidebar, AppHeader,\n * WorkspaceSwitcher, AppLauncher, UserMenu, ThemeProvider…).\n *\n * Tách khỏi entry chính vì tầng này kéo theo `next/navigation` và `next-themes` — hai\n * peer OPTIONAL. App không chạy trên Next thì đừng import entry này (hoặc tự cấp\n * `ShellLinkComponent` riêng qua `ShellProvider`).\n *\n * Toàn bộ file ở đây là client component: có state, có routing, có phím tắt.\n */\n\n/**\n * Toaster bám theo next-themes — về tier thì nó là primitive (`components/ui/sonner.tsx`),\n * nhưng đặt cửa ra ở entry shell vì nó gọi `useTheme()`, mà `next-themes` chỉ là peer\n * OPTIONAL: để ở entry chính là ép mọi app phải cài next-themes.\n * Dùng chung với `ThemeProvider` ở trên. Nếu app KHÔNG dùng next-themes thì lấy composite\n * `Toaster` ở \"@comitor/ui\" và tự truyền prop `theme`.\n */\nexport { SonnerToaster, type SonnerToasterProps } from \"../components/ui/sonner.js\";\nexport * from \"./app-header.js\";\nexport * from \"./app-launcher.js\";\nexport * from \"./app-shell.js\";\nexport * from \"./comitor-lockup.js\";\nexport * from \"./comitor-logo.js\";\nexport * from \"./mobile-menu.js\";\nexport * from \"./notifications-button.js\";\nexport * from \"./shell-context.js\";\nexport * from \"./shell-link.js\";\nexport * from \"./sidebar.js\";\nexport * from \"./sidebar-group.js\";\nexport * from \"./sidebar-menu-item.js\";\nexport * from \"./theme-provider.js\";\nexport * from \"./theme-toggle.js\";\nexport * from \"./types.js\";\nexport * from \"./user-menu.js\";\nexport * from \"./utils.js\";\nexport * from \"./workspace-switcher.js\";\n"],"mappings":"AAkBA,SAAS,qBAA8C;AACvD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { UserMenuProps } from './user-menu.js';
|
|
4
|
+
import './types.js';
|
|
5
|
+
import 'lucide-react';
|
|
6
|
+
|
|
7
|
+
interface MobileMenuProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
/** Slot ngay dưới WorkspaceSwitcher. */
|
|
10
|
+
header?: ReactNode;
|
|
11
|
+
/** Slot đáy (phiên bản app, liên kết hỗ trợ…). */
|
|
12
|
+
footer?: ReactNode;
|
|
13
|
+
showAppLauncher?: boolean;
|
|
14
|
+
showThemeToggle?: boolean;
|
|
15
|
+
/** Chuyển tiếp props cho `UserMenu` ở đáy. */
|
|
16
|
+
userMenuProps?: UserMenuProps;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Menu off-canvas cho màn hình hẹp (`Sheet` trượt từ trái):
|
|
20
|
+
* WorkspaceSwitcher (trục 1) → lưới app dạng danh sách (trục 2) → menu app hiện tại → user.
|
|
21
|
+
*
|
|
22
|
+
* Tự đóng khi đổi route (`ShellProvider` lo) và khi bấm vào một link thật trong menu.
|
|
23
|
+
*/
|
|
24
|
+
declare function MobileMenu({ className, header, footer, showAppLauncher, showThemeToggle, userMenuProps }: MobileMenuProps): React.JSX.Element;
|
|
25
|
+
|
|
26
|
+
export { MobileMenu, type MobileMenuProps };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Separator } from "../components/ui/separator.js";
|
|
4
|
+
import { Sheet, SheetContent, SheetHeader, SheetTitle } from "../components/ui/sheet.js";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { AppLauncher } from "./app-launcher.js";
|
|
7
|
+
import { useShell } from "./shell-context.js";
|
|
8
|
+
import { SidebarGroup } from "./sidebar-group.js";
|
|
9
|
+
import { ThemeToggle } from "./theme-toggle.js";
|
|
10
|
+
import { UserMenu } from "./user-menu.js";
|
|
11
|
+
import { appAccentStyle, flattenNavItems } from "./utils.js";
|
|
12
|
+
import { WorkspaceSwitcher } from "./workspace-switcher.js";
|
|
13
|
+
function MobileMenu({
|
|
14
|
+
className,
|
|
15
|
+
header,
|
|
16
|
+
footer,
|
|
17
|
+
showAppLauncher = true,
|
|
18
|
+
showThemeToggle = true,
|
|
19
|
+
userMenuProps
|
|
20
|
+
}) {
|
|
21
|
+
const { mobileMenuOpen, setMobileMenuOpen, nav, currentApp, user, labels } = useShell();
|
|
22
|
+
const allItems = flattenNavItems(nav);
|
|
23
|
+
const closeMenu = () => setMobileMenuOpen(false);
|
|
24
|
+
return /* @__PURE__ */ jsx(Sheet, { open: mobileMenuOpen, onOpenChange: setMobileMenuOpen, children: /* @__PURE__ */ jsxs(
|
|
25
|
+
SheetContent,
|
|
26
|
+
{
|
|
27
|
+
side: "left",
|
|
28
|
+
"aria-describedby": void 0,
|
|
29
|
+
style: appAccentStyle(currentApp),
|
|
30
|
+
className: cn("flex w-80 max-w-[85vw] flex-col gap-0 bg-sidebar p-0 md:hidden", className),
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ jsxs(SheetHeader, { className: "shrink-0 border-b border-sidebar-border p-2", children: [
|
|
33
|
+
/* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: labels.navigationLabel }),
|
|
34
|
+
/* @__PURE__ */ jsx(WorkspaceSwitcher, { align: "start" })
|
|
35
|
+
] }),
|
|
36
|
+
header ? /* @__PURE__ */ jsx("div", { className: "shrink-0 p-2", children: header }) : null,
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto scrollbar-thin", children: [
|
|
38
|
+
showAppLauncher ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
|
+
/* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(AppLauncher, { inline: true, variant: "list", onSelected: closeMenu }) }),
|
|
40
|
+
/* @__PURE__ */ jsx(Separator, { className: "bg-sidebar-border" })
|
|
41
|
+
] }) : null,
|
|
42
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 p-2", children: nav.map((group) => /* @__PURE__ */ jsx(SidebarGroup, { group, siblings: allItems, onNavigate: closeMenu }, group.id)) })
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 border-t border-sidebar-border p-2", children: [
|
|
45
|
+
user ? /* @__PURE__ */ jsx(UserMenu, { showName: true, ...userMenuProps, className: "min-w-0 flex-1" }) : null,
|
|
46
|
+
showThemeToggle ? /* @__PURE__ */ jsx(ThemeToggle, { labels }) : null
|
|
47
|
+
] }),
|
|
48
|
+
footer ? /* @__PURE__ */ jsx("div", { className: "shrink-0 border-t border-sidebar-border p-2", children: footer }) : null
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
) });
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
MobileMenu
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=mobile-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shell/mobile-menu.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { Separator } from \"../components/ui/separator.js\";\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from \"../components/ui/sheet.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { AppLauncher } from \"./app-launcher.js\";\nimport { useShell } from \"./shell-context.js\";\nimport { SidebarGroup } from \"./sidebar-group.js\";\nimport { ThemeToggle } from \"./theme-toggle.js\";\nimport { UserMenu, type UserMenuProps } from \"./user-menu.js\";\nimport { appAccentStyle, flattenNavItems } from \"./utils.js\";\nimport { WorkspaceSwitcher } from \"./workspace-switcher.js\";\n\nexport interface MobileMenuProps {\n className?: string;\n /** Slot ngay dưới WorkspaceSwitcher. */\n header?: ReactNode;\n /** Slot đáy (phiên bản app, liên kết hỗ trợ…). */\n footer?: ReactNode;\n showAppLauncher?: boolean;\n showThemeToggle?: boolean;\n /** Chuyển tiếp props cho `UserMenu` ở đáy. */\n userMenuProps?: UserMenuProps;\n}\n\n/**\n * Menu off-canvas cho màn hình hẹp (`Sheet` trượt từ trái):\n * WorkspaceSwitcher (trục 1) → lưới app dạng danh sách (trục 2) → menu app hiện tại → user.\n *\n * Tự đóng khi đổi route (`ShellProvider` lo) và khi bấm vào một link thật trong menu.\n */\nexport function MobileMenu({\n className,\n header,\n footer,\n showAppLauncher = true,\n showThemeToggle = true,\n userMenuProps\n}: MobileMenuProps) {\n const { mobileMenuOpen, setMobileMenuOpen, nav, currentApp, user, labels } = useShell();\n\n const allItems = flattenNavItems(nav);\n\n // Chỉ đóng khi bấm trúng LINK thật — `SidebarMenuItem` không gọi callback này\n // khi người dùng chỉ mở/đóng nhánh con, nên menu giữ nguyên cho họ đi tiếp.\n const closeMenu = () => setMobileMenuOpen(false);\n\n return (\n <Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>\n <SheetContent\n side=\"left\"\n aria-describedby={undefined}\n style={appAccentStyle(currentApp)}\n className={cn(\"flex w-80 max-w-[85vw] flex-col gap-0 bg-sidebar p-0 md:hidden\", className)}\n >\n <SheetHeader className=\"shrink-0 border-b border-sidebar-border p-2\">\n <SheetTitle className=\"sr-only\">{labels.navigationLabel}</SheetTitle>\n <WorkspaceSwitcher align=\"start\" />\n </SheetHeader>\n\n {header ? <div className=\"shrink-0 p-2\">{header}</div> : null}\n\n <div className=\"flex-1 overflow-y-auto scrollbar-thin\">\n {showAppLauncher ? (\n <>\n <div className=\"p-2\">\n <AppLauncher inline variant=\"list\" onSelected={closeMenu} />\n </div>\n <Separator className=\"bg-sidebar-border\" />\n </>\n ) : null}\n\n <div className=\"flex flex-col gap-4 p-2\">\n {nav.map((group) => (\n <SidebarGroup key={group.id} group={group} siblings={allItems} onNavigate={closeMenu} />\n ))}\n </div>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-2 border-t border-sidebar-border p-2\">\n {user ? <UserMenu showName {...userMenuProps} className=\"min-w-0 flex-1\" /> : null}\n {showThemeToggle ? <ThemeToggle labels={labels} /> : null}\n </div>\n\n {footer ? <div className=\"shrink-0 border-t border-sidebar-border p-2\">{footer}</div> : null}\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":";AAwDQ,SASI,UARF,KADF;AArDR,SAAS,iBAAiB;AAC1B,SAAS,OAAO,cAAc,aAAa,kBAAkB;AAC7D,SAAS,UAAU;AACnB,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,gBAAoC;AAC7C,SAAS,gBAAgB,uBAAuB;AAChD,SAAS,yBAAyB;AAoB3B,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB;AACF,GAAoB;AAClB,QAAM,EAAE,gBAAgB,mBAAmB,KAAK,YAAY,MAAM,OAAO,IAAI,SAAS;AAEtF,QAAM,WAAW,gBAAgB,GAAG;AAIpC,QAAM,YAAY,MAAM,kBAAkB,KAAK;AAE/C,SACE,oBAAC,SAAM,MAAM,gBAAgB,cAAc,mBACzC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,oBAAkB;AAAA,MAClB,OAAO,eAAe,UAAU;AAAA,MAChC,WAAW,GAAG,kEAAkE,SAAS;AAAA,MAEzF;AAAA,6BAAC,eAAY,WAAU,+CACrB;AAAA,8BAAC,cAAW,WAAU,WAAW,iBAAO,iBAAgB;AAAA,UACxD,oBAAC,qBAAkB,OAAM,SAAQ;AAAA,WACnC;AAAA,QAEC,SAAS,oBAAC,SAAI,WAAU,gBAAgB,kBAAO,IAAS;AAAA,QAEzD,qBAAC,SAAI,WAAU,yCACZ;AAAA,4BACC,iCACE;AAAA,gCAAC,SAAI,WAAU,OACb,8BAAC,eAAY,QAAM,MAAC,SAAQ,QAAO,YAAY,WAAW,GAC5D;AAAA,YACA,oBAAC,aAAU,WAAU,qBAAoB;AAAA,aAC3C,IACE;AAAA,UAEJ,oBAAC,SAAI,WAAU,2BACZ,cAAI,IAAI,CAAC,UACR,oBAAC,gBAA4B,OAAc,UAAU,UAAU,YAAY,aAAxD,MAAM,EAA6D,CACvF,GACH;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,uEACZ;AAAA,iBAAO,oBAAC,YAAS,UAAQ,MAAE,GAAG,eAAe,WAAU,kBAAiB,IAAK;AAAA,UAC7E,kBAAkB,oBAAC,eAAY,QAAgB,IAAK;AAAA,WACvD;AAAA,QAEC,SAAS,oBAAC,SAAI,WAAU,+CAA+C,kBAAO,IAAS;AAAA;AAAA;AAAA,EAC1F,GACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
|
|
4
|
+
interface NotificationsButtonProps extends Omit<ComponentProps<"button">, "children"> {
|
|
5
|
+
/** Số thông báo chưa đọc; 0 hoặc bỏ trống thì không hiện chấm số. */
|
|
6
|
+
count?: number;
|
|
7
|
+
/** Nhãn a11y (mặc định "Thông báo"). */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Vượt ngưỡng này thì hiển thị "n+" (mặc định 9). */
|
|
10
|
+
max?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Nút chuông + số chưa đọc. **Chỉ có cái nút** — nội dung panel thông báo là
|
|
14
|
+
* app-specific: đóng sẵn một NotificationPanel vào package thì app nào cũng phải
|
|
15
|
+
* uốn dữ liệu của mình cho vừa cái khuôn đó.
|
|
16
|
+
*
|
|
17
|
+
* App tự bọc trong Popover/Sheet của mình:
|
|
18
|
+
* `<PopoverTrigger asChild><NotificationsButton count={3} /></PopoverTrigger>`
|
|
19
|
+
*/
|
|
20
|
+
declare function NotificationsButton({ count, label, max, className, ...props }: NotificationsButtonProps): React.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { NotificationsButton, type NotificationsButtonProps };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Bell } from "lucide-react";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
import { DEFAULT_SHELL_LABELS } from "./types.js";
|
|
6
|
+
function NotificationsButton({ count = 0, label, max = 9, className, ...props }) {
|
|
7
|
+
const text = label ?? DEFAULT_SHELL_LABELS.notifications;
|
|
8
|
+
const hasUnread = count > 0;
|
|
9
|
+
return /* @__PURE__ */ jsxs(
|
|
10
|
+
"button",
|
|
11
|
+
{
|
|
12
|
+
type: "button",
|
|
13
|
+
"aria-label": hasUnread ? `${text} (${count})` : text,
|
|
14
|
+
className: cn(
|
|
15
|
+
"relative flex size-9 items-center justify-center rounded-md text-muted-foreground",
|
|
16
|
+
"transition-colors duration-150 ease-out hover:bg-muted hover:text-foreground",
|
|
17
|
+
className
|
|
18
|
+
),
|
|
19
|
+
...props,
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ jsx(Bell, { className: "size-4" }),
|
|
22
|
+
hasUnread ? /* @__PURE__ */ jsx(
|
|
23
|
+
"span",
|
|
24
|
+
{
|
|
25
|
+
className: cn(
|
|
26
|
+
"absolute right-1 top-1 flex h-4 min-w-4 items-center justify-center rounded-full px-1",
|
|
27
|
+
"bg-destructive text-[10px] font-semibold leading-none text-destructive-foreground"
|
|
28
|
+
),
|
|
29
|
+
children: count > max ? `${max}+` : count
|
|
30
|
+
}
|
|
31
|
+
) : null
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
NotificationsButton
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=notifications-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shell/notifications-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { Bell } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport { DEFAULT_SHELL_LABELS } from \"./types.js\";\n\nexport interface NotificationsButtonProps extends Omit<ComponentProps<\"button\">, \"children\"> {\n /** Số thông báo chưa đọc; 0 hoặc bỏ trống thì không hiện chấm số. */\n count?: number;\n /** Nhãn a11y (mặc định \"Thông báo\"). */\n label?: string;\n /** Vượt ngưỡng này thì hiển thị \"n+\" (mặc định 9). */\n max?: number;\n}\n\n/**\n * Nút chuông + số chưa đọc. **Chỉ có cái nút** — nội dung panel thông báo là\n * app-specific: đóng sẵn một NotificationPanel vào package thì app nào cũng phải\n * uốn dữ liệu của mình cho vừa cái khuôn đó.\n *\n * App tự bọc trong Popover/Sheet của mình:\n * `<PopoverTrigger asChild><NotificationsButton count={3} /></PopoverTrigger>`\n */\nexport function NotificationsButton({ count = 0, label, max = 9, className, ...props }: NotificationsButtonProps) {\n const text = label ?? DEFAULT_SHELL_LABELS.notifications;\n const hasUnread = count > 0;\n\n return (\n <button\n type=\"button\"\n aria-label={hasUnread ? `${text} (${count})` : text}\n className={cn(\n \"relative flex size-9 items-center justify-center rounded-md text-muted-foreground\",\n \"transition-colors duration-150 ease-out hover:bg-muted hover:text-foreground\",\n className\n )}\n {...props}\n >\n <Bell className=\"size-4\" />\n {hasUnread ? (\n <span\n className={cn(\n \"absolute right-1 top-1 flex h-4 min-w-4 items-center justify-center rounded-full px-1\",\n \"bg-destructive text-[10px] font-semibold leading-none text-destructive-foreground\"\n )}\n >\n {count > max ? `${max}+` : count}\n </span>\n ) : null}\n </button>\n );\n}\n"],"mappings":";AA6BI,SAUE,KAVF;AA3BJ,SAAS,YAAY;AAErB,SAAS,UAAU;AACnB,SAAS,4BAA4B;AAmB9B,SAAS,oBAAoB,EAAE,QAAQ,GAAG,OAAO,MAAM,GAAG,WAAW,GAAG,MAAM,GAA6B;AAChH,QAAM,OAAO,SAAS,qBAAqB;AAC3C,QAAM,YAAY,QAAQ;AAE1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,YAAY,GAAG,IAAI,KAAK,KAAK,MAAM;AAAA,MAC/C,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,QAAK,WAAU,UAAS;AAAA,QACxB,YACC;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,YACF;AAAA,YAEC,kBAAQ,MAAM,GAAG,GAAG,MAAM;AAAA;AAAA,QAC7B,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Workspace, AppDescriptor, ShellNav, ShellLinkComponent, ShellUser, ShellLabels, NavGroup } from './types.js';
|
|
4
|
+
import 'lucide-react';
|
|
5
|
+
|
|
6
|
+
interface ShellContextValue {
|
|
7
|
+
workspaces: Workspace[];
|
|
8
|
+
currentWorkspace: Workspace | null;
|
|
9
|
+
onWorkspaceChange?: (workspaceId: string) => void;
|
|
10
|
+
onCreateWorkspace?: () => void;
|
|
11
|
+
onWorkspaceSettings?: (workspaceId: string) => void;
|
|
12
|
+
onInviteMembers?: (workspaceId: string) => void;
|
|
13
|
+
apps: AppDescriptor[];
|
|
14
|
+
currentApp: AppDescriptor | null;
|
|
15
|
+
onAppSelect?: (app: AppDescriptor) => void;
|
|
16
|
+
onUpsell?: (appId: string) => void;
|
|
17
|
+
nav: NavGroup[];
|
|
18
|
+
pathname: string;
|
|
19
|
+
LinkComponent: ShellLinkComponent;
|
|
20
|
+
onNavigate?: (href: string) => void;
|
|
21
|
+
user: ShellUser | null;
|
|
22
|
+
onLogout?: () => void;
|
|
23
|
+
sidebarCollapsed: boolean;
|
|
24
|
+
setSidebarCollapsed: (collapsed: boolean) => void;
|
|
25
|
+
toggleSidebar: () => void;
|
|
26
|
+
mobileMenuOpen: boolean;
|
|
27
|
+
setMobileMenuOpen: (open: boolean) => void;
|
|
28
|
+
commandPaletteOpen: boolean;
|
|
29
|
+
setCommandPaletteOpen: (open: boolean) => void;
|
|
30
|
+
appLauncherOpen: boolean;
|
|
31
|
+
setAppLauncherOpen: (open: boolean) => void;
|
|
32
|
+
labels: ShellLabels;
|
|
33
|
+
}
|
|
34
|
+
/** Truy cập state của shell — phải gọi bên trong `<ShellProvider>`. */
|
|
35
|
+
declare function useShell(): ShellContextValue;
|
|
36
|
+
/**
|
|
37
|
+
* `true` khi đang chạy trên macOS — để hiện `⌘K` thay vì `Ctrl+K`.
|
|
38
|
+
* Dùng `useSyncExternalStore` với snapshot server = false: React tự khớp
|
|
39
|
+
* server/client, không cần cờ `mounted` thủ công và không gây hydration mismatch.
|
|
40
|
+
*/
|
|
41
|
+
declare function useIsMac(): boolean;
|
|
42
|
+
interface ShellProviderProps {
|
|
43
|
+
/** Trục 1 — danh sách workspace của user. Rỗng/1 phần tử thì WorkspaceSwitcher tự ẩn danh sách. */
|
|
44
|
+
workspaces?: Workspace[];
|
|
45
|
+
/** Workspace đang mở; bỏ trống → lấy phần tử đầu. */
|
|
46
|
+
currentWorkspaceId?: string;
|
|
47
|
+
onWorkspaceChange?: (workspaceId: string) => void;
|
|
48
|
+
onCreateWorkspace?: () => void;
|
|
49
|
+
onWorkspaceSettings?: (workspaceId: string) => void;
|
|
50
|
+
onInviteMembers?: (workspaceId: string) => void;
|
|
51
|
+
/** Trục 2 — danh sách app của hệ sinh thái (kể cả app chưa mở khoá). */
|
|
52
|
+
apps?: AppDescriptor[];
|
|
53
|
+
/** App đang mở; bỏ trống → suy từ `pathname` (khớp prefix dài nhất). */
|
|
54
|
+
currentAppId?: string;
|
|
55
|
+
onAppSelect?: (app: AppDescriptor) => void;
|
|
56
|
+
onUpsell?: (appId: string) => void;
|
|
57
|
+
/** Menu của app hiện tại — `NavItem[]` hoặc `NavGroup[]`. */
|
|
58
|
+
nav?: ShellNav;
|
|
59
|
+
/**
|
|
60
|
+
* Ghi đè pathname (Storybook, app không-Next). Bỏ trống → dùng `usePathname()`
|
|
61
|
+
* của next/navigation (trả `null` khi không có App Router → coi như "").
|
|
62
|
+
*/
|
|
63
|
+
pathname?: string;
|
|
64
|
+
/** Component link thay `next/link` (app không-Next). */
|
|
65
|
+
LinkComponent?: ShellLinkComponent;
|
|
66
|
+
/** Gọi sau mỗi lần người dùng bấm một mục điều hướng (analytics, đóng panel…). */
|
|
67
|
+
onNavigate?: (href: string) => void;
|
|
68
|
+
user?: ShellUser | null;
|
|
69
|
+
onLogout?: () => void;
|
|
70
|
+
/** Trạng thái thu gọn ban đầu (SSR). Sau khi mount, localStorage của workspace thắng. */
|
|
71
|
+
defaultSidebarCollapsed?: boolean;
|
|
72
|
+
/** Tắt ghi nhớ localStorage (Storybook, chế độ kiosk). */
|
|
73
|
+
persistSidebarState?: boolean;
|
|
74
|
+
/** Tắt bộ phím tắt toàn cục. */
|
|
75
|
+
enableShortcuts?: boolean;
|
|
76
|
+
/** Override chuỗi hiển thị (mặc định tiếng Việt). */
|
|
77
|
+
labels?: Partial<ShellLabels>;
|
|
78
|
+
children: ReactNode;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Provider của app shell Comitor: giữ hai trục điều hướng (workspace × app),
|
|
82
|
+
* trạng thái khung (sidebar/mobile/command palette/app launcher), phím tắt toàn cục,
|
|
83
|
+
* và bọc sẵn `TooltipProvider`.
|
|
84
|
+
*
|
|
85
|
+
* KHÔNG dùng `useRouter()` của next/navigation: hook đó *ném lỗi* khi thiếu App Router
|
|
86
|
+
* (Storybook, test). Mọi điều hướng chủ động là việc của app qua callback
|
|
87
|
+
* `onWorkspaceChange` / `onAppSelect` / `onNavigate`; link tĩnh đi qua `LinkComponent`.
|
|
88
|
+
*/
|
|
89
|
+
declare function ShellProvider({ workspaces, currentWorkspaceId, onWorkspaceChange, onCreateWorkspace, onWorkspaceSettings, onInviteMembers, apps, currentAppId, onAppSelect, onUpsell, nav, pathname: pathnameProp, LinkComponent, onNavigate, user, onLogout, defaultSidebarCollapsed, persistSidebarState, enableShortcuts, labels: labelsProp, children }: ShellProviderProps): React.JSX.Element;
|
|
90
|
+
|
|
91
|
+
export { type ShellContextValue, ShellProvider, type ShellProviderProps, useIsMac, useShell };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import NextLink from "next/link";
|
|
4
|
+
import { usePathname } from "next/navigation";
|
|
5
|
+
import {
|
|
6
|
+
createContext,
|
|
7
|
+
useCallback,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState,
|
|
12
|
+
useSyncExternalStore
|
|
13
|
+
} from "react";
|
|
14
|
+
import { TooltipProvider } from "../components/ui/tooltip.js";
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_SHELL_LABELS
|
|
17
|
+
} from "./types.js";
|
|
18
|
+
import { getEntitledApps, resolveCurrentApp, toNavGroups } from "./utils.js";
|
|
19
|
+
function DefaultShellLink({ href, children, ...props }) {
|
|
20
|
+
return /* @__PURE__ */ jsx(NextLink, { href, ...props, children });
|
|
21
|
+
}
|
|
22
|
+
const ShellContext = createContext(void 0);
|
|
23
|
+
function useShell() {
|
|
24
|
+
const context = useContext(ShellContext);
|
|
25
|
+
if (!context) {
|
|
26
|
+
throw new Error("useShell ph\u1EA3i \u0111\u01B0\u1EE3c d\xF9ng b\xEAn trong <ShellProvider> (ho\u1EB7c <AppShell>).");
|
|
27
|
+
}
|
|
28
|
+
return context;
|
|
29
|
+
}
|
|
30
|
+
function sidebarStorageKey(workspaceId) {
|
|
31
|
+
return `comitor-sidebar:${workspaceId ?? "default"}`;
|
|
32
|
+
}
|
|
33
|
+
function readStoredCollapsed(workspaceId) {
|
|
34
|
+
if (typeof window === "undefined") return null;
|
|
35
|
+
try {
|
|
36
|
+
const raw = window.localStorage.getItem(sidebarStorageKey(workspaceId));
|
|
37
|
+
if (raw === "1") return true;
|
|
38
|
+
if (raw === "0") return false;
|
|
39
|
+
return null;
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const emptySubscribe = () => () => {
|
|
45
|
+
};
|
|
46
|
+
function useIsMac() {
|
|
47
|
+
return useSyncExternalStore(
|
|
48
|
+
emptySubscribe,
|
|
49
|
+
() => /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent),
|
|
50
|
+
() => false
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function ShellProvider({
|
|
54
|
+
workspaces = [],
|
|
55
|
+
currentWorkspaceId,
|
|
56
|
+
onWorkspaceChange,
|
|
57
|
+
onCreateWorkspace,
|
|
58
|
+
onWorkspaceSettings,
|
|
59
|
+
onInviteMembers,
|
|
60
|
+
apps = [],
|
|
61
|
+
currentAppId,
|
|
62
|
+
onAppSelect,
|
|
63
|
+
onUpsell,
|
|
64
|
+
nav,
|
|
65
|
+
pathname: pathnameProp,
|
|
66
|
+
LinkComponent = DefaultShellLink,
|
|
67
|
+
onNavigate,
|
|
68
|
+
user = null,
|
|
69
|
+
onLogout,
|
|
70
|
+
defaultSidebarCollapsed = false,
|
|
71
|
+
persistSidebarState = true,
|
|
72
|
+
enableShortcuts = true,
|
|
73
|
+
labels: labelsProp,
|
|
74
|
+
children
|
|
75
|
+
}) {
|
|
76
|
+
const nextPathname = usePathname();
|
|
77
|
+
const pathname = pathnameProp ?? nextPathname ?? "";
|
|
78
|
+
const currentWorkspace = useMemo(
|
|
79
|
+
() => workspaces.find((workspace) => workspace.id === currentWorkspaceId) ?? workspaces[0] ?? null,
|
|
80
|
+
[workspaces, currentWorkspaceId]
|
|
81
|
+
);
|
|
82
|
+
const currentApp = useMemo(() => {
|
|
83
|
+
if (currentAppId) return apps.find((app) => app.id === currentAppId) ?? null;
|
|
84
|
+
return resolveCurrentApp(apps, pathname);
|
|
85
|
+
}, [apps, currentAppId, pathname]);
|
|
86
|
+
const navGroups = useMemo(() => toNavGroups(nav), [nav]);
|
|
87
|
+
const labels = useMemo(() => ({ ...DEFAULT_SHELL_LABELS, ...labelsProp }), [labelsProp]);
|
|
88
|
+
const [sidebarCollapsed, setSidebarCollapsed] = useState(defaultSidebarCollapsed);
|
|
89
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
90
|
+
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
|
|
91
|
+
const [appLauncherOpen, setAppLauncherOpen] = useState(false);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!persistSidebarState) return;
|
|
94
|
+
const stored = readStoredCollapsed(currentWorkspace?.id);
|
|
95
|
+
if (stored !== null) setSidebarCollapsed(stored);
|
|
96
|
+
}, [persistSidebarState, currentWorkspace?.id]);
|
|
97
|
+
const persistCollapsed = useCallback(
|
|
98
|
+
(collapsed) => {
|
|
99
|
+
if (!persistSidebarState || typeof window === "undefined") return;
|
|
100
|
+
try {
|
|
101
|
+
window.localStorage.setItem(sidebarStorageKey(currentWorkspace?.id), collapsed ? "1" : "0");
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
[persistSidebarState, currentWorkspace?.id]
|
|
106
|
+
);
|
|
107
|
+
const applySidebarCollapsed = useCallback(
|
|
108
|
+
(collapsed) => {
|
|
109
|
+
setSidebarCollapsed(collapsed);
|
|
110
|
+
persistCollapsed(collapsed);
|
|
111
|
+
},
|
|
112
|
+
[persistCollapsed]
|
|
113
|
+
);
|
|
114
|
+
const toggleSidebar = useCallback(() => {
|
|
115
|
+
setSidebarCollapsed((prev) => {
|
|
116
|
+
const next = !prev;
|
|
117
|
+
persistCollapsed(next);
|
|
118
|
+
return next;
|
|
119
|
+
});
|
|
120
|
+
}, [persistCollapsed]);
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
if (!enableShortcuts) return;
|
|
123
|
+
const entitledApps = getEntitledApps(apps);
|
|
124
|
+
const handleKeyDown = (event) => {
|
|
125
|
+
const target = event.target;
|
|
126
|
+
const isTyping = target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement || target instanceof HTMLElement && target.isContentEditable;
|
|
127
|
+
if (event.key === "Escape") {
|
|
128
|
+
setCommandPaletteOpen(false);
|
|
129
|
+
setMobileMenuOpen(false);
|
|
130
|
+
setAppLauncherOpen(false);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (isTyping) return;
|
|
134
|
+
const mod = event.metaKey || event.ctrlKey;
|
|
135
|
+
const key = event.key.toLowerCase();
|
|
136
|
+
if (mod && event.shiftKey && key === "k") {
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
setAppLauncherOpen((prev) => !prev);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (mod && !event.shiftKey && key === "k") {
|
|
142
|
+
event.preventDefault();
|
|
143
|
+
setCommandPaletteOpen((prev) => !prev);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (mod && !event.shiftKey && key === "b") {
|
|
147
|
+
event.preventDefault();
|
|
148
|
+
toggleSidebar();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (event.altKey && !event.ctrlKey && !event.metaKey) {
|
|
152
|
+
const match = /^Digit([1-9])$/.exec(event.code);
|
|
153
|
+
if (match?.[1]) {
|
|
154
|
+
const index = Number.parseInt(match[1], 10) - 1;
|
|
155
|
+
const app = entitledApps[index];
|
|
156
|
+
if (app) {
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
onAppSelect?.(app);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
164
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
165
|
+
}, [enableShortcuts, apps, onAppSelect, toggleSidebar]);
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
setMobileMenuOpen(false);
|
|
168
|
+
setAppLauncherOpen(false);
|
|
169
|
+
setCommandPaletteOpen(false);
|
|
170
|
+
}, [pathname]);
|
|
171
|
+
const value = useMemo(
|
|
172
|
+
() => ({
|
|
173
|
+
workspaces,
|
|
174
|
+
currentWorkspace,
|
|
175
|
+
onWorkspaceChange,
|
|
176
|
+
onCreateWorkspace,
|
|
177
|
+
onWorkspaceSettings,
|
|
178
|
+
onInviteMembers,
|
|
179
|
+
apps,
|
|
180
|
+
currentApp,
|
|
181
|
+
onAppSelect,
|
|
182
|
+
onUpsell,
|
|
183
|
+
nav: navGroups,
|
|
184
|
+
pathname,
|
|
185
|
+
LinkComponent,
|
|
186
|
+
onNavigate,
|
|
187
|
+
user,
|
|
188
|
+
onLogout,
|
|
189
|
+
sidebarCollapsed,
|
|
190
|
+
setSidebarCollapsed: applySidebarCollapsed,
|
|
191
|
+
toggleSidebar,
|
|
192
|
+
mobileMenuOpen,
|
|
193
|
+
setMobileMenuOpen,
|
|
194
|
+
commandPaletteOpen,
|
|
195
|
+
setCommandPaletteOpen,
|
|
196
|
+
appLauncherOpen,
|
|
197
|
+
setAppLauncherOpen,
|
|
198
|
+
labels
|
|
199
|
+
}),
|
|
200
|
+
[
|
|
201
|
+
workspaces,
|
|
202
|
+
currentWorkspace,
|
|
203
|
+
onWorkspaceChange,
|
|
204
|
+
onCreateWorkspace,
|
|
205
|
+
onWorkspaceSettings,
|
|
206
|
+
onInviteMembers,
|
|
207
|
+
apps,
|
|
208
|
+
currentApp,
|
|
209
|
+
onAppSelect,
|
|
210
|
+
onUpsell,
|
|
211
|
+
navGroups,
|
|
212
|
+
pathname,
|
|
213
|
+
LinkComponent,
|
|
214
|
+
onNavigate,
|
|
215
|
+
user,
|
|
216
|
+
onLogout,
|
|
217
|
+
sidebarCollapsed,
|
|
218
|
+
applySidebarCollapsed,
|
|
219
|
+
toggleSidebar,
|
|
220
|
+
mobileMenuOpen,
|
|
221
|
+
commandPaletteOpen,
|
|
222
|
+
appLauncherOpen,
|
|
223
|
+
labels
|
|
224
|
+
]
|
|
225
|
+
);
|
|
226
|
+
return /* @__PURE__ */ jsx(ShellContext.Provider, { value, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children }) });
|
|
227
|
+
}
|
|
228
|
+
export {
|
|
229
|
+
ShellProvider,
|
|
230
|
+
useIsMac,
|
|
231
|
+
useShell
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=shell-context.js.map
|