@xenide-io/the-old-ui-theme 0.4.4 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-54ZR4VL5.mjs → chunk-RZXHZWUB.mjs} +44 -17
- package/dist/{index-B5NOyoKS.d.mts → index-Od4pIP4F.d.mts} +7 -1
- package/dist/{index-B5NOyoKS.d.ts → index-Od4pIP4F.d.ts} +7 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -10
- package/dist/index.mjs +1 -1
- package/dist/suite.d.mts +152 -41
- package/dist/suite.d.ts +152 -41
- package/dist/suite.js +1366 -671
- package/dist/suite.mjs +1304 -610
- package/dist/ui.d.mts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +37 -10
- package/dist/ui.mjs +1 -1
- package/package.json +7 -3
- package/src/components/ui/Modal.tsx +70 -26
- package/src/styles/suite-skin.css +284 -24
- package/src/suite/components/ai-panel.test.ts +20 -0
- package/src/suite/components/ai-panel.tsx +494 -103
- package/src/suite/components/suite-app-layout.tsx +48 -28
- package/src/suite/components/suite-layout.tsx +84 -40
- package/src/suite/components/suite-mobile-drawer.tsx +35 -22
- package/src/suite/components/suite-notification-bell.tsx +9 -3
- package/src/suite/components/suite-settings-layout.tsx +82 -0
- package/src/suite/components/suite-settings-mobile-nav.tsx +18 -17
- package/src/suite/components/suite-skeleton.tsx +3 -3
- package/src/suite/components/today-calibrating.tsx +11 -35
- package/src/suite/components/today-page-frame.tsx +19 -11
- package/src/suite/components/today-ui.tsx +276 -19
- package/src/suite/index.ts +41 -25
- package/src/suite/lib/apps.ts +32 -2
- package/src/suite/lib/use-sidebar-width.ts +114 -0
- package/src/components/sections/AccordionShowcase.tsx +0 -45
- package/src/components/sections/AlertShowcase.tsx +0 -40
- package/src/components/sections/AvatarShowcase.tsx +0 -80
- package/src/components/sections/BadgeShowcase.tsx +0 -65
- package/src/components/sections/ButtonShowcase.tsx +0 -308
- package/src/components/sections/CalendarShowcase.tsx +0 -35
- package/src/components/sections/CardShowcase.tsx +0 -159
- package/src/components/sections/CodeMockupShowcase.tsx +0 -56
- package/src/components/sections/ColorPalette.tsx +0 -117
- package/src/components/sections/CommandPaletteShowcase.tsx +0 -48
- package/src/components/sections/CountdownShowcase.tsx +0 -43
- package/src/components/sections/DiffShowcase.tsx +0 -70
- package/src/components/sections/DrawerShowcase.tsx +0 -97
- package/src/components/sections/DropdownShowcase.tsx +0 -98
- package/src/components/sections/EmptyStateShowcase.tsx +0 -50
- package/src/components/sections/FilterChipsShowcase.tsx +0 -98
- package/src/components/sections/FormShowcase.tsx +0 -127
- package/src/components/sections/HoverCardShowcase.tsx +0 -50
- package/src/components/sections/IconShowcase.tsx +0 -121
- package/src/components/sections/IndicatorShowcase.tsx +0 -52
- package/src/components/sections/KbdShowcase.tsx +0 -57
- package/src/components/sections/ModalShowcase.tsx +0 -211
- package/src/components/sections/NavigationShowcase.tsx +0 -199
- package/src/components/sections/NewComponentsShowcase.tsx +0 -1052
- package/src/components/sections/ProductLayoutsShowcase.tsx +0 -78
- package/src/components/sections/ProgressShowcase.tsx +0 -82
- package/src/components/sections/QuillChartShowcase.tsx +0 -92
- package/src/components/sections/QuillDashboardShowcase.tsx +0 -149
- package/src/components/sections/SegmentedControlShowcase.tsx +0 -49
- package/src/components/sections/SetupThemeShowcase.tsx +0 -262
- package/src/components/sections/SidebarShowcase.tsx +0 -152
- package/src/components/sections/StackShowcase.tsx +0 -33
- package/src/components/sections/StepperShowcase.tsx +0 -37
- package/src/components/sections/SuiteShowcase.tsx +0 -669
- package/src/components/sections/SwapShowcase.tsx +0 -99
- package/src/components/sections/TabShowcase.tsx +0 -84
- package/src/components/sections/TableShowcase.tsx +0 -142
- package/src/components/sections/TimelineShowcase.tsx +0 -83
- package/src/components/sections/ToastShowcase.tsx +0 -108
- package/src/components/sections/TooltipShowcase.tsx +0 -38
- package/src/components/sections/UtilityShowcase.tsx +0 -81
- package/src/styles/excel-themes.css +0 -110
- package/src/styles/lemon-primitives.css +0 -550
package/dist/suite.js
CHANGED
|
@@ -68,10 +68,16 @@ __export(suite_exports, {
|
|
|
68
68
|
AppSwitcherMark: () => AppSwitcherMark,
|
|
69
69
|
CommandPaletteHost: () => CommandPaletteHost,
|
|
70
70
|
DeferredChrome: () => DeferredChrome,
|
|
71
|
+
SIDEBAR_COLLAPSE_THRESHOLD: () => SIDEBAR_COLLAPSE_THRESHOLD,
|
|
72
|
+
SIDEBAR_DEFAULT_WIDTH: () => SIDEBAR_DEFAULT_WIDTH,
|
|
73
|
+
SIDEBAR_MAX_WIDTH: () => SIDEBAR_MAX_WIDTH,
|
|
74
|
+
SIDEBAR_MIN_EXPANDED_WIDTH: () => SIDEBAR_MIN_EXPANDED_WIDTH,
|
|
75
|
+
SIDEBAR_RAIL_WIDTH: () => SIDEBAR_RAIL_WIDTH,
|
|
71
76
|
SUITE_APPS: () => SUITE_APPS2,
|
|
72
77
|
SUITE_APP_MAP: () => SUITE_APP_MAP,
|
|
73
78
|
SUITE_GLYPHS: () => SUITE_GLYPHS,
|
|
74
79
|
SUITE_ICON_NAMES: () => SUITE_ICON_NAMES,
|
|
80
|
+
SUITE_OPEN_ASK_AI_EVENT: () => SUITE_OPEN_ASK_AI_EVENT,
|
|
75
81
|
SUITE_SPRINGS: () => SUITE_SPRINGS,
|
|
76
82
|
SourceAppGlyph: () => SourceAppGlyph,
|
|
77
83
|
SuiteAiPanel: () => SuiteAiPanel,
|
|
@@ -89,6 +95,7 @@ __export(suite_exports, {
|
|
|
89
95
|
SuitePage: () => SuitePage,
|
|
90
96
|
SuitePageHeader: () => SuitePageHeader,
|
|
91
97
|
SuiteSectionHeader: () => SuiteSectionHeader,
|
|
98
|
+
SuiteSettingsLayout: () => SuiteSettingsLayout,
|
|
92
99
|
SuiteSettingsMobileNav: () => SuiteSettingsMobileNav,
|
|
93
100
|
SuiteSidebar: () => SuiteSidebar,
|
|
94
101
|
SuiteSkeleton: () => SuiteSkeleton,
|
|
@@ -98,11 +105,15 @@ __export(suite_exports, {
|
|
|
98
105
|
SuiteThemeProvider: () => SuiteThemeProvider,
|
|
99
106
|
SuiteToolbar: () => SuiteToolbar,
|
|
100
107
|
SuiteUserMenu: () => SuiteUserMenu,
|
|
108
|
+
TodayAskAiCard: () => TodayAskAiCard,
|
|
101
109
|
TodayCalibrating: () => TodayCalibrating,
|
|
110
|
+
TodayEmptyAction: () => TodayEmptyAction,
|
|
102
111
|
TodayEmptyState: () => TodayEmptyState,
|
|
103
112
|
TodayHero: () => TodayHero,
|
|
113
|
+
TodayLayout: () => TodayLayout,
|
|
104
114
|
TodayPageFrame: () => TodayPageFrame,
|
|
105
115
|
TodayPanel: () => TodayPanel,
|
|
116
|
+
TodayPrimaryAction: () => TodayPrimaryAction,
|
|
106
117
|
TodaySection: () => TodaySection,
|
|
107
118
|
TodayTimeIcon: () => TodayTimeIcon,
|
|
108
119
|
TodayTopBar: () => TodayTopBar,
|
|
@@ -111,11 +122,14 @@ __export(suite_exports, {
|
|
|
111
122
|
appSwitcherTriggerClass: () => appSwitcherTriggerClass,
|
|
112
123
|
cn: () => cn,
|
|
113
124
|
getTodayGreeting: () => getTodayGreeting,
|
|
114
|
-
m: () =>
|
|
125
|
+
m: () => import_react10.m,
|
|
126
|
+
openSuiteAskAi: () => openSuiteAskAi,
|
|
127
|
+
resolveSuiteNotificationHref: () => resolveSuiteNotificationHref,
|
|
115
128
|
sourceToSuiteApp: () => sourceToSuiteApp,
|
|
116
129
|
suiteAppBaseUrl: () => suiteAppBaseUrl,
|
|
117
130
|
suiteAppLabel: () => suiteAppLabel,
|
|
118
131
|
useIdleMount: () => useIdleMount,
|
|
132
|
+
useSidebarWidth: () => useSidebarWidth,
|
|
119
133
|
useSuiteTheme: () => useSuiteTheme
|
|
120
134
|
});
|
|
121
135
|
module.exports = __toCommonJS(suite_exports);
|
|
@@ -127,24 +141,32 @@ function TodayPageFrame({ children }) {
|
|
|
127
141
|
"div",
|
|
128
142
|
{
|
|
129
143
|
"data-test": "today-page",
|
|
130
|
-
className: "today-page-frame relative flex min-h-0 flex-1 flex-col overflow-
|
|
144
|
+
className: "today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-hidden",
|
|
131
145
|
children: [
|
|
132
146
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
133
147
|
"div",
|
|
134
148
|
{
|
|
135
|
-
className: "pointer-events-none absolute inset-
|
|
149
|
+
className: "pointer-events-none absolute inset-0 overflow-hidden",
|
|
136
150
|
"aria-hidden": true,
|
|
137
151
|
children: [
|
|
138
152
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__glow absolute inset-0" }),
|
|
139
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-
|
|
140
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-
|
|
141
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
142
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
143
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
153
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__top-fade absolute inset-x-0 top-0 h-[28rem]" }),
|
|
154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--1 absolute -left-28 top-16 h-96 w-[30rem] rounded-[45%]" }),
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--2 absolute -right-24 top-24 h-80 w-[22rem] rounded-[40%]" }),
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--3 absolute left-[22%] top-48 h-72 w-[24rem] rounded-[50%]" }),
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--4 absolute right-[18%] top-[42%] h-64 w-[20rem] rounded-[48%]" }),
|
|
158
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "today-page-frame__cloud today-page-frame__cloud--5 absolute left-[8%] top-[68%] h-56 w-[18rem] rounded-[42%]" })
|
|
144
159
|
]
|
|
145
160
|
}
|
|
146
161
|
),
|
|
147
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
163
|
+
"div",
|
|
164
|
+
{
|
|
165
|
+
"data-width": "full",
|
|
166
|
+
className: "suite-page-stage suite-page-inset relative z-[1] flex w-full min-w-0 flex-1 flex-col [&_.list-row]:min-h-[52px] [&_.list-row]:sm:min-h-[44px]",
|
|
167
|
+
children
|
|
168
|
+
}
|
|
169
|
+
)
|
|
148
170
|
]
|
|
149
171
|
}
|
|
150
172
|
);
|
|
@@ -597,15 +619,15 @@ function AnimatedSun({ className }) {
|
|
|
597
619
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { stopColor: "#f59e0b" }),
|
|
598
620
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { offset: "1", stopColor: "#fb923c" })
|
|
599
621
|
] }) }),
|
|
600
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("g", { className: "origin-center motion-safe:animate-[
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("g", { className: "origin-center opacity-80 motion-safe:animate-[pulse_8s_ease-in-out_infinite] motion-reduce:animate-none", children: [0, 45, 90, 135, 180, 225, 270, 315].map((angle) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
601
623
|
"line",
|
|
602
624
|
{
|
|
603
625
|
x1: "20",
|
|
604
|
-
y1: "
|
|
626
|
+
y1: "5",
|
|
605
627
|
x2: "20",
|
|
606
628
|
y2: "9",
|
|
607
629
|
stroke: "#fbbf24",
|
|
608
|
-
strokeWidth: "
|
|
630
|
+
strokeWidth: "1.75",
|
|
609
631
|
strokeLinecap: "round",
|
|
610
632
|
transform: `rotate(${angle} 20 20)`
|
|
611
633
|
},
|
|
@@ -639,10 +661,9 @@ function AnimatedMoon({ className }) {
|
|
|
639
661
|
fill: "url(#animatedMoonBody)"
|
|
640
662
|
}
|
|
641
663
|
),
|
|
642
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { className: "motion-safe:animate-[
|
|
643
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "29", cy: "10", r: "1.
|
|
644
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "34", cy: "16", r: "
|
|
645
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "25", cy: "5.5", r: "0.9", fill: "#c7d2fe" })
|
|
664
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { className: "opacity-70 motion-safe:animate-[pulse_10s_ease-in-out_infinite] motion-reduce:animate-none", children: [
|
|
665
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "29", cy: "10", r: "1.2", fill: "#c7d2fe" }),
|
|
666
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "34", cy: "16", r: "0.9", fill: "#c7d2fe" })
|
|
646
667
|
] })
|
|
647
668
|
]
|
|
648
669
|
}
|
|
@@ -704,30 +725,193 @@ function getTodayGreeting(user, stats) {
|
|
|
704
725
|
const overdueCount = (_d = stats == null ? void 0 : stats.overdueCount) != null ? _d : 0;
|
|
705
726
|
const hours = (_e = stats == null ? void 0 : stats.hours) != null ? _e : 0;
|
|
706
727
|
if (overdueCount > 0) {
|
|
707
|
-
return `${greeting}.
|
|
728
|
+
return `${greeting}. ${taskCount} task${taskCount === 1 ? "" : "s"} due today, ${overdueCount} overdue.`;
|
|
708
729
|
}
|
|
709
730
|
if (taskCount > 0) {
|
|
710
|
-
return `${greeting}.
|
|
731
|
+
return `${greeting}. ${taskCount} task${taskCount === 1 ? "" : "s"} due today.`;
|
|
711
732
|
}
|
|
712
733
|
if (hours > 0) {
|
|
713
|
-
return `${greeting}.
|
|
734
|
+
return `${greeting}. ${hours} hour${hours === 1 ? "" : "s"} logged today.`;
|
|
714
735
|
}
|
|
715
736
|
if (period === "evening" || period === "night") {
|
|
716
|
-
return `${greeting}.
|
|
737
|
+
return `${greeting}. Nice work \u2014 time to wrap up.`;
|
|
717
738
|
}
|
|
718
|
-
return `${greeting}.
|
|
739
|
+
return `${greeting}. Clear queue \u2014 take a nice, deep breath.`;
|
|
719
740
|
}
|
|
720
741
|
function TodayHero({
|
|
721
|
-
message = "Take a nice, deep breath."
|
|
742
|
+
message = "Take a nice, deep breath.",
|
|
743
|
+
brief,
|
|
744
|
+
briefMeta
|
|
745
|
+
}) {
|
|
746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mt-4 sm:mt-6", children: [
|
|
747
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
748
|
+
"p",
|
|
749
|
+
{
|
|
750
|
+
className: "today-hero max-w-2xl font-display text-lg font-semibold tracking-tight text-ph-ink sm:text-xl sm:leading-snug",
|
|
751
|
+
children: message
|
|
752
|
+
},
|
|
753
|
+
typeof message === "string" ? message : "hero"
|
|
754
|
+
),
|
|
755
|
+
brief ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mt-4 max-w-2xl", "data-test": "today-focus-brief", children: [
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[15px] leading-[1.65] text-ph-ink", children: brief }),
|
|
757
|
+
briefMeta ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mt-1.5 text-xs text-ph-mutedtext", children: briefMeta }) : null
|
|
758
|
+
] }) : null
|
|
759
|
+
] });
|
|
760
|
+
}
|
|
761
|
+
function TodayPrimaryAction({
|
|
762
|
+
label,
|
|
763
|
+
description,
|
|
764
|
+
icon,
|
|
765
|
+
accent = "neutral",
|
|
766
|
+
onClick,
|
|
767
|
+
href,
|
|
768
|
+
loading = false,
|
|
769
|
+
active = false,
|
|
770
|
+
className,
|
|
771
|
+
dataTest = "today-primary-action"
|
|
722
772
|
}) {
|
|
723
|
-
|
|
724
|
-
"
|
|
773
|
+
const classes = cn(
|
|
774
|
+
"today-primary-action group relative flex w-full max-w-md items-center gap-3 overflow-hidden rounded-xl px-3.5 py-2.5 text-left transition sm:px-4 sm:py-3",
|
|
775
|
+
`today-primary-action--${accent}`,
|
|
776
|
+
active && "today-primary-action--active",
|
|
777
|
+
loading && "pointer-events-none opacity-70",
|
|
778
|
+
className
|
|
779
|
+
);
|
|
780
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "today-primary-action__icon inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg sm:h-10 sm:w-10", children: icon }),
|
|
782
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
783
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "block text-sm font-semibold tracking-tight sm:text-base", children: label }),
|
|
784
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mt-0.5 block text-xs opacity-80 sm:text-sm", children: description }) : null
|
|
785
|
+
] }),
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
787
|
+
"span",
|
|
788
|
+
{
|
|
789
|
+
className: "today-primary-action__chevron shrink-0 text-base opacity-60 transition group-hover:translate-x-0.5 group-hover:opacity-100",
|
|
790
|
+
"aria-hidden": true,
|
|
791
|
+
children: "\u2192"
|
|
792
|
+
}
|
|
793
|
+
)
|
|
794
|
+
] });
|
|
795
|
+
if (href && !onClick) {
|
|
796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
797
|
+
"a",
|
|
798
|
+
{
|
|
799
|
+
href,
|
|
800
|
+
className: classes,
|
|
801
|
+
"data-test": dataTest,
|
|
802
|
+
"aria-busy": loading,
|
|
803
|
+
children: body
|
|
804
|
+
}
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
808
|
+
"button",
|
|
725
809
|
{
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
810
|
+
type: "button",
|
|
811
|
+
onClick,
|
|
812
|
+
disabled: loading,
|
|
813
|
+
className: classes,
|
|
814
|
+
"data-test": dataTest,
|
|
815
|
+
"aria-busy": loading,
|
|
816
|
+
children: body
|
|
817
|
+
}
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
function TodayEmptyAction({
|
|
821
|
+
title,
|
|
822
|
+
description,
|
|
823
|
+
actionLabel,
|
|
824
|
+
href,
|
|
825
|
+
onClick,
|
|
826
|
+
dataTest
|
|
827
|
+
}) {
|
|
828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
829
|
+
"div",
|
|
830
|
+
{
|
|
831
|
+
className: "rounded-lg border border-dashed border-ph-border/80 bg-ph-muted/30 px-4 py-4 text-center",
|
|
832
|
+
"data-test": dataTest,
|
|
833
|
+
children: [
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-sm font-semibold text-ph-ink", children: title }),
|
|
835
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-auto mt-1 max-w-sm text-xs leading-relaxed text-ph-subtle sm:text-sm", children: description }) : null,
|
|
836
|
+
actionLabel && (href || onClick) ? href ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
837
|
+
"a",
|
|
838
|
+
{
|
|
839
|
+
href,
|
|
840
|
+
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
841
|
+
children: actionLabel
|
|
842
|
+
}
|
|
843
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
844
|
+
"button",
|
|
845
|
+
{
|
|
846
|
+
type: "button",
|
|
847
|
+
onClick,
|
|
848
|
+
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
849
|
+
children: actionLabel
|
|
850
|
+
}
|
|
851
|
+
) : null
|
|
852
|
+
]
|
|
853
|
+
}
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
function TodayLayout({
|
|
857
|
+
primary,
|
|
858
|
+
main,
|
|
859
|
+
aside,
|
|
860
|
+
className
|
|
861
|
+
}) {
|
|
862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
863
|
+
"div",
|
|
864
|
+
{
|
|
865
|
+
className: cn("mt-5 space-y-6 sm:mt-6", className),
|
|
866
|
+
"data-test": "today-layout",
|
|
867
|
+
children: [
|
|
868
|
+
primary ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-w-md", children: primary }) : null,
|
|
869
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(16rem,20rem)] lg:items-start lg:gap-8", children: [
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "min-w-0 space-y-8", children: main }),
|
|
871
|
+
aside ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("aside", { className: "space-y-3 lg:sticky lg:top-6 lg:self-start", children: aside }) : null
|
|
872
|
+
] })
|
|
873
|
+
]
|
|
874
|
+
}
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
function TodayAskAiCard({
|
|
878
|
+
title = "Ask AI",
|
|
879
|
+
description = "Ask about your workspace, draft something, or look a fact up online.",
|
|
880
|
+
cta = "Ask",
|
|
881
|
+
className,
|
|
882
|
+
onClick,
|
|
883
|
+
href
|
|
884
|
+
}) {
|
|
885
|
+
const classes = cn(
|
|
886
|
+
"group flex w-full items-start gap-3.5 rounded-2xl border border-ph-border/70 bg-ph-surface px-4 py-3.5 text-left shadow-[0_1px_12px_-8px_rgba(15,23,42,0.1)] transition hover:border-ph-brand/35 hover:bg-[color-mix(in_oklab,var(--ph-accent)_6%,var(--ph-surface))] sm:px-5",
|
|
887
|
+
className
|
|
888
|
+
);
|
|
889
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-ph-brand/15 text-ph-brand shadow-sm ring-1 ring-black/[0.06]", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuiteIcon, { name: "stack-hex", accent: "shellstack", className: "h-5 w-5" }) }),
|
|
891
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "min-w-0 flex-1", children: [
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1", children: [
|
|
893
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-display text-sm font-bold tracking-tight text-ph-ink", children: title }),
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm font-medium text-ph-brand transition group-hover:underline", children: cta })
|
|
895
|
+
] }),
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mt-1 block text-sm leading-relaxed text-ph-subtle", children: description })
|
|
897
|
+
] })
|
|
898
|
+
] });
|
|
899
|
+
if (onClick) {
|
|
900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
901
|
+
"button",
|
|
902
|
+
{
|
|
903
|
+
type: "button",
|
|
904
|
+
onClick,
|
|
905
|
+
className: classes,
|
|
906
|
+
"data-test": "today-ask-ai",
|
|
907
|
+
children: body
|
|
908
|
+
}
|
|
909
|
+
);
|
|
910
|
+
}
|
|
911
|
+
if (href) {
|
|
912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { href, className: classes, "data-test": "today-ask-ai", children: body });
|
|
913
|
+
}
|
|
914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: classes, "data-test": "today-ask-ai", children: body });
|
|
731
915
|
}
|
|
732
916
|
function TodaySection({
|
|
733
917
|
icon: Icon,
|
|
@@ -738,7 +922,7 @@ function TodaySection({
|
|
|
738
922
|
testId,
|
|
739
923
|
children
|
|
740
924
|
}) {
|
|
741
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { "data-test": testId, className: "space-y-
|
|
925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { "data-test": testId, className: "space-y-5", children: [
|
|
742
926
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
|
|
743
927
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-w-0 items-start gap-3.5", children: [
|
|
744
928
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -769,8 +953,7 @@ function TodayPanel({
|
|
|
769
953
|
"div",
|
|
770
954
|
{
|
|
771
955
|
className: cn(
|
|
772
|
-
"border-ph-border/70 rounded-2xl border bg-ph-surface p-
|
|
773
|
-
"hover:shadow-[0_8px_32px_-12px_rgba(15,23,42,0.18)] hover:-translate-y-0.5 motion-reduce:transition-none motion-reduce:hover:transform-none",
|
|
956
|
+
"border-ph-border/70 rounded-2xl border bg-ph-surface p-5 shadow-[0_1px_16px_-8px_rgba(15,23,42,0.12)] sm:p-5",
|
|
774
957
|
className
|
|
775
958
|
),
|
|
776
959
|
children
|
|
@@ -948,6 +1131,70 @@ function AppSwitcher({
|
|
|
948
1131
|
var import_react2 = require("react");
|
|
949
1132
|
var import_navigation = require("next/navigation");
|
|
950
1133
|
var import_iconoir_react3 = require("iconoir-react");
|
|
1134
|
+
|
|
1135
|
+
// src/suite/lib/apps.ts
|
|
1136
|
+
var SUITE_APPS2 = [
|
|
1137
|
+
{
|
|
1138
|
+
slug: "shellstack",
|
|
1139
|
+
name: "ShellStack",
|
|
1140
|
+
description: "Organisation and billing",
|
|
1141
|
+
icon: "/icon-shellstack.svg",
|
|
1142
|
+
landing: "/home",
|
|
1143
|
+
baseUrlEnv: "NEXT_PUBLIC_SHELLSTACK_URL",
|
|
1144
|
+
baseUrlFallback: "http://localhost:3002"
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
slug: "tides",
|
|
1148
|
+
name: "Tides",
|
|
1149
|
+
description: "Projects and tasks",
|
|
1150
|
+
icon: "/tides-icon.svg",
|
|
1151
|
+
landing: "/today",
|
|
1152
|
+
baseUrlEnv: "NEXT_PUBLIC_TIDES_URL",
|
|
1153
|
+
baseUrlFallback: "http://localhost:3001"
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
slug: "turtletime",
|
|
1157
|
+
name: "TurtleTime",
|
|
1158
|
+
description: "Time tracking",
|
|
1159
|
+
icon: "/turtletime-icon.svg",
|
|
1160
|
+
landing: "/today",
|
|
1161
|
+
baseUrlEnv: "NEXT_PUBLIC_TURTLETIME_URL",
|
|
1162
|
+
baseUrlFallback: "http://localhost:3000"
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
slug: "kraken",
|
|
1166
|
+
name: "Kraken",
|
|
1167
|
+
description: "Documents and knowledge",
|
|
1168
|
+
icon: "/kraken-icon.svg",
|
|
1169
|
+
landing: "/today",
|
|
1170
|
+
baseUrlEnv: "NEXT_PUBLIC_KRAKEN_URL",
|
|
1171
|
+
baseUrlFallback: "http://localhost:3003"
|
|
1172
|
+
}
|
|
1173
|
+
];
|
|
1174
|
+
var SUITE_APP_MAP = Object.fromEntries(SUITE_APPS2.map((app) => [app.slug, app]));
|
|
1175
|
+
function suiteAppBaseUrl(slug) {
|
|
1176
|
+
const def = SUITE_APP_MAP[slug];
|
|
1177
|
+
const fromEnv = typeof process !== "undefined" ? process.env[def.baseUrlEnv] : void 0;
|
|
1178
|
+
return (fromEnv || def.baseUrlFallback).replace(/\/$/, "");
|
|
1179
|
+
}
|
|
1180
|
+
var SOURCE_APP_SLUG = {
|
|
1181
|
+
turtletime: "turtletime",
|
|
1182
|
+
tides: "tides",
|
|
1183
|
+
kraken: "kraken",
|
|
1184
|
+
portal: "shellstack",
|
|
1185
|
+
shellstack: "shellstack"
|
|
1186
|
+
};
|
|
1187
|
+
function resolveSuiteNotificationHref(href, sourceApp) {
|
|
1188
|
+
const value = (href || "").trim();
|
|
1189
|
+
if (!value) return "";
|
|
1190
|
+
if (/^(https?:|mailto:|\/\/)/i.test(value)) return value;
|
|
1191
|
+
const path = value.startsWith("/") ? value : `/${value}`;
|
|
1192
|
+
const slug = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()];
|
|
1193
|
+
if (!slug) return path;
|
|
1194
|
+
return `${suiteAppBaseUrl(slug)}${path}`;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
// src/suite/components/suite-notification-bell.tsx
|
|
951
1198
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
952
1199
|
var POLL_MS = 6e4;
|
|
953
1200
|
function timeAgo(iso) {
|
|
@@ -1038,9 +1285,13 @@ function SuiteNotificationBell({
|
|
|
1038
1285
|
} catch (e) {
|
|
1039
1286
|
}
|
|
1040
1287
|
}
|
|
1041
|
-
|
|
1042
|
-
if (
|
|
1043
|
-
|
|
1288
|
+
const target = resolveSuiteNotificationHref(n.href, n.source_app);
|
|
1289
|
+
if (!target) return;
|
|
1290
|
+
if (/^https?:\/\//i.test(target)) {
|
|
1291
|
+
window.location.assign(target);
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
router.push(target);
|
|
1044
1295
|
},
|
|
1045
1296
|
[router, markRead]
|
|
1046
1297
|
);
|
|
@@ -1193,6 +1444,7 @@ function SuiteMobileDrawer({
|
|
|
1193
1444
|
children,
|
|
1194
1445
|
side = "left",
|
|
1195
1446
|
showCloseButton = false,
|
|
1447
|
+
title,
|
|
1196
1448
|
closeLabel = "Close navigation",
|
|
1197
1449
|
backdropLabel = "Close navigation",
|
|
1198
1450
|
dialogLabel = "Navigation",
|
|
@@ -1270,23 +1522,35 @@ function SuiteMobileDrawer({
|
|
|
1270
1522
|
tabIndex: -1,
|
|
1271
1523
|
"data-test": panelDataTest,
|
|
1272
1524
|
className: cn(
|
|
1273
|
-
"suite-scroll-lock relative flex h-full w-[86%] max-w-
|
|
1525
|
+
"suite-scroll-lock relative flex h-full w-[86%] max-w-72 flex-col overflow-hidden bg-ph-surface shadow-xl outline-none motion-safe:transition-transform motion-safe:ease-spring-fast",
|
|
1274
1526
|
side === "right" && "ml-auto",
|
|
1275
1527
|
shown ? "translate-x-0" : side === "right" ? "translate-x-full" : "-translate-x-full",
|
|
1276
1528
|
panelClassName
|
|
1277
1529
|
),
|
|
1278
1530
|
style: { transitionDuration: `${durationMs}ms` },
|
|
1279
1531
|
children: [
|
|
1280
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
1281
|
-
"
|
|
1532
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1533
|
+
"div",
|
|
1282
1534
|
{
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
children:
|
|
1535
|
+
className: cn(
|
|
1536
|
+
"flex h-14 shrink-0 items-center border-b border-ph-border px-3",
|
|
1537
|
+
title ? "justify-between" : "justify-end"
|
|
1538
|
+
),
|
|
1539
|
+
children: [
|
|
1540
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate text-sm font-semibold text-ph-ink", children: title }) : null,
|
|
1541
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1542
|
+
"button",
|
|
1543
|
+
{
|
|
1544
|
+
type: "button",
|
|
1545
|
+
onClick: onClose,
|
|
1546
|
+
className: "-mr-1.5 inline-flex h-11 w-11 items-center justify-center rounded-lg text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
1547
|
+
"aria-label": closeLabel,
|
|
1548
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_iconoir_react4.Xmark, { className: "h-4 w-4", "aria-hidden": true })
|
|
1549
|
+
}
|
|
1550
|
+
)
|
|
1551
|
+
]
|
|
1288
1552
|
}
|
|
1289
|
-
)
|
|
1553
|
+
) : null,
|
|
1290
1554
|
children
|
|
1291
1555
|
]
|
|
1292
1556
|
}
|
|
@@ -1343,95 +1607,378 @@ function SuiteMobileHeader({
|
|
|
1343
1607
|
);
|
|
1344
1608
|
}
|
|
1345
1609
|
|
|
1346
|
-
// src/suite/components/suite-
|
|
1347
|
-
var
|
|
1348
|
-
var import_navigation2 = require("next/navigation");
|
|
1349
|
-
var import_iconoir_react6 = require("iconoir-react");
|
|
1350
|
-
|
|
1351
|
-
// src/components/ui/DropdownMenu.tsx
|
|
1352
|
-
var DropdownPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
|
|
1353
|
-
|
|
1354
|
-
// src/lib/cn.ts
|
|
1355
|
-
function cn2(...parts) {
|
|
1356
|
-
return parts.filter(Boolean).join(" ");
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
// src/components/ui/DropdownMenu.tsx
|
|
1610
|
+
// src/suite/components/suite-layout.tsx
|
|
1611
|
+
var import_react6 = require("react");
|
|
1360
1612
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1361
|
-
function
|
|
1613
|
+
function SuiteBreadcrumbs({ items, className }) {
|
|
1614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ol", { className: "flex min-w-0 items-center gap-1.5", children: items.map((item, index) => {
|
|
1615
|
+
const isLast = index === items.length - 1;
|
|
1616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("li", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1617
|
+
index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "select-none text-ph-border", "aria-hidden": "true", children: "/" }) : null,
|
|
1618
|
+
item.href && !isLast ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1619
|
+
"a",
|
|
1620
|
+
{
|
|
1621
|
+
href: item.href,
|
|
1622
|
+
className: "truncate transition hover:text-ph-ink",
|
|
1623
|
+
children: item.label
|
|
1624
|
+
}
|
|
1625
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1626
|
+
"span",
|
|
1627
|
+
{
|
|
1628
|
+
className: cn(
|
|
1629
|
+
"truncate",
|
|
1630
|
+
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
1631
|
+
),
|
|
1632
|
+
"aria-current": isLast ? "page" : void 0,
|
|
1633
|
+
children: item.label
|
|
1634
|
+
}
|
|
1635
|
+
)
|
|
1636
|
+
] }, index);
|
|
1637
|
+
}) }) });
|
|
1638
|
+
}
|
|
1639
|
+
function SuitePage({
|
|
1362
1640
|
children,
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1641
|
+
width = "full",
|
|
1642
|
+
inset = true,
|
|
1643
|
+
className,
|
|
1644
|
+
as: Component = "div",
|
|
1645
|
+
dataTest,
|
|
1646
|
+
id,
|
|
1647
|
+
role,
|
|
1648
|
+
"aria-live": ariaLive
|
|
1370
1649
|
}) {
|
|
1371
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1372
|
-
|
|
1650
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1651
|
+
Component,
|
|
1373
1652
|
{
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
]
|
|
1653
|
+
id,
|
|
1654
|
+
"data-test": dataTest,
|
|
1655
|
+
"data-width": width,
|
|
1656
|
+
role,
|
|
1657
|
+
"aria-live": ariaLive,
|
|
1658
|
+
className: cn(
|
|
1659
|
+
"suite-page-stage flex w-full min-w-0 flex-col",
|
|
1660
|
+
inset && "suite-page-inset",
|
|
1661
|
+
className
|
|
1662
|
+
),
|
|
1663
|
+
children
|
|
1386
1664
|
}
|
|
1387
|
-
)
|
|
1665
|
+
);
|
|
1388
1666
|
}
|
|
1389
|
-
function
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
"
|
|
1417
|
-
"
|
|
1418
|
-
"
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
{
|
|
1667
|
+
function SuitePageHeader({
|
|
1668
|
+
title,
|
|
1669
|
+
description,
|
|
1670
|
+
eyebrow,
|
|
1671
|
+
actions,
|
|
1672
|
+
className,
|
|
1673
|
+
titleClassName,
|
|
1674
|
+
dataTest,
|
|
1675
|
+
/** Optional icon rendered before the title. */
|
|
1676
|
+
icon,
|
|
1677
|
+
/** Use the animated sun/moon icon from the Today page. */
|
|
1678
|
+
todayIcon,
|
|
1679
|
+
todayIconClassName,
|
|
1680
|
+
/** Small badge/pill next to the title (e.g. "Beta", org name). */
|
|
1681
|
+
badge,
|
|
1682
|
+
/** Breadcrumb line rendered above the title. */
|
|
1683
|
+
breadcrumb,
|
|
1684
|
+
/** Stick to the top of the scrollport (desktop page titles). */
|
|
1685
|
+
sticky = false
|
|
1686
|
+
}) {
|
|
1687
|
+
const headerRef = (0, import_react6.useRef)(null);
|
|
1688
|
+
const [stuck, setStuck] = (0, import_react6.useState)(false);
|
|
1689
|
+
(0, import_react6.useEffect)(() => {
|
|
1690
|
+
var _a;
|
|
1691
|
+
if (!sticky) return;
|
|
1692
|
+
const el = headerRef.current;
|
|
1693
|
+
if (!el) return;
|
|
1694
|
+
const sentinel = document.createElement("div");
|
|
1695
|
+
sentinel.setAttribute("aria-hidden", "true");
|
|
1696
|
+
sentinel.style.cssText = "position:relative;height:1px;width:100%;margin:0;padding:0;pointer-events:none";
|
|
1697
|
+
(_a = el.parentElement) == null ? void 0 : _a.insertBefore(sentinel, el);
|
|
1698
|
+
const observer = new IntersectionObserver(
|
|
1699
|
+
([entry]) => {
|
|
1700
|
+
setStuck(!entry.isIntersecting);
|
|
1701
|
+
},
|
|
1702
|
+
{ threshold: [1], root: null }
|
|
1703
|
+
);
|
|
1704
|
+
observer.observe(sentinel);
|
|
1705
|
+
return () => {
|
|
1706
|
+
observer.disconnect();
|
|
1707
|
+
sentinel.remove();
|
|
1708
|
+
};
|
|
1709
|
+
}, [sticky]);
|
|
1710
|
+
const resolvedIcon = todayIcon ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1711
|
+
TodayTimeIcon,
|
|
1712
|
+
{
|
|
1713
|
+
className: cn(
|
|
1714
|
+
"h-7 w-7 text-amber-500 sm:h-8 sm:w-8",
|
|
1715
|
+
todayIconClassName
|
|
1716
|
+
)
|
|
1717
|
+
}
|
|
1718
|
+
) : icon;
|
|
1719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1720
|
+
"header",
|
|
1721
|
+
{
|
|
1722
|
+
ref: headerRef,
|
|
1723
|
+
"data-test": dataTest,
|
|
1724
|
+
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1725
|
+
className: cn(
|
|
1726
|
+
"flex items-start justify-between gap-4 pb-2 sm:pb-3",
|
|
1727
|
+
// No extra pt here — page inset sets the shared title baseline.
|
|
1728
|
+
// Stuck state adds pad via .suite-page-header-sticky[data-stuck].
|
|
1729
|
+
sticky && "suite-page-header-sticky",
|
|
1730
|
+
className
|
|
1731
|
+
),
|
|
1732
|
+
children: [
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
1734
|
+
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: eyebrow }) : null,
|
|
1735
|
+
breadcrumb ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: breadcrumb }) : null,
|
|
1736
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
1737
|
+
resolvedIcon ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1738
|
+
"div",
|
|
1739
|
+
{
|
|
1740
|
+
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-7 [&_svg]:w-7 sm:[&_svg]:h-8 sm:[&_svg]:w-8",
|
|
1741
|
+
"aria-hidden": "true",
|
|
1742
|
+
children: resolvedIcon
|
|
1743
|
+
}
|
|
1744
|
+
) : null,
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1746
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1747
|
+
"h1",
|
|
1748
|
+
{
|
|
1749
|
+
className: cn(
|
|
1750
|
+
"font-display text-[1.625rem] font-bold leading-none tracking-tight text-ph-ink sm:text-[2.25rem]",
|
|
1751
|
+
titleClassName
|
|
1752
|
+
),
|
|
1753
|
+
children: title
|
|
1754
|
+
}
|
|
1755
|
+
),
|
|
1756
|
+
badge ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-md bg-ph-muted px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-ph-subtle", children: badge }) : null
|
|
1757
|
+
] })
|
|
1758
|
+
] }),
|
|
1759
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1760
|
+
"div",
|
|
1761
|
+
{
|
|
1762
|
+
className: cn(
|
|
1763
|
+
"mt-1.5 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle",
|
|
1764
|
+
resolvedIcon && "sm:pl-11"
|
|
1765
|
+
),
|
|
1766
|
+
children: description
|
|
1767
|
+
}
|
|
1768
|
+
) : null
|
|
1769
|
+
] }),
|
|
1770
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex shrink-0 items-center gap-2 self-center", children: actions }) : null
|
|
1771
|
+
]
|
|
1772
|
+
}
|
|
1773
|
+
);
|
|
1774
|
+
}
|
|
1775
|
+
function SuiteToolbar({
|
|
1776
|
+
children,
|
|
1777
|
+
className,
|
|
1778
|
+
label = "Page tools",
|
|
1779
|
+
dataTest
|
|
1780
|
+
}) {
|
|
1781
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1782
|
+
"div",
|
|
1783
|
+
{
|
|
1784
|
+
role: "toolbar",
|
|
1785
|
+
"aria-label": label,
|
|
1786
|
+
"data-test": dataTest,
|
|
1787
|
+
className: cn("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
1788
|
+
children
|
|
1789
|
+
}
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1792
|
+
function SuiteTabList({
|
|
1793
|
+
children,
|
|
1794
|
+
className,
|
|
1795
|
+
label,
|
|
1796
|
+
dataTest
|
|
1797
|
+
}) {
|
|
1798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1799
|
+
"nav",
|
|
1800
|
+
{
|
|
1801
|
+
"aria-label": label,
|
|
1802
|
+
"data-test": dataTest,
|
|
1803
|
+
className: cn(
|
|
1804
|
+
"flex min-w-0 flex-wrap gap-2 [&_a]:min-h-[48px] [&_button]:min-h-[48px] sm:[&_a]:min-h-[44px] sm:[&_button]:min-h-[44px]",
|
|
1805
|
+
className
|
|
1806
|
+
),
|
|
1807
|
+
children
|
|
1808
|
+
}
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
function SuiteSectionHeader({
|
|
1812
|
+
title,
|
|
1813
|
+
description,
|
|
1814
|
+
action,
|
|
1815
|
+
className
|
|
1816
|
+
}) {
|
|
1817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1818
|
+
"div",
|
|
1819
|
+
{
|
|
1820
|
+
className: cn(
|
|
1821
|
+
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
1822
|
+
className
|
|
1823
|
+
),
|
|
1824
|
+
children: [
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
1826
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { className: "font-display text-balance text-lg font-semibold tracking-tight text-ph-ink sm:text-xl", children: title }),
|
|
1827
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
1828
|
+
] }),
|
|
1829
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
1830
|
+
]
|
|
1831
|
+
}
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
// src/suite/components/suite-settings-layout.tsx
|
|
1836
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1837
|
+
function SuiteSettingsLayout({
|
|
1838
|
+
children,
|
|
1839
|
+
sidebar,
|
|
1840
|
+
mobileNav,
|
|
1841
|
+
loading,
|
|
1842
|
+
title = "Settings",
|
|
1843
|
+
description,
|
|
1844
|
+
header,
|
|
1845
|
+
dataTest = "settings-page",
|
|
1846
|
+
headerDataTest = "settings-page-header",
|
|
1847
|
+
className,
|
|
1848
|
+
contentClassName
|
|
1849
|
+
}) {
|
|
1850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1851
|
+
SuitePage,
|
|
1852
|
+
{
|
|
1853
|
+
dataTest,
|
|
1854
|
+
className: cn("flex h-full flex-col overflow-hidden", className),
|
|
1855
|
+
children: [
|
|
1856
|
+
header != null ? header : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1857
|
+
SuitePageHeader,
|
|
1858
|
+
{
|
|
1859
|
+
sticky: true,
|
|
1860
|
+
dataTest: headerDataTest,
|
|
1861
|
+
title,
|
|
1862
|
+
description
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
loading != null ? loading : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "suite-page-body mt-6 flex min-h-0 flex-1 flex-col", children: [
|
|
1866
|
+
mobileNav ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "sticky top-0 z-20 mb-2 shrink-0 bg-ph-canvas/95 backdrop-blur lg:hidden", children: mobileNav }) : null,
|
|
1867
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-6 lg:flex-row lg:gap-8", children: [
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1869
|
+
"aside",
|
|
1870
|
+
{
|
|
1871
|
+
"aria-label": "Settings",
|
|
1872
|
+
className: "hidden w-56 shrink-0 bg-transparent lg:block lg:self-stretch lg:overflow-y-auto lg:overscroll-contain",
|
|
1873
|
+
children: sidebar
|
|
1874
|
+
}
|
|
1875
|
+
),
|
|
1876
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1877
|
+
"div",
|
|
1878
|
+
{
|
|
1879
|
+
className: cn(
|
|
1880
|
+
"min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain pb-6",
|
|
1881
|
+
contentClassName
|
|
1882
|
+
),
|
|
1883
|
+
children
|
|
1884
|
+
}
|
|
1885
|
+
)
|
|
1886
|
+
] })
|
|
1887
|
+
] })
|
|
1888
|
+
]
|
|
1889
|
+
}
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
// src/suite/components/suite-user-menu.tsx
|
|
1894
|
+
var import_image2 = __toESM(require("next/image"));
|
|
1895
|
+
var import_navigation2 = require("next/navigation");
|
|
1896
|
+
var import_iconoir_react6 = require("iconoir-react");
|
|
1897
|
+
|
|
1898
|
+
// src/components/ui/DropdownMenu.tsx
|
|
1899
|
+
var DropdownPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
|
|
1900
|
+
|
|
1901
|
+
// src/lib/cn.ts
|
|
1902
|
+
function cn2(...parts) {
|
|
1903
|
+
return parts.filter(Boolean).join(" ");
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// src/components/ui/DropdownMenu.tsx
|
|
1907
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1908
|
+
function DropdownContent({
|
|
1909
|
+
children,
|
|
1910
|
+
align = "start",
|
|
1911
|
+
side = "bottom",
|
|
1912
|
+
sideOffset = 7,
|
|
1913
|
+
alignOffset = 0,
|
|
1914
|
+
collisionPadding = 8,
|
|
1915
|
+
avoidCollisions = true,
|
|
1916
|
+
panelClassName
|
|
1917
|
+
}) {
|
|
1918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1919
|
+
DropdownPrimitive.Content,
|
|
1920
|
+
{
|
|
1921
|
+
className: cn2("ph-dropdown-panel", panelClassName),
|
|
1922
|
+
align,
|
|
1923
|
+
side,
|
|
1924
|
+
sideOffset,
|
|
1925
|
+
alignOffset,
|
|
1926
|
+
collisionPadding,
|
|
1927
|
+
avoidCollisions,
|
|
1928
|
+
sticky: "partial",
|
|
1929
|
+
children: [
|
|
1930
|
+
children,
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Arrow, { className: "ph-dropdown-arrow", width: 12, height: 6 })
|
|
1932
|
+
]
|
|
1933
|
+
}
|
|
1934
|
+
) });
|
|
1935
|
+
}
|
|
1936
|
+
function DropdownMenu(_a) {
|
|
1937
|
+
var _b = _a, {
|
|
1938
|
+
trigger,
|
|
1939
|
+
children,
|
|
1940
|
+
align,
|
|
1941
|
+
side,
|
|
1942
|
+
sideOffset,
|
|
1943
|
+
alignOffset,
|
|
1944
|
+
collisionPadding,
|
|
1945
|
+
avoidCollisions,
|
|
1946
|
+
className,
|
|
1947
|
+
panelClassName,
|
|
1948
|
+
"aria-label": ariaLabel,
|
|
1949
|
+
open,
|
|
1950
|
+
defaultOpen,
|
|
1951
|
+
onOpenChange,
|
|
1952
|
+
modal = false,
|
|
1953
|
+
disabled
|
|
1954
|
+
} = _b, props = __objRest(_b, [
|
|
1955
|
+
"trigger",
|
|
1956
|
+
"children",
|
|
1957
|
+
"align",
|
|
1958
|
+
"side",
|
|
1959
|
+
"sideOffset",
|
|
1960
|
+
"alignOffset",
|
|
1961
|
+
"collisionPadding",
|
|
1962
|
+
"avoidCollisions",
|
|
1963
|
+
"className",
|
|
1964
|
+
"panelClassName",
|
|
1965
|
+
"aria-label",
|
|
1966
|
+
"open",
|
|
1967
|
+
"defaultOpen",
|
|
1968
|
+
"onOpenChange",
|
|
1969
|
+
"modal",
|
|
1970
|
+
"disabled"
|
|
1971
|
+
]);
|
|
1972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", __spreadProps(__spreadValues({ className: cn2("ph-dropdown", className) }, props), { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1973
|
+
DropdownPrimitive.Root,
|
|
1974
|
+
{
|
|
1428
1975
|
open,
|
|
1429
1976
|
defaultOpen,
|
|
1430
1977
|
onOpenChange,
|
|
1431
1978
|
modal,
|
|
1432
1979
|
children: [
|
|
1433
|
-
/* @__PURE__ */ (0,
|
|
1434
|
-
/* @__PURE__ */ (0,
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Trigger, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "ph-dropdown-trigger", "aria-label": ariaLabel, children: trigger }) }),
|
|
1981
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1435
1982
|
DropdownContent,
|
|
1436
1983
|
{
|
|
1437
1984
|
align,
|
|
@@ -1450,7 +1997,7 @@ function DropdownMenu(_a) {
|
|
|
1450
1997
|
}
|
|
1451
1998
|
function DropdownItem(_a) {
|
|
1452
1999
|
var _b = _a, { className, children, disabled } = _b, props = __objRest(_b, ["className", "children", "disabled"]);
|
|
1453
|
-
return /* @__PURE__ */ (0,
|
|
2000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownPrimitive.Item, { asChild: true, disabled, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1454
2001
|
"button",
|
|
1455
2002
|
__spreadProps(__spreadValues({
|
|
1456
2003
|
type: "button",
|
|
@@ -1463,7 +2010,7 @@ function DropdownItem(_a) {
|
|
|
1463
2010
|
}
|
|
1464
2011
|
|
|
1465
2012
|
// src/suite/components/suite-user-menu.tsx
|
|
1466
|
-
var
|
|
2013
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1467
2014
|
function computeInitials(name, email) {
|
|
1468
2015
|
const source = (name || email || "?").trim();
|
|
1469
2016
|
return source.split(/[\s@]+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
@@ -1480,7 +2027,7 @@ function SuiteUserMenu({
|
|
|
1480
2027
|
}) {
|
|
1481
2028
|
const router = (0, import_navigation2.useRouter)();
|
|
1482
2029
|
const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
|
|
1483
|
-
const avatar = /* @__PURE__ */ (0,
|
|
2030
|
+
const avatar = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "inline-flex h-11 w-11 items-center justify-center rounded-full transition-colors hover:bg-ph-muted", children: image ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1484
2031
|
import_image2.default,
|
|
1485
2032
|
{
|
|
1486
2033
|
src: image,
|
|
@@ -1490,8 +2037,8 @@ function SuiteUserMenu({
|
|
|
1490
2037
|
className: "h-8 w-8 rounded-full object-cover",
|
|
1491
2038
|
unoptimized: true
|
|
1492
2039
|
}
|
|
1493
|
-
) : /* @__PURE__ */ (0,
|
|
1494
|
-
return /* @__PURE__ */ (0,
|
|
2040
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "flex h-8 w-8 items-center justify-center rounded-full bg-ph-muted text-sm font-semibold text-ph-brand", children: initials }) });
|
|
2041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1495
2042
|
DropdownMenu,
|
|
1496
2043
|
{
|
|
1497
2044
|
trigger: avatar,
|
|
@@ -1504,29 +2051,29 @@ function SuiteUserMenu({
|
|
|
1504
2051
|
className,
|
|
1505
2052
|
"data-test": dataTest,
|
|
1506
2053
|
children: [
|
|
1507
|
-
/* @__PURE__ */ (0,
|
|
1508
|
-
/* @__PURE__ */ (0,
|
|
1509
|
-
email ? /* @__PURE__ */ (0,
|
|
2054
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "px-2 py-1.5", children: [
|
|
2055
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "truncate text-sm font-medium text-ph-ink", children: name || email || "Account" }),
|
|
2056
|
+
email ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "truncate text-xs text-ph-mutedtext", children: email }) : null
|
|
1510
2057
|
] }),
|
|
1511
|
-
/* @__PURE__ */ (0,
|
|
1512
|
-
/* @__PURE__ */ (0,
|
|
2058
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "my-1 border-t border-ph-border" }),
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1513
2060
|
DropdownItem,
|
|
1514
2061
|
{
|
|
1515
2062
|
"data-test": `${dataTest}-settings`,
|
|
1516
2063
|
onClick: () => router.push(settingsHref),
|
|
1517
2064
|
children: [
|
|
1518
|
-
/* @__PURE__ */ (0,
|
|
2065
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_iconoir_react6.Settings, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
1519
2066
|
"Profile settings"
|
|
1520
2067
|
]
|
|
1521
2068
|
}
|
|
1522
2069
|
),
|
|
1523
|
-
/* @__PURE__ */ (0,
|
|
2070
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1524
2071
|
DropdownItem,
|
|
1525
2072
|
{
|
|
1526
2073
|
"data-test": `${dataTest}-sign-out`,
|
|
1527
2074
|
onClick: onSignOut,
|
|
1528
2075
|
children: [
|
|
1529
|
-
/* @__PURE__ */ (0,
|
|
2076
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_iconoir_react6.LogOut, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
1530
2077
|
"Sign out"
|
|
1531
2078
|
]
|
|
1532
2079
|
}
|
|
@@ -1538,7 +2085,7 @@ function SuiteUserMenu({
|
|
|
1538
2085
|
|
|
1539
2086
|
// src/suite/components/suite-bottom-nav.tsx
|
|
1540
2087
|
var import_link = __toESM(require("next/link"));
|
|
1541
|
-
var
|
|
2088
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1542
2089
|
function SuiteBottomNav({
|
|
1543
2090
|
items,
|
|
1544
2091
|
ariaLabel = "Primary navigation",
|
|
@@ -1551,8 +2098,8 @@ function SuiteBottomNav({
|
|
|
1551
2098
|
);
|
|
1552
2099
|
}
|
|
1553
2100
|
const activeIndex = items.findIndex((item) => item.active);
|
|
1554
|
-
return /* @__PURE__ */ (0,
|
|
1555
|
-
/* @__PURE__ */ (0,
|
|
2101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1556
2103
|
"div",
|
|
1557
2104
|
{
|
|
1558
2105
|
"aria-hidden": true,
|
|
@@ -1560,7 +2107,7 @@ function SuiteBottomNav({
|
|
|
1560
2107
|
style: { height: "calc(60px + env(safe-area-inset-bottom))" }
|
|
1561
2108
|
}
|
|
1562
2109
|
),
|
|
1563
|
-
/* @__PURE__ */ (0,
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1564
2111
|
"nav",
|
|
1565
2112
|
{
|
|
1566
2113
|
"aria-label": ariaLabel,
|
|
@@ -1575,12 +2122,12 @@ function SuiteBottomNav({
|
|
|
1575
2122
|
"--suite-nav-active": activeIndex >= 0 ? activeIndex : 0
|
|
1576
2123
|
},
|
|
1577
2124
|
children: [
|
|
1578
|
-
activeIndex >= 0 ? /* @__PURE__ */ (0,
|
|
2125
|
+
activeIndex >= 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
|
|
1579
2126
|
items.map((item) => {
|
|
1580
2127
|
var _a;
|
|
1581
2128
|
const Icon = item.icon;
|
|
1582
2129
|
const active = Boolean(item.active);
|
|
1583
|
-
return /* @__PURE__ */ (0,
|
|
2130
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1584
2131
|
import_link.default,
|
|
1585
2132
|
{
|
|
1586
2133
|
href: item.href,
|
|
@@ -1591,14 +2138,14 @@ function SuiteBottomNav({
|
|
|
1591
2138
|
active && "font-semibold text-ph-brand"
|
|
1592
2139
|
),
|
|
1593
2140
|
children: [
|
|
1594
|
-
/* @__PURE__ */ (0,
|
|
2141
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1595
2142
|
"span",
|
|
1596
2143
|
{
|
|
1597
2144
|
className: cn(
|
|
1598
2145
|
"suite-bottom-nav__icon relative z-10 inline-flex items-center justify-center",
|
|
1599
2146
|
active && "suite-bottom-nav__icon--active"
|
|
1600
2147
|
),
|
|
1601
|
-
children: /* @__PURE__ */ (0,
|
|
2148
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1602
2149
|
Icon,
|
|
1603
2150
|
{
|
|
1604
2151
|
className: "h-6 w-6",
|
|
@@ -1608,7 +2155,7 @@ function SuiteBottomNav({
|
|
|
1608
2155
|
)
|
|
1609
2156
|
}
|
|
1610
2157
|
),
|
|
1611
|
-
/* @__PURE__ */ (0,
|
|
2158
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "relative z-10 max-w-full truncate", children: item.label })
|
|
1612
2159
|
]
|
|
1613
2160
|
},
|
|
1614
2161
|
item.href
|
|
@@ -1620,117 +2167,39 @@ function SuiteBottomNav({
|
|
|
1620
2167
|
] });
|
|
1621
2168
|
}
|
|
1622
2169
|
|
|
1623
|
-
// src/suite/lib/apps.ts
|
|
1624
|
-
var SUITE_APPS2 = [
|
|
1625
|
-
{
|
|
1626
|
-
slug: "shellstack",
|
|
1627
|
-
name: "ShellStack",
|
|
1628
|
-
description: "Organisation and billing",
|
|
1629
|
-
icon: "/icon-shellstack.svg",
|
|
1630
|
-
landing: "/home",
|
|
1631
|
-
baseUrlEnv: "NEXT_PUBLIC_SHELLSTACK_URL",
|
|
1632
|
-
baseUrlFallback: "http://localhost:3002"
|
|
1633
|
-
},
|
|
1634
|
-
{
|
|
1635
|
-
slug: "tides",
|
|
1636
|
-
name: "Tides",
|
|
1637
|
-
description: "Projects and tasks",
|
|
1638
|
-
icon: "/tides-icon.svg",
|
|
1639
|
-
landing: "/today",
|
|
1640
|
-
baseUrlEnv: "NEXT_PUBLIC_TIDES_URL",
|
|
1641
|
-
baseUrlFallback: "http://localhost:3001"
|
|
1642
|
-
},
|
|
1643
|
-
{
|
|
1644
|
-
slug: "turtletime",
|
|
1645
|
-
name: "TurtleTime",
|
|
1646
|
-
description: "Time tracking",
|
|
1647
|
-
icon: "/turtletime-icon.svg",
|
|
1648
|
-
landing: "/tracker",
|
|
1649
|
-
baseUrlEnv: "NEXT_PUBLIC_TURTLETIME_URL",
|
|
1650
|
-
baseUrlFallback: "http://localhost:3000"
|
|
1651
|
-
},
|
|
1652
|
-
{
|
|
1653
|
-
slug: "kraken",
|
|
1654
|
-
name: "Kraken",
|
|
1655
|
-
description: "Documents and knowledge",
|
|
1656
|
-
icon: "/kraken-icon.svg",
|
|
1657
|
-
landing: "/today",
|
|
1658
|
-
baseUrlEnv: "NEXT_PUBLIC_KRAKEN_URL",
|
|
1659
|
-
baseUrlFallback: "http://localhost:3003"
|
|
1660
|
-
}
|
|
1661
|
-
];
|
|
1662
|
-
var SUITE_APP_MAP = Object.fromEntries(SUITE_APPS2.map((app) => [app.slug, app]));
|
|
1663
|
-
function suiteAppBaseUrl(slug) {
|
|
1664
|
-
const def = SUITE_APP_MAP[slug];
|
|
1665
|
-
const fromEnv = typeof process !== "undefined" ? process.env[def.baseUrlEnv] : void 0;
|
|
1666
|
-
return (fromEnv || def.baseUrlFallback).replace(/\/$/, "");
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
2170
|
// src/suite/components/today-calibrating.tsx
|
|
1670
2171
|
var import_iconoir_react7 = require("iconoir-react");
|
|
1671
|
-
var
|
|
2172
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1672
2173
|
function TodayCalibrating({
|
|
1673
2174
|
onRetry,
|
|
1674
2175
|
retrying = false,
|
|
1675
2176
|
className,
|
|
1676
2177
|
spinner: Spinner,
|
|
1677
|
-
variant = "ring",
|
|
2178
|
+
variant: _variant = "ring",
|
|
1678
2179
|
retrySpinnerClassName = "text-ph-brand"
|
|
1679
2180
|
}) {
|
|
1680
|
-
|
|
2181
|
+
void _variant;
|
|
2182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1681
2183
|
"div",
|
|
1682
2184
|
{
|
|
1683
2185
|
className: cn(
|
|
1684
|
-
"relative flex min-h-[14rem] flex-col items-center justify-center overflow-hidden rounded-2xl border border-ph-border bg-ph-surface px-5 py-8 text-center shadow-sm",
|
|
2186
|
+
"suite-auth-handoff relative flex min-h-[14rem] flex-col items-center justify-center overflow-hidden rounded-2xl border border-ph-border bg-ph-surface px-5 py-8 text-center shadow-sm",
|
|
1685
2187
|
className
|
|
1686
2188
|
),
|
|
1687
2189
|
"data-test": "today-calibrating",
|
|
1688
2190
|
children: [
|
|
1689
|
-
/* @__PURE__ */ (0,
|
|
2191
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1690
2192
|
"div",
|
|
1691
2193
|
{
|
|
1692
|
-
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.
|
|
2194
|
+
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.1),transparent_55%)]",
|
|
1693
2195
|
"aria-hidden": true
|
|
1694
2196
|
}
|
|
1695
2197
|
),
|
|
1696
|
-
/* @__PURE__ */ (0,
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
size: "lg",
|
|
1702
|
-
className: "absolute inset-0 m-auto opacity-40",
|
|
1703
|
-
label: "Loading today"
|
|
1704
|
-
}
|
|
1705
|
-
),
|
|
1706
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1707
|
-
"span",
|
|
1708
|
-
{
|
|
1709
|
-
className: "bg-ph-muted/30 absolute inset-2 animate-ping rounded-full",
|
|
1710
|
-
"aria-hidden": true
|
|
1711
|
-
}
|
|
1712
|
-
)
|
|
1713
|
-
] }) : null,
|
|
1714
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "relative flex h-14 w-14 items-center justify-center rounded-2xl border border-ph-border bg-ph-surface text-ph-ink shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1715
|
-
import_iconoir_react7.SunLight,
|
|
1716
|
-
{
|
|
1717
|
-
className: cn("h-9 w-9", variant === "pulse" && "animate-pulse"),
|
|
1718
|
-
strokeWidth: 2,
|
|
1719
|
-
"aria-hidden": true
|
|
1720
|
-
}
|
|
1721
|
-
) })
|
|
1722
|
-
] }),
|
|
1723
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "relative text-base font-semibold tracking-tight text-ph-ink sm:text-lg md:text-xl", children: "Calibrating your day" }),
|
|
1724
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "relative mt-1.5 max-w-sm text-sm sm:text-[15px] leading-relaxed text-ph-subtle", children: "Pulling together tasks, time and updates from your workspace\u2026" }),
|
|
1725
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "relative mt-5 flex gap-1.5", "aria-hidden": true, children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1726
|
-
"span",
|
|
1727
|
-
{
|
|
1728
|
-
className: "h-1.5 w-5 animate-pulse rounded-full bg-ph-muted",
|
|
1729
|
-
style: { animationDelay: `${i * 120}ms` }
|
|
1730
|
-
},
|
|
1731
|
-
i
|
|
1732
|
-
)) }),
|
|
1733
|
-
onRetry ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2198
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "relative mb-5 flex h-14 w-14 items-center justify-center rounded-2xl border border-ph-border bg-ph-surface text-ph-ink shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_iconoir_react7.SunLight, { className: "h-8 w-8", strokeWidth: 2, "aria-hidden": true }) }),
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { className: "relative text-base font-semibold tracking-tight text-ph-ink sm:text-lg md:text-xl", children: "Calibrating your day" }),
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "relative mt-1.5 max-w-sm text-sm sm:text-[15px] leading-relaxed text-ph-subtle", children: "Pulling together tasks, time and updates from your workspace\u2026" }),
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "relative mt-5 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, { size: "sm", className: "opacity-70", label: "Loading today" }) }),
|
|
2202
|
+
onRetry ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1734
2203
|
"button",
|
|
1735
2204
|
{
|
|
1736
2205
|
type: "button",
|
|
@@ -1738,7 +2207,7 @@ function TodayCalibrating({
|
|
|
1738
2207
|
disabled: retrying,
|
|
1739
2208
|
className: "relative mt-6 inline-flex items-center gap-2 rounded-xl border border-ph-border bg-ph-canvas px-4 py-2 text-sm font-medium text-ph-ink transition hover:bg-ph-muted disabled:opacity-60",
|
|
1740
2209
|
children: [
|
|
1741
|
-
retrying ? /* @__PURE__ */ (0,
|
|
2210
|
+
retrying ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, { size: "sm", className: retrySpinnerClassName }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_iconoir_react7.Refresh, { className: "h-4 w-4", "aria-hidden": true }),
|
|
1742
2211
|
"Try again"
|
|
1743
2212
|
]
|
|
1744
2213
|
}
|
|
@@ -1749,9 +2218,9 @@ function TodayCalibrating({
|
|
|
1749
2218
|
}
|
|
1750
2219
|
|
|
1751
2220
|
// src/suite/components/theme-provider.tsx
|
|
1752
|
-
var
|
|
1753
|
-
var
|
|
1754
|
-
var SuiteThemeContext = (0,
|
|
2221
|
+
var import_react7 = require("react");
|
|
2222
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2223
|
+
var SuiteThemeContext = (0, import_react7.createContext)(null);
|
|
1755
2224
|
function systemTheme(fallback) {
|
|
1756
2225
|
if (typeof window === "undefined") return fallback;
|
|
1757
2226
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
@@ -1788,7 +2257,7 @@ function SuiteThemeProvider({
|
|
|
1788
2257
|
config,
|
|
1789
2258
|
children
|
|
1790
2259
|
}) {
|
|
1791
|
-
const [state, setState] = (0,
|
|
2260
|
+
const [state, setState] = (0, import_react7.useState)(() => {
|
|
1792
2261
|
const theme2 = readStoredTheme(config.storageKey);
|
|
1793
2262
|
if (typeof document === "undefined") {
|
|
1794
2263
|
return { theme: theme2, resolvedTheme: config.fallbackTheme };
|
|
@@ -1798,7 +2267,7 @@ function SuiteThemeProvider({
|
|
|
1798
2267
|
return { theme: theme2, resolvedTheme: resolvedTheme2 };
|
|
1799
2268
|
});
|
|
1800
2269
|
const { theme, resolvedTheme } = state;
|
|
1801
|
-
(0,
|
|
2270
|
+
(0, import_react7.useEffect)(() => {
|
|
1802
2271
|
if (theme !== "system") return;
|
|
1803
2272
|
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1804
2273
|
const update = () => {
|
|
@@ -1808,7 +2277,7 @@ function SuiteThemeProvider({
|
|
|
1808
2277
|
media.addEventListener("change", update);
|
|
1809
2278
|
return () => media.removeEventListener("change", update);
|
|
1810
2279
|
}, [theme, config]);
|
|
1811
|
-
const setTheme = (0,
|
|
2280
|
+
const setTheme = (0, import_react7.useCallback)(
|
|
1812
2281
|
(next) => {
|
|
1813
2282
|
const resolved = applyTheme(next, config);
|
|
1814
2283
|
setState({ theme: next, resolvedTheme: resolved });
|
|
@@ -1816,7 +2285,7 @@ function SuiteThemeProvider({
|
|
|
1816
2285
|
},
|
|
1817
2286
|
[config]
|
|
1818
2287
|
);
|
|
1819
|
-
const toggleTheme = (0,
|
|
2288
|
+
const toggleTheme = (0, import_react7.useCallback)(() => {
|
|
1820
2289
|
setState((prev) => {
|
|
1821
2290
|
const next = resolveTheme(prev.theme, config.fallbackTheme) === "dark" ? "light" : "dark";
|
|
1822
2291
|
const resolved = applyTheme(next, config);
|
|
@@ -1824,52 +2293,178 @@ function SuiteThemeProvider({
|
|
|
1824
2293
|
return { theme: next, resolvedTheme: resolved };
|
|
1825
2294
|
});
|
|
1826
2295
|
}, [config]);
|
|
1827
|
-
const value = (0,
|
|
2296
|
+
const value = (0, import_react7.useMemo)(
|
|
1828
2297
|
() => ({ theme, resolvedTheme, setTheme, toggleTheme }),
|
|
1829
2298
|
[theme, resolvedTheme, setTheme, toggleTheme]
|
|
1830
2299
|
);
|
|
1831
|
-
return /* @__PURE__ */ (0,
|
|
2300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SuiteThemeContext.Provider, { value, children });
|
|
1832
2301
|
}
|
|
1833
2302
|
function useSuiteTheme() {
|
|
1834
|
-
const ctx = (0,
|
|
2303
|
+
const ctx = (0, import_react7.useContext)(SuiteThemeContext);
|
|
1835
2304
|
if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
|
|
1836
2305
|
return ctx;
|
|
1837
2306
|
}
|
|
1838
2307
|
|
|
1839
2308
|
// src/suite/components/ai-panel.tsx
|
|
1840
|
-
var
|
|
2309
|
+
var import_react8 = require("react");
|
|
1841
2310
|
var import_iconoir_react8 = require("iconoir-react");
|
|
1842
|
-
var
|
|
2311
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2312
|
+
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
2313
|
+
function openSuiteAskAi(detail) {
|
|
2314
|
+
if (typeof window === "undefined") return;
|
|
2315
|
+
window.dispatchEvent(
|
|
2316
|
+
new CustomEvent(SUITE_OPEN_ASK_AI_EVENT, {
|
|
2317
|
+
detail: detail != null ? detail : {}
|
|
2318
|
+
})
|
|
2319
|
+
);
|
|
2320
|
+
}
|
|
2321
|
+
var LAUNCHER_EDGE_GAP = 12;
|
|
2322
|
+
var LAUNCHER_STORAGE_KEY = "suite-ask-ai-launcher-position";
|
|
2323
|
+
function resolveSuiteAiLauncherPosition(side, desiredY, viewportWidth, viewportHeight, launcherWidth, launcherHeight) {
|
|
2324
|
+
const maxX = Math.max(
|
|
2325
|
+
LAUNCHER_EDGE_GAP,
|
|
2326
|
+
viewportWidth - launcherWidth - LAUNCHER_EDGE_GAP
|
|
2327
|
+
);
|
|
2328
|
+
const maxY = Math.max(
|
|
2329
|
+
LAUNCHER_EDGE_GAP,
|
|
2330
|
+
viewportHeight - launcherHeight - LAUNCHER_EDGE_GAP
|
|
2331
|
+
);
|
|
2332
|
+
return {
|
|
2333
|
+
x: side === "left" ? LAUNCHER_EDGE_GAP : maxX,
|
|
2334
|
+
y: Math.min(Math.max(desiredY, LAUNCHER_EDGE_GAP), maxY)
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
1843
2337
|
function SuiteAiPanel({
|
|
1844
|
-
presets,
|
|
1845
|
-
emptyState,
|
|
1846
|
-
|
|
1847
|
-
|
|
2338
|
+
presets = [],
|
|
2339
|
+
emptyState = "Ask anything about your workspace, or look something up online.",
|
|
2340
|
+
title = "Ask AI",
|
|
2341
|
+
fetchChat,
|
|
2342
|
+
sendMessage,
|
|
2343
|
+
clearChat,
|
|
1848
2344
|
brandIcon: BrandIcon,
|
|
1849
|
-
spinner: Spinner
|
|
2345
|
+
spinner: Spinner,
|
|
2346
|
+
hideLauncher = false
|
|
1850
2347
|
}) {
|
|
1851
|
-
const [open, setOpen] = (0,
|
|
1852
|
-
const [prompt, setPrompt] = (0,
|
|
1853
|
-
const [
|
|
1854
|
-
const [
|
|
1855
|
-
const [
|
|
1856
|
-
const [
|
|
2348
|
+
const [open, setOpen] = (0, import_react8.useState)(false);
|
|
2349
|
+
const [prompt, setPrompt] = (0, import_react8.useState)("");
|
|
2350
|
+
const [messages, setMessages] = (0, import_react8.useState)([]);
|
|
2351
|
+
const [loading, setLoading] = (0, import_react8.useState)(false);
|
|
2352
|
+
const [hydrating, setHydrating] = (0, import_react8.useState)(false);
|
|
2353
|
+
const [error, setError] = (0, import_react8.useState)("");
|
|
2354
|
+
const [copiedId, setCopiedId] = (0, import_react8.useState)(null);
|
|
2355
|
+
const [launcherSide, setLauncherSide] = (0, import_react8.useState)("right");
|
|
2356
|
+
const [launcherPosition, setLauncherPosition] = (0, import_react8.useState)(null);
|
|
2357
|
+
const [draggingLauncher, setDraggingLauncher] = (0, import_react8.useState)(false);
|
|
2358
|
+
const scrollerRef = (0, import_react8.useRef)(null);
|
|
2359
|
+
const launcherRef = (0, import_react8.useRef)(null);
|
|
2360
|
+
const launcherSideRef = (0, import_react8.useRef)("right");
|
|
2361
|
+
const launcherPositionRef = (0, import_react8.useRef)(null);
|
|
2362
|
+
const launcherDragRef = (0, import_react8.useRef)(null);
|
|
2363
|
+
const suppressLauncherClickRef = (0, import_react8.useRef)(false);
|
|
2364
|
+
const pendingPromptRef = (0, import_react8.useRef)(null);
|
|
2365
|
+
(0, import_react8.useEffect)(() => {
|
|
2366
|
+
const launcher = launcherRef.current;
|
|
2367
|
+
if (!launcher) return;
|
|
2368
|
+
let side = "right";
|
|
2369
|
+
let desiredY = window.innerHeight - launcher.offsetHeight - 20;
|
|
2370
|
+
try {
|
|
2371
|
+
const stored = JSON.parse(
|
|
2372
|
+
localStorage.getItem(LAUNCHER_STORAGE_KEY) || "null"
|
|
2373
|
+
);
|
|
2374
|
+
if ((stored == null ? void 0 : stored.side) === "left" || (stored == null ? void 0 : stored.side) === "right")
|
|
2375
|
+
side = stored.side;
|
|
2376
|
+
if (typeof (stored == null ? void 0 : stored.y) === "number") desiredY = stored.y;
|
|
2377
|
+
} catch (e) {
|
|
2378
|
+
}
|
|
2379
|
+
launcherSideRef.current = side;
|
|
2380
|
+
setLauncherSide(side);
|
|
2381
|
+
const placeLauncher = () => {
|
|
2382
|
+
var _a, _b;
|
|
2383
|
+
const element = launcherRef.current;
|
|
2384
|
+
if (!element) return;
|
|
2385
|
+
const next = resolveSuiteAiLauncherPosition(
|
|
2386
|
+
launcherSideRef.current,
|
|
2387
|
+
(_b = (_a = launcherPositionRef.current) == null ? void 0 : _a.y) != null ? _b : desiredY,
|
|
2388
|
+
window.innerWidth,
|
|
2389
|
+
window.innerHeight,
|
|
2390
|
+
element.offsetWidth,
|
|
2391
|
+
element.offsetHeight
|
|
2392
|
+
);
|
|
2393
|
+
launcherPositionRef.current = next;
|
|
2394
|
+
setLauncherPosition(next);
|
|
2395
|
+
};
|
|
2396
|
+
placeLauncher();
|
|
2397
|
+
window.addEventListener("resize", placeLauncher);
|
|
2398
|
+
return () => window.removeEventListener("resize", placeLauncher);
|
|
2399
|
+
}, []);
|
|
2400
|
+
const scrollToBottom = (0, import_react8.useCallback)(() => {
|
|
2401
|
+
const el = scrollerRef.current;
|
|
2402
|
+
if (!el) return;
|
|
2403
|
+
el.scrollTop = el.scrollHeight;
|
|
2404
|
+
}, []);
|
|
2405
|
+
const hydrate = (0, import_react8.useCallback)(async () => {
|
|
2406
|
+
var _a;
|
|
2407
|
+
setHydrating(true);
|
|
2408
|
+
setError("");
|
|
2409
|
+
try {
|
|
2410
|
+
const data = await fetchChat();
|
|
2411
|
+
setMessages((_a = data.messages) != null ? _a : []);
|
|
2412
|
+
if (!data.configured) {
|
|
2413
|
+
setError("ShellStack AI is not configured for this workspace yet.");
|
|
2414
|
+
}
|
|
2415
|
+
} catch (err) {
|
|
2416
|
+
setError(
|
|
2417
|
+
err instanceof Error ? err.message : "Could not load your Ask AI chat."
|
|
2418
|
+
);
|
|
2419
|
+
} finally {
|
|
2420
|
+
setHydrating(false);
|
|
2421
|
+
}
|
|
2422
|
+
}, [fetchChat]);
|
|
2423
|
+
(0, import_react8.useEffect)(() => {
|
|
2424
|
+
function onOpen(event) {
|
|
2425
|
+
var _a;
|
|
2426
|
+
const detail = event.detail;
|
|
2427
|
+
setOpen(true);
|
|
2428
|
+
if ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) {
|
|
2429
|
+
pendingPromptRef.current = detail.prompt.trim();
|
|
2430
|
+
setPrompt(detail.prompt.trim());
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2434
|
+
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2435
|
+
}, []);
|
|
2436
|
+
(0, import_react8.useEffect)(() => {
|
|
2437
|
+
if (!open) return;
|
|
2438
|
+
void hydrate().then(() => {
|
|
2439
|
+
const pending = pendingPromptRef.current;
|
|
2440
|
+
pendingPromptRef.current = null;
|
|
2441
|
+
if (pending) {
|
|
2442
|
+
setPrompt(pending);
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2445
|
+
}, [open, hydrate]);
|
|
2446
|
+
(0, import_react8.useEffect)(() => {
|
|
2447
|
+
if (open) scrollToBottom();
|
|
2448
|
+
}, [messages, loading, open, scrollToBottom]);
|
|
1857
2449
|
async function ask(text) {
|
|
2450
|
+
var _a;
|
|
1858
2451
|
const trimmed = text.trim();
|
|
1859
2452
|
if (!trimmed || loading) return;
|
|
1860
2453
|
setLoading(true);
|
|
1861
2454
|
setError("");
|
|
1862
|
-
|
|
1863
|
-
|
|
2455
|
+
setPrompt("");
|
|
2456
|
+
setMessages((prev) => [...prev, { role: "user", content: trimmed }]);
|
|
1864
2457
|
try {
|
|
1865
|
-
const
|
|
1866
|
-
|
|
1867
|
-
setError("ShellStack AI is not configured for this workspace yet.");
|
|
1868
|
-
return;
|
|
1869
|
-
}
|
|
1870
|
-
const result = await complete({ prompt: trimmed });
|
|
1871
|
-
setAnswer(result.text);
|
|
2458
|
+
const result = await sendMessage({ prompt: trimmed });
|
|
2459
|
+
setMessages((_a = result.messages) != null ? _a : []);
|
|
1872
2460
|
} catch (err) {
|
|
2461
|
+
setMessages(
|
|
2462
|
+
(prev) => {
|
|
2463
|
+
var _a2, _b;
|
|
2464
|
+
return ((_a2 = prev[prev.length - 1]) == null ? void 0 : _a2.role) === "user" && ((_b = prev[prev.length - 1]) == null ? void 0 : _b.content) === trimmed ? prev.slice(0, -1) : prev;
|
|
2465
|
+
}
|
|
2466
|
+
);
|
|
2467
|
+
setPrompt(trimmed);
|
|
1873
2468
|
setError(
|
|
1874
2469
|
err instanceof Error ? err.message : "The AI request failed. Try again."
|
|
1875
2470
|
);
|
|
@@ -1877,133 +2472,391 @@ function SuiteAiPanel({
|
|
|
1877
2472
|
setLoading(false);
|
|
1878
2473
|
}
|
|
1879
2474
|
}
|
|
1880
|
-
async function
|
|
1881
|
-
if (
|
|
2475
|
+
async function handleClear() {
|
|
2476
|
+
if (loading) return;
|
|
1882
2477
|
try {
|
|
1883
|
-
await
|
|
1884
|
-
|
|
1885
|
-
|
|
2478
|
+
await clearChat();
|
|
2479
|
+
setMessages([]);
|
|
2480
|
+
setError("");
|
|
2481
|
+
} catch (err) {
|
|
2482
|
+
setError(
|
|
2483
|
+
err instanceof Error ? err.message : "Could not clear this chat."
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
async function copyMessage(index, content) {
|
|
2488
|
+
try {
|
|
2489
|
+
await navigator.clipboard.writeText(content);
|
|
2490
|
+
setCopiedId(index);
|
|
2491
|
+
window.setTimeout(() => setCopiedId(null), 1500);
|
|
1886
2492
|
} catch (e) {
|
|
1887
2493
|
}
|
|
1888
2494
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2495
|
+
function saveLauncherPosition(side, position) {
|
|
2496
|
+
try {
|
|
2497
|
+
localStorage.setItem(
|
|
2498
|
+
LAUNCHER_STORAGE_KEY,
|
|
2499
|
+
JSON.stringify({ side, y: position.y })
|
|
2500
|
+
);
|
|
2501
|
+
} catch (e) {
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
function dockLauncher(side, desiredY) {
|
|
2505
|
+
const launcher = launcherRef.current;
|
|
2506
|
+
if (!launcher) return;
|
|
2507
|
+
const next = resolveSuiteAiLauncherPosition(
|
|
2508
|
+
side,
|
|
2509
|
+
desiredY,
|
|
2510
|
+
window.innerWidth,
|
|
2511
|
+
window.innerHeight,
|
|
2512
|
+
launcher.offsetWidth,
|
|
2513
|
+
launcher.offsetHeight
|
|
2514
|
+
);
|
|
2515
|
+
launcherSideRef.current = side;
|
|
2516
|
+
launcherPositionRef.current = next;
|
|
2517
|
+
setLauncherSide(side);
|
|
2518
|
+
setLauncherPosition(next);
|
|
2519
|
+
saveLauncherPosition(side, next);
|
|
2520
|
+
}
|
|
2521
|
+
function startLauncherDrag(event) {
|
|
2522
|
+
if (event.pointerType === "mouse" && event.button !== 0) return;
|
|
2523
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
2524
|
+
launcherDragRef.current = {
|
|
2525
|
+
pointerId: event.pointerId,
|
|
2526
|
+
offsetX: event.clientX - rect.left,
|
|
2527
|
+
offsetY: event.clientY - rect.top,
|
|
2528
|
+
startX: event.clientX,
|
|
2529
|
+
startY: event.clientY
|
|
2530
|
+
};
|
|
2531
|
+
suppressLauncherClickRef.current = false;
|
|
2532
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2533
|
+
setDraggingLauncher(true);
|
|
2534
|
+
}
|
|
2535
|
+
function moveLauncher(event) {
|
|
2536
|
+
const drag = launcherDragRef.current;
|
|
2537
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
2538
|
+
const launcher = event.currentTarget;
|
|
2539
|
+
const maxX = Math.max(
|
|
2540
|
+
LAUNCHER_EDGE_GAP,
|
|
2541
|
+
window.innerWidth - launcher.offsetWidth - LAUNCHER_EDGE_GAP
|
|
2542
|
+
);
|
|
2543
|
+
const maxY = Math.max(
|
|
2544
|
+
LAUNCHER_EDGE_GAP,
|
|
2545
|
+
window.innerHeight - launcher.offsetHeight - LAUNCHER_EDGE_GAP
|
|
2546
|
+
);
|
|
2547
|
+
const next = {
|
|
2548
|
+
x: Math.min(
|
|
2549
|
+
Math.max(event.clientX - drag.offsetX, LAUNCHER_EDGE_GAP),
|
|
2550
|
+
maxX
|
|
2551
|
+
),
|
|
2552
|
+
y: Math.min(
|
|
2553
|
+
Math.max(event.clientY - drag.offsetY, LAUNCHER_EDGE_GAP),
|
|
2554
|
+
maxY
|
|
2555
|
+
)
|
|
2556
|
+
};
|
|
2557
|
+
if (Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) > 4) {
|
|
2558
|
+
suppressLauncherClickRef.current = true;
|
|
2559
|
+
}
|
|
2560
|
+
launcherPositionRef.current = next;
|
|
2561
|
+
setLauncherPosition(next);
|
|
2562
|
+
}
|
|
2563
|
+
function finishLauncherDrag(event) {
|
|
2564
|
+
var _a, _b, _c, _d;
|
|
2565
|
+
const drag = launcherDragRef.current;
|
|
2566
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
2567
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
2568
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
2569
|
+
}
|
|
2570
|
+
launcherDragRef.current = null;
|
|
2571
|
+
setDraggingLauncher(false);
|
|
2572
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
2573
|
+
const currentX = (_b = (_a = launcherPositionRef.current) == null ? void 0 : _a.x) != null ? _b : rect.left;
|
|
2574
|
+
const side = currentX + rect.width / 2 < window.innerWidth / 2 ? "left" : "right";
|
|
2575
|
+
dockLauncher(side, (_d = (_c = launcherPositionRef.current) == null ? void 0 : _c.y) != null ? _d : rect.top);
|
|
2576
|
+
}
|
|
2577
|
+
function moveLauncherWithKeyboard(event) {
|
|
2578
|
+
var _a, _b;
|
|
2579
|
+
if (!["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key))
|
|
2580
|
+
return;
|
|
2581
|
+
event.preventDefault();
|
|
2582
|
+
const currentY = (_b = (_a = launcherPositionRef.current) == null ? void 0 : _a.y) != null ? _b : event.currentTarget.getBoundingClientRect().top;
|
|
2583
|
+
if (event.key === "ArrowLeft") dockLauncher("left", currentY);
|
|
2584
|
+
else if (event.key === "ArrowRight") dockLauncher("right", currentY);
|
|
2585
|
+
else
|
|
2586
|
+
dockLauncher(
|
|
2587
|
+
launcherSideRef.current,
|
|
2588
|
+
currentY + (event.key === "ArrowUp" ? -24 : 24)
|
|
2589
|
+
);
|
|
2590
|
+
}
|
|
2591
|
+
const Icon = BrandIcon != null ? BrandIcon : import_iconoir_react8.Sparks;
|
|
2592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2593
|
+
!hideLauncher ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2595
|
+
"button",
|
|
2596
|
+
{
|
|
2597
|
+
ref: launcherRef,
|
|
2598
|
+
type: "button",
|
|
2599
|
+
"data-test": "ai-panel-launcher",
|
|
2600
|
+
onClick: () => {
|
|
2601
|
+
if (suppressLauncherClickRef.current) {
|
|
2602
|
+
suppressLauncherClickRef.current = false;
|
|
2603
|
+
return;
|
|
2604
|
+
}
|
|
2605
|
+
setOpen(true);
|
|
2606
|
+
},
|
|
2607
|
+
onPointerDown: startLauncherDrag,
|
|
2608
|
+
onPointerMove: moveLauncher,
|
|
2609
|
+
onPointerUp: finishLauncherDrag,
|
|
2610
|
+
onPointerCancel: finishLauncherDrag,
|
|
2611
|
+
onKeyDown: moveLauncherWithKeyboard,
|
|
2612
|
+
className: `fixed z-30 flex touch-none select-none items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-4 py-2.5 text-sm font-medium text-ph-ink shadow-ph hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand ${draggingLauncher ? "cursor-grabbing" : "cursor-grab"}`,
|
|
2613
|
+
style: launcherPosition ? { left: launcherPosition.x, top: launcherPosition.y } : { bottom: 20, right: 20 },
|
|
2614
|
+
"aria-label": "Open Ask AI",
|
|
2615
|
+
"aria-describedby": "suite-ask-ai-launcher-help",
|
|
2616
|
+
children: [
|
|
2617
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { className: "h-4 w-4 text-ph-brand" }),
|
|
2618
|
+
"Ask AI"
|
|
2619
|
+
]
|
|
2620
|
+
}
|
|
2621
|
+
),
|
|
2622
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { id: "suite-ask-ai-launcher-help", className: "sr-only", children: "Drag to reposition, or use arrow keys. The launcher docks to the nearest screen edge." })
|
|
2623
|
+
] }) : null,
|
|
2624
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "fixed inset-0 z-40", role: "dialog", "aria-modal": "true", children: [
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1906
2626
|
"button",
|
|
1907
2627
|
{
|
|
1908
2628
|
type: "button",
|
|
1909
2629
|
className: "absolute inset-0 bg-black/25",
|
|
1910
2630
|
onClick: () => setOpen(false),
|
|
1911
|
-
"aria-label": "Close AI
|
|
2631
|
+
"aria-label": "Close Ask AI"
|
|
1912
2632
|
}
|
|
1913
2633
|
),
|
|
1914
|
-
/* @__PURE__ */ (0,
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
/* @__PURE__ */ (0,
|
|
1953
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2635
|
+
"aside",
|
|
2636
|
+
{
|
|
2637
|
+
className: `absolute inset-y-0 flex w-full max-w-md flex-col bg-ph-surface shadow-2xl ${launcherSide === "left" ? "left-0 border-r border-ph-border" : "right-0 border-l border-ph-border"}`,
|
|
2638
|
+
"data-test": "suite-ask-ai-panel",
|
|
2639
|
+
children: [
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center justify-between border-b border-ph-border px-4 py-3", children: [
|
|
2641
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "min-w-0", children: [
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2644
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-sm font-semibold text-ph-ink", children: title })
|
|
2645
|
+
] }),
|
|
2646
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-0.5 text-[11px] text-ph-mutedtext", children: "Shared across your suite \xB7 same chat in every app" })
|
|
2647
|
+
] }),
|
|
2648
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2649
|
+
messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2650
|
+
"button",
|
|
2651
|
+
{
|
|
2652
|
+
type: "button",
|
|
2653
|
+
onClick: () => void handleClear(),
|
|
2654
|
+
disabled: loading,
|
|
2655
|
+
className: "rounded-md px-2 py-1 text-xs text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink disabled:opacity-50",
|
|
2656
|
+
"data-test": "ask-ai-clear",
|
|
2657
|
+
children: "Clear"
|
|
2658
|
+
}
|
|
2659
|
+
) : null,
|
|
2660
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2661
|
+
"button",
|
|
2662
|
+
{
|
|
2663
|
+
type: "button",
|
|
2664
|
+
onClick: () => setOpen(false),
|
|
2665
|
+
className: "rounded p-1 hover:bg-ph-muted",
|
|
2666
|
+
"aria-label": "Close",
|
|
2667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_iconoir_react8.Xmark, { className: "h-4 w-4" })
|
|
2668
|
+
}
|
|
2669
|
+
)
|
|
2670
|
+
] })
|
|
2671
|
+
] }),
|
|
2672
|
+
presets.length > 0 && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex flex-wrap gap-1.5 border-b border-ph-border px-4 py-2", children: presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1954
2673
|
"button",
|
|
1955
2674
|
{
|
|
1956
2675
|
type: "button",
|
|
1957
|
-
onClick: () => void
|
|
1958
|
-
|
|
2676
|
+
onClick: () => void ask(preset.prompt),
|
|
2677
|
+
disabled: loading || hydrating,
|
|
2678
|
+
className: "rounded-full border border-ph-border px-2.5 py-1 text-xs text-ph-ink hover:bg-ph-muted disabled:opacity-50",
|
|
2679
|
+
children: preset.label
|
|
2680
|
+
},
|
|
2681
|
+
preset.label
|
|
2682
|
+
)) }) : null,
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2684
|
+
"div",
|
|
2685
|
+
{
|
|
2686
|
+
ref: scrollerRef,
|
|
2687
|
+
className: "flex-1 space-y-3 overflow-y-auto p-4",
|
|
1959
2688
|
children: [
|
|
1960
|
-
|
|
1961
|
-
|
|
2689
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "bg-ph-danger/10 rounded-lg px-3 py-2 text-sm text-ph-danger", children: error }) : null,
|
|
2690
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2691
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2692
|
+
"Loading chat\u2026"
|
|
2693
|
+
] }) : null,
|
|
2694
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mt-10 px-2 text-center", children: [
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-2 text-sm leading-relaxed text-ph-subtle", children: emptyState })
|
|
2697
|
+
] }) : null,
|
|
2698
|
+
messages.map((message, index) => {
|
|
2699
|
+
const isUser = message.role === "user";
|
|
2700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2701
|
+
"div",
|
|
2702
|
+
{
|
|
2703
|
+
className: isUser ? "ml-8 rounded-2xl bg-ph-brand/10 px-3.5 py-2.5 text-sm text-ph-ink" : "mr-4 rounded-2xl bg-ph-muted px-3.5 py-2.5 text-sm text-ph-ink",
|
|
2704
|
+
"data-test": isUser ? "ask-ai-user" : "ask-ai-assistant",
|
|
2705
|
+
children: [
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "whitespace-pre-wrap", children: message.content }),
|
|
2707
|
+
!isUser ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2708
|
+
"button",
|
|
2709
|
+
{
|
|
2710
|
+
type: "button",
|
|
2711
|
+
onClick: () => void copyMessage(index, message.content),
|
|
2712
|
+
className: "mt-2 inline-flex items-center gap-1 text-xs text-ph-mutedtext hover:text-ph-ink",
|
|
2713
|
+
children: [
|
|
2714
|
+
copiedId === index ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_iconoir_react8.Check, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_iconoir_react8.Copy, { className: "h-3 w-3" }),
|
|
2715
|
+
copiedId === index ? "Copied" : "Copy"
|
|
2716
|
+
]
|
|
2717
|
+
}
|
|
2718
|
+
) : null
|
|
2719
|
+
]
|
|
2720
|
+
},
|
|
2721
|
+
`${message.role}-${index}-${message.content.slice(0, 24)}`
|
|
2722
|
+
);
|
|
2723
|
+
}),
|
|
2724
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2725
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2726
|
+
"Thinking\u2026"
|
|
2727
|
+
] }) : null
|
|
1962
2728
|
]
|
|
1963
2729
|
}
|
|
1964
|
-
)
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2730
|
+
),
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "border-t border-ph-border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex gap-2", children: [
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2733
|
+
"textarea",
|
|
2734
|
+
{
|
|
2735
|
+
value: prompt,
|
|
2736
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
2737
|
+
onKeyDown: (e) => {
|
|
2738
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
2739
|
+
e.preventDefault();
|
|
2740
|
+
void ask(prompt);
|
|
2741
|
+
}
|
|
2742
|
+
},
|
|
2743
|
+
placeholder: "Ask anything\u2026",
|
|
2744
|
+
rows: 2,
|
|
2745
|
+
disabled: loading,
|
|
2746
|
+
"data-test": "ask-ai-input",
|
|
2747
|
+
className: "flex-1 resize-none rounded-xl border border-ph-border bg-ph-canvas p-2.5 text-sm text-ph-ink outline-none focus:ring-1 focus:ring-ph-brand"
|
|
1978
2748
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
] }) })
|
|
1997
|
-
] })
|
|
1998
|
-
] })
|
|
2749
|
+
),
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2751
|
+
"button",
|
|
2752
|
+
{
|
|
2753
|
+
type: "button",
|
|
2754
|
+
onClick: () => void ask(prompt),
|
|
2755
|
+
disabled: loading || !prompt.trim(),
|
|
2756
|
+
"data-test": "ask-ai-send",
|
|
2757
|
+
className: "self-end rounded-xl bg-ph-brand px-3.5 py-2 text-sm font-medium text-white disabled:opacity-50",
|
|
2758
|
+
children: "Ask"
|
|
2759
|
+
}
|
|
2760
|
+
)
|
|
2761
|
+
] }) })
|
|
2762
|
+
]
|
|
2763
|
+
}
|
|
2764
|
+
)
|
|
2765
|
+
] }) : null
|
|
1999
2766
|
] });
|
|
2000
2767
|
}
|
|
2001
2768
|
|
|
2769
|
+
// src/suite/lib/use-sidebar-width.ts
|
|
2770
|
+
var import_react9 = require("react");
|
|
2771
|
+
var SIDEBAR_RAIL_WIDTH = 56;
|
|
2772
|
+
var SIDEBAR_COLLAPSE_THRESHOLD = 80;
|
|
2773
|
+
var SIDEBAR_MIN_EXPANDED_WIDTH = 180;
|
|
2774
|
+
var SIDEBAR_MAX_WIDTH = 320;
|
|
2775
|
+
var SIDEBAR_DEFAULT_WIDTH = 320;
|
|
2776
|
+
function clampWidth(width) {
|
|
2777
|
+
return Math.min(SIDEBAR_MAX_WIDTH, Math.max(SIDEBAR_RAIL_WIDTH, width));
|
|
2778
|
+
}
|
|
2779
|
+
function snapWidth(width) {
|
|
2780
|
+
if (width <= SIDEBAR_COLLAPSE_THRESHOLD) return SIDEBAR_RAIL_WIDTH;
|
|
2781
|
+
if (width < SIDEBAR_MIN_EXPANDED_WIDTH) return SIDEBAR_MIN_EXPANDED_WIDTH;
|
|
2782
|
+
return Math.min(SIDEBAR_MAX_WIDTH, width);
|
|
2783
|
+
}
|
|
2784
|
+
function useSidebarWidth(storageKey) {
|
|
2785
|
+
const [width, setWidth] = (0, import_react9.useState)(SIDEBAR_DEFAULT_WIDTH);
|
|
2786
|
+
const [narrowViewport, setNarrowViewport] = (0, import_react9.useState)(false);
|
|
2787
|
+
const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
|
|
2788
|
+
(0, import_react9.useEffect)(() => {
|
|
2789
|
+
let stored = null;
|
|
2790
|
+
try {
|
|
2791
|
+
stored = localStorage.getItem(storageKey);
|
|
2792
|
+
} catch (e) {
|
|
2793
|
+
}
|
|
2794
|
+
if (!stored) return;
|
|
2795
|
+
const parsed = Number.parseInt(stored, 10);
|
|
2796
|
+
if (!Number.isNaN(parsed)) {
|
|
2797
|
+
queueMicrotask(() => setWidth(snapWidth(clampWidth(parsed))));
|
|
2798
|
+
}
|
|
2799
|
+
}, [storageKey]);
|
|
2800
|
+
(0, import_react9.useEffect)(() => {
|
|
2801
|
+
const media = window.matchMedia("(max-width: 639px)");
|
|
2802
|
+
const sync = () => setNarrowViewport(media.matches);
|
|
2803
|
+
sync();
|
|
2804
|
+
media.addEventListener("change", sync);
|
|
2805
|
+
return () => media.removeEventListener("change", sync);
|
|
2806
|
+
}, []);
|
|
2807
|
+
const persist = (0, import_react9.useCallback)(
|
|
2808
|
+
(value) => {
|
|
2809
|
+
try {
|
|
2810
|
+
localStorage.setItem(storageKey, String(value));
|
|
2811
|
+
} catch (e) {
|
|
2812
|
+
}
|
|
2813
|
+
},
|
|
2814
|
+
[storageKey]
|
|
2815
|
+
);
|
|
2816
|
+
const setCollapsed = (0, import_react9.useCallback)(
|
|
2817
|
+
(value) => {
|
|
2818
|
+
setWidth((current) => {
|
|
2819
|
+
const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? SIDEBAR_DEFAULT_WIDTH : snapWidth(current);
|
|
2820
|
+
persist(next);
|
|
2821
|
+
return next;
|
|
2822
|
+
});
|
|
2823
|
+
},
|
|
2824
|
+
[persist]
|
|
2825
|
+
);
|
|
2826
|
+
const resetWidth = (0, import_react9.useCallback)(() => {
|
|
2827
|
+
setWidth(SIDEBAR_DEFAULT_WIDTH);
|
|
2828
|
+
persist(SIDEBAR_DEFAULT_WIDTH);
|
|
2829
|
+
}, [persist]);
|
|
2830
|
+
const startResize = (0, import_react9.useCallback)(
|
|
2831
|
+
(event) => {
|
|
2832
|
+
event.preventDefault();
|
|
2833
|
+
const startX = event.clientX;
|
|
2834
|
+
const startWidth = width;
|
|
2835
|
+
const onMove = (moveEvent) => {
|
|
2836
|
+
setWidth(clampWidth(startWidth + moveEvent.clientX - startX));
|
|
2837
|
+
};
|
|
2838
|
+
const onUp = () => {
|
|
2839
|
+
document.removeEventListener("pointermove", onMove);
|
|
2840
|
+
document.removeEventListener("pointerup", onUp);
|
|
2841
|
+
setWidth((current) => {
|
|
2842
|
+
const snapped = snapWidth(current);
|
|
2843
|
+
persist(snapped);
|
|
2844
|
+
return snapped;
|
|
2845
|
+
});
|
|
2846
|
+
};
|
|
2847
|
+
document.addEventListener("pointermove", onMove);
|
|
2848
|
+
document.addEventListener("pointerup", onUp);
|
|
2849
|
+
},
|
|
2850
|
+
[persist, width]
|
|
2851
|
+
);
|
|
2852
|
+
return { width, collapsed, setCollapsed, resetWidth, startResize };
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2002
2855
|
// src/suite/lib/motion.tsx
|
|
2003
|
-
var
|
|
2004
|
-
var
|
|
2856
|
+
var import_react10 = require("motion/react");
|
|
2857
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2005
2858
|
function SuiteMotionProvider({ children }) {
|
|
2006
|
-
return /* @__PURE__ */ (0,
|
|
2859
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react10.LazyMotion, { features: import_react10.domAnimation, strict: true, children });
|
|
2007
2860
|
}
|
|
2008
2861
|
var SUITE_SPRINGS = {
|
|
2009
2862
|
/** Snappy panel/sheet entrances — small overshoot. */
|
|
@@ -2014,217 +2867,25 @@ var SUITE_SPRINGS = {
|
|
|
2014
2867
|
press: { type: "spring", stiffness: 600, damping: 35, mass: 0.5 }
|
|
2015
2868
|
};
|
|
2016
2869
|
|
|
2017
|
-
// src/suite/components/suite-layout.tsx
|
|
2018
|
-
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2019
|
-
var WIDTHS = {
|
|
2020
|
-
full: "max-w-none",
|
|
2021
|
-
wide: "max-w-7xl",
|
|
2022
|
-
content: "max-w-6xl",
|
|
2023
|
-
narrow: "max-w-4xl"
|
|
2024
|
-
};
|
|
2025
|
-
function SuiteBreadcrumbs({ items, className }) {
|
|
2026
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { className: "flex min-w-0 items-center gap-1.5", children: items.map((item, index) => {
|
|
2027
|
-
const isLast = index === items.length - 1;
|
|
2028
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
2029
|
-
index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "select-none text-ph-border", "aria-hidden": "true", children: "/" }) : null,
|
|
2030
|
-
item.href && !isLast ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2031
|
-
"a",
|
|
2032
|
-
{
|
|
2033
|
-
href: item.href,
|
|
2034
|
-
className: "truncate transition hover:text-ph-ink",
|
|
2035
|
-
children: item.label
|
|
2036
|
-
}
|
|
2037
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2038
|
-
"span",
|
|
2039
|
-
{
|
|
2040
|
-
className: cn(
|
|
2041
|
-
"truncate",
|
|
2042
|
-
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
2043
|
-
),
|
|
2044
|
-
"aria-current": isLast ? "page" : void 0,
|
|
2045
|
-
children: item.label
|
|
2046
|
-
}
|
|
2047
|
-
)
|
|
2048
|
-
] }, index);
|
|
2049
|
-
}) }) });
|
|
2050
|
-
}
|
|
2051
|
-
function SuitePage({
|
|
2052
|
-
children,
|
|
2053
|
-
width = "wide",
|
|
2054
|
-
inset = true,
|
|
2055
|
-
className,
|
|
2056
|
-
as: Component = "div",
|
|
2057
|
-
dataTest,
|
|
2058
|
-
id,
|
|
2059
|
-
role,
|
|
2060
|
-
"aria-live": ariaLive
|
|
2061
|
-
}) {
|
|
2062
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2063
|
-
Component,
|
|
2064
|
-
{
|
|
2065
|
-
id,
|
|
2066
|
-
"data-test": dataTest,
|
|
2067
|
-
role,
|
|
2068
|
-
"aria-live": ariaLive,
|
|
2069
|
-
className: cn(
|
|
2070
|
-
"mx-auto flex w-full min-w-0 flex-col",
|
|
2071
|
-
WIDTHS[width],
|
|
2072
|
-
// Tight inset keeps page titles aligned without excessive whitespace.
|
|
2073
|
-
inset && "px-4 pb-5 pt-2 sm:px-6 sm:pb-6 sm:pt-3 lg:px-8",
|
|
2074
|
-
className
|
|
2075
|
-
),
|
|
2076
|
-
children
|
|
2077
|
-
}
|
|
2078
|
-
);
|
|
2079
|
-
}
|
|
2080
|
-
function SuitePageHeader({
|
|
2081
|
-
title,
|
|
2082
|
-
description,
|
|
2083
|
-
eyebrow,
|
|
2084
|
-
actions,
|
|
2085
|
-
className,
|
|
2086
|
-
titleClassName,
|
|
2087
|
-
dataTest,
|
|
2088
|
-
/** Optional icon rendered before the title. */
|
|
2089
|
-
icon,
|
|
2090
|
-
/** Use the animated sun/moon icon from the Today page. */
|
|
2091
|
-
todayIcon,
|
|
2092
|
-
todayIconClassName,
|
|
2093
|
-
/** Small badge/pill next to the title (e.g. "Beta", org name). */
|
|
2094
|
-
badge,
|
|
2095
|
-
/** Breadcrumb line rendered above the title. */
|
|
2096
|
-
breadcrumb
|
|
2097
|
-
}) {
|
|
2098
|
-
const resolvedIcon = todayIcon ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2099
|
-
TodayTimeIcon,
|
|
2100
|
-
{
|
|
2101
|
-
className: cn(
|
|
2102
|
-
"h-6 w-6 sm:h-7 sm:w-7 text-amber-500",
|
|
2103
|
-
todayIconClassName
|
|
2104
|
-
)
|
|
2105
|
-
}
|
|
2106
|
-
) : icon;
|
|
2107
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2108
|
-
"header",
|
|
2109
|
-
{
|
|
2110
|
-
"data-test": dataTest,
|
|
2111
|
-
className: cn(
|
|
2112
|
-
"flex items-start justify-between gap-4 pb-2 sm:pb-3",
|
|
2113
|
-
className
|
|
2114
|
-
),
|
|
2115
|
-
children: [
|
|
2116
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex min-w-0 items-start gap-3", children: [
|
|
2117
|
-
resolvedIcon ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2118
|
-
"div",
|
|
2119
|
-
{
|
|
2120
|
-
className: "hidden shrink-0 pt-1 sm:block",
|
|
2121
|
-
"aria-hidden": "true",
|
|
2122
|
-
children: resolvedIcon
|
|
2123
|
-
}
|
|
2124
|
-
) : null,
|
|
2125
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
2126
|
-
eyebrow ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: eyebrow }) : null,
|
|
2127
|
-
breadcrumb ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: breadcrumb }) : null,
|
|
2128
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
2129
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2130
|
-
"h1",
|
|
2131
|
-
{
|
|
2132
|
-
className: cn(
|
|
2133
|
-
"font-display text-[1.625rem] font-bold leading-tight tracking-tight text-ph-ink sm:text-[2.25rem]",
|
|
2134
|
-
titleClassName
|
|
2135
|
-
),
|
|
2136
|
-
children: title
|
|
2137
|
-
}
|
|
2138
|
-
),
|
|
2139
|
-
badge ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "rounded-md bg-ph-muted px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-ph-subtle", children: badge }) : null
|
|
2140
|
-
] }),
|
|
2141
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
2142
|
-
] })
|
|
2143
|
-
] }),
|
|
2144
|
-
actions ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex shrink-0 items-center gap-2 pt-1", children: actions }) : null
|
|
2145
|
-
]
|
|
2146
|
-
}
|
|
2147
|
-
);
|
|
2148
|
-
}
|
|
2149
|
-
function SuiteToolbar({
|
|
2150
|
-
children,
|
|
2151
|
-
className,
|
|
2152
|
-
label = "Page tools",
|
|
2153
|
-
dataTest
|
|
2154
|
-
}) {
|
|
2155
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2156
|
-
"div",
|
|
2157
|
-
{
|
|
2158
|
-
role: "toolbar",
|
|
2159
|
-
"aria-label": label,
|
|
2160
|
-
"data-test": dataTest,
|
|
2161
|
-
className: cn("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
2162
|
-
children
|
|
2163
|
-
}
|
|
2164
|
-
);
|
|
2165
|
-
}
|
|
2166
|
-
function SuiteTabList({
|
|
2167
|
-
children,
|
|
2168
|
-
className,
|
|
2169
|
-
label,
|
|
2170
|
-
dataTest
|
|
2171
|
-
}) {
|
|
2172
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2173
|
-
"nav",
|
|
2174
|
-
{
|
|
2175
|
-
"aria-label": label,
|
|
2176
|
-
"data-test": dataTest,
|
|
2177
|
-
className: cn(
|
|
2178
|
-
"flex min-w-0 flex-wrap gap-2 [&_a]:min-h-[48px] [&_button]:min-h-[48px] sm:[&_a]:min-h-[44px] sm:[&_button]:min-h-[44px]",
|
|
2179
|
-
className
|
|
2180
|
-
),
|
|
2181
|
-
children
|
|
2182
|
-
}
|
|
2183
|
-
);
|
|
2184
|
-
}
|
|
2185
|
-
function SuiteSectionHeader({
|
|
2186
|
-
title,
|
|
2187
|
-
description,
|
|
2188
|
-
action,
|
|
2189
|
-
className
|
|
2190
|
-
}) {
|
|
2191
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2192
|
-
"div",
|
|
2193
|
-
{
|
|
2194
|
-
className: cn(
|
|
2195
|
-
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
2196
|
-
className
|
|
2197
|
-
),
|
|
2198
|
-
children: [
|
|
2199
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "min-w-0", children: [
|
|
2200
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { className: "font-display text-balance text-lg font-semibold tracking-tight text-ph-ink sm:text-xl", children: title }),
|
|
2201
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
2202
|
-
] }),
|
|
2203
|
-
action ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
2204
|
-
]
|
|
2205
|
-
}
|
|
2206
|
-
);
|
|
2207
|
-
}
|
|
2208
|
-
|
|
2209
2870
|
// src/suite/components/suite-skeleton.tsx
|
|
2210
|
-
var
|
|
2871
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2211
2872
|
function SuiteSkeleton({
|
|
2212
2873
|
className,
|
|
2213
2874
|
lines = 1,
|
|
2214
2875
|
circle,
|
|
2215
2876
|
width
|
|
2216
2877
|
}) {
|
|
2217
|
-
return /* @__PURE__ */ (0,
|
|
2878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2218
2879
|
"div",
|
|
2219
2880
|
{
|
|
2220
2881
|
className: cn("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
2221
2882
|
"aria-hidden": true,
|
|
2222
|
-
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0,
|
|
2883
|
+
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2223
2884
|
"div",
|
|
2224
2885
|
{
|
|
2225
2886
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2226
2887
|
style: { animationDelay: `${index * 80}ms` },
|
|
2227
|
-
children: /* @__PURE__ */ (0,
|
|
2888
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2228
2889
|
"div",
|
|
2229
2890
|
{
|
|
2230
2891
|
className: cn(
|
|
@@ -2248,35 +2909,35 @@ function SuiteSkeletonCard({
|
|
|
2248
2909
|
rows = 3,
|
|
2249
2910
|
header = true
|
|
2250
2911
|
}) {
|
|
2251
|
-
return /* @__PURE__ */ (0,
|
|
2912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2252
2913
|
"div",
|
|
2253
2914
|
{
|
|
2254
2915
|
className: cn(
|
|
2255
|
-
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border
|
|
2916
|
+
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border bg-ph-surface p-6 shadow-sm",
|
|
2256
2917
|
className
|
|
2257
2918
|
),
|
|
2258
2919
|
"aria-hidden": true,
|
|
2259
2920
|
children: [
|
|
2260
|
-
header ? /* @__PURE__ */ (0,
|
|
2921
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2261
2922
|
"div",
|
|
2262
2923
|
{
|
|
2263
2924
|
className: "mb-5 flex items-center gap-3 animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2264
2925
|
style: { animationDelay: "100ms" },
|
|
2265
2926
|
children: [
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-xl" }),
|
|
2928
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 space-y-2", children: [
|
|
2929
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-4 w-1/3" }),
|
|
2930
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2270
2931
|
] })
|
|
2271
2932
|
]
|
|
2272
2933
|
}
|
|
2273
2934
|
) : null,
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2935
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-3", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2275
2936
|
"div",
|
|
2276
2937
|
{
|
|
2277
2938
|
className: "animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2278
2939
|
style: { animationDelay: `${200 + index * 80}ms` },
|
|
2279
|
-
children: /* @__PURE__ */ (0,
|
|
2940
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2280
2941
|
"div",
|
|
2281
2942
|
{
|
|
2282
2943
|
className: "ph-skeleton h-3",
|
|
@@ -2294,16 +2955,16 @@ function SuiteSkeletonList({
|
|
|
2294
2955
|
className,
|
|
2295
2956
|
items = 4
|
|
2296
2957
|
}) {
|
|
2297
|
-
return /* @__PURE__ */ (0,
|
|
2958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("space-y-3", className), "aria-hidden": true, children: Array.from({ length: items }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2298
2959
|
"div",
|
|
2299
2960
|
{
|
|
2300
2961
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2301
2962
|
style: { animationDelay: `${index * 100}ms` },
|
|
2302
|
-
children: /* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2304
|
-
/* @__PURE__ */ (0,
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-3 rounded-xl border border-ph-border bg-ph-surface p-4", children: [
|
|
2964
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-lg" }),
|
|
2965
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
2966
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3.5 w-3/4" }),
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2307
2968
|
] })
|
|
2308
2969
|
] })
|
|
2309
2970
|
},
|
|
@@ -2318,22 +2979,22 @@ function SuiteEmptyState({
|
|
|
2318
2979
|
className,
|
|
2319
2980
|
size = "md"
|
|
2320
2981
|
}) {
|
|
2321
|
-
return /* @__PURE__ */ (0,
|
|
2982
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2322
2983
|
"div",
|
|
2323
2984
|
{
|
|
2324
2985
|
className: cn(
|
|
2325
|
-
"relative overflow-hidden rounded-2xl border border-ph-border
|
|
2986
|
+
"relative overflow-hidden rounded-2xl border border-ph-border bg-ph-surface text-center",
|
|
2326
2987
|
size === "sm" ? "px-5 py-8" : "px-6 py-12 sm:px-10 sm:py-16",
|
|
2327
2988
|
className
|
|
2328
2989
|
),
|
|
2329
2990
|
children: [
|
|
2330
|
-
/* @__PURE__ */ (0,
|
|
2331
|
-
/* @__PURE__ */ (0,
|
|
2332
|
-
/* @__PURE__ */ (0,
|
|
2991
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "pointer-events-none absolute inset-0 overflow-hidden opacity-60", "aria-hidden": true, children: [
|
|
2992
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute -left-10 -top-10 h-40 w-40 rounded-full bg-ph-brand/10 blur-3xl" }),
|
|
2993
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute -bottom-10 -right-10 h-40 w-40 rounded-full bg-ph-accent/10 blur-3xl" })
|
|
2333
2994
|
] }),
|
|
2334
|
-
/* @__PURE__ */ (0,
|
|
2335
|
-
icon ? /* @__PURE__ */ (0,
|
|
2336
|
-
/* @__PURE__ */ (0,
|
|
2995
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
|
|
2996
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mx-auto mb-4 inline-flex items-center justify-center rounded-2xl bg-ph-muted p-3 shadow-sm ring-1 ring-black/[0.06]", children: icon }) : null,
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2337
2998
|
"h3",
|
|
2338
2999
|
{
|
|
2339
3000
|
className: cn(
|
|
@@ -2343,8 +3004,8 @@ function SuiteEmptyState({
|
|
|
2343
3004
|
children: title
|
|
2344
3005
|
}
|
|
2345
3006
|
),
|
|
2346
|
-
description ? /* @__PURE__ */ (0,
|
|
2347
|
-
action ? /* @__PURE__ */ (0,
|
|
3007
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mx-auto mt-2 max-w-sm text-sm leading-relaxed text-ph-subtle", children: description }) : null,
|
|
3008
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-5 flex flex-wrap items-center justify-center gap-2", children: action }) : null
|
|
2348
3009
|
] })
|
|
2349
3010
|
]
|
|
2350
3011
|
}
|
|
@@ -2352,24 +3013,26 @@ function SuiteEmptyState({
|
|
|
2352
3013
|
}
|
|
2353
3014
|
|
|
2354
3015
|
// src/suite/components/suite-settings-mobile-nav.tsx
|
|
2355
|
-
var
|
|
2356
|
-
var
|
|
3016
|
+
var import_react11 = require("react");
|
|
3017
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2357
3018
|
function SuiteSettingsMobileNav({
|
|
2358
3019
|
items,
|
|
2359
3020
|
activeHref,
|
|
2360
3021
|
onSelect,
|
|
2361
|
-
dataTest
|
|
3022
|
+
dataTest,
|
|
3023
|
+
ariaLabel = "Settings sections",
|
|
3024
|
+
className
|
|
2362
3025
|
}) {
|
|
2363
|
-
return /* @__PURE__ */ (0,
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2364
3027
|
"nav",
|
|
2365
3028
|
{
|
|
2366
3029
|
"data-test": dataTest,
|
|
2367
|
-
"aria-label":
|
|
2368
|
-
className: "-
|
|
2369
|
-
children: /* @__PURE__ */ (0,
|
|
3030
|
+
"aria-label": ariaLabel,
|
|
3031
|
+
className: cn("suite-settings-mobile-nav lg:hidden", className),
|
|
3032
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex snap-x gap-2 overflow-x-auto pb-3 pt-1 scrollbar-hide [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: items.map((item) => {
|
|
2370
3033
|
const Icon = item.icon;
|
|
2371
3034
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
2372
|
-
const iconNode = (0,
|
|
3035
|
+
const iconNode = (0, import_react11.isValidElement)(item.icon) ? item.icon : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2373
3036
|
Icon,
|
|
2374
3037
|
{
|
|
2375
3038
|
className: cn(
|
|
@@ -2379,7 +3042,7 @@ function SuiteSettingsMobileNav({
|
|
|
2379
3042
|
"aria-hidden": true
|
|
2380
3043
|
}
|
|
2381
3044
|
);
|
|
2382
|
-
return /* @__PURE__ */ (0,
|
|
3045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2383
3046
|
"button",
|
|
2384
3047
|
{
|
|
2385
3048
|
type: "button",
|
|
@@ -2387,14 +3050,14 @@ function SuiteSettingsMobileNav({
|
|
|
2387
3050
|
onClick: () => onSelect(item.href),
|
|
2388
3051
|
"aria-current": active ? "page" : void 0,
|
|
2389
3052
|
className: cn(
|
|
2390
|
-
"group relative flex shrink-0 snap-start items-center gap-2 rounded-full px-3.5 py-2.5 text-sm font-medium transition",
|
|
3053
|
+
"group relative flex shrink-0 snap-start items-center gap-2 rounded-full px-3.5 py-2.5 text-sm font-medium transition-colors",
|
|
2391
3054
|
"min-h-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
2392
3055
|
active ? "bg-ph-ink text-ph-surface shadow-sm" : "bg-ph-surface text-ph-subtle ring-1 ring-ph-border hover:bg-ph-muted hover:text-ph-ink"
|
|
2393
3056
|
),
|
|
2394
3057
|
children: [
|
|
2395
3058
|
iconNode,
|
|
2396
|
-
/* @__PURE__ */ (0,
|
|
2397
|
-
active ? /* @__PURE__ */ (0,
|
|
3059
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "whitespace-nowrap", children: item.label }),
|
|
3060
|
+
active ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "absolute inset-x-0 -bottom-3 h-0.5 rounded-full bg-ph-ink lg:hidden" }) : null
|
|
2398
3061
|
]
|
|
2399
3062
|
},
|
|
2400
3063
|
item.href
|
|
@@ -2408,10 +3071,10 @@ function SuiteSettingsMobileNav({
|
|
|
2408
3071
|
var import_link2 = __toESM(require("next/link"));
|
|
2409
3072
|
|
|
2410
3073
|
// src/components/ui/Tooltip.tsx
|
|
2411
|
-
var
|
|
3074
|
+
var import_react12 = require("react");
|
|
2412
3075
|
var import_react_dom = require("react-dom");
|
|
2413
|
-
var
|
|
2414
|
-
var TooltipDelayContext = (0,
|
|
3076
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3077
|
+
var TooltipDelayContext = (0, import_react12.createContext)(0);
|
|
2415
3078
|
function tooltipPosition(trigger, side, align, offset) {
|
|
2416
3079
|
const horizontal = align === "start" ? trigger.left : align === "end" ? trigger.right : trigger.left + trigger.width / 2;
|
|
2417
3080
|
const vertical = align === "start" ? trigger.top : align === "end" ? trigger.bottom : trigger.top + trigger.height / 2;
|
|
@@ -2451,12 +3114,12 @@ function Tooltip({
|
|
|
2451
3114
|
onOpenChange,
|
|
2452
3115
|
delayDuration
|
|
2453
3116
|
}) {
|
|
2454
|
-
const providerDelay = (0,
|
|
2455
|
-
const generatedId = (0,
|
|
2456
|
-
const triggerRef = (0,
|
|
2457
|
-
const timerRef = (0,
|
|
2458
|
-
const [internalOpen, setInternalOpen] = (0,
|
|
2459
|
-
const [position, setPosition] = (0,
|
|
3117
|
+
const providerDelay = (0, import_react12.useContext)(TooltipDelayContext);
|
|
3118
|
+
const generatedId = (0, import_react12.useId)().replace(/:/g, "");
|
|
3119
|
+
const triggerRef = (0, import_react12.useRef)(null);
|
|
3120
|
+
const timerRef = (0, import_react12.useRef)(null);
|
|
3121
|
+
const [internalOpen, setInternalOpen] = (0, import_react12.useState)(defaultOpen);
|
|
3122
|
+
const [position, setPosition] = (0, import_react12.useState)(null);
|
|
2460
3123
|
const isOpen = open != null ? open : internalOpen;
|
|
2461
3124
|
const triggerId = children.props.id;
|
|
2462
3125
|
const tooltipId = triggerId ? `${triggerId}-tooltip` : `ph-tooltip-${generatedId}`;
|
|
@@ -2490,7 +3153,7 @@ function Tooltip({
|
|
|
2490
3153
|
clearTimer();
|
|
2491
3154
|
setOpen(false);
|
|
2492
3155
|
}
|
|
2493
|
-
(0,
|
|
3156
|
+
(0, import_react12.useEffect)(() => {
|
|
2494
3157
|
if (!isOpen) return;
|
|
2495
3158
|
const reposition = () => updatePosition();
|
|
2496
3159
|
window.addEventListener("resize", reposition);
|
|
@@ -2500,11 +3163,11 @@ function Tooltip({
|
|
|
2500
3163
|
window.removeEventListener("scroll", reposition, true);
|
|
2501
3164
|
};
|
|
2502
3165
|
});
|
|
2503
|
-
(0,
|
|
3166
|
+
(0, import_react12.useEffect)(() => () => clearTimer(), []);
|
|
2504
3167
|
const describedBy = [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ");
|
|
2505
|
-
const trigger = (0,
|
|
2506
|
-
return /* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
3168
|
+
const trigger = (0, import_react12.cloneElement)(children, { "aria-describedby": describedBy });
|
|
3169
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2508
3171
|
"span",
|
|
2509
3172
|
{
|
|
2510
3173
|
ref: triggerRef,
|
|
@@ -2520,12 +3183,12 @@ function Tooltip({
|
|
|
2520
3183
|
}
|
|
2521
3184
|
),
|
|
2522
3185
|
isOpen && position && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
|
|
2523
|
-
/* @__PURE__ */ (0,
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2524
3187
|
"span",
|
|
2525
3188
|
{
|
|
2526
3189
|
style: __spreadValues({ position: "fixed" }, position),
|
|
2527
3190
|
className: "pointer-events-none z-[200]",
|
|
2528
|
-
children: /* @__PURE__ */ (0,
|
|
3191
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2529
3192
|
"span",
|
|
2530
3193
|
{
|
|
2531
3194
|
id: tooltipId,
|
|
@@ -2543,7 +3206,7 @@ function Tooltip({
|
|
|
2543
3206
|
}
|
|
2544
3207
|
|
|
2545
3208
|
// src/suite/components/suite-sidebar.tsx
|
|
2546
|
-
var
|
|
3209
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2547
3210
|
function renderNode(node, collapsed) {
|
|
2548
3211
|
if (typeof node === "function") return node(collapsed);
|
|
2549
3212
|
return node;
|
|
@@ -2560,7 +3223,7 @@ function SuiteSidebar({
|
|
|
2560
3223
|
className,
|
|
2561
3224
|
surface = false
|
|
2562
3225
|
}) {
|
|
2563
|
-
return /* @__PURE__ */ (0,
|
|
3226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2564
3227
|
"div",
|
|
2565
3228
|
{
|
|
2566
3229
|
className: cn(
|
|
@@ -2569,7 +3232,7 @@ function SuiteSidebar({
|
|
|
2569
3232
|
className
|
|
2570
3233
|
),
|
|
2571
3234
|
children: [
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2573
3236
|
"div",
|
|
2574
3237
|
{
|
|
2575
3238
|
className: cn(
|
|
@@ -2578,12 +3241,12 @@ function SuiteSidebar({
|
|
|
2578
3241
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
2579
3242
|
),
|
|
2580
3243
|
children: [
|
|
2581
|
-
/* @__PURE__ */ (0,
|
|
2582
|
-
collapsed ? null : /* @__PURE__ */ (0,
|
|
3244
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
3245
|
+
collapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
2583
3246
|
]
|
|
2584
3247
|
}
|
|
2585
3248
|
),
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
3249
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2587
3250
|
"div",
|
|
2588
3251
|
{
|
|
2589
3252
|
className: cn(
|
|
@@ -2592,17 +3255,17 @@ function SuiteSidebar({
|
|
|
2592
3255
|
collapsed ? "px-1.5 py-2" : "p-2"
|
|
2593
3256
|
),
|
|
2594
3257
|
children: [
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
3258
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2596
3259
|
"nav",
|
|
2597
3260
|
{
|
|
2598
3261
|
"aria-label": "Pages",
|
|
2599
3262
|
className: "shrink-0 space-y-0.5",
|
|
2600
3263
|
children: [
|
|
2601
|
-
/* @__PURE__ */ (0,
|
|
2602
|
-
/* @__PURE__ */ (0,
|
|
3264
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
|
|
3265
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-0.5", children: navItems.map((item) => {
|
|
2603
3266
|
const Icon = item.icon;
|
|
2604
3267
|
const active = Boolean(item.active);
|
|
2605
|
-
const link = /* @__PURE__ */ (0,
|
|
3268
|
+
const link = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2606
3269
|
import_link2.default,
|
|
2607
3270
|
{
|
|
2608
3271
|
href: item.href,
|
|
@@ -2615,7 +3278,7 @@ function SuiteSidebar({
|
|
|
2615
3278
|
collapsed ? "mx-auto size-10 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
2616
3279
|
),
|
|
2617
3280
|
children: [
|
|
2618
|
-
/* @__PURE__ */ (0,
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2619
3282
|
"span",
|
|
2620
3283
|
{
|
|
2621
3284
|
className: cn(
|
|
@@ -2623,7 +3286,7 @@ function SuiteSidebar({
|
|
|
2623
3286
|
item.iconClassName
|
|
2624
3287
|
),
|
|
2625
3288
|
"aria-hidden": true,
|
|
2626
|
-
children: /* @__PURE__ */ (0,
|
|
3289
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2627
3290
|
Icon,
|
|
2628
3291
|
{
|
|
2629
3292
|
className: "h-full w-full",
|
|
@@ -2632,7 +3295,7 @@ function SuiteSidebar({
|
|
|
2632
3295
|
)
|
|
2633
3296
|
}
|
|
2634
3297
|
),
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
3298
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2636
3299
|
"span",
|
|
2637
3300
|
{
|
|
2638
3301
|
className: cn(
|
|
@@ -2643,17 +3306,17 @@ function SuiteSidebar({
|
|
|
2643
3306
|
children: item.label
|
|
2644
3307
|
}
|
|
2645
3308
|
),
|
|
2646
|
-
!collapsed && item.badge ? /* @__PURE__ */ (0,
|
|
3309
|
+
!collapsed && item.badge ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
|
|
2647
3310
|
]
|
|
2648
3311
|
},
|
|
2649
3312
|
item.label
|
|
2650
3313
|
);
|
|
2651
|
-
return collapsed ? /* @__PURE__ */ (0,
|
|
3314
|
+
return collapsed ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
|
|
2652
3315
|
}) })
|
|
2653
3316
|
]
|
|
2654
3317
|
}
|
|
2655
3318
|
),
|
|
2656
|
-
secondaryNav ? /* @__PURE__ */ (0,
|
|
3319
|
+
secondaryNav ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2657
3320
|
"div",
|
|
2658
3321
|
{
|
|
2659
3322
|
className: "min-h-0 flex-1",
|
|
@@ -2664,7 +3327,7 @@ function SuiteSidebar({
|
|
|
2664
3327
|
]
|
|
2665
3328
|
}
|
|
2666
3329
|
),
|
|
2667
|
-
/* @__PURE__ */ (0,
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2668
3331
|
"div",
|
|
2669
3332
|
{
|
|
2670
3333
|
className: cn(
|
|
@@ -2672,7 +3335,7 @@ function SuiteSidebar({
|
|
|
2672
3335
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
2673
3336
|
collapsed ? "p-1.5" : "p-3"
|
|
2674
3337
|
),
|
|
2675
|
-
children: /* @__PURE__ */ (0,
|
|
3338
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2676
3339
|
"div",
|
|
2677
3340
|
{
|
|
2678
3341
|
className: cn(
|
|
@@ -2681,7 +3344,7 @@ function SuiteSidebar({
|
|
|
2681
3344
|
),
|
|
2682
3345
|
children: [
|
|
2683
3346
|
renderNode(userMenu, collapsed),
|
|
2684
|
-
!collapsed && footerExtras ? /* @__PURE__ */ (0,
|
|
3347
|
+
!collapsed && footerExtras ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ml-auto shrink-0", children: renderNode(footerExtras, collapsed) }) : null
|
|
2685
3348
|
]
|
|
2686
3349
|
}
|
|
2687
3350
|
)
|
|
@@ -2693,7 +3356,7 @@ function SuiteSidebar({
|
|
|
2693
3356
|
}
|
|
2694
3357
|
|
|
2695
3358
|
// src/suite/components/suite-app-layout.tsx
|
|
2696
|
-
var
|
|
3359
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2697
3360
|
function SuiteAppLayout({
|
|
2698
3361
|
sidebar,
|
|
2699
3362
|
children,
|
|
@@ -2701,41 +3364,59 @@ function SuiteAppLayout({
|
|
|
2701
3364
|
bottomNav,
|
|
2702
3365
|
sidebarWidth = 240,
|
|
2703
3366
|
collapsed = false,
|
|
3367
|
+
lockMainScroll = false,
|
|
2704
3368
|
onStartResize,
|
|
2705
3369
|
onResetWidth,
|
|
2706
3370
|
className
|
|
2707
3371
|
}) {
|
|
2708
|
-
return /* @__PURE__ */ (0,
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
3372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3373
|
+
"div",
|
|
3374
|
+
{
|
|
3375
|
+
"data-test": "app-shell",
|
|
3376
|
+
className: cn("flex min-h-dvh lg:h-screen lg:overflow-hidden", className),
|
|
3377
|
+
children: [
|
|
3378
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3379
|
+
"aside",
|
|
3380
|
+
{
|
|
3381
|
+
className: "relative hidden shrink-0 flex-col overflow-hidden border-r border-ph-border transition-[width] duration-200 ease-out lg:flex",
|
|
3382
|
+
style: { width: `${sidebarWidth}px` },
|
|
3383
|
+
"data-collapsed": collapsed ? "true" : "false",
|
|
3384
|
+
children: [
|
|
3385
|
+
sidebar,
|
|
3386
|
+
onStartResize ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3387
|
+
"div",
|
|
3388
|
+
{
|
|
3389
|
+
role: "separator",
|
|
3390
|
+
"aria-orientation": "vertical",
|
|
3391
|
+
"aria-label": "Resize sidebar",
|
|
3392
|
+
onPointerDown: onStartResize,
|
|
3393
|
+
onDoubleClick: onResetWidth,
|
|
3394
|
+
className: "absolute inset-y-0 right-0 z-10 w-1 cursor-col-resize transition-colors hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
|
|
3395
|
+
}
|
|
3396
|
+
) : null
|
|
3397
|
+
]
|
|
3398
|
+
}
|
|
3399
|
+
),
|
|
3400
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
3401
|
+
mobileHeader ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 lg:hidden", children: mobileHeader }) : null,
|
|
3402
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3403
|
+
"main",
|
|
3404
|
+
{
|
|
3405
|
+
id: "main-content",
|
|
3406
|
+
tabIndex: -1,
|
|
3407
|
+
"data-lock-scroll": lockMainScroll ? "true" : void 0,
|
|
3408
|
+
className: cn(
|
|
3409
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
3410
|
+
lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
|
|
3411
|
+
),
|
|
3412
|
+
children
|
|
3413
|
+
}
|
|
3414
|
+
),
|
|
3415
|
+
bottomNav ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 lg:hidden", children: bottomNav }) : null
|
|
3416
|
+
] })
|
|
3417
|
+
]
|
|
3418
|
+
}
|
|
3419
|
+
);
|
|
2739
3420
|
}
|
|
2740
3421
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2741
3422
|
0 && (module.exports = {
|
|
@@ -2748,10 +3429,16 @@ function SuiteAppLayout({
|
|
|
2748
3429
|
AppSwitcherMark,
|
|
2749
3430
|
CommandPaletteHost,
|
|
2750
3431
|
DeferredChrome,
|
|
3432
|
+
SIDEBAR_COLLAPSE_THRESHOLD,
|
|
3433
|
+
SIDEBAR_DEFAULT_WIDTH,
|
|
3434
|
+
SIDEBAR_MAX_WIDTH,
|
|
3435
|
+
SIDEBAR_MIN_EXPANDED_WIDTH,
|
|
3436
|
+
SIDEBAR_RAIL_WIDTH,
|
|
2751
3437
|
SUITE_APPS,
|
|
2752
3438
|
SUITE_APP_MAP,
|
|
2753
3439
|
SUITE_GLYPHS,
|
|
2754
3440
|
SUITE_ICON_NAMES,
|
|
3441
|
+
SUITE_OPEN_ASK_AI_EVENT,
|
|
2755
3442
|
SUITE_SPRINGS,
|
|
2756
3443
|
SourceAppGlyph,
|
|
2757
3444
|
SuiteAiPanel,
|
|
@@ -2769,6 +3456,7 @@ function SuiteAppLayout({
|
|
|
2769
3456
|
SuitePage,
|
|
2770
3457
|
SuitePageHeader,
|
|
2771
3458
|
SuiteSectionHeader,
|
|
3459
|
+
SuiteSettingsLayout,
|
|
2772
3460
|
SuiteSettingsMobileNav,
|
|
2773
3461
|
SuiteSidebar,
|
|
2774
3462
|
SuiteSkeleton,
|
|
@@ -2778,11 +3466,15 @@ function SuiteAppLayout({
|
|
|
2778
3466
|
SuiteThemeProvider,
|
|
2779
3467
|
SuiteToolbar,
|
|
2780
3468
|
SuiteUserMenu,
|
|
3469
|
+
TodayAskAiCard,
|
|
2781
3470
|
TodayCalibrating,
|
|
3471
|
+
TodayEmptyAction,
|
|
2782
3472
|
TodayEmptyState,
|
|
2783
3473
|
TodayHero,
|
|
3474
|
+
TodayLayout,
|
|
2784
3475
|
TodayPageFrame,
|
|
2785
3476
|
TodayPanel,
|
|
3477
|
+
TodayPrimaryAction,
|
|
2786
3478
|
TodaySection,
|
|
2787
3479
|
TodayTimeIcon,
|
|
2788
3480
|
TodayTopBar,
|
|
@@ -2792,9 +3484,12 @@ function SuiteAppLayout({
|
|
|
2792
3484
|
cn,
|
|
2793
3485
|
getTodayGreeting,
|
|
2794
3486
|
m,
|
|
3487
|
+
openSuiteAskAi,
|
|
3488
|
+
resolveSuiteNotificationHref,
|
|
2795
3489
|
sourceToSuiteApp,
|
|
2796
3490
|
suiteAppBaseUrl,
|
|
2797
3491
|
suiteAppLabel,
|
|
2798
3492
|
useIdleMount,
|
|
3493
|
+
useSidebarWidth,
|
|
2799
3494
|
useSuiteTheme
|
|
2800
3495
|
});
|