@hyunsdev/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 +674 -0
- package/README.md +89 -0
- package/SKILL.md +38 -0
- package/dist/WindowContext-DybYtZJa.d.ts +50 -0
- package/dist/_styles-BbTx89aX.d.ts +3 -0
- package/dist/chunk-23KUNTRD.js +49 -0
- package/dist/chunk-23KUNTRD.js.map +1 -0
- package/dist/chunk-3RTSANKB.js +51 -0
- package/dist/chunk-3RTSANKB.js.map +1 -0
- package/dist/chunk-4QIWBOF4.js +129 -0
- package/dist/chunk-4QIWBOF4.js.map +1 -0
- package/dist/chunk-5JCWC7IU.js +293 -0
- package/dist/chunk-5JCWC7IU.js.map +1 -0
- package/dist/chunk-6ANDNGHD.js +33 -0
- package/dist/chunk-6ANDNGHD.js.map +1 -0
- package/dist/chunk-7W7QZHEZ.js +42 -0
- package/dist/chunk-7W7QZHEZ.js.map +1 -0
- package/dist/chunk-BHO4WT2N.js +51 -0
- package/dist/chunk-BHO4WT2N.js.map +1 -0
- package/dist/chunk-BI3KKBIC.js +11 -0
- package/dist/chunk-BI3KKBIC.js.map +1 -0
- package/dist/chunk-D3SP7GL3.js +55 -0
- package/dist/chunk-D3SP7GL3.js.map +1 -0
- package/dist/chunk-D7W4RSQX.js +115 -0
- package/dist/chunk-D7W4RSQX.js.map +1 -0
- package/dist/chunk-DN2AEEA2.js +11 -0
- package/dist/chunk-DN2AEEA2.js.map +1 -0
- package/dist/chunk-ETTKFCO6.js +84 -0
- package/dist/chunk-ETTKFCO6.js.map +1 -0
- package/dist/chunk-GJT7TDBS.js +66 -0
- package/dist/chunk-GJT7TDBS.js.map +1 -0
- package/dist/chunk-HZT6RQYZ.js +109 -0
- package/dist/chunk-HZT6RQYZ.js.map +1 -0
- package/dist/chunk-JB2QZV7K.js +60 -0
- package/dist/chunk-JB2QZV7K.js.map +1 -0
- package/dist/chunk-KJJB2PVC.js +21 -0
- package/dist/chunk-KJJB2PVC.js.map +1 -0
- package/dist/chunk-NE3IVPMO.js +31 -0
- package/dist/chunk-NE3IVPMO.js.map +1 -0
- package/dist/chunk-O2BG2KSY.js +23 -0
- package/dist/chunk-O2BG2KSY.js.map +1 -0
- package/dist/chunk-OUFGNJ3V.js +1726 -0
- package/dist/chunk-OUFGNJ3V.js.map +1 -0
- package/dist/chunk-PLZMCJSL.js +351 -0
- package/dist/chunk-PLZMCJSL.js.map +1 -0
- package/dist/chunk-POG5DZBT.js +104 -0
- package/dist/chunk-POG5DZBT.js.map +1 -0
- package/dist/chunk-SECZM6JE.js +170 -0
- package/dist/chunk-SECZM6JE.js.map +1 -0
- package/dist/chunk-T64WPXSC.js +48 -0
- package/dist/chunk-T64WPXSC.js.map +1 -0
- package/dist/chunk-TU5CYBB4.js +90 -0
- package/dist/chunk-TU5CYBB4.js.map +1 -0
- package/dist/chunk-UVAI2U6X.js +153 -0
- package/dist/chunk-UVAI2U6X.js.map +1 -0
- package/dist/chunk-UXCBLYG6.js +142 -0
- package/dist/chunk-UXCBLYG6.js.map +1 -0
- package/dist/chunk-VUR4MQMH.js +53 -0
- package/dist/chunk-VUR4MQMH.js.map +1 -0
- package/dist/chunk-WIEKNG4S.js +26 -0
- package/dist/chunk-WIEKNG4S.js.map +1 -0
- package/dist/chunk-WIZ4OLOB.js +23 -0
- package/dist/chunk-WIZ4OLOB.js.map +1 -0
- package/dist/chunk-WJRJBMFN.js +21 -0
- package/dist/chunk-WJRJBMFN.js.map +1 -0
- package/dist/chunk-YUPLJP3F.js +33 -0
- package/dist/chunk-YUPLJP3F.js.map +1 -0
- package/dist/chunk-Z7ITPSUF.js +184 -0
- package/dist/chunk-Z7ITPSUF.js.map +1 -0
- package/dist/chunk-ZC76ALSI.js +75 -0
- package/dist/chunk-ZC76ALSI.js.map +1 -0
- package/dist/code-block-core-xkE94Rk5.d.ts +30 -0
- package/dist/components/accordion.d.ts +9 -0
- package/dist/components/accordion.js +98 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert-dialog.d.ts +26 -0
- package/dist/components/alert-dialog.js +341 -0
- package/dist/components/alert-dialog.js.map +1 -0
- package/dist/components/alert.d.ts +13 -0
- package/dist/components/alert.js +76 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/aspect-ratio.d.ts +6 -0
- package/dist/components/aspect-ratio.js +12 -0
- package/dist/components/aspect-ratio.js.map +1 -0
- package/dist/components/avatar.d.ts +13 -0
- package/dist/components/avatar.js +19 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +12 -0
- package/dist/components/badge.js +11 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.d.ts +13 -0
- package/dist/components/breadcrumb.js +102 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button-group.d.ts +16 -0
- package/dist/components/button-group.js +15 -0
- package/dist/components/button-group.js.map +1 -0
- package/dist/components/button.d.ts +14 -0
- package/dist/components/button.js +11 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/calendar.d.ts +14 -0
- package/dist/components/calendar.js +13 -0
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/card.d.ts +13 -0
- package/dist/components/card.js +21 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/carousel.d.ts +32 -0
- package/dist/components/carousel.js +196 -0
- package/dist/components/carousel.js.map +1 -0
- package/dist/components/chart.d.ts +46 -0
- package/dist/components/chart.js +254 -0
- package/dist/components/chart.js.map +1 -0
- package/dist/components/checkbox.d.ts +6 -0
- package/dist/components/checkbox.js +41 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/code-block-core.d.ts +3 -0
- package/dist/components/code-block-core.js +13 -0
- package/dist/components/code-block-core.js.map +1 -0
- package/dist/components/code-block-custom.d.ts +20 -0
- package/dist/components/code-block-custom.js +16 -0
- package/dist/components/code-block-custom.js.map +1 -0
- package/dist/components/code-block-shiki.d.ts +13 -0
- package/dist/components/code-block-shiki.js +15 -0
- package/dist/components/code-block-shiki.js.map +1 -0
- package/dist/components/code-block.d.ts +5 -0
- package/dist/components/code-block.js +14 -0
- package/dist/components/code-block.js.map +1 -0
- package/dist/components/collapsible.d.ts +8 -0
- package/dist/components/collapsible.js +24 -0
- package/dist/components/collapsible.js.map +1 -0
- package/dist/components/collection.d.ts +63 -0
- package/dist/components/collection.js +598 -0
- package/dist/components/collection.js.map +1 -0
- package/dist/components/color-dot.d.ts +19 -0
- package/dist/components/color-dot.js +41 -0
- package/dist/components/color-dot.js.map +1 -0
- package/dist/components/color-picker.d.ts +12 -0
- package/dist/components/color-picker.js +142 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.d.ts +74 -0
- package/dist/components/combobox.js +610 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/command.d.ts +21 -0
- package/dist/components/command.js +31 -0
- package/dist/components/command.js.map +1 -0
- package/dist/components/date-picker.d.ts +43 -0
- package/dist/components/date-picker.js +235 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/dialog.d.ts +25 -0
- package/dist/components/dialog.js +31 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/drawer.d.ts +15 -0
- package/dist/components/drawer.js +124 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +34 -0
- package/dist/components/dropdown-menu.js +248 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/empty.d.ts +15 -0
- package/dist/components/empty.js +104 -0
- package/dist/components/empty.js.map +1 -0
- package/dist/components/field.d.ts +29 -0
- package/dist/components/field.js +214 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/format-bytes.d.ts +12 -0
- package/dist/components/format-bytes.js +30 -0
- package/dist/components/format-bytes.js.map +1 -0
- package/dist/components/format-number.d.ts +12 -0
- package/dist/components/format-number.js +30 -0
- package/dist/components/format-number.js.map +1 -0
- package/dist/components/gauge.d.ts +11 -0
- package/dist/components/gauge.js +82 -0
- package/dist/components/gauge.js.map +1 -0
- package/dist/components/hover-card.d.ts +8 -0
- package/dist/components/hover-card.js +45 -0
- package/dist/components/hover-card.js.map +1 -0
- package/dist/components/input-group.d.ts +24 -0
- package/dist/components/input-group.js +23 -0
- package/dist/components/input-group.js.map +1 -0
- package/dist/components/input-otp.d.ts +20 -0
- package/dist/components/input-otp.js +95 -0
- package/dist/components/input-otp.js.map +1 -0
- package/dist/components/input.d.ts +9 -0
- package/dist/components/input.js +9 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/item.d.ts +27 -0
- package/dist/components/item.js +182 -0
- package/dist/components/item.js.map +1 -0
- package/dist/components/kbd.d.ts +6 -0
- package/dist/components/kbd.js +34 -0
- package/dist/components/kbd.js.map +1 -0
- package/dist/components/label.d.ts +6 -0
- package/dist/components/label.js +9 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/loading-bar.d.ts +8 -0
- package/dist/components/loading-bar.js +127 -0
- package/dist/components/loading-bar.js.map +1 -0
- package/dist/components/loading-dots.d.ts +5 -0
- package/dist/components/loading-dots.js +45 -0
- package/dist/components/loading-dots.js.map +1 -0
- package/dist/components/main-provider.d.ts +7 -0
- package/dist/components/main-provider.js +12 -0
- package/dist/components/main-provider.js.map +1 -0
- package/dist/components/mark.d.ts +11 -0
- package/dist/components/mark.js +44 -0
- package/dist/components/mark.js.map +1 -0
- package/dist/components/pagination.d.ts +21 -0
- package/dist/components/pagination.js +114 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.d.ts +12 -0
- package/dist/components/popover.js +22 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/prev-next-navigation.d.ts +15 -0
- package/dist/components/prev-next-navigation.js +85 -0
- package/dist/components/prev-next-navigation.js.map +1 -0
- package/dist/components/progress.d.ts +6 -0
- package/dist/components/progress.js +38 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio-group.d.ts +7 -0
- package/dist/components/radio-group.js +57 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/relative-time.d.ts +16 -0
- package/dist/components/relative-time.js +75 -0
- package/dist/components/relative-time.js.map +1 -0
- package/dist/components/resizable.d.ts +10 -0
- package/dist/components/resizable.js +45 -0
- package/dist/components/resizable.js.map +1 -0
- package/dist/components/scroll-area.d.ts +7 -0
- package/dist/components/scroll-area.js +11 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/select.d.ts +20 -0
- package/dist/components/select.js +189 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +6 -0
- package/dist/components/separator.js +9 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +16 -0
- package/dist/components/sheet.js +25 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/show-more.d.ts +15 -0
- package/dist/components/show-more.js +79 -0
- package/dist/components/show-more.js.map +1 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.js +8 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.d.ts +6 -0
- package/dist/components/slider.js +65 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/snippet.d.ts +13 -0
- package/dist/components/snippet.js +135 -0
- package/dist/components/snippet.js.map +1 -0
- package/dist/components/sonner.d.ts +6 -0
- package/dist/components/sonner.js +10 -0
- package/dist/components/sonner.js.map +1 -0
- package/dist/components/spinner.d.ts +5 -0
- package/dist/components/spinner.js +8 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stat.d.ts +17 -0
- package/dist/components/stat.js +71 -0
- package/dist/components/stat.js.map +1 -0
- package/dist/components/steps.d.ts +17 -0
- package/dist/components/steps.js +133 -0
- package/dist/components/steps.js.map +1 -0
- package/dist/components/switch.d.ts +8 -0
- package/dist/components/switch.js +44 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +101 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +14 -0
- package/dist/components/tabs.js +88 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +5 -0
- package/dist/components/textarea.js +9 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/theme-provider.d.ts +10 -0
- package/dist/components/theme-provider.js +14 -0
- package/dist/components/theme-provider.js.map +1 -0
- package/dist/components/time-picker.d.ts +17 -0
- package/dist/components/time-picker.js +219 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/timeline.d.ts +17 -0
- package/dist/components/timeline.js +138 -0
- package/dist/components/timeline.js.map +1 -0
- package/dist/components/toggle-group.d.ts +14 -0
- package/dist/components/toggle-group.js +82 -0
- package/dist/components/toggle-group.js.map +1 -0
- package/dist/components/toggle.d.ts +12 -0
- package/dist/components/toggle.js +11 -0
- package/dist/components/toggle.js.map +1 -0
- package/dist/components/tooltip.d.ts +9 -0
- package/dist/components/tooltip.js +15 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/typography.d.ts +17 -0
- package/dist/components/typography.js +91 -0
- package/dist/components/typography.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +7 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-theme.d.ts +3 -0
- package/dist/hooks/use-theme.js +8 -0
- package/dist/hooks/use-theme.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/layouts/center/index.d.ts +18 -0
- package/dist/layouts/center/index.js +73 -0
- package/dist/layouts/center/index.js.map +1 -0
- package/dist/layouts/chat/index.d.ts +42 -0
- package/dist/layouts/chat/index.js +191 -0
- package/dist/layouts/chat/index.js.map +1 -0
- package/dist/layouts/command/index.d.ts +2 -0
- package/dist/layouts/command/index.js +1 -0
- package/dist/layouts/command/index.js.map +1 -0
- package/dist/layouts/panel/index.d.ts +55 -0
- package/dist/layouts/panel/index.js +513 -0
- package/dist/layouts/panel/index.js.map +1 -0
- package/dist/layouts/presentation/index.d.ts +14 -0
- package/dist/layouts/presentation/index.js +100 -0
- package/dist/layouts/presentation/index.js.map +1 -0
- package/dist/layouts/site/index.d.ts +17 -0
- package/dist/layouts/site/index.js +82 -0
- package/dist/layouts/site/index.js.map +1 -0
- package/dist/layouts/window/index.d.ts +223 -0
- package/dist/layouts/window/index.js +127 -0
- package/dist/layouts/window/index.js.map +1 -0
- package/dist/layouts/workbench/index.d.ts +281 -0
- package/dist/layouts/workbench/index.js +2457 -0
- package/dist/layouts/workbench/index.js.map +1 -0
- package/dist/lib/format.d.ts +15 -0
- package/dist/lib/format.js +9 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/theme.d.ts +22 -0
- package/dist/lib/theme.js +25 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +7 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles/fonts.css +1 -0
- package/dist/styles/globals.css +717 -0
- package/dist/styles/tokens.css +693 -0
- package/package.json +137 -0
|
@@ -0,0 +1,1726 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sidedockFocusClass,
|
|
3
|
+
sidedockOutlineStrokeClass,
|
|
4
|
+
sidedockShellClass
|
|
5
|
+
} from "./chunk-BI3KKBIC.js";
|
|
6
|
+
import {
|
|
7
|
+
Skeleton
|
|
8
|
+
} from "./chunk-KJJB2PVC.js";
|
|
9
|
+
import {
|
|
10
|
+
ScrollArea,
|
|
11
|
+
ScrollBar
|
|
12
|
+
} from "./chunk-GJT7TDBS.js";
|
|
13
|
+
import {
|
|
14
|
+
Dialog,
|
|
15
|
+
DialogClose,
|
|
16
|
+
DialogContent,
|
|
17
|
+
DialogDescription,
|
|
18
|
+
DialogHeader,
|
|
19
|
+
DialogTitle
|
|
20
|
+
} from "./chunk-PLZMCJSL.js";
|
|
21
|
+
import {
|
|
22
|
+
Input
|
|
23
|
+
} from "./chunk-YUPLJP3F.js";
|
|
24
|
+
import {
|
|
25
|
+
Separator
|
|
26
|
+
} from "./chunk-6ANDNGHD.js";
|
|
27
|
+
import {
|
|
28
|
+
Tooltip,
|
|
29
|
+
TooltipContent,
|
|
30
|
+
TooltipTrigger
|
|
31
|
+
} from "./chunk-D3SP7GL3.js";
|
|
32
|
+
import {
|
|
33
|
+
Button
|
|
34
|
+
} from "./chunk-TU5CYBB4.js";
|
|
35
|
+
import {
|
|
36
|
+
cn
|
|
37
|
+
} from "./chunk-DN2AEEA2.js";
|
|
38
|
+
|
|
39
|
+
// src/layouts/window/components/WindowRow.tsx
|
|
40
|
+
import * as Slot from "@radix-ui/react-slot";
|
|
41
|
+
import { jsx } from "react/jsx-runtime";
|
|
42
|
+
function WindowGroup({ className, ...props }) {
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
"data-slot": "window-group",
|
|
47
|
+
className: cn("relative mt-4 flex w-full min-w-0 flex-col px-2 py-2 md:px-8", className),
|
|
48
|
+
...props
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function WindowGroupLabel({
|
|
53
|
+
className,
|
|
54
|
+
asChild = false,
|
|
55
|
+
...props
|
|
56
|
+
}) {
|
|
57
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
58
|
+
return /* @__PURE__ */ jsx(
|
|
59
|
+
Comp,
|
|
60
|
+
{
|
|
61
|
+
"data-slot": "window-group-label",
|
|
62
|
+
"data-sidebar": "group-label",
|
|
63
|
+
className: cn(
|
|
64
|
+
"text-text-muted focus-visible:ring-focus-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
65
|
+
className
|
|
66
|
+
),
|
|
67
|
+
...props
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
function WindowGroupContent({ className, ...props }) {
|
|
72
|
+
return /* @__PURE__ */ jsx(
|
|
73
|
+
"div",
|
|
74
|
+
{
|
|
75
|
+
"data-slot": "window-group-content",
|
|
76
|
+
className: cn("relative flex w-full min-w-0 flex-col px-2 py-2", className),
|
|
77
|
+
...props
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
function WindowRow({ className, ...props }) {
|
|
82
|
+
return /* @__PURE__ */ jsx(
|
|
83
|
+
"div",
|
|
84
|
+
{
|
|
85
|
+
"data-slot": "window-row",
|
|
86
|
+
className: cn(
|
|
87
|
+
"relative flex w-full min-w-0 justify-between gap-2 py-3 first:pt-0 last:pb-0",
|
|
88
|
+
className
|
|
89
|
+
),
|
|
90
|
+
...props
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function WindowRowContent({ className, ...props }) {
|
|
95
|
+
return /* @__PURE__ */ jsx(
|
|
96
|
+
"div",
|
|
97
|
+
{
|
|
98
|
+
"data-slot": "window-row-content",
|
|
99
|
+
className: cn("relative flex w-full min-w-0 flex-col", className),
|
|
100
|
+
...props
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
function WindowRowTitle({ className, ...props }) {
|
|
105
|
+
return /* @__PURE__ */ jsx("div", { "data-slot": "window-row-title", className: cn("text text-base", className), ...props });
|
|
106
|
+
}
|
|
107
|
+
function WindowRowDescription({ className, ...props }) {
|
|
108
|
+
return /* @__PURE__ */ jsx(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
"data-slot": "window-row-description",
|
|
112
|
+
className: cn("text-text-muted text-xs", className),
|
|
113
|
+
...props
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function WindowRowActions({ className, ...props }) {
|
|
118
|
+
return /* @__PURE__ */ jsx(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
"data-slot": "window-row-actions",
|
|
122
|
+
className: cn("relative flex shrink-0 items-center gap-1", className),
|
|
123
|
+
...props
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
function WindowRowSeparator({
|
|
128
|
+
className,
|
|
129
|
+
...props
|
|
130
|
+
}) {
|
|
131
|
+
return /* @__PURE__ */ jsx(
|
|
132
|
+
Separator,
|
|
133
|
+
{
|
|
134
|
+
"data-slot": "window-row-separator",
|
|
135
|
+
"data-sidebar": "separator",
|
|
136
|
+
className: cn("bg-window-border w-auto", className),
|
|
137
|
+
...props
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/layouts/window/core/Window.tsx
|
|
143
|
+
import * as React3 from "react";
|
|
144
|
+
import { XIcon } from "lucide-react";
|
|
145
|
+
import { motion } from "motion/react";
|
|
146
|
+
|
|
147
|
+
// src/layouts/window/WindowManager.tsx
|
|
148
|
+
import * as React2 from "react";
|
|
149
|
+
|
|
150
|
+
// src/layouts/window/core/WindowContext.tsx
|
|
151
|
+
import React from "react";
|
|
152
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
153
|
+
var WindowStateContext = React.createContext(null);
|
|
154
|
+
function WindowStateProvider({
|
|
155
|
+
children,
|
|
156
|
+
value
|
|
157
|
+
}) {
|
|
158
|
+
return /* @__PURE__ */ jsx2(WindowStateContext.Provider, { value, children });
|
|
159
|
+
}
|
|
160
|
+
function useWindow() {
|
|
161
|
+
const context = React.useContext(WindowStateContext);
|
|
162
|
+
if (!context) {
|
|
163
|
+
throw new Error("useWindow must be used within a WindowProvider.");
|
|
164
|
+
}
|
|
165
|
+
return context;
|
|
166
|
+
}
|
|
167
|
+
function resolveOpenState(currentOpen, nextOpen) {
|
|
168
|
+
return typeof nextOpen === "function" ? nextOpen(currentOpen) : nextOpen;
|
|
169
|
+
}
|
|
170
|
+
function WindowProvider({
|
|
171
|
+
children,
|
|
172
|
+
defaultOpen = false,
|
|
173
|
+
onCloseRequest,
|
|
174
|
+
onOpenChange,
|
|
175
|
+
open
|
|
176
|
+
}) {
|
|
177
|
+
const [blockedInteractionCount, setBlockedInteractionCount] = React.useState(0);
|
|
178
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
|
|
179
|
+
const isControlled = open !== void 0;
|
|
180
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
181
|
+
const isOpenRef = React.useRef(isOpen);
|
|
182
|
+
const closeRequestVersionRef = React.useRef(0);
|
|
183
|
+
React.useEffect(() => {
|
|
184
|
+
isOpenRef.current = isOpen;
|
|
185
|
+
}, [isOpen]);
|
|
186
|
+
const forceSetOpen = React.useCallback(
|
|
187
|
+
(nextOpen) => {
|
|
188
|
+
const resolvedOpen = resolveOpenState(isOpen, nextOpen);
|
|
189
|
+
if (!isControlled) {
|
|
190
|
+
setUncontrolledOpen(resolvedOpen);
|
|
191
|
+
}
|
|
192
|
+
onOpenChange?.(resolvedOpen);
|
|
193
|
+
},
|
|
194
|
+
[isControlled, isOpen, onOpenChange]
|
|
195
|
+
);
|
|
196
|
+
const openWindow = React.useCallback(() => {
|
|
197
|
+
closeRequestVersionRef.current += 1;
|
|
198
|
+
forceSetOpen(true);
|
|
199
|
+
}, [forceSetOpen]);
|
|
200
|
+
const forceCloseWindow = React.useCallback(() => {
|
|
201
|
+
forceSetOpen(false);
|
|
202
|
+
}, [forceSetOpen]);
|
|
203
|
+
const indicateBlockedInteraction = React.useCallback(() => {
|
|
204
|
+
setBlockedInteractionCount((currentCount) => currentCount + 1);
|
|
205
|
+
}, []);
|
|
206
|
+
const closeWindow = React.useCallback(
|
|
207
|
+
async (reason) => {
|
|
208
|
+
if (!isOpenRef.current) {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
const closeRequestVersion = closeRequestVersionRef.current + 1;
|
|
212
|
+
closeRequestVersionRef.current = closeRequestVersion;
|
|
213
|
+
const closeAllowed = await onCloseRequest?.(reason) ?? true;
|
|
214
|
+
if (!closeAllowed) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
if (closeRequestVersion !== closeRequestVersionRef.current) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
forceCloseWindow();
|
|
221
|
+
return true;
|
|
222
|
+
},
|
|
223
|
+
[forceCloseWindow, onCloseRequest]
|
|
224
|
+
);
|
|
225
|
+
const toggleWindow = React.useCallback(() => {
|
|
226
|
+
if (isOpenRef.current) {
|
|
227
|
+
void closeWindow("programmatic").catch((error) => {
|
|
228
|
+
console.error("Failed to toggle window closed.", error);
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
openWindow();
|
|
233
|
+
}, [closeWindow, openWindow]);
|
|
234
|
+
const contextValue = React.useMemo(
|
|
235
|
+
() => ({
|
|
236
|
+
blockedInteractionCount,
|
|
237
|
+
close: closeWindow,
|
|
238
|
+
forceClose: forceCloseWindow,
|
|
239
|
+
indicateBlockedInteraction,
|
|
240
|
+
isOpen,
|
|
241
|
+
open: openWindow,
|
|
242
|
+
toggle: toggleWindow
|
|
243
|
+
}),
|
|
244
|
+
[
|
|
245
|
+
blockedInteractionCount,
|
|
246
|
+
closeWindow,
|
|
247
|
+
forceCloseWindow,
|
|
248
|
+
indicateBlockedInteraction,
|
|
249
|
+
isOpen,
|
|
250
|
+
openWindow,
|
|
251
|
+
toggleWindow
|
|
252
|
+
]
|
|
253
|
+
);
|
|
254
|
+
return /* @__PURE__ */ jsx2(WindowStateProvider, { value: contextValue, children });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/layouts/window/WindowManager.tsx
|
|
258
|
+
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
259
|
+
var WindowManagerContext = React2.createContext(null);
|
|
260
|
+
function defineWindow(definition) {
|
|
261
|
+
return definition;
|
|
262
|
+
}
|
|
263
|
+
function WindowManagerProvider({
|
|
264
|
+
children,
|
|
265
|
+
defaultActiveWindowId = null,
|
|
266
|
+
windows
|
|
267
|
+
}) {
|
|
268
|
+
const windowMap = React2.useMemo(() => {
|
|
269
|
+
const nextWindowMap = /* @__PURE__ */ new Map();
|
|
270
|
+
windows.forEach((windowDefinition) => {
|
|
271
|
+
if (nextWindowMap.has(windowDefinition.id)) {
|
|
272
|
+
throw new Error(`Duplicate Window id "${windowDefinition.id}" is not allowed.`);
|
|
273
|
+
}
|
|
274
|
+
nextWindowMap.set(windowDefinition.id, windowDefinition);
|
|
275
|
+
});
|
|
276
|
+
return nextWindowMap;
|
|
277
|
+
}, [windows]);
|
|
278
|
+
if (defaultActiveWindowId !== null && !windowMap.has(defaultActiveWindowId)) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
`WindowManagerProvider could not find a registered window for "${defaultActiveWindowId}".`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const [activeWindowId, setActiveWindowId] = React2.useState(defaultActiveWindowId);
|
|
284
|
+
const activeWindowIdRef = React2.useRef(activeWindowId);
|
|
285
|
+
const windowControllersRef = React2.useRef(/* @__PURE__ */ new Map());
|
|
286
|
+
React2.useEffect(() => {
|
|
287
|
+
activeWindowIdRef.current = activeWindowId;
|
|
288
|
+
}, [activeWindowId]);
|
|
289
|
+
const getWindow = React2.useCallback((id) => windowMap.get(id), [windowMap]);
|
|
290
|
+
const isOpen = React2.useCallback((id) => activeWindowId === id, [activeWindowId]);
|
|
291
|
+
const registerWindowController = React2.useCallback(
|
|
292
|
+
(id, controller) => {
|
|
293
|
+
windowControllersRef.current.set(id, controller);
|
|
294
|
+
return () => {
|
|
295
|
+
const registeredController = windowControllersRef.current.get(id);
|
|
296
|
+
if (registeredController === controller) {
|
|
297
|
+
windowControllersRef.current.delete(id);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
},
|
|
301
|
+
[]
|
|
302
|
+
);
|
|
303
|
+
const closeActiveWindow = React2.useCallback(async () => {
|
|
304
|
+
const currentActiveWindowId = activeWindowIdRef.current;
|
|
305
|
+
if (!currentActiveWindowId) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
const activeWindowController = windowControllersRef.current.get(currentActiveWindowId);
|
|
309
|
+
if (!activeWindowController) {
|
|
310
|
+
throw new Error(
|
|
311
|
+
`WindowManagerProvider could not find a controller for "${currentActiveWindowId}".`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
return activeWindowController.close("programmatic");
|
|
315
|
+
}, []);
|
|
316
|
+
const openWindow = React2.useCallback(
|
|
317
|
+
async (id) => {
|
|
318
|
+
if (!windowMap.has(id)) {
|
|
319
|
+
throw new Error(`WindowManagerProvider could not find a registered window for "${id}".`);
|
|
320
|
+
}
|
|
321
|
+
const currentActiveWindowId = activeWindowIdRef.current;
|
|
322
|
+
if (currentActiveWindowId === id) {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
if (currentActiveWindowId) {
|
|
326
|
+
const activeWindowController = windowControllersRef.current.get(currentActiveWindowId);
|
|
327
|
+
if (!activeWindowController) {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`WindowManagerProvider could not find a controller for "${currentActiveWindowId}".`
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
const closeSucceeded = await activeWindowController.close("window-switch");
|
|
333
|
+
if (!closeSucceeded) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
setActiveWindowId(id);
|
|
338
|
+
return true;
|
|
339
|
+
},
|
|
340
|
+
[windowMap]
|
|
341
|
+
);
|
|
342
|
+
const setWindowOpenState = React2.useCallback((id, open) => {
|
|
343
|
+
setActiveWindowId((currentActiveWindowId) => {
|
|
344
|
+
if (open) {
|
|
345
|
+
return id;
|
|
346
|
+
}
|
|
347
|
+
if (currentActiveWindowId === id) {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
return currentActiveWindowId;
|
|
351
|
+
});
|
|
352
|
+
}, []);
|
|
353
|
+
const contextValue = React2.useMemo(
|
|
354
|
+
() => ({
|
|
355
|
+
activeWindowId,
|
|
356
|
+
closeActiveWindow,
|
|
357
|
+
getWindow,
|
|
358
|
+
isOpen,
|
|
359
|
+
openWindow,
|
|
360
|
+
registerWindowController,
|
|
361
|
+
setWindowOpenState,
|
|
362
|
+
windows
|
|
363
|
+
}),
|
|
364
|
+
[
|
|
365
|
+
activeWindowId,
|
|
366
|
+
closeActiveWindow,
|
|
367
|
+
getWindow,
|
|
368
|
+
isOpen,
|
|
369
|
+
openWindow,
|
|
370
|
+
registerWindowController,
|
|
371
|
+
setWindowOpenState,
|
|
372
|
+
windows
|
|
373
|
+
]
|
|
374
|
+
);
|
|
375
|
+
return /* @__PURE__ */ jsx3(WindowManagerContext.Provider, { value: contextValue, children });
|
|
376
|
+
}
|
|
377
|
+
function useWindowManager() {
|
|
378
|
+
const context = React2.useContext(WindowManagerContext);
|
|
379
|
+
if (!context) {
|
|
380
|
+
throw new Error("useWindowManager must be used within a WindowManagerProvider.");
|
|
381
|
+
}
|
|
382
|
+
return context;
|
|
383
|
+
}
|
|
384
|
+
function ManagedWindowControllerBridge({ id }) {
|
|
385
|
+
const { close } = useWindow();
|
|
386
|
+
const { registerWindowController } = useWindowManager();
|
|
387
|
+
React2.useEffect(
|
|
388
|
+
() => registerWindowController(id, { close }),
|
|
389
|
+
[close, id, registerWindowController]
|
|
390
|
+
);
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
function ManagedWindowInstance({
|
|
394
|
+
definition,
|
|
395
|
+
isOpen
|
|
396
|
+
}) {
|
|
397
|
+
const { setWindowOpenState } = useWindowManager();
|
|
398
|
+
return /* @__PURE__ */ jsxs(
|
|
399
|
+
WindowProvider,
|
|
400
|
+
{
|
|
401
|
+
open: isOpen,
|
|
402
|
+
onCloseRequest: definition.onCloseRequest,
|
|
403
|
+
onOpenChange: (nextOpen) => {
|
|
404
|
+
setWindowOpenState(definition.id, nextOpen);
|
|
405
|
+
},
|
|
406
|
+
children: [
|
|
407
|
+
/* @__PURE__ */ jsx3(ManagedWindowControllerBridge, { id: definition.id }),
|
|
408
|
+
definition.render()
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
function WindowHost() {
|
|
414
|
+
const { activeWindowId, windows } = useWindowManager();
|
|
415
|
+
return /* @__PURE__ */ jsx3(Fragment, { children: windows.map((windowDefinition) => /* @__PURE__ */ jsx3(
|
|
416
|
+
ManagedWindowInstance,
|
|
417
|
+
{
|
|
418
|
+
definition: windowDefinition,
|
|
419
|
+
isOpen: activeWindowId === windowDefinition.id
|
|
420
|
+
},
|
|
421
|
+
windowDefinition.id
|
|
422
|
+
)) });
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/layouts/window/core/Window.tsx
|
|
426
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
427
|
+
var MotionDialogContent = motion.create(DialogContent);
|
|
428
|
+
var WindowSizeContext = React3.createContext(null);
|
|
429
|
+
var DEFAULT_WINDOW_SIZE_CLASS = "h-[min(90vh,48rem)] w-[min(1120px,calc(100%-1rem))] max-w-280 sm:max-w-280";
|
|
430
|
+
function getWindowSizeClass(size) {
|
|
431
|
+
if (size === void 0 || size === "default") {
|
|
432
|
+
return DEFAULT_WINDOW_SIZE_CLASS;
|
|
433
|
+
}
|
|
434
|
+
return "max-w-[calc(100%-1rem)] sm:max-w-[calc(100%-1rem)]";
|
|
435
|
+
}
|
|
436
|
+
function getWindowSizeStyle(size) {
|
|
437
|
+
if (size === void 0 || size === "default") {
|
|
438
|
+
return void 0;
|
|
439
|
+
}
|
|
440
|
+
if (size === "content") {
|
|
441
|
+
return {
|
|
442
|
+
height: "fit-content",
|
|
443
|
+
maxHeight: "min(90vh, 48rem)",
|
|
444
|
+
maxWidth: "min(1120px, calc(100% - 1rem))",
|
|
445
|
+
width: "fit-content"
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
maxHeight: "min(90vh, 48rem)",
|
|
450
|
+
maxWidth: "min(1120px, calc(100% - 1rem))",
|
|
451
|
+
...size
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function WindowCloseButton({
|
|
455
|
+
className,
|
|
456
|
+
onClick,
|
|
457
|
+
type = "button",
|
|
458
|
+
...props
|
|
459
|
+
}) {
|
|
460
|
+
return /* @__PURE__ */ jsx4(DialogClose, { asChild: true, children: /* @__PURE__ */ jsxs2(
|
|
461
|
+
Button,
|
|
462
|
+
{
|
|
463
|
+
"data-slot": "window-close-button",
|
|
464
|
+
variant: "ghost",
|
|
465
|
+
size: "icon-sm",
|
|
466
|
+
type,
|
|
467
|
+
className: cn("absolute top-2 right-2 z-10", className),
|
|
468
|
+
onClick,
|
|
469
|
+
...props,
|
|
470
|
+
children: [
|
|
471
|
+
/* @__PURE__ */ jsx4(XIcon, {}),
|
|
472
|
+
/* @__PURE__ */ jsx4("span", { className: "sr-only", children: "Close" })
|
|
473
|
+
]
|
|
474
|
+
}
|
|
475
|
+
) });
|
|
476
|
+
}
|
|
477
|
+
function WindowLayout({
|
|
478
|
+
children,
|
|
479
|
+
className,
|
|
480
|
+
forceMount: forceMountProp,
|
|
481
|
+
showCloseButton = true,
|
|
482
|
+
size
|
|
483
|
+
}) {
|
|
484
|
+
const windowManager = React3.useContext(WindowManagerContext);
|
|
485
|
+
const { blockedInteractionCount, close, forceClose, isOpen, open } = useWindow();
|
|
486
|
+
const [sizeRequest, setSizeRequest] = React3.useState(null);
|
|
487
|
+
const forceMount = forceMountProp ?? windowManager !== null;
|
|
488
|
+
const resolvedSize = sizeRequest?.size ?? size;
|
|
489
|
+
const sizeContextValue = React3.useMemo(
|
|
490
|
+
() => ({
|
|
491
|
+
requestSize: (token, nextSize) => {
|
|
492
|
+
setSizeRequest((currentRequest) => {
|
|
493
|
+
if (nextSize === void 0) {
|
|
494
|
+
return currentRequest?.token === token ? null : currentRequest;
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
size: nextSize,
|
|
498
|
+
token
|
|
499
|
+
};
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}),
|
|
503
|
+
[]
|
|
504
|
+
);
|
|
505
|
+
const handleOpenChange = React3.useCallback(
|
|
506
|
+
(nextOpen) => {
|
|
507
|
+
if (nextOpen) {
|
|
508
|
+
open();
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
forceClose();
|
|
512
|
+
},
|
|
513
|
+
[forceClose, open]
|
|
514
|
+
);
|
|
515
|
+
const windowSizeStyle = getWindowSizeStyle(resolvedSize);
|
|
516
|
+
return /* @__PURE__ */ jsx4(Dialog, { open: isOpen, onCloseRequest: close, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs2(
|
|
517
|
+
MotionDialogContent,
|
|
518
|
+
{
|
|
519
|
+
layout: "size",
|
|
520
|
+
blockedInteractionCount,
|
|
521
|
+
...forceMount === true ? { forceMount: true } : {},
|
|
522
|
+
showCloseButton: false,
|
|
523
|
+
...windowSizeStyle !== void 0 ? { style: windowSizeStyle } : {},
|
|
524
|
+
transition: {
|
|
525
|
+
layout: {
|
|
526
|
+
duration: 0.18,
|
|
527
|
+
ease: [0, 0.5, 0, 1]
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
className: cn(
|
|
531
|
+
"border-window-border bg-window-background text-window-text shadow-window overflow-hidden rounded-[var(--radius-window)] p-0",
|
|
532
|
+
getWindowSizeClass(resolvedSize),
|
|
533
|
+
"flex gap-0",
|
|
534
|
+
className
|
|
535
|
+
),
|
|
536
|
+
children: [
|
|
537
|
+
/* @__PURE__ */ jsxs2(DialogHeader, { className: "sr-only", children: [
|
|
538
|
+
/* @__PURE__ */ jsx4(DialogTitle, { children: "Window Layout" }),
|
|
539
|
+
/* @__PURE__ */ jsx4(DialogDescription, { children: "Displays a modal window with a navigation sidebar and context content." })
|
|
540
|
+
] }),
|
|
541
|
+
/* @__PURE__ */ jsx4(WindowSizeContext.Provider, { value: sizeContextValue, children: /* @__PURE__ */ jsxs2(
|
|
542
|
+
"div",
|
|
543
|
+
{
|
|
544
|
+
"data-slot": "window-layout",
|
|
545
|
+
className: "relative flex min-h-0 min-w-0 flex-auto overflow-hidden",
|
|
546
|
+
children: [
|
|
547
|
+
showCloseButton && /* @__PURE__ */ jsx4(WindowCloseButton, {}),
|
|
548
|
+
/* @__PURE__ */ jsx4("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-px bg-white/50 dark:bg-white/10" }),
|
|
549
|
+
/* @__PURE__ */ jsx4("div", { className: "flex min-h-0 min-w-0 flex-auto flex-col md:flex-row", children })
|
|
550
|
+
]
|
|
551
|
+
}
|
|
552
|
+
) })
|
|
553
|
+
]
|
|
554
|
+
}
|
|
555
|
+
) });
|
|
556
|
+
}
|
|
557
|
+
function useWindowSizeRequest(size) {
|
|
558
|
+
const context = React3.useContext(WindowSizeContext);
|
|
559
|
+
React3.useLayoutEffect(() => {
|
|
560
|
+
if (!context) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const token = /* @__PURE__ */ Symbol("window-size-request");
|
|
564
|
+
context.requestSize(token, size);
|
|
565
|
+
return () => {
|
|
566
|
+
context.requestSize(token, void 0);
|
|
567
|
+
};
|
|
568
|
+
}, [context, size]);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// src/layouts/window/core/WindowContent.tsx
|
|
572
|
+
import "react";
|
|
573
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
574
|
+
function WindowContent({
|
|
575
|
+
children,
|
|
576
|
+
className,
|
|
577
|
+
...props
|
|
578
|
+
}) {
|
|
579
|
+
return /* @__PURE__ */ jsxs3(
|
|
580
|
+
ScrollArea,
|
|
581
|
+
{
|
|
582
|
+
"data-slot": "window-layout-content",
|
|
583
|
+
className: cn(
|
|
584
|
+
"bg-window-background relative flex min-h-0 w-full min-w-0 flex-1 flex-col overflow-auto",
|
|
585
|
+
className
|
|
586
|
+
),
|
|
587
|
+
...props,
|
|
588
|
+
children: [
|
|
589
|
+
children,
|
|
590
|
+
/* @__PURE__ */ jsx5(ScrollBar, {})
|
|
591
|
+
]
|
|
592
|
+
}
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/layouts/window/core/WindowSidebar.tsx
|
|
597
|
+
import React5 from "react";
|
|
598
|
+
import * as Slot2 from "@radix-ui/react-slot";
|
|
599
|
+
import { cva } from "class-variance-authority";
|
|
600
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
601
|
+
function WindowSidebar({ className, ...props }) {
|
|
602
|
+
return /* @__PURE__ */ jsx6(
|
|
603
|
+
"aside",
|
|
604
|
+
{
|
|
605
|
+
"data-slot": "window-layout-sidebar",
|
|
606
|
+
className: cn(
|
|
607
|
+
"border-sidedock-border relative flex max-h-[min(20rem,40vh)] min-h-48 w-full shrink-0 flex-col overflow-auto border-b md:border-r md:border-b-0",
|
|
608
|
+
sidedockShellClass,
|
|
609
|
+
"md:h-full md:max-h-none md:w-64",
|
|
610
|
+
className
|
|
611
|
+
),
|
|
612
|
+
...props
|
|
613
|
+
}
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
function WindowSidebarInput({ className, ...props }) {
|
|
617
|
+
return /* @__PURE__ */ jsx6(
|
|
618
|
+
Input,
|
|
619
|
+
{
|
|
620
|
+
"data-slot": "sidebar-input",
|
|
621
|
+
"data-sidebar": "input",
|
|
622
|
+
className: cn("h-8 w-full shadow-none", className),
|
|
623
|
+
...props
|
|
624
|
+
}
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
function WindowSidebarHeader({ className, ...props }) {
|
|
628
|
+
return /* @__PURE__ */ jsx6(
|
|
629
|
+
"div",
|
|
630
|
+
{
|
|
631
|
+
"data-slot": "sidebar-header",
|
|
632
|
+
"data-sidebar": "header",
|
|
633
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
634
|
+
...props
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
function WindowSidebarFooter({ className, ...props }) {
|
|
639
|
+
return /* @__PURE__ */ jsx6(
|
|
640
|
+
"div",
|
|
641
|
+
{
|
|
642
|
+
"data-slot": "sidebar-footer",
|
|
643
|
+
"data-sidebar": "footer",
|
|
644
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
645
|
+
...props
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
function WindowSidebarContent({
|
|
650
|
+
children,
|
|
651
|
+
className,
|
|
652
|
+
...props
|
|
653
|
+
}) {
|
|
654
|
+
return /* @__PURE__ */ jsxs4(
|
|
655
|
+
ScrollArea,
|
|
656
|
+
{
|
|
657
|
+
"data-slot": "sidebar-content",
|
|
658
|
+
"data-sidebar": "content",
|
|
659
|
+
className: cn(
|
|
660
|
+
"no-scrollbar flex min-h-0 flex-1 flex-col gap-0 group-data-[collapsible=icon]:overflow-hidden",
|
|
661
|
+
className
|
|
662
|
+
),
|
|
663
|
+
...props,
|
|
664
|
+
children: [
|
|
665
|
+
children,
|
|
666
|
+
/* @__PURE__ */ jsx6(ScrollBar, {})
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
function WindowSidebarGroup({ className, ...props }) {
|
|
672
|
+
return /* @__PURE__ */ jsx6(
|
|
673
|
+
"div",
|
|
674
|
+
{
|
|
675
|
+
"data-slot": "sidebar-group",
|
|
676
|
+
"data-sidebar": "group",
|
|
677
|
+
className: cn("relative flex w-full min-w-0 flex-col p-2", className),
|
|
678
|
+
...props
|
|
679
|
+
}
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
function WindowSidebarGroupLabel({
|
|
683
|
+
className,
|
|
684
|
+
asChild = false,
|
|
685
|
+
...props
|
|
686
|
+
}) {
|
|
687
|
+
const Comp = asChild ? Slot2.Root : "div";
|
|
688
|
+
return /* @__PURE__ */ jsx6(
|
|
689
|
+
Comp,
|
|
690
|
+
{
|
|
691
|
+
"data-slot": "sidebar-group-label",
|
|
692
|
+
"data-sidebar": "group-label",
|
|
693
|
+
className: cn(
|
|
694
|
+
"text-sidedock-label flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
695
|
+
sidedockFocusClass,
|
|
696
|
+
className
|
|
697
|
+
),
|
|
698
|
+
...props
|
|
699
|
+
}
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
function WindowSidebarGroupAction({
|
|
703
|
+
className,
|
|
704
|
+
asChild = false,
|
|
705
|
+
...props
|
|
706
|
+
}) {
|
|
707
|
+
const Comp = asChild ? Slot2.Root : "button";
|
|
708
|
+
return /* @__PURE__ */ jsx6(
|
|
709
|
+
Comp,
|
|
710
|
+
{
|
|
711
|
+
"data-slot": "sidebar-group-action",
|
|
712
|
+
"data-sidebar": "group-action",
|
|
713
|
+
className: cn(
|
|
714
|
+
"text-sidedock-text hover:bg-sidedock-hover-background hover:text-sidedock-text-hover absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
|
715
|
+
sidedockFocusClass,
|
|
716
|
+
className
|
|
717
|
+
),
|
|
718
|
+
...props
|
|
719
|
+
}
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
function WindowSidebarGroupContent({ className, ...props }) {
|
|
723
|
+
return /* @__PURE__ */ jsx6(
|
|
724
|
+
"div",
|
|
725
|
+
{
|
|
726
|
+
"data-slot": "sidebar-group-content",
|
|
727
|
+
"data-sidebar": "group-content",
|
|
728
|
+
className: cn("w-full text-sm", className),
|
|
729
|
+
...props
|
|
730
|
+
}
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
function WindowSidebarMenu({ className, ...props }) {
|
|
734
|
+
return /* @__PURE__ */ jsx6(
|
|
735
|
+
"ul",
|
|
736
|
+
{
|
|
737
|
+
"data-slot": "sidebar-menu",
|
|
738
|
+
"data-sidebar": "menu",
|
|
739
|
+
className: cn("flex w-full min-w-0 flex-col gap-0.5", className),
|
|
740
|
+
...props
|
|
741
|
+
}
|
|
742
|
+
);
|
|
743
|
+
}
|
|
744
|
+
function WindowSidebarMenuItem({ className, ...props }) {
|
|
745
|
+
return /* @__PURE__ */ jsx6(
|
|
746
|
+
"li",
|
|
747
|
+
{
|
|
748
|
+
"data-slot": "sidebar-menu-item",
|
|
749
|
+
"data-sidebar": "menu-item",
|
|
750
|
+
className: cn("group/menu-item relative", className),
|
|
751
|
+
...props
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
var sidebarMenuButtonVariants = cva(
|
|
756
|
+
cn(
|
|
757
|
+
"cursor-pointer peer/menu-button group/menu-button text-sidedock-text flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidedock-hover-background hover:text-sidedock-text-hover active:bg-sidedock-active-background active:text-sidedock-text-active disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidedock-hover-background data-open:hover:text-sidedock-text-hover data-active:bg-sidedock-active-background data-active:text-sidedock-text-active data-active:font-medium [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
|
|
758
|
+
sidedockFocusClass
|
|
759
|
+
),
|
|
760
|
+
{
|
|
761
|
+
variants: {
|
|
762
|
+
variant: {
|
|
763
|
+
default: "",
|
|
764
|
+
outline: cn("bg-background-primary text-text-normal", sidedockOutlineStrokeClass)
|
|
765
|
+
},
|
|
766
|
+
size: {
|
|
767
|
+
default: "h-7 text-sm",
|
|
768
|
+
sm: "h-6 text-xs",
|
|
769
|
+
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
defaultVariants: {
|
|
773
|
+
variant: "default",
|
|
774
|
+
size: "default"
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
);
|
|
778
|
+
function WindowSidebarMenuButton({
|
|
779
|
+
asChild = false,
|
|
780
|
+
isActive = false,
|
|
781
|
+
variant = "default",
|
|
782
|
+
size = "default",
|
|
783
|
+
tooltip,
|
|
784
|
+
leadingVisual,
|
|
785
|
+
trailingVisual,
|
|
786
|
+
trailingVisualVisibility = "always",
|
|
787
|
+
className,
|
|
788
|
+
children,
|
|
789
|
+
...props
|
|
790
|
+
}) {
|
|
791
|
+
const Comp = asChild ? Slot2.Root : "button";
|
|
792
|
+
const { isOpen } = useWindow();
|
|
793
|
+
const button = /* @__PURE__ */ jsxs4(
|
|
794
|
+
Comp,
|
|
795
|
+
{
|
|
796
|
+
"data-slot": "sidebar-menu-button",
|
|
797
|
+
"data-sidebar": "menu-button",
|
|
798
|
+
"data-size": size,
|
|
799
|
+
"data-active": isActive,
|
|
800
|
+
className: cn(sidebarMenuButtonVariants({ variant, size }), className),
|
|
801
|
+
...props,
|
|
802
|
+
children: [
|
|
803
|
+
leadingVisual ? /* @__PURE__ */ jsx6(
|
|
804
|
+
"span",
|
|
805
|
+
{
|
|
806
|
+
"data-slot": "sidebar-menu-button-leading-visual",
|
|
807
|
+
className: "flex shrink-0 items-center justify-center",
|
|
808
|
+
children: leadingVisual
|
|
809
|
+
}
|
|
810
|
+
) : null,
|
|
811
|
+
/* @__PURE__ */ jsx6(Slot2.Slottable, { children: /* @__PURE__ */ jsx6("span", { "data-slot": "sidebar-menu-button-label", className: "flex min-w-0 flex-1 truncate", children }) }),
|
|
812
|
+
trailingVisual ? /* @__PURE__ */ jsx6(
|
|
813
|
+
"span",
|
|
814
|
+
{
|
|
815
|
+
"data-slot": "sidebar-menu-button-trailing-visual",
|
|
816
|
+
className: cn(
|
|
817
|
+
"ml-auto flex shrink-0 items-center justify-center",
|
|
818
|
+
trailingVisualVisibility === "hover" && "invisible opacity-0 group-hover/menu-button:visible group-hover/menu-button:opacity-100 group-focus-visible/menu-button:visible group-focus-visible/menu-button:opacity-100"
|
|
819
|
+
),
|
|
820
|
+
children: trailingVisual
|
|
821
|
+
}
|
|
822
|
+
) : null
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
);
|
|
826
|
+
if (!tooltip) {
|
|
827
|
+
return button;
|
|
828
|
+
}
|
|
829
|
+
if (typeof tooltip === "string") {
|
|
830
|
+
tooltip = {
|
|
831
|
+
children: tooltip
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
return /* @__PURE__ */ jsxs4(Tooltip, { children: [
|
|
835
|
+
/* @__PURE__ */ jsx6(TooltipTrigger, { asChild: true, children: button }),
|
|
836
|
+
/* @__PURE__ */ jsx6(TooltipContent, { side: "right", align: "center", hidden: !isOpen, ...tooltip })
|
|
837
|
+
] });
|
|
838
|
+
}
|
|
839
|
+
function WindowSidebarMenuAction({
|
|
840
|
+
className,
|
|
841
|
+
asChild = false,
|
|
842
|
+
showOnHover = false,
|
|
843
|
+
...props
|
|
844
|
+
}) {
|
|
845
|
+
const Comp = asChild ? Slot2.Root : "button";
|
|
846
|
+
return /* @__PURE__ */ jsx6(
|
|
847
|
+
Comp,
|
|
848
|
+
{
|
|
849
|
+
"data-slot": "sidebar-menu-action",
|
|
850
|
+
"data-sidebar": "menu-action",
|
|
851
|
+
className: cn(
|
|
852
|
+
"text-sidedock-text peer-hover/menu-button:text-sidedock-text-hover hover:bg-sidedock-hover-background hover:text-sidedock-text-hover absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
|
853
|
+
sidedockFocusClass,
|
|
854
|
+
showOnHover && "peer-data-active/menu-button:text-sidedock-text-active group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 aria-expanded:opacity-100 md:opacity-0",
|
|
855
|
+
className
|
|
856
|
+
),
|
|
857
|
+
...props
|
|
858
|
+
}
|
|
859
|
+
);
|
|
860
|
+
}
|
|
861
|
+
function WindowSidebarMenuBadge({ className, ...props }) {
|
|
862
|
+
return /* @__PURE__ */ jsx6(
|
|
863
|
+
"div",
|
|
864
|
+
{
|
|
865
|
+
"data-slot": "sidebar-menu-badge",
|
|
866
|
+
"data-sidebar": "menu-badge",
|
|
867
|
+
className: cn(
|
|
868
|
+
"text-sidedock-text peer-hover/menu-button:text-sidedock-text-hover peer-data-active/menu-button:text-sidedock-text-active pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none group-data-[collapsible=icon]:hidden peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1",
|
|
869
|
+
className
|
|
870
|
+
),
|
|
871
|
+
...props
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
function WindowSidebarMenuSkeleton({
|
|
876
|
+
className,
|
|
877
|
+
showIcon = false,
|
|
878
|
+
...props
|
|
879
|
+
}) {
|
|
880
|
+
const [width] = React5.useState(() => {
|
|
881
|
+
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
882
|
+
});
|
|
883
|
+
const skeletonStyle = {
|
|
884
|
+
"--skeleton-width": width
|
|
885
|
+
};
|
|
886
|
+
return /* @__PURE__ */ jsxs4(
|
|
887
|
+
"div",
|
|
888
|
+
{
|
|
889
|
+
"data-slot": "sidebar-menu-skeleton",
|
|
890
|
+
"data-sidebar": "menu-skeleton",
|
|
891
|
+
className: cn("flex h-8 items-center gap-2 rounded-md px-2", className),
|
|
892
|
+
...props,
|
|
893
|
+
children: [
|
|
894
|
+
showIcon && /* @__PURE__ */ jsx6(Skeleton, { className: "size-4 rounded-md", "data-sidebar": "menu-skeleton-icon" }),
|
|
895
|
+
/* @__PURE__ */ jsx6(
|
|
896
|
+
Skeleton,
|
|
897
|
+
{
|
|
898
|
+
className: "h-4 max-w-(--skeleton-width) flex-1",
|
|
899
|
+
"data-sidebar": "menu-skeleton-text",
|
|
900
|
+
style: skeletonStyle
|
|
901
|
+
}
|
|
902
|
+
)
|
|
903
|
+
]
|
|
904
|
+
}
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// src/layouts/window/WindowFlow.tsx
|
|
909
|
+
import * as React7 from "react";
|
|
910
|
+
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
|
|
911
|
+
import { AnimatePresence, motion as motion2 } from "motion/react";
|
|
912
|
+
|
|
913
|
+
// src/layouts/window/WindowFlowContext.tsx
|
|
914
|
+
import * as React6 from "react";
|
|
915
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
916
|
+
var WindowFlowContext = React6.createContext(null);
|
|
917
|
+
function defineWindowFlowStep(definition) {
|
|
918
|
+
return definition;
|
|
919
|
+
}
|
|
920
|
+
function WindowFlowProvider({
|
|
921
|
+
children,
|
|
922
|
+
defaultStep,
|
|
923
|
+
onStepChangeRequest,
|
|
924
|
+
onStepChange,
|
|
925
|
+
step,
|
|
926
|
+
steps
|
|
927
|
+
}) {
|
|
928
|
+
const windowContext = React6.useContext(WindowStateContext);
|
|
929
|
+
const stepMap = React6.useMemo(() => {
|
|
930
|
+
const nextStepMap = /* @__PURE__ */ new Map();
|
|
931
|
+
steps.forEach((stepDefinition) => {
|
|
932
|
+
if (nextStepMap.has(stepDefinition.id)) {
|
|
933
|
+
throw new Error(`Duplicate WindowFlow step id "${stepDefinition.id}" is not allowed.`);
|
|
934
|
+
}
|
|
935
|
+
nextStepMap.set(stepDefinition.id, stepDefinition);
|
|
936
|
+
});
|
|
937
|
+
return nextStepMap;
|
|
938
|
+
}, [steps]);
|
|
939
|
+
const initialStep = step ?? defaultStep;
|
|
940
|
+
if (initialStep === void 0) {
|
|
941
|
+
throw new Error("WindowFlowProvider requires a step or defaultStep.");
|
|
942
|
+
}
|
|
943
|
+
if (!stepMap.has(initialStep)) {
|
|
944
|
+
throw new Error(`WindowFlowProvider could not find a registered step for "${initialStep}".`);
|
|
945
|
+
}
|
|
946
|
+
const [uncontrolledStep, setUncontrolledStep] = React6.useState(initialStep);
|
|
947
|
+
const [direction, setDirection] = React6.useState("none");
|
|
948
|
+
const isControlled = step !== void 0;
|
|
949
|
+
const activeStep = isControlled ? step : uncontrolledStep;
|
|
950
|
+
const activeStepRef = React6.useRef(activeStep);
|
|
951
|
+
const stepChangeRequestVersionRef = React6.useRef(0);
|
|
952
|
+
const indicateBlockedInteraction = windowContext?.indicateBlockedInteraction;
|
|
953
|
+
const activeStepIndex = steps.findIndex((stepDefinition) => stepDefinition.id === activeStep);
|
|
954
|
+
if (activeStepIndex === -1) {
|
|
955
|
+
throw new Error(`WindowFlowProvider could not find a registered step for "${activeStep}".`);
|
|
956
|
+
}
|
|
957
|
+
React6.useEffect(() => {
|
|
958
|
+
activeStepRef.current = activeStep;
|
|
959
|
+
}, [activeStep]);
|
|
960
|
+
const getStep = React6.useCallback(
|
|
961
|
+
(targetStep) => stepMap.get(targetStep),
|
|
962
|
+
[stepMap]
|
|
963
|
+
);
|
|
964
|
+
const setFlowStep = React6.useCallback(
|
|
965
|
+
async (nextStep2, reason = "programmatic") => {
|
|
966
|
+
const currentStep = activeStepRef.current;
|
|
967
|
+
if (nextStep2 === currentStep) {
|
|
968
|
+
return true;
|
|
969
|
+
}
|
|
970
|
+
if (!stepMap.has(nextStep2)) {
|
|
971
|
+
throw new Error(`WindowFlowProvider could not find a registered step for "${nextStep2}".`);
|
|
972
|
+
}
|
|
973
|
+
const currentStepIndex = steps.findIndex(
|
|
974
|
+
(stepDefinition) => stepDefinition.id === currentStep
|
|
975
|
+
);
|
|
976
|
+
const nextStepIndex = steps.findIndex((stepDefinition) => stepDefinition.id === nextStep2);
|
|
977
|
+
const nextDirection = nextStepIndex > currentStepIndex ? "next" : nextStepIndex < currentStepIndex ? "previous" : "none";
|
|
978
|
+
const stepChangeRequestVersion = stepChangeRequestVersionRef.current + 1;
|
|
979
|
+
stepChangeRequestVersionRef.current = stepChangeRequestVersion;
|
|
980
|
+
const stepChangeAllowed = await onStepChangeRequest?.({
|
|
981
|
+
from: currentStep,
|
|
982
|
+
reason,
|
|
983
|
+
to: nextStep2
|
|
984
|
+
}) ?? true;
|
|
985
|
+
if (!stepChangeAllowed) {
|
|
986
|
+
indicateBlockedInteraction?.();
|
|
987
|
+
return false;
|
|
988
|
+
}
|
|
989
|
+
if (stepChangeRequestVersion !== stepChangeRequestVersionRef.current) {
|
|
990
|
+
return false;
|
|
991
|
+
}
|
|
992
|
+
setDirection(nextDirection);
|
|
993
|
+
if (!isControlled) {
|
|
994
|
+
setUncontrolledStep(nextStep2);
|
|
995
|
+
}
|
|
996
|
+
onStepChange?.(nextStep2);
|
|
997
|
+
return true;
|
|
998
|
+
},
|
|
999
|
+
[indicateBlockedInteraction, isControlled, onStepChange, onStepChangeRequest, stepMap, steps]
|
|
1000
|
+
);
|
|
1001
|
+
const previousStep = React6.useCallback(
|
|
1002
|
+
(reason = "programmatic") => {
|
|
1003
|
+
const currentStepIndex = steps.findIndex(
|
|
1004
|
+
(stepDefinition) => stepDefinition.id === activeStepRef.current
|
|
1005
|
+
);
|
|
1006
|
+
const previousStepDefinition = steps[currentStepIndex - 1];
|
|
1007
|
+
if (!previousStepDefinition) {
|
|
1008
|
+
return Promise.resolve(false);
|
|
1009
|
+
}
|
|
1010
|
+
return setFlowStep(previousStepDefinition.id, reason);
|
|
1011
|
+
},
|
|
1012
|
+
[setFlowStep, steps]
|
|
1013
|
+
);
|
|
1014
|
+
const nextStep = React6.useCallback(
|
|
1015
|
+
(reason = "programmatic") => {
|
|
1016
|
+
const currentStepIndex = steps.findIndex(
|
|
1017
|
+
(stepDefinition) => stepDefinition.id === activeStepRef.current
|
|
1018
|
+
);
|
|
1019
|
+
const nextStepDefinition = steps[currentStepIndex + 1];
|
|
1020
|
+
if (!nextStepDefinition) {
|
|
1021
|
+
return Promise.resolve(false);
|
|
1022
|
+
}
|
|
1023
|
+
return setFlowStep(nextStepDefinition.id, reason);
|
|
1024
|
+
},
|
|
1025
|
+
[setFlowStep, steps]
|
|
1026
|
+
);
|
|
1027
|
+
const contextValue = React6.useMemo(
|
|
1028
|
+
() => ({
|
|
1029
|
+
canGoNext: activeStepIndex < steps.length - 1,
|
|
1030
|
+
canGoPrevious: activeStepIndex > 0,
|
|
1031
|
+
direction,
|
|
1032
|
+
getStep,
|
|
1033
|
+
isFirstStep: activeStepIndex === 0,
|
|
1034
|
+
isLastStep: activeStepIndex === steps.length - 1,
|
|
1035
|
+
nextStep,
|
|
1036
|
+
previousStep,
|
|
1037
|
+
setStep: setFlowStep,
|
|
1038
|
+
step: activeStep,
|
|
1039
|
+
stepIndex: activeStepIndex,
|
|
1040
|
+
steps
|
|
1041
|
+
}),
|
|
1042
|
+
[activeStep, activeStepIndex, direction, getStep, nextStep, previousStep, setFlowStep, steps]
|
|
1043
|
+
);
|
|
1044
|
+
return /* @__PURE__ */ jsx7(WindowFlowContext.Provider, { value: contextValue, children });
|
|
1045
|
+
}
|
|
1046
|
+
function useWindowFlow() {
|
|
1047
|
+
const context = React6.useContext(WindowFlowContext);
|
|
1048
|
+
if (!context) {
|
|
1049
|
+
throw new Error("useWindowFlow must be used within a WindowFlowProvider.");
|
|
1050
|
+
}
|
|
1051
|
+
return context;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// src/layouts/window/WindowFlow.tsx
|
|
1055
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1056
|
+
function WindowFlowLayout({ className, ...props }) {
|
|
1057
|
+
const { getStep, step } = useWindowFlow();
|
|
1058
|
+
const activeStep = getStep(step);
|
|
1059
|
+
const windowSize = React7.useMemo(
|
|
1060
|
+
() => getFlowStepWindowSize(activeStep?.windowSize),
|
|
1061
|
+
[activeStep?.windowSize]
|
|
1062
|
+
);
|
|
1063
|
+
useWindowSizeRequest(windowSize);
|
|
1064
|
+
return /* @__PURE__ */ jsx8(
|
|
1065
|
+
"div",
|
|
1066
|
+
{
|
|
1067
|
+
"data-slot": "window-flow-layout",
|
|
1068
|
+
className: cn("flex min-h-0 min-w-0 flex-auto flex-col", className),
|
|
1069
|
+
...props
|
|
1070
|
+
}
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
function WindowFlowHeader({ className, ...props }) {
|
|
1074
|
+
return /* @__PURE__ */ jsx8(
|
|
1075
|
+
"div",
|
|
1076
|
+
{
|
|
1077
|
+
"data-slot": "window-flow-header",
|
|
1078
|
+
className: cn(
|
|
1079
|
+
"border-window-border flex shrink-0 flex-col gap-3 border-b px-6 py-5",
|
|
1080
|
+
className
|
|
1081
|
+
),
|
|
1082
|
+
...props
|
|
1083
|
+
}
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
function WindowFlowContent({ className, ...props }) {
|
|
1087
|
+
return /* @__PURE__ */ jsx8(
|
|
1088
|
+
"div",
|
|
1089
|
+
{
|
|
1090
|
+
"data-slot": "window-flow-content",
|
|
1091
|
+
className: cn("relative flex min-h-0 min-w-0 flex-auto flex-col overflow-hidden", className),
|
|
1092
|
+
...props
|
|
1093
|
+
}
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
function WindowFlowFooter({ className, ...props }) {
|
|
1097
|
+
return /* @__PURE__ */ jsx8(
|
|
1098
|
+
"div",
|
|
1099
|
+
{
|
|
1100
|
+
"data-slot": "window-flow-footer",
|
|
1101
|
+
className: cn(
|
|
1102
|
+
"border-window-border flex shrink-0 items-center justify-between gap-3 border-t px-6 py-4",
|
|
1103
|
+
className
|
|
1104
|
+
),
|
|
1105
|
+
...props
|
|
1106
|
+
}
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
var WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS = 0.08;
|
|
1110
|
+
var WINDOW_FLOW_ENTER_TRANSITION_DURATION_SECONDS = 0.16;
|
|
1111
|
+
var WINDOW_FLOW_ENTER_TRANSITION_DELAY_SECONDS = 0.04;
|
|
1112
|
+
var WINDOW_FLOW_EXIT_TRANSITION_OFFSET_PX = 24;
|
|
1113
|
+
var WINDOW_FLOW_ENTER_TRANSITION_OFFSET_PX = 48;
|
|
1114
|
+
var WINDOW_FLOW_EXIT_X_TRANSITION_EASE = [0, 0.5, 0, 1];
|
|
1115
|
+
var WINDOW_FLOW_ENTER_X_TRANSITION_EASE = [0, 0.5, 0, 1];
|
|
1116
|
+
var WINDOW_FLOW_EXIT_OPACITY_TRANSITION_EASE = [
|
|
1117
|
+
0.35,
|
|
1118
|
+
0.35,
|
|
1119
|
+
0.65,
|
|
1120
|
+
0.65
|
|
1121
|
+
];
|
|
1122
|
+
var WINDOW_FLOW_ENTER_OPACITY_TRANSITION_EASE = [
|
|
1123
|
+
0.35,
|
|
1124
|
+
0.35,
|
|
1125
|
+
0.65,
|
|
1126
|
+
0.65
|
|
1127
|
+
];
|
|
1128
|
+
function getFlowPosition(stepIndex, activeStepIndex) {
|
|
1129
|
+
if (stepIndex < activeStepIndex) {
|
|
1130
|
+
return "previous";
|
|
1131
|
+
}
|
|
1132
|
+
if (stepIndex > activeStepIndex) {
|
|
1133
|
+
return "next";
|
|
1134
|
+
}
|
|
1135
|
+
return "active";
|
|
1136
|
+
}
|
|
1137
|
+
function getFlowEnterAnimation(direction) {
|
|
1138
|
+
if (direction === "next") {
|
|
1139
|
+
return {
|
|
1140
|
+
x: WINDOW_FLOW_ENTER_TRANSITION_OFFSET_PX,
|
|
1141
|
+
opacity: 0
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
if (direction === "previous") {
|
|
1145
|
+
return {
|
|
1146
|
+
x: -WINDOW_FLOW_ENTER_TRANSITION_OFFSET_PX,
|
|
1147
|
+
opacity: 0
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
return {
|
|
1151
|
+
x: 0,
|
|
1152
|
+
opacity: 1
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
function getFlowAnimateState(direction) {
|
|
1156
|
+
const delay = direction === "none" ? 0 : WINDOW_FLOW_ENTER_TRANSITION_DELAY_SECONDS;
|
|
1157
|
+
return {
|
|
1158
|
+
x: 0,
|
|
1159
|
+
opacity: 1,
|
|
1160
|
+
transition: {
|
|
1161
|
+
x: {
|
|
1162
|
+
delay,
|
|
1163
|
+
duration: WINDOW_FLOW_ENTER_TRANSITION_DURATION_SECONDS,
|
|
1164
|
+
ease: WINDOW_FLOW_ENTER_X_TRANSITION_EASE
|
|
1165
|
+
},
|
|
1166
|
+
opacity: {
|
|
1167
|
+
delay,
|
|
1168
|
+
duration: WINDOW_FLOW_ENTER_TRANSITION_DURATION_SECONDS,
|
|
1169
|
+
ease: WINDOW_FLOW_ENTER_OPACITY_TRANSITION_EASE
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
function getFlowExitAnimation(direction) {
|
|
1175
|
+
if (direction === "next") {
|
|
1176
|
+
return {
|
|
1177
|
+
x: -WINDOW_FLOW_EXIT_TRANSITION_OFFSET_PX,
|
|
1178
|
+
opacity: 0,
|
|
1179
|
+
transition: {
|
|
1180
|
+
x: {
|
|
1181
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1182
|
+
ease: WINDOW_FLOW_EXIT_X_TRANSITION_EASE
|
|
1183
|
+
},
|
|
1184
|
+
opacity: {
|
|
1185
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1186
|
+
ease: WINDOW_FLOW_EXIT_OPACITY_TRANSITION_EASE
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
if (direction === "previous") {
|
|
1192
|
+
return {
|
|
1193
|
+
x: WINDOW_FLOW_EXIT_TRANSITION_OFFSET_PX,
|
|
1194
|
+
opacity: 0,
|
|
1195
|
+
transition: {
|
|
1196
|
+
x: {
|
|
1197
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1198
|
+
ease: WINDOW_FLOW_EXIT_X_TRANSITION_EASE
|
|
1199
|
+
},
|
|
1200
|
+
opacity: {
|
|
1201
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1202
|
+
ease: WINDOW_FLOW_EXIT_OPACITY_TRANSITION_EASE
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
return {
|
|
1208
|
+
x: 0,
|
|
1209
|
+
opacity: 0,
|
|
1210
|
+
transition: {
|
|
1211
|
+
x: {
|
|
1212
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1213
|
+
ease: WINDOW_FLOW_EXIT_X_TRANSITION_EASE
|
|
1214
|
+
},
|
|
1215
|
+
opacity: {
|
|
1216
|
+
duration: WINDOW_FLOW_EXIT_TRANSITION_DURATION_SECONDS,
|
|
1217
|
+
ease: WINDOW_FLOW_EXIT_OPACITY_TRANSITION_EASE
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
var windowFlowViewVariants = {
|
|
1223
|
+
center: getFlowAnimateState,
|
|
1224
|
+
enter: getFlowEnterAnimation,
|
|
1225
|
+
exit: getFlowExitAnimation
|
|
1226
|
+
};
|
|
1227
|
+
function getFlowInitialState(direction) {
|
|
1228
|
+
return direction === "none" ? false : "enter";
|
|
1229
|
+
}
|
|
1230
|
+
function getFlowStepWindowSize(size) {
|
|
1231
|
+
if (typeof size === "object" && size.height === void 0 && size.minHeight !== void 0) {
|
|
1232
|
+
return {
|
|
1233
|
+
...size,
|
|
1234
|
+
height: size.minHeight
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
return size;
|
|
1238
|
+
}
|
|
1239
|
+
function shouldMeasureFlowStepSize(size) {
|
|
1240
|
+
if (size === "content") {
|
|
1241
|
+
return true;
|
|
1242
|
+
}
|
|
1243
|
+
return typeof size === "object" && size.height === void 0;
|
|
1244
|
+
}
|
|
1245
|
+
function useElementHeight() {
|
|
1246
|
+
const elementRef = React7.useRef(null);
|
|
1247
|
+
const resizeObserverRef = React7.useRef(null);
|
|
1248
|
+
const [height, setHeight] = React7.useState(null);
|
|
1249
|
+
const updateHeight = React7.useCallback((element) => {
|
|
1250
|
+
const nextHeight = element ? element.getBoundingClientRect().height : null;
|
|
1251
|
+
setHeight((currentHeight) => currentHeight === nextHeight ? currentHeight : nextHeight);
|
|
1252
|
+
}, []);
|
|
1253
|
+
const ref = React7.useCallback(
|
|
1254
|
+
(element) => {
|
|
1255
|
+
resizeObserverRef.current?.disconnect();
|
|
1256
|
+
resizeObserverRef.current = null;
|
|
1257
|
+
elementRef.current = element;
|
|
1258
|
+
if (!element) {
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
updateHeight(element);
|
|
1262
|
+
if (element && typeof ResizeObserver !== "undefined") {
|
|
1263
|
+
resizeObserverRef.current = new ResizeObserver(([entry]) => {
|
|
1264
|
+
if (!entry) {
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
setHeight(entry.contentRect.height);
|
|
1268
|
+
});
|
|
1269
|
+
resizeObserverRef.current.observe(element);
|
|
1270
|
+
}
|
|
1271
|
+
},
|
|
1272
|
+
[updateHeight]
|
|
1273
|
+
);
|
|
1274
|
+
React7.useEffect(() => {
|
|
1275
|
+
return () => {
|
|
1276
|
+
resizeObserverRef.current?.disconnect();
|
|
1277
|
+
};
|
|
1278
|
+
}, []);
|
|
1279
|
+
React7.useLayoutEffect(() => {
|
|
1280
|
+
updateHeight(elementRef.current);
|
|
1281
|
+
});
|
|
1282
|
+
return [ref, height];
|
|
1283
|
+
}
|
|
1284
|
+
function getFlowViewLayoutClass(measuredSize, activeViewHeight) {
|
|
1285
|
+
if (!measuredSize) {
|
|
1286
|
+
return "absolute inset-0";
|
|
1287
|
+
}
|
|
1288
|
+
if (activeViewHeight === null) {
|
|
1289
|
+
return "relative w-full";
|
|
1290
|
+
}
|
|
1291
|
+
return "absolute inset-x-0 top-0";
|
|
1292
|
+
}
|
|
1293
|
+
function WindowFlowView({
|
|
1294
|
+
children,
|
|
1295
|
+
className,
|
|
1296
|
+
direction: directionProp,
|
|
1297
|
+
pageIndex,
|
|
1298
|
+
step,
|
|
1299
|
+
...props
|
|
1300
|
+
}) {
|
|
1301
|
+
const { direction, stepIndex, steps } = useWindowFlow();
|
|
1302
|
+
const ownStepIndex = pageIndex ?? steps.findIndex((stepDefinition) => stepDefinition.id === step);
|
|
1303
|
+
const active = ownStepIndex === stepIndex;
|
|
1304
|
+
const position = getFlowPosition(ownStepIndex, stepIndex);
|
|
1305
|
+
const resolvedDirection = directionProp ?? direction;
|
|
1306
|
+
return /* @__PURE__ */ jsx8(
|
|
1307
|
+
motion2.div,
|
|
1308
|
+
{
|
|
1309
|
+
"data-slot": "window-flow-view",
|
|
1310
|
+
"data-active": active,
|
|
1311
|
+
"data-flow-direction": resolvedDirection,
|
|
1312
|
+
"data-flow-position": position,
|
|
1313
|
+
"data-step": step,
|
|
1314
|
+
"aria-hidden": !active,
|
|
1315
|
+
className: cn(
|
|
1316
|
+
"min-h-0 min-w-0 overflow-auto motion-reduce:transform-none!",
|
|
1317
|
+
active ? "pointer-events-auto" : "pointer-events-none",
|
|
1318
|
+
className
|
|
1319
|
+
),
|
|
1320
|
+
custom: resolvedDirection,
|
|
1321
|
+
variants: windowFlowViewVariants,
|
|
1322
|
+
initial: getFlowInitialState(resolvedDirection),
|
|
1323
|
+
animate: "center",
|
|
1324
|
+
exit: "exit",
|
|
1325
|
+
...props,
|
|
1326
|
+
children
|
|
1327
|
+
}
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
function WindowFlowViews({ children, className, style, ...props }) {
|
|
1331
|
+
const { direction, getStep, step, steps } = useWindowFlow();
|
|
1332
|
+
if (steps.length === 0) {
|
|
1333
|
+
throw new Error("WindowFlowViews requires registered steps on WindowFlowProvider.");
|
|
1334
|
+
}
|
|
1335
|
+
const activeStep = getStep(step);
|
|
1336
|
+
if (!activeStep) {
|
|
1337
|
+
throw new Error(`WindowFlowViews could not find a registered step for "${step}".`);
|
|
1338
|
+
}
|
|
1339
|
+
const activeWindowSize = getFlowStepWindowSize(activeStep.windowSize);
|
|
1340
|
+
const [activeViewRef, activeViewHeight] = useElementHeight();
|
|
1341
|
+
const measuredSize = shouldMeasureFlowStepSize(activeWindowSize);
|
|
1342
|
+
return /* @__PURE__ */ jsxs5(
|
|
1343
|
+
motion2.div,
|
|
1344
|
+
{
|
|
1345
|
+
"data-slot": "window-flow-views",
|
|
1346
|
+
"data-flow-direction": direction,
|
|
1347
|
+
className: cn("relative flex min-h-0 min-w-0 flex-auto overflow-hidden", className),
|
|
1348
|
+
style: {
|
|
1349
|
+
...style,
|
|
1350
|
+
...measuredSize && activeViewHeight !== null ? { height: activeViewHeight } : null
|
|
1351
|
+
},
|
|
1352
|
+
...props,
|
|
1353
|
+
children: [
|
|
1354
|
+
children,
|
|
1355
|
+
/* @__PURE__ */ jsx8(AnimatePresence, { custom: direction, initial: false, children: /* @__PURE__ */ jsx8(
|
|
1356
|
+
motion2.div,
|
|
1357
|
+
{
|
|
1358
|
+
custom: direction,
|
|
1359
|
+
"data-slot": "window-flow-view",
|
|
1360
|
+
"data-active": true,
|
|
1361
|
+
"data-flow-direction": direction,
|
|
1362
|
+
"data-flow-position": "active",
|
|
1363
|
+
"data-step": activeStep.id,
|
|
1364
|
+
ref: activeViewRef,
|
|
1365
|
+
className: cn(
|
|
1366
|
+
"min-h-0 min-w-0 overflow-auto motion-reduce:transform-none!",
|
|
1367
|
+
getFlowViewLayoutClass(measuredSize, activeViewHeight)
|
|
1368
|
+
),
|
|
1369
|
+
variants: windowFlowViewVariants,
|
|
1370
|
+
initial: getFlowInitialState(direction),
|
|
1371
|
+
animate: "center",
|
|
1372
|
+
exit: "exit",
|
|
1373
|
+
children: activeStep.render()
|
|
1374
|
+
},
|
|
1375
|
+
activeStep.id
|
|
1376
|
+
) })
|
|
1377
|
+
]
|
|
1378
|
+
}
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
function WindowFlowPreviousButton({
|
|
1382
|
+
children = "Back",
|
|
1383
|
+
disabled,
|
|
1384
|
+
onClick,
|
|
1385
|
+
type = "button",
|
|
1386
|
+
variant = "outline",
|
|
1387
|
+
...props
|
|
1388
|
+
}) {
|
|
1389
|
+
const { canGoPrevious, previousStep } = useWindowFlow();
|
|
1390
|
+
return /* @__PURE__ */ jsxs5(
|
|
1391
|
+
Button,
|
|
1392
|
+
{
|
|
1393
|
+
disabled: disabled ?? !canGoPrevious,
|
|
1394
|
+
onClick: (event) => {
|
|
1395
|
+
onClick?.(event);
|
|
1396
|
+
if (!event.defaultPrevented) {
|
|
1397
|
+
void previousStep("previous-button").catch((error) => {
|
|
1398
|
+
console.error("Failed to move to the previous window flow step.", error);
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
},
|
|
1402
|
+
type,
|
|
1403
|
+
variant,
|
|
1404
|
+
...props,
|
|
1405
|
+
children: [
|
|
1406
|
+
/* @__PURE__ */ jsx8(ArrowLeftIcon, {}),
|
|
1407
|
+
children
|
|
1408
|
+
]
|
|
1409
|
+
}
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
function WindowFlowNextButton({
|
|
1413
|
+
children,
|
|
1414
|
+
disabled,
|
|
1415
|
+
onClick,
|
|
1416
|
+
type = "button",
|
|
1417
|
+
variant = "accent",
|
|
1418
|
+
...props
|
|
1419
|
+
}) {
|
|
1420
|
+
const { canGoNext, isLastStep, nextStep } = useWindowFlow();
|
|
1421
|
+
return /* @__PURE__ */ jsxs5(
|
|
1422
|
+
Button,
|
|
1423
|
+
{
|
|
1424
|
+
disabled: disabled ?? !canGoNext,
|
|
1425
|
+
onClick: (event) => {
|
|
1426
|
+
onClick?.(event);
|
|
1427
|
+
if (!event.defaultPrevented) {
|
|
1428
|
+
void nextStep("next-button").catch((error) => {
|
|
1429
|
+
console.error("Failed to move to the next window flow step.", error);
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
},
|
|
1433
|
+
type,
|
|
1434
|
+
variant,
|
|
1435
|
+
...props,
|
|
1436
|
+
children: [
|
|
1437
|
+
children ?? (isLastStep ? "Done" : "Next"),
|
|
1438
|
+
/* @__PURE__ */ jsx8(ArrowRightIcon, {})
|
|
1439
|
+
]
|
|
1440
|
+
}
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
function WindowFlowProgress({ className, ...props }) {
|
|
1444
|
+
const { stepIndex, steps } = useWindowFlow();
|
|
1445
|
+
return /* @__PURE__ */ jsx8(
|
|
1446
|
+
"div",
|
|
1447
|
+
{
|
|
1448
|
+
"data-slot": "window-flow-progress",
|
|
1449
|
+
className: cn("flex w-full items-center gap-1.5", className),
|
|
1450
|
+
...props,
|
|
1451
|
+
children: steps.map((stepDefinition, index) => /* @__PURE__ */ jsx8(
|
|
1452
|
+
"div",
|
|
1453
|
+
{
|
|
1454
|
+
"data-active": index === stepIndex,
|
|
1455
|
+
"data-complete": index < stepIndex,
|
|
1456
|
+
"data-slot": "window-flow-progress-segment",
|
|
1457
|
+
className: cn(
|
|
1458
|
+
"bg-background-tertiary h-1.5 min-w-0 flex-1 rounded-full transition-colors",
|
|
1459
|
+
index <= stepIndex && "bg-interactive-accent"
|
|
1460
|
+
)
|
|
1461
|
+
},
|
|
1462
|
+
stepDefinition.id
|
|
1463
|
+
))
|
|
1464
|
+
}
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
// src/layouts/window/WindowPage.tsx
|
|
1469
|
+
import "react";
|
|
1470
|
+
|
|
1471
|
+
// src/layouts/window/WindowPageContext.tsx
|
|
1472
|
+
import * as React8 from "react";
|
|
1473
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1474
|
+
var WindowPageContext = React8.createContext(null);
|
|
1475
|
+
function defineWindowPage(definition) {
|
|
1476
|
+
return definition;
|
|
1477
|
+
}
|
|
1478
|
+
function WindowPageProvider({
|
|
1479
|
+
children,
|
|
1480
|
+
defaultPage,
|
|
1481
|
+
onPageChangeRequest,
|
|
1482
|
+
onPageChange,
|
|
1483
|
+
pages = [],
|
|
1484
|
+
page
|
|
1485
|
+
}) {
|
|
1486
|
+
const windowContext = React8.useContext(WindowStateContext);
|
|
1487
|
+
const pageMap = React8.useMemo(() => {
|
|
1488
|
+
const nextPageMap = /* @__PURE__ */ new Map();
|
|
1489
|
+
pages.forEach((pageDefinition) => {
|
|
1490
|
+
if (nextPageMap.has(pageDefinition.id)) {
|
|
1491
|
+
throw new Error(`Duplicate WindowPage id "${pageDefinition.id}" is not allowed.`);
|
|
1492
|
+
}
|
|
1493
|
+
nextPageMap.set(pageDefinition.id, pageDefinition);
|
|
1494
|
+
});
|
|
1495
|
+
return nextPageMap;
|
|
1496
|
+
}, [pages]);
|
|
1497
|
+
const initialPage = page ?? defaultPage;
|
|
1498
|
+
if (initialPage === void 0) {
|
|
1499
|
+
throw new Error("WindowPageProvider requires a page or defaultPage.");
|
|
1500
|
+
}
|
|
1501
|
+
if (pages.length > 0 && !pageMap.has(initialPage)) {
|
|
1502
|
+
throw new Error(`WindowPageProvider could not find a registered page for "${initialPage}".`);
|
|
1503
|
+
}
|
|
1504
|
+
const [uncontrolledPage, setUncontrolledPage] = React8.useState(initialPage);
|
|
1505
|
+
const isControlled = page !== void 0;
|
|
1506
|
+
const activePage = isControlled ? page : uncontrolledPage;
|
|
1507
|
+
const activePageRef = React8.useRef(activePage);
|
|
1508
|
+
const pageChangeRequestVersionRef = React8.useRef(0);
|
|
1509
|
+
const indicateBlockedInteraction = windowContext?.indicateBlockedInteraction;
|
|
1510
|
+
if (pages.length > 0 && !pageMap.has(activePage)) {
|
|
1511
|
+
throw new Error(`WindowPageProvider could not find a registered page for "${activePage}".`);
|
|
1512
|
+
}
|
|
1513
|
+
React8.useEffect(() => {
|
|
1514
|
+
activePageRef.current = activePage;
|
|
1515
|
+
}, [activePage]);
|
|
1516
|
+
const getPage = React8.useCallback(
|
|
1517
|
+
(targetPage) => pageMap.get(targetPage),
|
|
1518
|
+
[pageMap]
|
|
1519
|
+
);
|
|
1520
|
+
const setPage = React8.useCallback(
|
|
1521
|
+
async (nextPage, reason = "programmatic") => {
|
|
1522
|
+
const currentPage = activePageRef.current;
|
|
1523
|
+
if (nextPage === currentPage) {
|
|
1524
|
+
return true;
|
|
1525
|
+
}
|
|
1526
|
+
if (pages.length > 0 && !pageMap.has(nextPage)) {
|
|
1527
|
+
throw new Error(`WindowPageProvider could not find a registered page for "${nextPage}".`);
|
|
1528
|
+
}
|
|
1529
|
+
const pageChangeRequestVersion = pageChangeRequestVersionRef.current + 1;
|
|
1530
|
+
pageChangeRequestVersionRef.current = pageChangeRequestVersion;
|
|
1531
|
+
const pageChangeAllowed = await onPageChangeRequest?.({
|
|
1532
|
+
from: currentPage,
|
|
1533
|
+
reason,
|
|
1534
|
+
to: nextPage
|
|
1535
|
+
}) ?? true;
|
|
1536
|
+
if (!pageChangeAllowed) {
|
|
1537
|
+
indicateBlockedInteraction?.();
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
if (pageChangeRequestVersion !== pageChangeRequestVersionRef.current) {
|
|
1541
|
+
return false;
|
|
1542
|
+
}
|
|
1543
|
+
if (!isControlled) {
|
|
1544
|
+
setUncontrolledPage(nextPage);
|
|
1545
|
+
}
|
|
1546
|
+
onPageChange?.(nextPage);
|
|
1547
|
+
return true;
|
|
1548
|
+
},
|
|
1549
|
+
[
|
|
1550
|
+
indicateBlockedInteraction,
|
|
1551
|
+
isControlled,
|
|
1552
|
+
onPageChange,
|
|
1553
|
+
onPageChangeRequest,
|
|
1554
|
+
pageMap,
|
|
1555
|
+
pages.length
|
|
1556
|
+
]
|
|
1557
|
+
);
|
|
1558
|
+
const isActive = React8.useCallback(
|
|
1559
|
+
(targetPage) => activePage === targetPage,
|
|
1560
|
+
[activePage]
|
|
1561
|
+
);
|
|
1562
|
+
const contextValue = React8.useMemo(
|
|
1563
|
+
() => ({
|
|
1564
|
+
getPage,
|
|
1565
|
+
isActive,
|
|
1566
|
+
pages,
|
|
1567
|
+
page: activePage,
|
|
1568
|
+
setPage
|
|
1569
|
+
}),
|
|
1570
|
+
[activePage, getPage, isActive, pages, setPage]
|
|
1571
|
+
);
|
|
1572
|
+
return /* @__PURE__ */ jsx9(WindowPageContext.Provider, { value: contextValue, children });
|
|
1573
|
+
}
|
|
1574
|
+
function useWindowPage() {
|
|
1575
|
+
const context = React8.useContext(WindowPageContext);
|
|
1576
|
+
if (!context) {
|
|
1577
|
+
throw new Error("useWindowPage must be used within a WindowPageProvider.");
|
|
1578
|
+
}
|
|
1579
|
+
return context;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
// src/layouts/window/WindowPage.tsx
|
|
1583
|
+
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1584
|
+
function WindowPageNavButton({ onClick, page, ...props }) {
|
|
1585
|
+
const { isActive, setPage } = useWindowPage();
|
|
1586
|
+
return /* @__PURE__ */ jsx10(
|
|
1587
|
+
WindowSidebarMenuButton,
|
|
1588
|
+
{
|
|
1589
|
+
"data-slot": "window-page-nav-button",
|
|
1590
|
+
isActive: isActive(page),
|
|
1591
|
+
onClick: (event) => {
|
|
1592
|
+
onClick?.(event);
|
|
1593
|
+
if (!event.defaultPrevented) {
|
|
1594
|
+
void setPage(page, "nav-button").catch((error) => {
|
|
1595
|
+
console.error("Failed to change window page from nav button.", error);
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
},
|
|
1599
|
+
...props
|
|
1600
|
+
}
|
|
1601
|
+
);
|
|
1602
|
+
}
|
|
1603
|
+
function useRegisteredWindowPages() {
|
|
1604
|
+
const context = useWindowPage();
|
|
1605
|
+
if (context.pages.length === 0) {
|
|
1606
|
+
throw new Error(
|
|
1607
|
+
"WindowPageList and WindowPageViews require registered pages on WindowPageProvider."
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
return context;
|
|
1611
|
+
}
|
|
1612
|
+
function WindowPageView({
|
|
1613
|
+
children,
|
|
1614
|
+
className,
|
|
1615
|
+
keepMounted = false,
|
|
1616
|
+
page,
|
|
1617
|
+
...props
|
|
1618
|
+
}) {
|
|
1619
|
+
const { isActive } = useWindowPage();
|
|
1620
|
+
const active = isActive(page);
|
|
1621
|
+
if (!keepMounted && !active) {
|
|
1622
|
+
return null;
|
|
1623
|
+
}
|
|
1624
|
+
return /* @__PURE__ */ jsx10(
|
|
1625
|
+
"div",
|
|
1626
|
+
{
|
|
1627
|
+
"data-slot": "window-page-view",
|
|
1628
|
+
"data-active": active,
|
|
1629
|
+
"data-page": page,
|
|
1630
|
+
"aria-hidden": !active,
|
|
1631
|
+
hidden: !active,
|
|
1632
|
+
className: cn(className),
|
|
1633
|
+
...props,
|
|
1634
|
+
children
|
|
1635
|
+
}
|
|
1636
|
+
);
|
|
1637
|
+
}
|
|
1638
|
+
function WindowPageList({ className, ...props }) {
|
|
1639
|
+
const { pages } = useRegisteredWindowPages();
|
|
1640
|
+
return /* @__PURE__ */ jsx10(WindowSidebarMenu, { "data-slot": "window-page-list", className: cn(className), ...props, children: pages.map((pageDefinition) => {
|
|
1641
|
+
const Icon = pageDefinition.icon;
|
|
1642
|
+
return /* @__PURE__ */ jsx10(WindowSidebarMenuItem, { children: /* @__PURE__ */ jsx10(
|
|
1643
|
+
WindowPageNavButton,
|
|
1644
|
+
{
|
|
1645
|
+
page: pageDefinition.id,
|
|
1646
|
+
leadingVisual: Icon ? /* @__PURE__ */ jsx10(Icon, { className: "size-4" }) : void 0,
|
|
1647
|
+
children: pageDefinition.label
|
|
1648
|
+
}
|
|
1649
|
+
) }, pageDefinition.id);
|
|
1650
|
+
}) });
|
|
1651
|
+
}
|
|
1652
|
+
function WindowPageViews({ children, className, ...props }) {
|
|
1653
|
+
const { pages } = useRegisteredWindowPages();
|
|
1654
|
+
return /* @__PURE__ */ jsxs6("div", { "data-slot": "window-page-views", className: cn(className), ...props, children: [
|
|
1655
|
+
children,
|
|
1656
|
+
pages.map((pageDefinition) => /* @__PURE__ */ jsx10(
|
|
1657
|
+
WindowPageView,
|
|
1658
|
+
{
|
|
1659
|
+
page: pageDefinition.id,
|
|
1660
|
+
keepMounted: pageDefinition.keepMounted,
|
|
1661
|
+
children: pageDefinition.render()
|
|
1662
|
+
},
|
|
1663
|
+
pageDefinition.id
|
|
1664
|
+
))
|
|
1665
|
+
] });
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
export {
|
|
1669
|
+
WindowGroup,
|
|
1670
|
+
WindowGroupLabel,
|
|
1671
|
+
WindowGroupContent,
|
|
1672
|
+
WindowRow,
|
|
1673
|
+
WindowRowContent,
|
|
1674
|
+
WindowRowTitle,
|
|
1675
|
+
WindowRowDescription,
|
|
1676
|
+
WindowRowActions,
|
|
1677
|
+
WindowRowSeparator,
|
|
1678
|
+
WindowStateContext,
|
|
1679
|
+
WindowStateProvider,
|
|
1680
|
+
useWindow,
|
|
1681
|
+
WindowProvider,
|
|
1682
|
+
WindowManagerContext,
|
|
1683
|
+
defineWindow,
|
|
1684
|
+
WindowManagerProvider,
|
|
1685
|
+
useWindowManager,
|
|
1686
|
+
WindowHost,
|
|
1687
|
+
WindowCloseButton,
|
|
1688
|
+
WindowLayout,
|
|
1689
|
+
useWindowSizeRequest,
|
|
1690
|
+
WindowContent,
|
|
1691
|
+
WindowSidebar,
|
|
1692
|
+
WindowSidebarInput,
|
|
1693
|
+
WindowSidebarHeader,
|
|
1694
|
+
WindowSidebarFooter,
|
|
1695
|
+
WindowSidebarContent,
|
|
1696
|
+
WindowSidebarGroup,
|
|
1697
|
+
WindowSidebarGroupLabel,
|
|
1698
|
+
WindowSidebarGroupAction,
|
|
1699
|
+
WindowSidebarGroupContent,
|
|
1700
|
+
WindowSidebarMenu,
|
|
1701
|
+
WindowSidebarMenuItem,
|
|
1702
|
+
WindowSidebarMenuButton,
|
|
1703
|
+
WindowSidebarMenuAction,
|
|
1704
|
+
WindowSidebarMenuBadge,
|
|
1705
|
+
WindowSidebarMenuSkeleton,
|
|
1706
|
+
defineWindowFlowStep,
|
|
1707
|
+
WindowFlowProvider,
|
|
1708
|
+
useWindowFlow,
|
|
1709
|
+
WindowFlowLayout,
|
|
1710
|
+
WindowFlowHeader,
|
|
1711
|
+
WindowFlowContent,
|
|
1712
|
+
WindowFlowFooter,
|
|
1713
|
+
WindowFlowView,
|
|
1714
|
+
WindowFlowViews,
|
|
1715
|
+
WindowFlowPreviousButton,
|
|
1716
|
+
WindowFlowNextButton,
|
|
1717
|
+
WindowFlowProgress,
|
|
1718
|
+
defineWindowPage,
|
|
1719
|
+
WindowPageProvider,
|
|
1720
|
+
useWindowPage,
|
|
1721
|
+
WindowPageNavButton,
|
|
1722
|
+
WindowPageView,
|
|
1723
|
+
WindowPageList,
|
|
1724
|
+
WindowPageViews
|
|
1725
|
+
};
|
|
1726
|
+
//# sourceMappingURL=chunk-OUFGNJ3V.js.map
|