@xenide-io/the-old-ui-theme 0.4.3 → 0.4.6
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 +1184 -661
- package/dist/suite.mjs +1123 -601
- 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.tsx +269 -103
- package/src/suite/components/suite-app-layout.tsx +48 -28
- package/src/suite/components/suite-layout.tsx +85 -41
- 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,119 @@ 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
|
+
}
|
|
1843
2321
|
function SuiteAiPanel({
|
|
1844
|
-
presets,
|
|
1845
|
-
emptyState,
|
|
1846
|
-
|
|
1847
|
-
|
|
2322
|
+
presets = [],
|
|
2323
|
+
emptyState = "Ask anything about your workspace, or look something up online.",
|
|
2324
|
+
title = "Ask AI",
|
|
2325
|
+
fetchChat,
|
|
2326
|
+
sendMessage,
|
|
2327
|
+
clearChat,
|
|
1848
2328
|
brandIcon: BrandIcon,
|
|
1849
|
-
spinner: Spinner
|
|
2329
|
+
spinner: Spinner,
|
|
2330
|
+
hideLauncher = false
|
|
1850
2331
|
}) {
|
|
1851
|
-
const [open, setOpen] = (0,
|
|
1852
|
-
const [prompt, setPrompt] = (0,
|
|
1853
|
-
const [
|
|
1854
|
-
const [
|
|
1855
|
-
const [
|
|
1856
|
-
const [
|
|
2332
|
+
const [open, setOpen] = (0, import_react8.useState)(false);
|
|
2333
|
+
const [prompt, setPrompt] = (0, import_react8.useState)("");
|
|
2334
|
+
const [messages, setMessages] = (0, import_react8.useState)([]);
|
|
2335
|
+
const [loading, setLoading] = (0, import_react8.useState)(false);
|
|
2336
|
+
const [hydrating, setHydrating] = (0, import_react8.useState)(false);
|
|
2337
|
+
const [error, setError] = (0, import_react8.useState)("");
|
|
2338
|
+
const [copiedId, setCopiedId] = (0, import_react8.useState)(null);
|
|
2339
|
+
const scrollerRef = (0, import_react8.useRef)(null);
|
|
2340
|
+
const pendingPromptRef = (0, import_react8.useRef)(null);
|
|
2341
|
+
const scrollToBottom = (0, import_react8.useCallback)(() => {
|
|
2342
|
+
const el = scrollerRef.current;
|
|
2343
|
+
if (!el) return;
|
|
2344
|
+
el.scrollTop = el.scrollHeight;
|
|
2345
|
+
}, []);
|
|
2346
|
+
const hydrate = (0, import_react8.useCallback)(async () => {
|
|
2347
|
+
var _a;
|
|
2348
|
+
setHydrating(true);
|
|
2349
|
+
setError("");
|
|
2350
|
+
try {
|
|
2351
|
+
const data = await fetchChat();
|
|
2352
|
+
setMessages((_a = data.messages) != null ? _a : []);
|
|
2353
|
+
if (!data.configured) {
|
|
2354
|
+
setError("ShellStack AI is not configured for this workspace yet.");
|
|
2355
|
+
}
|
|
2356
|
+
} catch (err) {
|
|
2357
|
+
setError(
|
|
2358
|
+
err instanceof Error ? err.message : "Could not load your Ask AI chat."
|
|
2359
|
+
);
|
|
2360
|
+
} finally {
|
|
2361
|
+
setHydrating(false);
|
|
2362
|
+
}
|
|
2363
|
+
}, [fetchChat]);
|
|
2364
|
+
(0, import_react8.useEffect)(() => {
|
|
2365
|
+
function onOpen(event) {
|
|
2366
|
+
var _a;
|
|
2367
|
+
const detail = event.detail;
|
|
2368
|
+
setOpen(true);
|
|
2369
|
+
if ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) {
|
|
2370
|
+
pendingPromptRef.current = detail.prompt.trim();
|
|
2371
|
+
setPrompt(detail.prompt.trim());
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2375
|
+
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2376
|
+
}, []);
|
|
2377
|
+
(0, import_react8.useEffect)(() => {
|
|
2378
|
+
if (!open) return;
|
|
2379
|
+
void hydrate().then(() => {
|
|
2380
|
+
const pending = pendingPromptRef.current;
|
|
2381
|
+
pendingPromptRef.current = null;
|
|
2382
|
+
if (pending) {
|
|
2383
|
+
setPrompt(pending);
|
|
2384
|
+
}
|
|
2385
|
+
});
|
|
2386
|
+
}, [open, hydrate]);
|
|
2387
|
+
(0, import_react8.useEffect)(() => {
|
|
2388
|
+
if (open) scrollToBottom();
|
|
2389
|
+
}, [messages, loading, open, scrollToBottom]);
|
|
1857
2390
|
async function ask(text) {
|
|
2391
|
+
var _a;
|
|
1858
2392
|
const trimmed = text.trim();
|
|
1859
2393
|
if (!trimmed || loading) return;
|
|
1860
2394
|
setLoading(true);
|
|
1861
2395
|
setError("");
|
|
1862
|
-
|
|
1863
|
-
|
|
2396
|
+
setPrompt("");
|
|
2397
|
+
setMessages((prev) => [...prev, { role: "user", content: trimmed }]);
|
|
1864
2398
|
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);
|
|
2399
|
+
const result = await sendMessage({ prompt: trimmed });
|
|
2400
|
+
setMessages((_a = result.messages) != null ? _a : []);
|
|
1872
2401
|
} catch (err) {
|
|
2402
|
+
setMessages(
|
|
2403
|
+
(prev) => {
|
|
2404
|
+
var _a2, _b;
|
|
2405
|
+
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;
|
|
2406
|
+
}
|
|
2407
|
+
);
|
|
2408
|
+
setPrompt(trimmed);
|
|
1873
2409
|
setError(
|
|
1874
2410
|
err instanceof Error ? err.message : "The AI request failed. Try again."
|
|
1875
2411
|
);
|
|
@@ -1877,133 +2413,278 @@ function SuiteAiPanel({
|
|
|
1877
2413
|
setLoading(false);
|
|
1878
2414
|
}
|
|
1879
2415
|
}
|
|
1880
|
-
async function
|
|
1881
|
-
if (
|
|
2416
|
+
async function handleClear() {
|
|
2417
|
+
if (loading) return;
|
|
1882
2418
|
try {
|
|
1883
|
-
await
|
|
1884
|
-
|
|
1885
|
-
|
|
2419
|
+
await clearChat();
|
|
2420
|
+
setMessages([]);
|
|
2421
|
+
setError("");
|
|
2422
|
+
} catch (err) {
|
|
2423
|
+
setError(
|
|
2424
|
+
err instanceof Error ? err.message : "Could not clear this chat."
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
async function copyMessage(index, content) {
|
|
2429
|
+
try {
|
|
2430
|
+
await navigator.clipboard.writeText(content);
|
|
2431
|
+
setCopiedId(index);
|
|
2432
|
+
window.setTimeout(() => setCopiedId(null), 1500);
|
|
1886
2433
|
} catch (e) {
|
|
1887
2434
|
}
|
|
1888
2435
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
2436
|
+
const Icon = BrandIcon != null ? BrandIcon : import_iconoir_react8.Sparks;
|
|
2437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2438
|
+
!hideLauncher ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1891
2439
|
"button",
|
|
1892
2440
|
{
|
|
1893
2441
|
type: "button",
|
|
1894
2442
|
"data-test": "ai-panel-launcher",
|
|
1895
2443
|
onClick: () => setOpen(true),
|
|
1896
2444
|
className: "fixed bottom-5 right-5 z-30 flex 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",
|
|
1897
|
-
"aria-label": "Open
|
|
2445
|
+
"aria-label": "Open Ask AI",
|
|
1898
2446
|
children: [
|
|
1899
|
-
/* @__PURE__ */ (0,
|
|
2447
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { className: "h-4 w-4 text-ph-brand" }),
|
|
1900
2448
|
"Ask AI"
|
|
1901
2449
|
]
|
|
1902
2450
|
}
|
|
1903
|
-
),
|
|
1904
|
-
open
|
|
1905
|
-
/* @__PURE__ */ (0,
|
|
2451
|
+
) : null,
|
|
2452
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "fixed inset-0 z-40", role: "dialog", "aria-modal": "true", children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1906
2454
|
"button",
|
|
1907
2455
|
{
|
|
1908
2456
|
type: "button",
|
|
1909
2457
|
className: "absolute inset-0 bg-black/25",
|
|
1910
2458
|
onClick: () => setOpen(false),
|
|
1911
|
-
"aria-label": "Close AI
|
|
2459
|
+
"aria-label": "Close Ask AI"
|
|
1912
2460
|
}
|
|
1913
2461
|
),
|
|
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)(
|
|
2462
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2463
|
+
"aside",
|
|
2464
|
+
{
|
|
2465
|
+
className: "absolute inset-y-0 right-0 flex w-full max-w-md flex-col border-l border-ph-border bg-ph-surface shadow-2xl",
|
|
2466
|
+
"data-test": "suite-ask-ai-panel",
|
|
2467
|
+
children: [
|
|
2468
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center justify-between border-b border-ph-border px-4 py-3", children: [
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "min-w-0", children: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2472
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-sm font-semibold text-ph-ink", children: title })
|
|
2473
|
+
] }),
|
|
2474
|
+
/* @__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" })
|
|
2475
|
+
] }),
|
|
2476
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2477
|
+
messages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2478
|
+
"button",
|
|
2479
|
+
{
|
|
2480
|
+
type: "button",
|
|
2481
|
+
onClick: () => void handleClear(),
|
|
2482
|
+
disabled: loading,
|
|
2483
|
+
className: "rounded-md px-2 py-1 text-xs text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink disabled:opacity-50",
|
|
2484
|
+
"data-test": "ask-ai-clear",
|
|
2485
|
+
children: "Clear"
|
|
2486
|
+
}
|
|
2487
|
+
) : null,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2489
|
+
"button",
|
|
2490
|
+
{
|
|
2491
|
+
type: "button",
|
|
2492
|
+
onClick: () => setOpen(false),
|
|
2493
|
+
className: "rounded p-1 hover:bg-ph-muted",
|
|
2494
|
+
"aria-label": "Close",
|
|
2495
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_iconoir_react8.Xmark, { className: "h-4 w-4" })
|
|
2496
|
+
}
|
|
2497
|
+
)
|
|
2498
|
+
] })
|
|
2499
|
+
] }),
|
|
2500
|
+
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
2501
|
"button",
|
|
1955
2502
|
{
|
|
1956
2503
|
type: "button",
|
|
1957
|
-
onClick: () => void
|
|
1958
|
-
|
|
2504
|
+
onClick: () => void ask(preset.prompt),
|
|
2505
|
+
disabled: loading || hydrating,
|
|
2506
|
+
className: "rounded-full border border-ph-border px-2.5 py-1 text-xs text-ph-ink hover:bg-ph-muted disabled:opacity-50",
|
|
2507
|
+
children: preset.label
|
|
2508
|
+
},
|
|
2509
|
+
preset.label
|
|
2510
|
+
)) }) : null,
|
|
2511
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2512
|
+
"div",
|
|
2513
|
+
{
|
|
2514
|
+
ref: scrollerRef,
|
|
2515
|
+
className: "flex-1 space-y-3 overflow-y-auto p-4",
|
|
1959
2516
|
children: [
|
|
1960
|
-
|
|
1961
|
-
|
|
2517
|
+
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,
|
|
2518
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2520
|
+
"Loading chat\u2026"
|
|
2521
|
+
] }) : null,
|
|
2522
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mt-10 px-2 text-center", children: [
|
|
2523
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2524
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-2 text-sm leading-relaxed text-ph-subtle", children: emptyState })
|
|
2525
|
+
] }) : null,
|
|
2526
|
+
messages.map((message, index) => {
|
|
2527
|
+
const isUser = message.role === "user";
|
|
2528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2529
|
+
"div",
|
|
2530
|
+
{
|
|
2531
|
+
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",
|
|
2532
|
+
"data-test": isUser ? "ask-ai-user" : "ask-ai-assistant",
|
|
2533
|
+
children: [
|
|
2534
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "whitespace-pre-wrap", children: message.content }),
|
|
2535
|
+
!isUser ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2536
|
+
"button",
|
|
2537
|
+
{
|
|
2538
|
+
type: "button",
|
|
2539
|
+
onClick: () => void copyMessage(index, message.content),
|
|
2540
|
+
className: "mt-2 inline-flex items-center gap-1 text-xs text-ph-mutedtext hover:text-ph-ink",
|
|
2541
|
+
children: [
|
|
2542
|
+
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" }),
|
|
2543
|
+
copiedId === index ? "Copied" : "Copy"
|
|
2544
|
+
]
|
|
2545
|
+
}
|
|
2546
|
+
) : null
|
|
2547
|
+
]
|
|
2548
|
+
},
|
|
2549
|
+
`${message.role}-${index}-${message.content.slice(0, 24)}`
|
|
2550
|
+
);
|
|
2551
|
+
}),
|
|
2552
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2554
|
+
"Thinking\u2026"
|
|
2555
|
+
] }) : null
|
|
1962
2556
|
]
|
|
1963
2557
|
}
|
|
1964
|
-
)
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2558
|
+
),
|
|
2559
|
+
/* @__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: [
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2561
|
+
"textarea",
|
|
2562
|
+
{
|
|
2563
|
+
value: prompt,
|
|
2564
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
2565
|
+
onKeyDown: (e) => {
|
|
2566
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
2567
|
+
e.preventDefault();
|
|
2568
|
+
void ask(prompt);
|
|
2569
|
+
}
|
|
2570
|
+
},
|
|
2571
|
+
placeholder: "Ask anything\u2026",
|
|
2572
|
+
rows: 2,
|
|
2573
|
+
disabled: loading,
|
|
2574
|
+
"data-test": "ask-ai-input",
|
|
2575
|
+
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
2576
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
] }) })
|
|
1997
|
-
] })
|
|
1998
|
-
] })
|
|
2577
|
+
),
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2579
|
+
"button",
|
|
2580
|
+
{
|
|
2581
|
+
type: "button",
|
|
2582
|
+
onClick: () => void ask(prompt),
|
|
2583
|
+
disabled: loading || !prompt.trim(),
|
|
2584
|
+
"data-test": "ask-ai-send",
|
|
2585
|
+
className: "self-end rounded-xl bg-ph-brand px-3.5 py-2 text-sm font-medium text-white disabled:opacity-50",
|
|
2586
|
+
children: "Ask"
|
|
2587
|
+
}
|
|
2588
|
+
)
|
|
2589
|
+
] }) })
|
|
2590
|
+
]
|
|
2591
|
+
}
|
|
2592
|
+
)
|
|
2593
|
+
] }) : null
|
|
1999
2594
|
] });
|
|
2000
2595
|
}
|
|
2001
2596
|
|
|
2597
|
+
// src/suite/lib/use-sidebar-width.ts
|
|
2598
|
+
var import_react9 = require("react");
|
|
2599
|
+
var SIDEBAR_RAIL_WIDTH = 56;
|
|
2600
|
+
var SIDEBAR_COLLAPSE_THRESHOLD = 80;
|
|
2601
|
+
var SIDEBAR_MIN_EXPANDED_WIDTH = 180;
|
|
2602
|
+
var SIDEBAR_MAX_WIDTH = 320;
|
|
2603
|
+
var SIDEBAR_DEFAULT_WIDTH = 320;
|
|
2604
|
+
function clampWidth(width) {
|
|
2605
|
+
return Math.min(SIDEBAR_MAX_WIDTH, Math.max(SIDEBAR_RAIL_WIDTH, width));
|
|
2606
|
+
}
|
|
2607
|
+
function snapWidth(width) {
|
|
2608
|
+
if (width <= SIDEBAR_COLLAPSE_THRESHOLD) return SIDEBAR_RAIL_WIDTH;
|
|
2609
|
+
if (width < SIDEBAR_MIN_EXPANDED_WIDTH) return SIDEBAR_MIN_EXPANDED_WIDTH;
|
|
2610
|
+
return Math.min(SIDEBAR_MAX_WIDTH, width);
|
|
2611
|
+
}
|
|
2612
|
+
function useSidebarWidth(storageKey) {
|
|
2613
|
+
const [width, setWidth] = (0, import_react9.useState)(SIDEBAR_DEFAULT_WIDTH);
|
|
2614
|
+
const [narrowViewport, setNarrowViewport] = (0, import_react9.useState)(false);
|
|
2615
|
+
const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
|
|
2616
|
+
(0, import_react9.useEffect)(() => {
|
|
2617
|
+
let stored = null;
|
|
2618
|
+
try {
|
|
2619
|
+
stored = localStorage.getItem(storageKey);
|
|
2620
|
+
} catch (e) {
|
|
2621
|
+
}
|
|
2622
|
+
if (!stored) return;
|
|
2623
|
+
const parsed = Number.parseInt(stored, 10);
|
|
2624
|
+
if (!Number.isNaN(parsed)) {
|
|
2625
|
+
queueMicrotask(() => setWidth(snapWidth(clampWidth(parsed))));
|
|
2626
|
+
}
|
|
2627
|
+
}, [storageKey]);
|
|
2628
|
+
(0, import_react9.useEffect)(() => {
|
|
2629
|
+
const media = window.matchMedia("(max-width: 639px)");
|
|
2630
|
+
const sync = () => setNarrowViewport(media.matches);
|
|
2631
|
+
sync();
|
|
2632
|
+
media.addEventListener("change", sync);
|
|
2633
|
+
return () => media.removeEventListener("change", sync);
|
|
2634
|
+
}, []);
|
|
2635
|
+
const persist = (0, import_react9.useCallback)(
|
|
2636
|
+
(value) => {
|
|
2637
|
+
try {
|
|
2638
|
+
localStorage.setItem(storageKey, String(value));
|
|
2639
|
+
} catch (e) {
|
|
2640
|
+
}
|
|
2641
|
+
},
|
|
2642
|
+
[storageKey]
|
|
2643
|
+
);
|
|
2644
|
+
const setCollapsed = (0, import_react9.useCallback)(
|
|
2645
|
+
(value) => {
|
|
2646
|
+
setWidth((current) => {
|
|
2647
|
+
const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? SIDEBAR_DEFAULT_WIDTH : snapWidth(current);
|
|
2648
|
+
persist(next);
|
|
2649
|
+
return next;
|
|
2650
|
+
});
|
|
2651
|
+
},
|
|
2652
|
+
[persist]
|
|
2653
|
+
);
|
|
2654
|
+
const resetWidth = (0, import_react9.useCallback)(() => {
|
|
2655
|
+
setWidth(SIDEBAR_DEFAULT_WIDTH);
|
|
2656
|
+
persist(SIDEBAR_DEFAULT_WIDTH);
|
|
2657
|
+
}, [persist]);
|
|
2658
|
+
const startResize = (0, import_react9.useCallback)(
|
|
2659
|
+
(event) => {
|
|
2660
|
+
event.preventDefault();
|
|
2661
|
+
const startX = event.clientX;
|
|
2662
|
+
const startWidth = width;
|
|
2663
|
+
const onMove = (moveEvent) => {
|
|
2664
|
+
setWidth(clampWidth(startWidth + moveEvent.clientX - startX));
|
|
2665
|
+
};
|
|
2666
|
+
const onUp = () => {
|
|
2667
|
+
document.removeEventListener("pointermove", onMove);
|
|
2668
|
+
document.removeEventListener("pointerup", onUp);
|
|
2669
|
+
setWidth((current) => {
|
|
2670
|
+
const snapped = snapWidth(current);
|
|
2671
|
+
persist(snapped);
|
|
2672
|
+
return snapped;
|
|
2673
|
+
});
|
|
2674
|
+
};
|
|
2675
|
+
document.addEventListener("pointermove", onMove);
|
|
2676
|
+
document.addEventListener("pointerup", onUp);
|
|
2677
|
+
},
|
|
2678
|
+
[persist, width]
|
|
2679
|
+
);
|
|
2680
|
+
return { width, collapsed, setCollapsed, resetWidth, startResize };
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2002
2683
|
// src/suite/lib/motion.tsx
|
|
2003
|
-
var
|
|
2004
|
-
var
|
|
2684
|
+
var import_react10 = require("motion/react");
|
|
2685
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2005
2686
|
function SuiteMotionProvider({ children }) {
|
|
2006
|
-
return /* @__PURE__ */ (0,
|
|
2687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react10.LazyMotion, { features: import_react10.domAnimation, strict: true, children });
|
|
2007
2688
|
}
|
|
2008
2689
|
var SUITE_SPRINGS = {
|
|
2009
2690
|
/** Snappy panel/sheet entrances — small overshoot. */
|
|
@@ -2014,217 +2695,25 @@ var SUITE_SPRINGS = {
|
|
|
2014
2695
|
press: { type: "spring", stiffness: 600, damping: 35, mass: 0.5 }
|
|
2015
2696
|
};
|
|
2016
2697
|
|
|
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-6 pt-4 sm:px-6 sm:pb-7 sm:pt-5 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-4 sm:pb-5",
|
|
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
2698
|
// src/suite/components/suite-skeleton.tsx
|
|
2210
|
-
var
|
|
2699
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2211
2700
|
function SuiteSkeleton({
|
|
2212
2701
|
className,
|
|
2213
2702
|
lines = 1,
|
|
2214
2703
|
circle,
|
|
2215
2704
|
width
|
|
2216
2705
|
}) {
|
|
2217
|
-
return /* @__PURE__ */ (0,
|
|
2706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2218
2707
|
"div",
|
|
2219
2708
|
{
|
|
2220
2709
|
className: cn("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
2221
2710
|
"aria-hidden": true,
|
|
2222
|
-
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0,
|
|
2711
|
+
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2223
2712
|
"div",
|
|
2224
2713
|
{
|
|
2225
2714
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2226
2715
|
style: { animationDelay: `${index * 80}ms` },
|
|
2227
|
-
children: /* @__PURE__ */ (0,
|
|
2716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2228
2717
|
"div",
|
|
2229
2718
|
{
|
|
2230
2719
|
className: cn(
|
|
@@ -2248,35 +2737,35 @@ function SuiteSkeletonCard({
|
|
|
2248
2737
|
rows = 3,
|
|
2249
2738
|
header = true
|
|
2250
2739
|
}) {
|
|
2251
|
-
return /* @__PURE__ */ (0,
|
|
2740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2252
2741
|
"div",
|
|
2253
2742
|
{
|
|
2254
2743
|
className: cn(
|
|
2255
|
-
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border
|
|
2744
|
+
"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
2745
|
className
|
|
2257
2746
|
),
|
|
2258
2747
|
"aria-hidden": true,
|
|
2259
2748
|
children: [
|
|
2260
|
-
header ? /* @__PURE__ */ (0,
|
|
2749
|
+
header ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2261
2750
|
"div",
|
|
2262
2751
|
{
|
|
2263
2752
|
className: "mb-5 flex items-center gap-3 animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2264
2753
|
style: { animationDelay: "100ms" },
|
|
2265
2754
|
children: [
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-xl" }),
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1 space-y-2", children: [
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-4 w-1/3" }),
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2270
2759
|
] })
|
|
2271
2760
|
]
|
|
2272
2761
|
}
|
|
2273
2762
|
) : null,
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2763
|
+
/* @__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
2764
|
"div",
|
|
2276
2765
|
{
|
|
2277
2766
|
className: "animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2278
2767
|
style: { animationDelay: `${200 + index * 80}ms` },
|
|
2279
|
-
children: /* @__PURE__ */ (0,
|
|
2768
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2280
2769
|
"div",
|
|
2281
2770
|
{
|
|
2282
2771
|
className: "ph-skeleton h-3",
|
|
@@ -2294,16 +2783,16 @@ function SuiteSkeletonList({
|
|
|
2294
2783
|
className,
|
|
2295
2784
|
items = 4
|
|
2296
2785
|
}) {
|
|
2297
|
-
return /* @__PURE__ */ (0,
|
|
2786
|
+
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
2787
|
"div",
|
|
2299
2788
|
{
|
|
2300
2789
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2301
2790
|
style: { animationDelay: `${index * 100}ms` },
|
|
2302
|
-
children: /* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2304
|
-
/* @__PURE__ */ (0,
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2791
|
+
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: [
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-10 w-10 rounded-lg" }),
|
|
2793
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3.5 w-3/4" }),
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2307
2796
|
] })
|
|
2308
2797
|
] })
|
|
2309
2798
|
},
|
|
@@ -2318,22 +2807,22 @@ function SuiteEmptyState({
|
|
|
2318
2807
|
className,
|
|
2319
2808
|
size = "md"
|
|
2320
2809
|
}) {
|
|
2321
|
-
return /* @__PURE__ */ (0,
|
|
2810
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2322
2811
|
"div",
|
|
2323
2812
|
{
|
|
2324
2813
|
className: cn(
|
|
2325
|
-
"relative overflow-hidden rounded-2xl border border-ph-border
|
|
2814
|
+
"relative overflow-hidden rounded-2xl border border-ph-border bg-ph-surface text-center",
|
|
2326
2815
|
size === "sm" ? "px-5 py-8" : "px-6 py-12 sm:px-10 sm:py-16",
|
|
2327
2816
|
className
|
|
2328
2817
|
),
|
|
2329
2818
|
children: [
|
|
2330
|
-
/* @__PURE__ */ (0,
|
|
2331
|
-
/* @__PURE__ */ (0,
|
|
2332
|
-
/* @__PURE__ */ (0,
|
|
2819
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "pointer-events-none absolute inset-0 overflow-hidden opacity-60", "aria-hidden": true, children: [
|
|
2820
|
+
/* @__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" }),
|
|
2821
|
+
/* @__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
2822
|
] }),
|
|
2334
|
-
/* @__PURE__ */ (0,
|
|
2335
|
-
icon ? /* @__PURE__ */ (0,
|
|
2336
|
-
/* @__PURE__ */ (0,
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
|
|
2824
|
+
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,
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2337
2826
|
"h3",
|
|
2338
2827
|
{
|
|
2339
2828
|
className: cn(
|
|
@@ -2343,8 +2832,8 @@ function SuiteEmptyState({
|
|
|
2343
2832
|
children: title
|
|
2344
2833
|
}
|
|
2345
2834
|
),
|
|
2346
|
-
description ? /* @__PURE__ */ (0,
|
|
2347
|
-
action ? /* @__PURE__ */ (0,
|
|
2835
|
+
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,
|
|
2836
|
+
action ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-5 flex flex-wrap items-center justify-center gap-2", children: action }) : null
|
|
2348
2837
|
] })
|
|
2349
2838
|
]
|
|
2350
2839
|
}
|
|
@@ -2352,24 +2841,26 @@ function SuiteEmptyState({
|
|
|
2352
2841
|
}
|
|
2353
2842
|
|
|
2354
2843
|
// src/suite/components/suite-settings-mobile-nav.tsx
|
|
2355
|
-
var
|
|
2356
|
-
var
|
|
2844
|
+
var import_react11 = require("react");
|
|
2845
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2357
2846
|
function SuiteSettingsMobileNav({
|
|
2358
2847
|
items,
|
|
2359
2848
|
activeHref,
|
|
2360
2849
|
onSelect,
|
|
2361
|
-
dataTest
|
|
2850
|
+
dataTest,
|
|
2851
|
+
ariaLabel = "Settings sections",
|
|
2852
|
+
className
|
|
2362
2853
|
}) {
|
|
2363
|
-
return /* @__PURE__ */ (0,
|
|
2854
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2364
2855
|
"nav",
|
|
2365
2856
|
{
|
|
2366
2857
|
"data-test": dataTest,
|
|
2367
|
-
"aria-label":
|
|
2368
|
-
className: "-
|
|
2369
|
-
children: /* @__PURE__ */ (0,
|
|
2858
|
+
"aria-label": ariaLabel,
|
|
2859
|
+
className: cn("suite-settings-mobile-nav lg:hidden", className),
|
|
2860
|
+
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
2861
|
const Icon = item.icon;
|
|
2371
2862
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
2372
|
-
const iconNode = (0,
|
|
2863
|
+
const iconNode = (0, import_react11.isValidElement)(item.icon) ? item.icon : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2373
2864
|
Icon,
|
|
2374
2865
|
{
|
|
2375
2866
|
className: cn(
|
|
@@ -2379,7 +2870,7 @@ function SuiteSettingsMobileNav({
|
|
|
2379
2870
|
"aria-hidden": true
|
|
2380
2871
|
}
|
|
2381
2872
|
);
|
|
2382
|
-
return /* @__PURE__ */ (0,
|
|
2873
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2383
2874
|
"button",
|
|
2384
2875
|
{
|
|
2385
2876
|
type: "button",
|
|
@@ -2387,14 +2878,14 @@ function SuiteSettingsMobileNav({
|
|
|
2387
2878
|
onClick: () => onSelect(item.href),
|
|
2388
2879
|
"aria-current": active ? "page" : void 0,
|
|
2389
2880
|
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",
|
|
2881
|
+
"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
2882
|
"min-h-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
2392
2883
|
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
2884
|
),
|
|
2394
2885
|
children: [
|
|
2395
2886
|
iconNode,
|
|
2396
|
-
/* @__PURE__ */ (0,
|
|
2397
|
-
active ? /* @__PURE__ */ (0,
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "whitespace-nowrap", children: item.label }),
|
|
2888
|
+
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
2889
|
]
|
|
2399
2890
|
},
|
|
2400
2891
|
item.href
|
|
@@ -2408,10 +2899,10 @@ function SuiteSettingsMobileNav({
|
|
|
2408
2899
|
var import_link2 = __toESM(require("next/link"));
|
|
2409
2900
|
|
|
2410
2901
|
// src/components/ui/Tooltip.tsx
|
|
2411
|
-
var
|
|
2902
|
+
var import_react12 = require("react");
|
|
2412
2903
|
var import_react_dom = require("react-dom");
|
|
2413
|
-
var
|
|
2414
|
-
var TooltipDelayContext = (0,
|
|
2904
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2905
|
+
var TooltipDelayContext = (0, import_react12.createContext)(0);
|
|
2415
2906
|
function tooltipPosition(trigger, side, align, offset) {
|
|
2416
2907
|
const horizontal = align === "start" ? trigger.left : align === "end" ? trigger.right : trigger.left + trigger.width / 2;
|
|
2417
2908
|
const vertical = align === "start" ? trigger.top : align === "end" ? trigger.bottom : trigger.top + trigger.height / 2;
|
|
@@ -2451,12 +2942,12 @@ function Tooltip({
|
|
|
2451
2942
|
onOpenChange,
|
|
2452
2943
|
delayDuration
|
|
2453
2944
|
}) {
|
|
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,
|
|
2945
|
+
const providerDelay = (0, import_react12.useContext)(TooltipDelayContext);
|
|
2946
|
+
const generatedId = (0, import_react12.useId)().replace(/:/g, "");
|
|
2947
|
+
const triggerRef = (0, import_react12.useRef)(null);
|
|
2948
|
+
const timerRef = (0, import_react12.useRef)(null);
|
|
2949
|
+
const [internalOpen, setInternalOpen] = (0, import_react12.useState)(defaultOpen);
|
|
2950
|
+
const [position, setPosition] = (0, import_react12.useState)(null);
|
|
2460
2951
|
const isOpen = open != null ? open : internalOpen;
|
|
2461
2952
|
const triggerId = children.props.id;
|
|
2462
2953
|
const tooltipId = triggerId ? `${triggerId}-tooltip` : `ph-tooltip-${generatedId}`;
|
|
@@ -2490,7 +2981,7 @@ function Tooltip({
|
|
|
2490
2981
|
clearTimer();
|
|
2491
2982
|
setOpen(false);
|
|
2492
2983
|
}
|
|
2493
|
-
(0,
|
|
2984
|
+
(0, import_react12.useEffect)(() => {
|
|
2494
2985
|
if (!isOpen) return;
|
|
2495
2986
|
const reposition = () => updatePosition();
|
|
2496
2987
|
window.addEventListener("resize", reposition);
|
|
@@ -2500,11 +2991,11 @@ function Tooltip({
|
|
|
2500
2991
|
window.removeEventListener("scroll", reposition, true);
|
|
2501
2992
|
};
|
|
2502
2993
|
});
|
|
2503
|
-
(0,
|
|
2994
|
+
(0, import_react12.useEffect)(() => () => clearTimer(), []);
|
|
2504
2995
|
const describedBy = [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ");
|
|
2505
|
-
const trigger = (0,
|
|
2506
|
-
return /* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2996
|
+
const trigger = (0, import_react12.cloneElement)(children, { "aria-describedby": describedBy });
|
|
2997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
2998
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2508
2999
|
"span",
|
|
2509
3000
|
{
|
|
2510
3001
|
ref: triggerRef,
|
|
@@ -2520,12 +3011,12 @@ function Tooltip({
|
|
|
2520
3011
|
}
|
|
2521
3012
|
),
|
|
2522
3013
|
isOpen && position && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
|
|
2523
|
-
/* @__PURE__ */ (0,
|
|
3014
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2524
3015
|
"span",
|
|
2525
3016
|
{
|
|
2526
3017
|
style: __spreadValues({ position: "fixed" }, position),
|
|
2527
3018
|
className: "pointer-events-none z-[200]",
|
|
2528
|
-
children: /* @__PURE__ */ (0,
|
|
3019
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2529
3020
|
"span",
|
|
2530
3021
|
{
|
|
2531
3022
|
id: tooltipId,
|
|
@@ -2543,7 +3034,7 @@ function Tooltip({
|
|
|
2543
3034
|
}
|
|
2544
3035
|
|
|
2545
3036
|
// src/suite/components/suite-sidebar.tsx
|
|
2546
|
-
var
|
|
3037
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2547
3038
|
function renderNode(node, collapsed) {
|
|
2548
3039
|
if (typeof node === "function") return node(collapsed);
|
|
2549
3040
|
return node;
|
|
@@ -2560,7 +3051,7 @@ function SuiteSidebar({
|
|
|
2560
3051
|
className,
|
|
2561
3052
|
surface = false
|
|
2562
3053
|
}) {
|
|
2563
|
-
return /* @__PURE__ */ (0,
|
|
3054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2564
3055
|
"div",
|
|
2565
3056
|
{
|
|
2566
3057
|
className: cn(
|
|
@@ -2569,7 +3060,7 @@ function SuiteSidebar({
|
|
|
2569
3060
|
className
|
|
2570
3061
|
),
|
|
2571
3062
|
children: [
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2573
3064
|
"div",
|
|
2574
3065
|
{
|
|
2575
3066
|
className: cn(
|
|
@@ -2578,12 +3069,12 @@ function SuiteSidebar({
|
|
|
2578
3069
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
2579
3070
|
),
|
|
2580
3071
|
children: [
|
|
2581
|
-
/* @__PURE__ */ (0,
|
|
2582
|
-
collapsed ? null : /* @__PURE__ */ (0,
|
|
3072
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
3073
|
+
collapsed ? null : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
2583
3074
|
]
|
|
2584
3075
|
}
|
|
2585
3076
|
),
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
3077
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2587
3078
|
"div",
|
|
2588
3079
|
{
|
|
2589
3080
|
className: cn(
|
|
@@ -2592,17 +3083,17 @@ function SuiteSidebar({
|
|
|
2592
3083
|
collapsed ? "px-1.5 py-2" : "p-2"
|
|
2593
3084
|
),
|
|
2594
3085
|
children: [
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
3086
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2596
3087
|
"nav",
|
|
2597
3088
|
{
|
|
2598
3089
|
"aria-label": "Pages",
|
|
2599
3090
|
className: "shrink-0 space-y-0.5",
|
|
2600
3091
|
children: [
|
|
2601
|
-
/* @__PURE__ */ (0,
|
|
2602
|
-
/* @__PURE__ */ (0,
|
|
3092
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
|
|
3093
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "space-y-0.5", children: navItems.map((item) => {
|
|
2603
3094
|
const Icon = item.icon;
|
|
2604
3095
|
const active = Boolean(item.active);
|
|
2605
|
-
const link = /* @__PURE__ */ (0,
|
|
3096
|
+
const link = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2606
3097
|
import_link2.default,
|
|
2607
3098
|
{
|
|
2608
3099
|
href: item.href,
|
|
@@ -2615,7 +3106,7 @@ function SuiteSidebar({
|
|
|
2615
3106
|
collapsed ? "mx-auto size-10 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
2616
3107
|
),
|
|
2617
3108
|
children: [
|
|
2618
|
-
/* @__PURE__ */ (0,
|
|
3109
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2619
3110
|
"span",
|
|
2620
3111
|
{
|
|
2621
3112
|
className: cn(
|
|
@@ -2623,7 +3114,7 @@ function SuiteSidebar({
|
|
|
2623
3114
|
item.iconClassName
|
|
2624
3115
|
),
|
|
2625
3116
|
"aria-hidden": true,
|
|
2626
|
-
children: /* @__PURE__ */ (0,
|
|
3117
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2627
3118
|
Icon,
|
|
2628
3119
|
{
|
|
2629
3120
|
className: "h-full w-full",
|
|
@@ -2632,7 +3123,7 @@ function SuiteSidebar({
|
|
|
2632
3123
|
)
|
|
2633
3124
|
}
|
|
2634
3125
|
),
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
3126
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2636
3127
|
"span",
|
|
2637
3128
|
{
|
|
2638
3129
|
className: cn(
|
|
@@ -2643,17 +3134,17 @@ function SuiteSidebar({
|
|
|
2643
3134
|
children: item.label
|
|
2644
3135
|
}
|
|
2645
3136
|
),
|
|
2646
|
-
!collapsed && item.badge ? /* @__PURE__ */ (0,
|
|
3137
|
+
!collapsed && item.badge ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
|
|
2647
3138
|
]
|
|
2648
3139
|
},
|
|
2649
3140
|
item.label
|
|
2650
3141
|
);
|
|
2651
|
-
return collapsed ? /* @__PURE__ */ (0,
|
|
3142
|
+
return collapsed ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
|
|
2652
3143
|
}) })
|
|
2653
3144
|
]
|
|
2654
3145
|
}
|
|
2655
3146
|
),
|
|
2656
|
-
secondaryNav ? /* @__PURE__ */ (0,
|
|
3147
|
+
secondaryNav ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2657
3148
|
"div",
|
|
2658
3149
|
{
|
|
2659
3150
|
className: "min-h-0 flex-1",
|
|
@@ -2664,7 +3155,7 @@ function SuiteSidebar({
|
|
|
2664
3155
|
]
|
|
2665
3156
|
}
|
|
2666
3157
|
),
|
|
2667
|
-
/* @__PURE__ */ (0,
|
|
3158
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2668
3159
|
"div",
|
|
2669
3160
|
{
|
|
2670
3161
|
className: cn(
|
|
@@ -2672,7 +3163,7 @@ function SuiteSidebar({
|
|
|
2672
3163
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
2673
3164
|
collapsed ? "p-1.5" : "p-3"
|
|
2674
3165
|
),
|
|
2675
|
-
children: /* @__PURE__ */ (0,
|
|
3166
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2676
3167
|
"div",
|
|
2677
3168
|
{
|
|
2678
3169
|
className: cn(
|
|
@@ -2681,7 +3172,7 @@ function SuiteSidebar({
|
|
|
2681
3172
|
),
|
|
2682
3173
|
children: [
|
|
2683
3174
|
renderNode(userMenu, collapsed),
|
|
2684
|
-
!collapsed && footerExtras ? /* @__PURE__ */ (0,
|
|
3175
|
+
!collapsed && footerExtras ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "ml-auto shrink-0", children: renderNode(footerExtras, collapsed) }) : null
|
|
2685
3176
|
]
|
|
2686
3177
|
}
|
|
2687
3178
|
)
|
|
@@ -2693,7 +3184,7 @@ function SuiteSidebar({
|
|
|
2693
3184
|
}
|
|
2694
3185
|
|
|
2695
3186
|
// src/suite/components/suite-app-layout.tsx
|
|
2696
|
-
var
|
|
3187
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2697
3188
|
function SuiteAppLayout({
|
|
2698
3189
|
sidebar,
|
|
2699
3190
|
children,
|
|
@@ -2701,41 +3192,59 @@ function SuiteAppLayout({
|
|
|
2701
3192
|
bottomNav,
|
|
2702
3193
|
sidebarWidth = 240,
|
|
2703
3194
|
collapsed = false,
|
|
3195
|
+
lockMainScroll = false,
|
|
2704
3196
|
onStartResize,
|
|
2705
3197
|
onResetWidth,
|
|
2706
3198
|
className
|
|
2707
3199
|
}) {
|
|
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
|
-
|
|
3200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3201
|
+
"div",
|
|
3202
|
+
{
|
|
3203
|
+
"data-test": "app-shell",
|
|
3204
|
+
className: cn("flex min-h-dvh lg:h-screen lg:overflow-hidden", className),
|
|
3205
|
+
children: [
|
|
3206
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3207
|
+
"aside",
|
|
3208
|
+
{
|
|
3209
|
+
className: "relative hidden shrink-0 flex-col overflow-hidden border-r border-ph-border transition-[width] duration-200 ease-out lg:flex",
|
|
3210
|
+
style: { width: `${sidebarWidth}px` },
|
|
3211
|
+
"data-collapsed": collapsed ? "true" : "false",
|
|
3212
|
+
children: [
|
|
3213
|
+
sidebar,
|
|
3214
|
+
onStartResize ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3215
|
+
"div",
|
|
3216
|
+
{
|
|
3217
|
+
role: "separator",
|
|
3218
|
+
"aria-orientation": "vertical",
|
|
3219
|
+
"aria-label": "Resize sidebar",
|
|
3220
|
+
onPointerDown: onStartResize,
|
|
3221
|
+
onDoubleClick: onResetWidth,
|
|
3222
|
+
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)]"
|
|
3223
|
+
}
|
|
3224
|
+
) : null
|
|
3225
|
+
]
|
|
3226
|
+
}
|
|
3227
|
+
),
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
3229
|
+
mobileHeader ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 lg:hidden", children: mobileHeader }) : null,
|
|
3230
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3231
|
+
"main",
|
|
3232
|
+
{
|
|
3233
|
+
id: "main-content",
|
|
3234
|
+
tabIndex: -1,
|
|
3235
|
+
"data-lock-scroll": lockMainScroll ? "true" : void 0,
|
|
3236
|
+
className: cn(
|
|
3237
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
3238
|
+
lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
|
|
3239
|
+
),
|
|
3240
|
+
children
|
|
3241
|
+
}
|
|
3242
|
+
),
|
|
3243
|
+
bottomNav ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "shrink-0 lg:hidden", children: bottomNav }) : null
|
|
3244
|
+
] })
|
|
3245
|
+
]
|
|
3246
|
+
}
|
|
3247
|
+
);
|
|
2739
3248
|
}
|
|
2740
3249
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2741
3250
|
0 && (module.exports = {
|
|
@@ -2748,10 +3257,16 @@ function SuiteAppLayout({
|
|
|
2748
3257
|
AppSwitcherMark,
|
|
2749
3258
|
CommandPaletteHost,
|
|
2750
3259
|
DeferredChrome,
|
|
3260
|
+
SIDEBAR_COLLAPSE_THRESHOLD,
|
|
3261
|
+
SIDEBAR_DEFAULT_WIDTH,
|
|
3262
|
+
SIDEBAR_MAX_WIDTH,
|
|
3263
|
+
SIDEBAR_MIN_EXPANDED_WIDTH,
|
|
3264
|
+
SIDEBAR_RAIL_WIDTH,
|
|
2751
3265
|
SUITE_APPS,
|
|
2752
3266
|
SUITE_APP_MAP,
|
|
2753
3267
|
SUITE_GLYPHS,
|
|
2754
3268
|
SUITE_ICON_NAMES,
|
|
3269
|
+
SUITE_OPEN_ASK_AI_EVENT,
|
|
2755
3270
|
SUITE_SPRINGS,
|
|
2756
3271
|
SourceAppGlyph,
|
|
2757
3272
|
SuiteAiPanel,
|
|
@@ -2769,6 +3284,7 @@ function SuiteAppLayout({
|
|
|
2769
3284
|
SuitePage,
|
|
2770
3285
|
SuitePageHeader,
|
|
2771
3286
|
SuiteSectionHeader,
|
|
3287
|
+
SuiteSettingsLayout,
|
|
2772
3288
|
SuiteSettingsMobileNav,
|
|
2773
3289
|
SuiteSidebar,
|
|
2774
3290
|
SuiteSkeleton,
|
|
@@ -2778,11 +3294,15 @@ function SuiteAppLayout({
|
|
|
2778
3294
|
SuiteThemeProvider,
|
|
2779
3295
|
SuiteToolbar,
|
|
2780
3296
|
SuiteUserMenu,
|
|
3297
|
+
TodayAskAiCard,
|
|
2781
3298
|
TodayCalibrating,
|
|
3299
|
+
TodayEmptyAction,
|
|
2782
3300
|
TodayEmptyState,
|
|
2783
3301
|
TodayHero,
|
|
3302
|
+
TodayLayout,
|
|
2784
3303
|
TodayPageFrame,
|
|
2785
3304
|
TodayPanel,
|
|
3305
|
+
TodayPrimaryAction,
|
|
2786
3306
|
TodaySection,
|
|
2787
3307
|
TodayTimeIcon,
|
|
2788
3308
|
TodayTopBar,
|
|
@@ -2792,9 +3312,12 @@ function SuiteAppLayout({
|
|
|
2792
3312
|
cn,
|
|
2793
3313
|
getTodayGreeting,
|
|
2794
3314
|
m,
|
|
3315
|
+
openSuiteAskAi,
|
|
3316
|
+
resolveSuiteNotificationHref,
|
|
2795
3317
|
sourceToSuiteApp,
|
|
2796
3318
|
suiteAppBaseUrl,
|
|
2797
3319
|
suiteAppLabel,
|
|
2798
3320
|
useIdleMount,
|
|
3321
|
+
useSidebarWidth,
|
|
2799
3322
|
useSuiteTheme
|
|
2800
3323
|
});
|