@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.mjs
CHANGED
|
@@ -15,24 +15,32 @@ function TodayPageFrame({ children }) {
|
|
|
15
15
|
"div",
|
|
16
16
|
{
|
|
17
17
|
"data-test": "today-page",
|
|
18
|
-
className: "today-page-frame relative flex min-h-0 flex-1 flex-col overflow-
|
|
18
|
+
className: "today-page-frame relative flex min-h-0 w-full flex-1 flex-col overflow-x-hidden",
|
|
19
19
|
children: [
|
|
20
20
|
/* @__PURE__ */ jsxs(
|
|
21
21
|
"div",
|
|
22
22
|
{
|
|
23
|
-
className: "pointer-events-none absolute inset-
|
|
23
|
+
className: "pointer-events-none absolute inset-0 overflow-hidden",
|
|
24
24
|
"aria-hidden": true,
|
|
25
25
|
children: [
|
|
26
26
|
/* @__PURE__ */ jsx("div", { className: "today-page-frame__glow absolute inset-0" }),
|
|
27
|
-
/* @__PURE__ */ jsx("div", { className: "today-page-
|
|
28
|
-
/* @__PURE__ */ jsx("div", { className: "today-page-
|
|
29
|
-
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
30
|
-
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
31
|
-
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--
|
|
27
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__top-fade absolute inset-x-0 top-0 h-[28rem]" }),
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--1 absolute -left-28 top-16 h-96 w-[30rem] rounded-[45%]" }),
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--2 absolute -right-24 top-24 h-80 w-[22rem] rounded-[40%]" }),
|
|
30
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--3 absolute left-[22%] top-48 h-72 w-[24rem] rounded-[50%]" }),
|
|
31
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--4 absolute right-[18%] top-[42%] h-64 w-[20rem] rounded-[48%]" }),
|
|
32
|
+
/* @__PURE__ */ jsx("div", { className: "today-page-frame__cloud today-page-frame__cloud--5 absolute left-[8%] top-[68%] h-56 w-[18rem] rounded-[42%]" })
|
|
32
33
|
]
|
|
33
34
|
}
|
|
34
35
|
),
|
|
35
|
-
/* @__PURE__ */ jsx(
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"div",
|
|
38
|
+
{
|
|
39
|
+
"data-width": "full",
|
|
40
|
+
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]",
|
|
41
|
+
children
|
|
42
|
+
}
|
|
43
|
+
)
|
|
36
44
|
]
|
|
37
45
|
}
|
|
38
46
|
);
|
|
@@ -392,7 +400,7 @@ function SuiteIcon({
|
|
|
392
400
|
}
|
|
393
401
|
|
|
394
402
|
// src/suite/components/today-ui.tsx
|
|
395
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
403
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
396
404
|
var APP_META = {
|
|
397
405
|
shellstack: { name: "ShellStack" },
|
|
398
406
|
tides: { name: "Tides" },
|
|
@@ -485,15 +493,15 @@ function AnimatedSun({ className }) {
|
|
|
485
493
|
/* @__PURE__ */ jsx5("stop", { stopColor: "#f59e0b" }),
|
|
486
494
|
/* @__PURE__ */ jsx5("stop", { offset: "1", stopColor: "#fb923c" })
|
|
487
495
|
] }) }),
|
|
488
|
-
/* @__PURE__ */ jsx5("g", { className: "origin-center motion-safe:animate-[
|
|
496
|
+
/* @__PURE__ */ jsx5("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__ */ jsx5(
|
|
489
497
|
"line",
|
|
490
498
|
{
|
|
491
499
|
x1: "20",
|
|
492
|
-
y1: "
|
|
500
|
+
y1: "5",
|
|
493
501
|
x2: "20",
|
|
494
502
|
y2: "9",
|
|
495
503
|
stroke: "#fbbf24",
|
|
496
|
-
strokeWidth: "
|
|
504
|
+
strokeWidth: "1.75",
|
|
497
505
|
strokeLinecap: "round",
|
|
498
506
|
transform: `rotate(${angle} 20 20)`
|
|
499
507
|
},
|
|
@@ -527,10 +535,9 @@ function AnimatedMoon({ className }) {
|
|
|
527
535
|
fill: "url(#animatedMoonBody)"
|
|
528
536
|
}
|
|
529
537
|
),
|
|
530
|
-
/* @__PURE__ */ jsxs5("g", { className: "motion-safe:animate-[
|
|
531
|
-
/* @__PURE__ */ jsx5("circle", { cx: "29", cy: "10", r: "1.
|
|
532
|
-
/* @__PURE__ */ jsx5("circle", { cx: "34", cy: "16", r: "
|
|
533
|
-
/* @__PURE__ */ jsx5("circle", { cx: "25", cy: "5.5", r: "0.9", fill: "#c7d2fe" })
|
|
538
|
+
/* @__PURE__ */ jsxs5("g", { className: "opacity-70 motion-safe:animate-[pulse_10s_ease-in-out_infinite] motion-reduce:animate-none", children: [
|
|
539
|
+
/* @__PURE__ */ jsx5("circle", { cx: "29", cy: "10", r: "1.2", fill: "#c7d2fe" }),
|
|
540
|
+
/* @__PURE__ */ jsx5("circle", { cx: "34", cy: "16", r: "0.9", fill: "#c7d2fe" })
|
|
534
541
|
] })
|
|
535
542
|
]
|
|
536
543
|
}
|
|
@@ -592,30 +599,193 @@ function getTodayGreeting(user, stats) {
|
|
|
592
599
|
const overdueCount = (_d = stats == null ? void 0 : stats.overdueCount) != null ? _d : 0;
|
|
593
600
|
const hours = (_e = stats == null ? void 0 : stats.hours) != null ? _e : 0;
|
|
594
601
|
if (overdueCount > 0) {
|
|
595
|
-
return `${greeting}.
|
|
602
|
+
return `${greeting}. ${taskCount} task${taskCount === 1 ? "" : "s"} due today, ${overdueCount} overdue.`;
|
|
596
603
|
}
|
|
597
604
|
if (taskCount > 0) {
|
|
598
|
-
return `${greeting}.
|
|
605
|
+
return `${greeting}. ${taskCount} task${taskCount === 1 ? "" : "s"} due today.`;
|
|
599
606
|
}
|
|
600
607
|
if (hours > 0) {
|
|
601
|
-
return `${greeting}.
|
|
608
|
+
return `${greeting}. ${hours} hour${hours === 1 ? "" : "s"} logged today.`;
|
|
602
609
|
}
|
|
603
610
|
if (period === "evening" || period === "night") {
|
|
604
|
-
return `${greeting}.
|
|
611
|
+
return `${greeting}. Nice work \u2014 time to wrap up.`;
|
|
605
612
|
}
|
|
606
|
-
return `${greeting}.
|
|
613
|
+
return `${greeting}. Clear queue \u2014 take a nice, deep breath.`;
|
|
607
614
|
}
|
|
608
615
|
function TodayHero({
|
|
609
|
-
message = "Take a nice, deep breath."
|
|
616
|
+
message = "Take a nice, deep breath.",
|
|
617
|
+
brief,
|
|
618
|
+
briefMeta
|
|
619
|
+
}) {
|
|
620
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mt-4 sm:mt-6", children: [
|
|
621
|
+
/* @__PURE__ */ jsx5(
|
|
622
|
+
"p",
|
|
623
|
+
{
|
|
624
|
+
className: "today-hero max-w-2xl font-display text-lg font-semibold tracking-tight text-ph-ink sm:text-xl sm:leading-snug",
|
|
625
|
+
children: message
|
|
626
|
+
},
|
|
627
|
+
typeof message === "string" ? message : "hero"
|
|
628
|
+
),
|
|
629
|
+
brief ? /* @__PURE__ */ jsxs5("div", { className: "mt-4 max-w-2xl", "data-test": "today-focus-brief", children: [
|
|
630
|
+
/* @__PURE__ */ jsx5("p", { className: "text-[15px] leading-[1.65] text-ph-ink", children: brief }),
|
|
631
|
+
briefMeta ? /* @__PURE__ */ jsx5("p", { className: "mt-1.5 text-xs text-ph-mutedtext", children: briefMeta }) : null
|
|
632
|
+
] }) : null
|
|
633
|
+
] });
|
|
634
|
+
}
|
|
635
|
+
function TodayPrimaryAction({
|
|
636
|
+
label,
|
|
637
|
+
description,
|
|
638
|
+
icon,
|
|
639
|
+
accent = "neutral",
|
|
640
|
+
onClick,
|
|
641
|
+
href,
|
|
642
|
+
loading = false,
|
|
643
|
+
active = false,
|
|
644
|
+
className,
|
|
645
|
+
dataTest = "today-primary-action"
|
|
610
646
|
}) {
|
|
611
|
-
|
|
612
|
-
"
|
|
647
|
+
const classes = cn(
|
|
648
|
+
"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",
|
|
649
|
+
`today-primary-action--${accent}`,
|
|
650
|
+
active && "today-primary-action--active",
|
|
651
|
+
loading && "pointer-events-none opacity-70",
|
|
652
|
+
className
|
|
653
|
+
);
|
|
654
|
+
const body = /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
655
|
+
/* @__PURE__ */ jsx5("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 }),
|
|
656
|
+
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
657
|
+
/* @__PURE__ */ jsx5("span", { className: "block text-sm font-semibold tracking-tight sm:text-base", children: label }),
|
|
658
|
+
description ? /* @__PURE__ */ jsx5("span", { className: "mt-0.5 block text-xs opacity-80 sm:text-sm", children: description }) : null
|
|
659
|
+
] }),
|
|
660
|
+
/* @__PURE__ */ jsx5(
|
|
661
|
+
"span",
|
|
662
|
+
{
|
|
663
|
+
className: "today-primary-action__chevron shrink-0 text-base opacity-60 transition group-hover:translate-x-0.5 group-hover:opacity-100",
|
|
664
|
+
"aria-hidden": true,
|
|
665
|
+
children: "\u2192"
|
|
666
|
+
}
|
|
667
|
+
)
|
|
668
|
+
] });
|
|
669
|
+
if (href && !onClick) {
|
|
670
|
+
return /* @__PURE__ */ jsx5(
|
|
671
|
+
"a",
|
|
672
|
+
{
|
|
673
|
+
href,
|
|
674
|
+
className: classes,
|
|
675
|
+
"data-test": dataTest,
|
|
676
|
+
"aria-busy": loading,
|
|
677
|
+
children: body
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
return /* @__PURE__ */ jsx5(
|
|
682
|
+
"button",
|
|
613
683
|
{
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
684
|
+
type: "button",
|
|
685
|
+
onClick,
|
|
686
|
+
disabled: loading,
|
|
687
|
+
className: classes,
|
|
688
|
+
"data-test": dataTest,
|
|
689
|
+
"aria-busy": loading,
|
|
690
|
+
children: body
|
|
691
|
+
}
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
function TodayEmptyAction({
|
|
695
|
+
title,
|
|
696
|
+
description,
|
|
697
|
+
actionLabel,
|
|
698
|
+
href,
|
|
699
|
+
onClick,
|
|
700
|
+
dataTest
|
|
701
|
+
}) {
|
|
702
|
+
return /* @__PURE__ */ jsxs5(
|
|
703
|
+
"div",
|
|
704
|
+
{
|
|
705
|
+
className: "rounded-lg border border-dashed border-ph-border/80 bg-ph-muted/30 px-4 py-4 text-center",
|
|
706
|
+
"data-test": dataTest,
|
|
707
|
+
children: [
|
|
708
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm font-semibold text-ph-ink", children: title }),
|
|
709
|
+
description ? /* @__PURE__ */ jsx5("p", { className: "mx-auto mt-1 max-w-sm text-xs leading-relaxed text-ph-subtle sm:text-sm", children: description }) : null,
|
|
710
|
+
actionLabel && (href || onClick) ? href ? /* @__PURE__ */ jsx5(
|
|
711
|
+
"a",
|
|
712
|
+
{
|
|
713
|
+
href,
|
|
714
|
+
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
715
|
+
children: actionLabel
|
|
716
|
+
}
|
|
717
|
+
) : /* @__PURE__ */ jsx5(
|
|
718
|
+
"button",
|
|
719
|
+
{
|
|
720
|
+
type: "button",
|
|
721
|
+
onClick,
|
|
722
|
+
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
723
|
+
children: actionLabel
|
|
724
|
+
}
|
|
725
|
+
) : null
|
|
726
|
+
]
|
|
727
|
+
}
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
function TodayLayout({
|
|
731
|
+
primary,
|
|
732
|
+
main,
|
|
733
|
+
aside,
|
|
734
|
+
className
|
|
735
|
+
}) {
|
|
736
|
+
return /* @__PURE__ */ jsxs5(
|
|
737
|
+
"div",
|
|
738
|
+
{
|
|
739
|
+
className: cn("mt-5 space-y-6 sm:mt-6", className),
|
|
740
|
+
"data-test": "today-layout",
|
|
741
|
+
children: [
|
|
742
|
+
primary ? /* @__PURE__ */ jsx5("div", { className: "max-w-md", children: primary }) : null,
|
|
743
|
+
/* @__PURE__ */ jsxs5("div", { className: "grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(16rem,20rem)] lg:items-start lg:gap-8", children: [
|
|
744
|
+
/* @__PURE__ */ jsx5("div", { className: "min-w-0 space-y-8", children: main }),
|
|
745
|
+
aside ? /* @__PURE__ */ jsx5("aside", { className: "space-y-3 lg:sticky lg:top-6 lg:self-start", children: aside }) : null
|
|
746
|
+
] })
|
|
747
|
+
]
|
|
748
|
+
}
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
function TodayAskAiCard({
|
|
752
|
+
title = "Ask AI",
|
|
753
|
+
description = "Ask about your workspace, draft something, or look a fact up online.",
|
|
754
|
+
cta = "Ask",
|
|
755
|
+
className,
|
|
756
|
+
onClick,
|
|
757
|
+
href
|
|
758
|
+
}) {
|
|
759
|
+
const classes = cn(
|
|
760
|
+
"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",
|
|
761
|
+
className
|
|
762
|
+
);
|
|
763
|
+
const body = /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
764
|
+
/* @__PURE__ */ jsx5("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__ */ jsx5(SuiteIcon, { name: "stack-hex", accent: "shellstack", className: "h-5 w-5" }) }),
|
|
765
|
+
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
766
|
+
/* @__PURE__ */ jsxs5("span", { className: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1", children: [
|
|
767
|
+
/* @__PURE__ */ jsx5("span", { className: "font-display text-sm font-bold tracking-tight text-ph-ink", children: title }),
|
|
768
|
+
/* @__PURE__ */ jsx5("span", { className: "text-sm font-medium text-ph-brand transition group-hover:underline", children: cta })
|
|
769
|
+
] }),
|
|
770
|
+
/* @__PURE__ */ jsx5("span", { className: "mt-1 block text-sm leading-relaxed text-ph-subtle", children: description })
|
|
771
|
+
] })
|
|
772
|
+
] });
|
|
773
|
+
if (onClick) {
|
|
774
|
+
return /* @__PURE__ */ jsx5(
|
|
775
|
+
"button",
|
|
776
|
+
{
|
|
777
|
+
type: "button",
|
|
778
|
+
onClick,
|
|
779
|
+
className: classes,
|
|
780
|
+
"data-test": "today-ask-ai",
|
|
781
|
+
children: body
|
|
782
|
+
}
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
if (href) {
|
|
786
|
+
return /* @__PURE__ */ jsx5("a", { href, className: classes, "data-test": "today-ask-ai", children: body });
|
|
787
|
+
}
|
|
788
|
+
return /* @__PURE__ */ jsx5("div", { className: classes, "data-test": "today-ask-ai", children: body });
|
|
619
789
|
}
|
|
620
790
|
function TodaySection({
|
|
621
791
|
icon: Icon,
|
|
@@ -626,7 +796,7 @@ function TodaySection({
|
|
|
626
796
|
testId,
|
|
627
797
|
children
|
|
628
798
|
}) {
|
|
629
|
-
return /* @__PURE__ */ jsxs5("section", { "data-test": testId, className: "space-y-
|
|
799
|
+
return /* @__PURE__ */ jsxs5("section", { "data-test": testId, className: "space-y-5", children: [
|
|
630
800
|
/* @__PURE__ */ jsxs5("div", { className: "flex items-start justify-between gap-4", children: [
|
|
631
801
|
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-start gap-3.5", children: [
|
|
632
802
|
/* @__PURE__ */ jsx5(
|
|
@@ -657,8 +827,7 @@ function TodayPanel({
|
|
|
657
827
|
"div",
|
|
658
828
|
{
|
|
659
829
|
className: cn(
|
|
660
|
-
"border-ph-border/70 rounded-2xl border bg-ph-surface p-
|
|
661
|
-
"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",
|
|
830
|
+
"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",
|
|
662
831
|
className
|
|
663
832
|
),
|
|
664
833
|
children
|
|
@@ -836,6 +1005,70 @@ function AppSwitcher({
|
|
|
836
1005
|
import { useCallback, useEffect, useState as useState2 } from "react";
|
|
837
1006
|
import { useRouter } from "next/navigation";
|
|
838
1007
|
import { Bell } from "iconoir-react";
|
|
1008
|
+
|
|
1009
|
+
// src/suite/lib/apps.ts
|
|
1010
|
+
var SUITE_APPS2 = [
|
|
1011
|
+
{
|
|
1012
|
+
slug: "shellstack",
|
|
1013
|
+
name: "ShellStack",
|
|
1014
|
+
description: "Organisation and billing",
|
|
1015
|
+
icon: "/icon-shellstack.svg",
|
|
1016
|
+
landing: "/home",
|
|
1017
|
+
baseUrlEnv: "NEXT_PUBLIC_SHELLSTACK_URL",
|
|
1018
|
+
baseUrlFallback: "http://localhost:3002"
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
slug: "tides",
|
|
1022
|
+
name: "Tides",
|
|
1023
|
+
description: "Projects and tasks",
|
|
1024
|
+
icon: "/tides-icon.svg",
|
|
1025
|
+
landing: "/today",
|
|
1026
|
+
baseUrlEnv: "NEXT_PUBLIC_TIDES_URL",
|
|
1027
|
+
baseUrlFallback: "http://localhost:3001"
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
slug: "turtletime",
|
|
1031
|
+
name: "TurtleTime",
|
|
1032
|
+
description: "Time tracking",
|
|
1033
|
+
icon: "/turtletime-icon.svg",
|
|
1034
|
+
landing: "/today",
|
|
1035
|
+
baseUrlEnv: "NEXT_PUBLIC_TURTLETIME_URL",
|
|
1036
|
+
baseUrlFallback: "http://localhost:3000"
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
slug: "kraken",
|
|
1040
|
+
name: "Kraken",
|
|
1041
|
+
description: "Documents and knowledge",
|
|
1042
|
+
icon: "/kraken-icon.svg",
|
|
1043
|
+
landing: "/today",
|
|
1044
|
+
baseUrlEnv: "NEXT_PUBLIC_KRAKEN_URL",
|
|
1045
|
+
baseUrlFallback: "http://localhost:3003"
|
|
1046
|
+
}
|
|
1047
|
+
];
|
|
1048
|
+
var SUITE_APP_MAP = Object.fromEntries(SUITE_APPS2.map((app) => [app.slug, app]));
|
|
1049
|
+
function suiteAppBaseUrl(slug) {
|
|
1050
|
+
const def = SUITE_APP_MAP[slug];
|
|
1051
|
+
const fromEnv = typeof process !== "undefined" ? process.env[def.baseUrlEnv] : void 0;
|
|
1052
|
+
return (fromEnv || def.baseUrlFallback).replace(/\/$/, "");
|
|
1053
|
+
}
|
|
1054
|
+
var SOURCE_APP_SLUG = {
|
|
1055
|
+
turtletime: "turtletime",
|
|
1056
|
+
tides: "tides",
|
|
1057
|
+
kraken: "kraken",
|
|
1058
|
+
portal: "shellstack",
|
|
1059
|
+
shellstack: "shellstack"
|
|
1060
|
+
};
|
|
1061
|
+
function resolveSuiteNotificationHref(href, sourceApp) {
|
|
1062
|
+
const value = (href || "").trim();
|
|
1063
|
+
if (!value) return "";
|
|
1064
|
+
if (/^(https?:|mailto:|\/\/)/i.test(value)) return value;
|
|
1065
|
+
const path = value.startsWith("/") ? value : `/${value}`;
|
|
1066
|
+
const slug = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()];
|
|
1067
|
+
if (!slug) return path;
|
|
1068
|
+
return `${suiteAppBaseUrl(slug)}${path}`;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// src/suite/components/suite-notification-bell.tsx
|
|
839
1072
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
840
1073
|
var POLL_MS = 6e4;
|
|
841
1074
|
function timeAgo(iso) {
|
|
@@ -926,9 +1159,13 @@ function SuiteNotificationBell({
|
|
|
926
1159
|
} catch (e) {
|
|
927
1160
|
}
|
|
928
1161
|
}
|
|
929
|
-
|
|
930
|
-
if (
|
|
931
|
-
|
|
1162
|
+
const target = resolveSuiteNotificationHref(n.href, n.source_app);
|
|
1163
|
+
if (!target) return;
|
|
1164
|
+
if (/^https?:\/\//i.test(target)) {
|
|
1165
|
+
window.location.assign(target);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
router.push(target);
|
|
932
1169
|
},
|
|
933
1170
|
[router, markRead]
|
|
934
1171
|
);
|
|
@@ -1064,11 +1301,11 @@ function useIdleMount(timeoutMs = 1200) {
|
|
|
1064
1301
|
}
|
|
1065
1302
|
|
|
1066
1303
|
// src/suite/components/deferred-chrome.tsx
|
|
1067
|
-
import { Fragment as
|
|
1304
|
+
import { Fragment as Fragment3, jsx as jsx9 } from "react/jsx-runtime";
|
|
1068
1305
|
function DeferredChrome({ children }) {
|
|
1069
1306
|
const ready = useIdleMount();
|
|
1070
1307
|
if (!ready) return null;
|
|
1071
|
-
return /* @__PURE__ */ jsx9(
|
|
1308
|
+
return /* @__PURE__ */ jsx9(Fragment3, { children });
|
|
1072
1309
|
}
|
|
1073
1310
|
|
|
1074
1311
|
// src/suite/components/suite-mobile-drawer.tsx
|
|
@@ -1081,6 +1318,7 @@ function SuiteMobileDrawer({
|
|
|
1081
1318
|
children,
|
|
1082
1319
|
side = "left",
|
|
1083
1320
|
showCloseButton = false,
|
|
1321
|
+
title,
|
|
1084
1322
|
closeLabel = "Close navigation",
|
|
1085
1323
|
backdropLabel = "Close navigation",
|
|
1086
1324
|
dialogLabel = "Navigation",
|
|
@@ -1158,23 +1396,35 @@ function SuiteMobileDrawer({
|
|
|
1158
1396
|
tabIndex: -1,
|
|
1159
1397
|
"data-test": panelDataTest,
|
|
1160
1398
|
className: cn(
|
|
1161
|
-
"suite-scroll-lock relative flex h-full w-[86%] max-w-
|
|
1399
|
+
"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",
|
|
1162
1400
|
side === "right" && "ml-auto",
|
|
1163
1401
|
shown ? "translate-x-0" : side === "right" ? "translate-x-full" : "-translate-x-full",
|
|
1164
1402
|
panelClassName
|
|
1165
1403
|
),
|
|
1166
1404
|
style: { transitionDuration: `${durationMs}ms` },
|
|
1167
1405
|
children: [
|
|
1168
|
-
showCloseButton ? /* @__PURE__ */
|
|
1169
|
-
"
|
|
1406
|
+
showCloseButton ? /* @__PURE__ */ jsxs8(
|
|
1407
|
+
"div",
|
|
1170
1408
|
{
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
children:
|
|
1409
|
+
className: cn(
|
|
1410
|
+
"flex h-14 shrink-0 items-center border-b border-ph-border px-3",
|
|
1411
|
+
title ? "justify-between" : "justify-end"
|
|
1412
|
+
),
|
|
1413
|
+
children: [
|
|
1414
|
+
title ? /* @__PURE__ */ jsx10("span", { className: "truncate text-sm font-semibold text-ph-ink", children: title }) : null,
|
|
1415
|
+
/* @__PURE__ */ jsx10(
|
|
1416
|
+
"button",
|
|
1417
|
+
{
|
|
1418
|
+
type: "button",
|
|
1419
|
+
onClick: onClose,
|
|
1420
|
+
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",
|
|
1421
|
+
"aria-label": closeLabel,
|
|
1422
|
+
children: /* @__PURE__ */ jsx10(X, { className: "h-4 w-4", "aria-hidden": true })
|
|
1423
|
+
}
|
|
1424
|
+
)
|
|
1425
|
+
]
|
|
1176
1426
|
}
|
|
1177
|
-
)
|
|
1427
|
+
) : null,
|
|
1178
1428
|
children
|
|
1179
1429
|
]
|
|
1180
1430
|
}
|
|
@@ -1231,74 +1481,361 @@ function SuiteMobileHeader({
|
|
|
1231
1481
|
);
|
|
1232
1482
|
}
|
|
1233
1483
|
|
|
1234
|
-
// src/suite/components/suite-
|
|
1235
|
-
import
|
|
1236
|
-
|
|
1237
|
-
|
|
1484
|
+
// src/suite/components/suite-layout.tsx
|
|
1485
|
+
import {
|
|
1486
|
+
useEffect as useEffect5,
|
|
1487
|
+
useRef as useRef2,
|
|
1488
|
+
useState as useState6
|
|
1489
|
+
} from "react";
|
|
1238
1490
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1239
|
-
function
|
|
1240
|
-
|
|
1241
|
-
|
|
1491
|
+
function SuiteBreadcrumbs({ items, className }) {
|
|
1492
|
+
return /* @__PURE__ */ jsx12("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx12("ol", { className: "flex min-w-0 items-center gap-1.5", children: items.map((item, index) => {
|
|
1493
|
+
const isLast = index === items.length - 1;
|
|
1494
|
+
return /* @__PURE__ */ jsxs10("li", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1495
|
+
index > 0 ? /* @__PURE__ */ jsx12("span", { className: "select-none text-ph-border", "aria-hidden": "true", children: "/" }) : null,
|
|
1496
|
+
item.href && !isLast ? /* @__PURE__ */ jsx12(
|
|
1497
|
+
"a",
|
|
1498
|
+
{
|
|
1499
|
+
href: item.href,
|
|
1500
|
+
className: "truncate transition hover:text-ph-ink",
|
|
1501
|
+
children: item.label
|
|
1502
|
+
}
|
|
1503
|
+
) : /* @__PURE__ */ jsx12(
|
|
1504
|
+
"span",
|
|
1505
|
+
{
|
|
1506
|
+
className: cn(
|
|
1507
|
+
"truncate",
|
|
1508
|
+
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
1509
|
+
),
|
|
1510
|
+
"aria-current": isLast ? "page" : void 0,
|
|
1511
|
+
children: item.label
|
|
1512
|
+
}
|
|
1513
|
+
)
|
|
1514
|
+
] }, index);
|
|
1515
|
+
}) }) });
|
|
1242
1516
|
}
|
|
1243
|
-
function
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1517
|
+
function SuitePage({
|
|
1518
|
+
children,
|
|
1519
|
+
width = "full",
|
|
1520
|
+
inset = true,
|
|
1521
|
+
className,
|
|
1522
|
+
as: Component = "div",
|
|
1523
|
+
dataTest,
|
|
1524
|
+
id,
|
|
1525
|
+
role,
|
|
1526
|
+
"aria-live": ariaLive
|
|
1252
1527
|
}) {
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
const avatar = /* @__PURE__ */ jsx12("span", { className: "inline-flex h-11 w-11 items-center justify-center rounded-full transition-colors hover:bg-ph-muted", children: image ? /* @__PURE__ */ jsx12(
|
|
1256
|
-
Image2,
|
|
1528
|
+
return /* @__PURE__ */ jsx12(
|
|
1529
|
+
Component,
|
|
1257
1530
|
{
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
width:
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1531
|
+
id,
|
|
1532
|
+
"data-test": dataTest,
|
|
1533
|
+
"data-width": width,
|
|
1534
|
+
role,
|
|
1535
|
+
"aria-live": ariaLive,
|
|
1536
|
+
className: cn(
|
|
1537
|
+
"suite-page-stage flex w-full min-w-0 flex-col",
|
|
1538
|
+
inset && "suite-page-inset",
|
|
1539
|
+
className
|
|
1540
|
+
),
|
|
1541
|
+
children
|
|
1542
|
+
}
|
|
1543
|
+
);
|
|
1544
|
+
}
|
|
1545
|
+
function SuitePageHeader({
|
|
1546
|
+
title,
|
|
1547
|
+
description,
|
|
1548
|
+
eyebrow,
|
|
1549
|
+
actions,
|
|
1550
|
+
className,
|
|
1551
|
+
titleClassName,
|
|
1552
|
+
dataTest,
|
|
1553
|
+
/** Optional icon rendered before the title. */
|
|
1554
|
+
icon,
|
|
1555
|
+
/** Use the animated sun/moon icon from the Today page. */
|
|
1556
|
+
todayIcon,
|
|
1557
|
+
todayIconClassName,
|
|
1558
|
+
/** Small badge/pill next to the title (e.g. "Beta", org name). */
|
|
1559
|
+
badge,
|
|
1560
|
+
/** Breadcrumb line rendered above the title. */
|
|
1561
|
+
breadcrumb,
|
|
1562
|
+
/** Stick to the top of the scrollport (desktop page titles). */
|
|
1563
|
+
sticky = false
|
|
1564
|
+
}) {
|
|
1565
|
+
const headerRef = useRef2(null);
|
|
1566
|
+
const [stuck, setStuck] = useState6(false);
|
|
1567
|
+
useEffect5(() => {
|
|
1568
|
+
var _a;
|
|
1569
|
+
if (!sticky) return;
|
|
1570
|
+
const el = headerRef.current;
|
|
1571
|
+
if (!el) return;
|
|
1572
|
+
const sentinel = document.createElement("div");
|
|
1573
|
+
sentinel.setAttribute("aria-hidden", "true");
|
|
1574
|
+
sentinel.style.cssText = "position:relative;height:1px;width:100%;margin:0;padding:0;pointer-events:none";
|
|
1575
|
+
(_a = el.parentElement) == null ? void 0 : _a.insertBefore(sentinel, el);
|
|
1576
|
+
const observer = new IntersectionObserver(
|
|
1577
|
+
([entry]) => {
|
|
1578
|
+
setStuck(!entry.isIntersecting);
|
|
1579
|
+
},
|
|
1580
|
+
{ threshold: [1], root: null }
|
|
1581
|
+
);
|
|
1582
|
+
observer.observe(sentinel);
|
|
1583
|
+
return () => {
|
|
1584
|
+
observer.disconnect();
|
|
1585
|
+
sentinel.remove();
|
|
1586
|
+
};
|
|
1587
|
+
}, [sticky]);
|
|
1588
|
+
const resolvedIcon = todayIcon ? /* @__PURE__ */ jsx12(
|
|
1589
|
+
TodayTimeIcon,
|
|
1590
|
+
{
|
|
1591
|
+
className: cn(
|
|
1592
|
+
"h-7 w-7 text-amber-500 sm:h-8 sm:w-8",
|
|
1593
|
+
todayIconClassName
|
|
1594
|
+
)
|
|
1264
1595
|
}
|
|
1265
|
-
) :
|
|
1596
|
+
) : icon;
|
|
1266
1597
|
return /* @__PURE__ */ jsxs10(
|
|
1267
|
-
|
|
1598
|
+
"header",
|
|
1268
1599
|
{
|
|
1269
|
-
|
|
1270
|
-
"aria-label": "Account menu",
|
|
1271
|
-
align: "end",
|
|
1272
|
-
side: "bottom",
|
|
1273
|
-
sideOffset: 6,
|
|
1274
|
-
collisionPadding: 16,
|
|
1275
|
-
modal: false,
|
|
1276
|
-
className,
|
|
1600
|
+
ref: headerRef,
|
|
1277
1601
|
"data-test": dataTest,
|
|
1602
|
+
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1603
|
+
className: cn(
|
|
1604
|
+
"flex items-start justify-between gap-4 pb-2 sm:pb-3",
|
|
1605
|
+
// No extra pt here — page inset sets the shared title baseline.
|
|
1606
|
+
// Stuck state adds pad via .suite-page-header-sticky[data-stuck].
|
|
1607
|
+
sticky && "suite-page-header-sticky",
|
|
1608
|
+
className
|
|
1609
|
+
),
|
|
1278
1610
|
children: [
|
|
1279
|
-
/* @__PURE__ */ jsxs10("div", { className: "
|
|
1280
|
-
/* @__PURE__ */ jsx12("
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1611
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
1612
|
+
eyebrow ? /* @__PURE__ */ jsx12("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: eyebrow }) : null,
|
|
1613
|
+
breadcrumb ? /* @__PURE__ */ jsx12("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: breadcrumb }) : null,
|
|
1614
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
1615
|
+
resolvedIcon ? /* @__PURE__ */ jsx12(
|
|
1616
|
+
"div",
|
|
1617
|
+
{
|
|
1618
|
+
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-7 [&_svg]:w-7 sm:[&_svg]:h-8 sm:[&_svg]:w-8",
|
|
1619
|
+
"aria-hidden": "true",
|
|
1620
|
+
children: resolvedIcon
|
|
1621
|
+
}
|
|
1622
|
+
) : null,
|
|
1623
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1624
|
+
/* @__PURE__ */ jsx12(
|
|
1625
|
+
"h1",
|
|
1626
|
+
{
|
|
1627
|
+
className: cn(
|
|
1628
|
+
"font-display text-[1.625rem] font-bold leading-none tracking-tight text-ph-ink sm:text-[2.25rem]",
|
|
1629
|
+
titleClassName
|
|
1630
|
+
),
|
|
1631
|
+
children: title
|
|
1632
|
+
}
|
|
1633
|
+
),
|
|
1634
|
+
badge ? /* @__PURE__ */ jsx12("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
|
|
1635
|
+
] })
|
|
1636
|
+
] }),
|
|
1637
|
+
description ? /* @__PURE__ */ jsx12(
|
|
1638
|
+
"div",
|
|
1639
|
+
{
|
|
1640
|
+
className: cn(
|
|
1641
|
+
"mt-1.5 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle",
|
|
1642
|
+
resolvedIcon && "sm:pl-11"
|
|
1643
|
+
),
|
|
1644
|
+
children: description
|
|
1645
|
+
}
|
|
1646
|
+
) : null
|
|
1647
|
+
] }),
|
|
1648
|
+
actions ? /* @__PURE__ */ jsx12("div", { className: "flex shrink-0 items-center gap-2 self-center", children: actions }) : null
|
|
1649
|
+
]
|
|
1650
|
+
}
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
function SuiteToolbar({
|
|
1654
|
+
children,
|
|
1655
|
+
className,
|
|
1656
|
+
label = "Page tools",
|
|
1657
|
+
dataTest
|
|
1658
|
+
}) {
|
|
1659
|
+
return /* @__PURE__ */ jsx12(
|
|
1660
|
+
"div",
|
|
1661
|
+
{
|
|
1662
|
+
role: "toolbar",
|
|
1663
|
+
"aria-label": label,
|
|
1664
|
+
"data-test": dataTest,
|
|
1665
|
+
className: cn("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
1666
|
+
children
|
|
1667
|
+
}
|
|
1668
|
+
);
|
|
1669
|
+
}
|
|
1670
|
+
function SuiteTabList({
|
|
1671
|
+
children,
|
|
1672
|
+
className,
|
|
1673
|
+
label,
|
|
1674
|
+
dataTest
|
|
1675
|
+
}) {
|
|
1676
|
+
return /* @__PURE__ */ jsx12(
|
|
1677
|
+
"nav",
|
|
1678
|
+
{
|
|
1679
|
+
"aria-label": label,
|
|
1680
|
+
"data-test": dataTest,
|
|
1681
|
+
className: cn(
|
|
1682
|
+
"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]",
|
|
1683
|
+
className
|
|
1684
|
+
),
|
|
1685
|
+
children
|
|
1686
|
+
}
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
function SuiteSectionHeader({
|
|
1690
|
+
title,
|
|
1691
|
+
description,
|
|
1692
|
+
action,
|
|
1693
|
+
className
|
|
1694
|
+
}) {
|
|
1695
|
+
return /* @__PURE__ */ jsxs10(
|
|
1696
|
+
"div",
|
|
1697
|
+
{
|
|
1698
|
+
className: cn(
|
|
1699
|
+
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
1700
|
+
className
|
|
1701
|
+
),
|
|
1702
|
+
children: [
|
|
1703
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
|
|
1704
|
+
/* @__PURE__ */ jsx12("h2", { className: "font-display text-balance text-lg font-semibold tracking-tight text-ph-ink sm:text-xl", children: title }),
|
|
1705
|
+
description ? /* @__PURE__ */ jsx12("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
1706
|
+
] }),
|
|
1707
|
+
action ? /* @__PURE__ */ jsx12("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
1708
|
+
]
|
|
1709
|
+
}
|
|
1710
|
+
);
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
// src/suite/components/suite-settings-layout.tsx
|
|
1714
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1715
|
+
function SuiteSettingsLayout({
|
|
1716
|
+
children,
|
|
1717
|
+
sidebar,
|
|
1718
|
+
mobileNav,
|
|
1719
|
+
loading,
|
|
1720
|
+
title = "Settings",
|
|
1721
|
+
description,
|
|
1722
|
+
header,
|
|
1723
|
+
dataTest = "settings-page",
|
|
1724
|
+
headerDataTest = "settings-page-header",
|
|
1725
|
+
className,
|
|
1726
|
+
contentClassName
|
|
1727
|
+
}) {
|
|
1728
|
+
return /* @__PURE__ */ jsxs11(
|
|
1729
|
+
SuitePage,
|
|
1730
|
+
{
|
|
1731
|
+
dataTest,
|
|
1732
|
+
className: cn("flex h-full flex-col overflow-hidden", className),
|
|
1733
|
+
children: [
|
|
1734
|
+
header != null ? header : /* @__PURE__ */ jsx13(
|
|
1735
|
+
SuitePageHeader,
|
|
1736
|
+
{
|
|
1737
|
+
sticky: true,
|
|
1738
|
+
dataTest: headerDataTest,
|
|
1739
|
+
title,
|
|
1740
|
+
description
|
|
1741
|
+
}
|
|
1742
|
+
),
|
|
1743
|
+
loading != null ? loading : /* @__PURE__ */ jsxs11("div", { className: "suite-page-body mt-6 flex min-h-0 flex-1 flex-col", children: [
|
|
1744
|
+
mobileNav ? /* @__PURE__ */ jsx13("div", { className: "sticky top-0 z-20 mb-2 shrink-0 bg-ph-canvas/95 backdrop-blur lg:hidden", children: mobileNav }) : null,
|
|
1745
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex min-h-0 flex-1 flex-col gap-6 lg:flex-row lg:gap-8", children: [
|
|
1746
|
+
/* @__PURE__ */ jsx13(
|
|
1747
|
+
"aside",
|
|
1748
|
+
{
|
|
1749
|
+
"aria-label": "Settings",
|
|
1750
|
+
className: "hidden w-56 shrink-0 bg-transparent lg:block lg:self-stretch lg:overflow-y-auto lg:overscroll-contain",
|
|
1751
|
+
children: sidebar
|
|
1752
|
+
}
|
|
1753
|
+
),
|
|
1754
|
+
/* @__PURE__ */ jsx13(
|
|
1755
|
+
"div",
|
|
1756
|
+
{
|
|
1757
|
+
className: cn(
|
|
1758
|
+
"min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain pb-6",
|
|
1759
|
+
contentClassName
|
|
1760
|
+
),
|
|
1761
|
+
children
|
|
1762
|
+
}
|
|
1763
|
+
)
|
|
1764
|
+
] })
|
|
1765
|
+
] })
|
|
1766
|
+
]
|
|
1767
|
+
}
|
|
1768
|
+
);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
// src/suite/components/suite-user-menu.tsx
|
|
1772
|
+
import Image2 from "next/image";
|
|
1773
|
+
import { useRouter as useRouter2 } from "next/navigation";
|
|
1774
|
+
import { LogOut, Settings } from "iconoir-react";
|
|
1775
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1776
|
+
function computeInitials(name, email) {
|
|
1777
|
+
const source = (name || email || "?").trim();
|
|
1778
|
+
return source.split(/[\s@]+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
1779
|
+
}
|
|
1780
|
+
function SuiteUserMenu({
|
|
1781
|
+
name,
|
|
1782
|
+
email,
|
|
1783
|
+
image,
|
|
1784
|
+
settingsHref,
|
|
1785
|
+
onSignOut,
|
|
1786
|
+
fallbackInitials,
|
|
1787
|
+
dataTest = "suite-user-menu",
|
|
1788
|
+
className
|
|
1789
|
+
}) {
|
|
1790
|
+
const router = useRouter2();
|
|
1791
|
+
const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
|
|
1792
|
+
const avatar = /* @__PURE__ */ jsx14("span", { className: "inline-flex h-11 w-11 items-center justify-center rounded-full transition-colors hover:bg-ph-muted", children: image ? /* @__PURE__ */ jsx14(
|
|
1793
|
+
Image2,
|
|
1794
|
+
{
|
|
1795
|
+
src: image,
|
|
1796
|
+
alt: "",
|
|
1797
|
+
width: 32,
|
|
1798
|
+
height: 32,
|
|
1799
|
+
className: "h-8 w-8 rounded-full object-cover",
|
|
1800
|
+
unoptimized: true
|
|
1801
|
+
}
|
|
1802
|
+
) : /* @__PURE__ */ jsx14("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 }) });
|
|
1803
|
+
return /* @__PURE__ */ jsxs12(
|
|
1804
|
+
DropdownMenu,
|
|
1805
|
+
{
|
|
1806
|
+
trigger: avatar,
|
|
1807
|
+
"aria-label": "Account menu",
|
|
1808
|
+
align: "end",
|
|
1809
|
+
side: "bottom",
|
|
1810
|
+
sideOffset: 6,
|
|
1811
|
+
collisionPadding: 16,
|
|
1812
|
+
modal: false,
|
|
1813
|
+
className,
|
|
1814
|
+
"data-test": dataTest,
|
|
1815
|
+
children: [
|
|
1816
|
+
/* @__PURE__ */ jsxs12("div", { className: "px-2 py-1.5", children: [
|
|
1817
|
+
/* @__PURE__ */ jsx14("p", { className: "truncate text-sm font-medium text-ph-ink", children: name || email || "Account" }),
|
|
1818
|
+
email ? /* @__PURE__ */ jsx14("p", { className: "truncate text-xs text-ph-mutedtext", children: email }) : null
|
|
1819
|
+
] }),
|
|
1820
|
+
/* @__PURE__ */ jsx14("div", { className: "my-1 border-t border-ph-border" }),
|
|
1821
|
+
/* @__PURE__ */ jsxs12(
|
|
1822
|
+
DropdownItem,
|
|
1823
|
+
{
|
|
1824
|
+
"data-test": `${dataTest}-settings`,
|
|
1825
|
+
onClick: () => router.push(settingsHref),
|
|
1826
|
+
children: [
|
|
1827
|
+
/* @__PURE__ */ jsx14(Settings, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
1291
1828
|
"Profile settings"
|
|
1292
1829
|
]
|
|
1293
1830
|
}
|
|
1294
1831
|
),
|
|
1295
|
-
/* @__PURE__ */
|
|
1832
|
+
/* @__PURE__ */ jsxs12(
|
|
1296
1833
|
DropdownItem,
|
|
1297
1834
|
{
|
|
1298
1835
|
"data-test": `${dataTest}-sign-out`,
|
|
1299
1836
|
onClick: onSignOut,
|
|
1300
1837
|
children: [
|
|
1301
|
-
/* @__PURE__ */
|
|
1838
|
+
/* @__PURE__ */ jsx14(LogOut, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
1302
1839
|
"Sign out"
|
|
1303
1840
|
]
|
|
1304
1841
|
}
|
|
@@ -1310,7 +1847,7 @@ function SuiteUserMenu({
|
|
|
1310
1847
|
|
|
1311
1848
|
// src/suite/components/suite-bottom-nav.tsx
|
|
1312
1849
|
import Link from "next/link";
|
|
1313
|
-
import { Fragment as
|
|
1850
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1314
1851
|
function SuiteBottomNav({
|
|
1315
1852
|
items,
|
|
1316
1853
|
ariaLabel = "Primary navigation",
|
|
@@ -1323,8 +1860,8 @@ function SuiteBottomNav({
|
|
|
1323
1860
|
);
|
|
1324
1861
|
}
|
|
1325
1862
|
const activeIndex = items.findIndex((item) => item.active);
|
|
1326
|
-
return /* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1863
|
+
return /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
1864
|
+
/* @__PURE__ */ jsx15(
|
|
1328
1865
|
"div",
|
|
1329
1866
|
{
|
|
1330
1867
|
"aria-hidden": true,
|
|
@@ -1332,7 +1869,7 @@ function SuiteBottomNav({
|
|
|
1332
1869
|
style: { height: "calc(60px + env(safe-area-inset-bottom))" }
|
|
1333
1870
|
}
|
|
1334
1871
|
),
|
|
1335
|
-
/* @__PURE__ */
|
|
1872
|
+
/* @__PURE__ */ jsxs13(
|
|
1336
1873
|
"nav",
|
|
1337
1874
|
{
|
|
1338
1875
|
"aria-label": ariaLabel,
|
|
@@ -1347,12 +1884,12 @@ function SuiteBottomNav({
|
|
|
1347
1884
|
"--suite-nav-active": activeIndex >= 0 ? activeIndex : 0
|
|
1348
1885
|
},
|
|
1349
1886
|
children: [
|
|
1350
|
-
activeIndex >= 0 ? /* @__PURE__ */
|
|
1887
|
+
activeIndex >= 0 ? /* @__PURE__ */ jsx15("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
|
|
1351
1888
|
items.map((item) => {
|
|
1352
1889
|
var _a;
|
|
1353
1890
|
const Icon = item.icon;
|
|
1354
1891
|
const active = Boolean(item.active);
|
|
1355
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ jsxs13(
|
|
1356
1893
|
Link,
|
|
1357
1894
|
{
|
|
1358
1895
|
href: item.href,
|
|
@@ -1363,14 +1900,14 @@ function SuiteBottomNav({
|
|
|
1363
1900
|
active && "font-semibold text-ph-brand"
|
|
1364
1901
|
),
|
|
1365
1902
|
children: [
|
|
1366
|
-
/* @__PURE__ */
|
|
1903
|
+
/* @__PURE__ */ jsx15(
|
|
1367
1904
|
"span",
|
|
1368
1905
|
{
|
|
1369
1906
|
className: cn(
|
|
1370
1907
|
"suite-bottom-nav__icon relative z-10 inline-flex items-center justify-center",
|
|
1371
1908
|
active && "suite-bottom-nav__icon--active"
|
|
1372
1909
|
),
|
|
1373
|
-
children: /* @__PURE__ */
|
|
1910
|
+
children: /* @__PURE__ */ jsx15(
|
|
1374
1911
|
Icon,
|
|
1375
1912
|
{
|
|
1376
1913
|
className: "h-6 w-6",
|
|
@@ -1380,7 +1917,7 @@ function SuiteBottomNav({
|
|
|
1380
1917
|
)
|
|
1381
1918
|
}
|
|
1382
1919
|
),
|
|
1383
|
-
/* @__PURE__ */
|
|
1920
|
+
/* @__PURE__ */ jsx15("span", { className: "relative z-10 max-w-full truncate", children: item.label })
|
|
1384
1921
|
]
|
|
1385
1922
|
},
|
|
1386
1923
|
item.href
|
|
@@ -1392,117 +1929,39 @@ function SuiteBottomNav({
|
|
|
1392
1929
|
] });
|
|
1393
1930
|
}
|
|
1394
1931
|
|
|
1395
|
-
// src/suite/lib/apps.ts
|
|
1396
|
-
var SUITE_APPS2 = [
|
|
1397
|
-
{
|
|
1398
|
-
slug: "shellstack",
|
|
1399
|
-
name: "ShellStack",
|
|
1400
|
-
description: "Organisation and billing",
|
|
1401
|
-
icon: "/icon-shellstack.svg",
|
|
1402
|
-
landing: "/home",
|
|
1403
|
-
baseUrlEnv: "NEXT_PUBLIC_SHELLSTACK_URL",
|
|
1404
|
-
baseUrlFallback: "http://localhost:3002"
|
|
1405
|
-
},
|
|
1406
|
-
{
|
|
1407
|
-
slug: "tides",
|
|
1408
|
-
name: "Tides",
|
|
1409
|
-
description: "Projects and tasks",
|
|
1410
|
-
icon: "/tides-icon.svg",
|
|
1411
|
-
landing: "/today",
|
|
1412
|
-
baseUrlEnv: "NEXT_PUBLIC_TIDES_URL",
|
|
1413
|
-
baseUrlFallback: "http://localhost:3001"
|
|
1414
|
-
},
|
|
1415
|
-
{
|
|
1416
|
-
slug: "turtletime",
|
|
1417
|
-
name: "TurtleTime",
|
|
1418
|
-
description: "Time tracking",
|
|
1419
|
-
icon: "/turtletime-icon.svg",
|
|
1420
|
-
landing: "/tracker",
|
|
1421
|
-
baseUrlEnv: "NEXT_PUBLIC_TURTLETIME_URL",
|
|
1422
|
-
baseUrlFallback: "http://localhost:3000"
|
|
1423
|
-
},
|
|
1424
|
-
{
|
|
1425
|
-
slug: "kraken",
|
|
1426
|
-
name: "Kraken",
|
|
1427
|
-
description: "Documents and knowledge",
|
|
1428
|
-
icon: "/kraken-icon.svg",
|
|
1429
|
-
landing: "/today",
|
|
1430
|
-
baseUrlEnv: "NEXT_PUBLIC_KRAKEN_URL",
|
|
1431
|
-
baseUrlFallback: "http://localhost:3003"
|
|
1432
|
-
}
|
|
1433
|
-
];
|
|
1434
|
-
var SUITE_APP_MAP = Object.fromEntries(SUITE_APPS2.map((app) => [app.slug, app]));
|
|
1435
|
-
function suiteAppBaseUrl(slug) {
|
|
1436
|
-
const def = SUITE_APP_MAP[slug];
|
|
1437
|
-
const fromEnv = typeof process !== "undefined" ? process.env[def.baseUrlEnv] : void 0;
|
|
1438
|
-
return (fromEnv || def.baseUrlFallback).replace(/\/$/, "");
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
1932
|
// src/suite/components/today-calibrating.tsx
|
|
1442
1933
|
import { Refresh as RefreshCw2, SunLight as Sun } from "iconoir-react";
|
|
1443
|
-
import {
|
|
1934
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1444
1935
|
function TodayCalibrating({
|
|
1445
1936
|
onRetry,
|
|
1446
1937
|
retrying = false,
|
|
1447
1938
|
className,
|
|
1448
1939
|
spinner: Spinner,
|
|
1449
|
-
variant = "ring",
|
|
1940
|
+
variant: _variant = "ring",
|
|
1450
1941
|
retrySpinnerClassName = "text-ph-brand"
|
|
1451
1942
|
}) {
|
|
1452
|
-
|
|
1943
|
+
void _variant;
|
|
1944
|
+
return /* @__PURE__ */ jsxs14(
|
|
1453
1945
|
"div",
|
|
1454
1946
|
{
|
|
1455
1947
|
className: cn(
|
|
1456
|
-
"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",
|
|
1948
|
+
"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",
|
|
1457
1949
|
className
|
|
1458
1950
|
),
|
|
1459
1951
|
"data-test": "today-calibrating",
|
|
1460
1952
|
children: [
|
|
1461
|
-
/* @__PURE__ */
|
|
1953
|
+
/* @__PURE__ */ jsx16(
|
|
1462
1954
|
"div",
|
|
1463
1955
|
{
|
|
1464
|
-
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.
|
|
1956
|
+
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.1),transparent_55%)]",
|
|
1465
1957
|
"aria-hidden": true
|
|
1466
1958
|
}
|
|
1467
1959
|
),
|
|
1468
|
-
/* @__PURE__ */
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
size: "lg",
|
|
1474
|
-
className: "absolute inset-0 m-auto opacity-40",
|
|
1475
|
-
label: "Loading today"
|
|
1476
|
-
}
|
|
1477
|
-
),
|
|
1478
|
-
/* @__PURE__ */ jsx14(
|
|
1479
|
-
"span",
|
|
1480
|
-
{
|
|
1481
|
-
className: "bg-ph-muted/30 absolute inset-2 animate-ping rounded-full",
|
|
1482
|
-
"aria-hidden": true
|
|
1483
|
-
}
|
|
1484
|
-
)
|
|
1485
|
-
] }) : null,
|
|
1486
|
-
/* @__PURE__ */ jsx14("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__ */ jsx14(
|
|
1487
|
-
Sun,
|
|
1488
|
-
{
|
|
1489
|
-
className: cn("h-9 w-9", variant === "pulse" && "animate-pulse"),
|
|
1490
|
-
strokeWidth: 2,
|
|
1491
|
-
"aria-hidden": true
|
|
1492
|
-
}
|
|
1493
|
-
) })
|
|
1494
|
-
] }),
|
|
1495
|
-
/* @__PURE__ */ jsx14("h2", { className: "relative text-base font-semibold tracking-tight text-ph-ink sm:text-lg md:text-xl", children: "Calibrating your day" }),
|
|
1496
|
-
/* @__PURE__ */ jsx14("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" }),
|
|
1497
|
-
/* @__PURE__ */ jsx14("div", { className: "relative mt-5 flex gap-1.5", "aria-hidden": true, children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx14(
|
|
1498
|
-
"span",
|
|
1499
|
-
{
|
|
1500
|
-
className: "h-1.5 w-5 animate-pulse rounded-full bg-ph-muted",
|
|
1501
|
-
style: { animationDelay: `${i * 120}ms` }
|
|
1502
|
-
},
|
|
1503
|
-
i
|
|
1504
|
-
)) }),
|
|
1505
|
-
onRetry ? /* @__PURE__ */ jsxs12(
|
|
1960
|
+
/* @__PURE__ */ jsx16("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__ */ jsx16(Sun, { className: "h-8 w-8", strokeWidth: 2, "aria-hidden": true }) }),
|
|
1961
|
+
/* @__PURE__ */ jsx16("h2", { className: "relative text-base font-semibold tracking-tight text-ph-ink sm:text-lg md:text-xl", children: "Calibrating your day" }),
|
|
1962
|
+
/* @__PURE__ */ jsx16("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" }),
|
|
1963
|
+
/* @__PURE__ */ jsx16("div", { className: "relative mt-5 flex justify-center", children: /* @__PURE__ */ jsx16(Spinner, { size: "sm", className: "opacity-70", label: "Loading today" }) }),
|
|
1964
|
+
onRetry ? /* @__PURE__ */ jsxs14(
|
|
1506
1965
|
"button",
|
|
1507
1966
|
{
|
|
1508
1967
|
type: "button",
|
|
@@ -1510,7 +1969,7 @@ function TodayCalibrating({
|
|
|
1510
1969
|
disabled: retrying,
|
|
1511
1970
|
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",
|
|
1512
1971
|
children: [
|
|
1513
|
-
retrying ? /* @__PURE__ */
|
|
1972
|
+
retrying ? /* @__PURE__ */ jsx16(Spinner, { size: "sm", className: retrySpinnerClassName }) : /* @__PURE__ */ jsx16(RefreshCw2, { className: "h-4 w-4", "aria-hidden": true }),
|
|
1514
1973
|
"Try again"
|
|
1515
1974
|
]
|
|
1516
1975
|
}
|
|
@@ -1525,11 +1984,11 @@ import {
|
|
|
1525
1984
|
createContext,
|
|
1526
1985
|
useCallback as useCallback2,
|
|
1527
1986
|
useContext,
|
|
1528
|
-
useEffect as
|
|
1987
|
+
useEffect as useEffect6,
|
|
1529
1988
|
useMemo,
|
|
1530
|
-
useState as
|
|
1989
|
+
useState as useState7
|
|
1531
1990
|
} from "react";
|
|
1532
|
-
import { jsx as
|
|
1991
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1533
1992
|
var SuiteThemeContext = createContext(null);
|
|
1534
1993
|
function systemTheme(fallback) {
|
|
1535
1994
|
if (typeof window === "undefined") return fallback;
|
|
@@ -1567,7 +2026,7 @@ function SuiteThemeProvider({
|
|
|
1567
2026
|
config,
|
|
1568
2027
|
children
|
|
1569
2028
|
}) {
|
|
1570
|
-
const [state, setState] =
|
|
2029
|
+
const [state, setState] = useState7(() => {
|
|
1571
2030
|
const theme2 = readStoredTheme(config.storageKey);
|
|
1572
2031
|
if (typeof document === "undefined") {
|
|
1573
2032
|
return { theme: theme2, resolvedTheme: config.fallbackTheme };
|
|
@@ -1577,7 +2036,7 @@ function SuiteThemeProvider({
|
|
|
1577
2036
|
return { theme: theme2, resolvedTheme: resolvedTheme2 };
|
|
1578
2037
|
});
|
|
1579
2038
|
const { theme, resolvedTheme } = state;
|
|
1580
|
-
|
|
2039
|
+
useEffect6(() => {
|
|
1581
2040
|
if (theme !== "system") return;
|
|
1582
2041
|
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1583
2042
|
const update = () => {
|
|
@@ -1607,7 +2066,7 @@ function SuiteThemeProvider({
|
|
|
1607
2066
|
() => ({ theme, resolvedTheme, setTheme, toggleTheme }),
|
|
1608
2067
|
[theme, resolvedTheme, setTheme, toggleTheme]
|
|
1609
2068
|
);
|
|
1610
|
-
return /* @__PURE__ */
|
|
2069
|
+
return /* @__PURE__ */ jsx17(SuiteThemeContext.Provider, { value, children });
|
|
1611
2070
|
}
|
|
1612
2071
|
function useSuiteTheme() {
|
|
1613
2072
|
const ctx = useContext(SuiteThemeContext);
|
|
@@ -1616,39 +2075,111 @@ function useSuiteTheme() {
|
|
|
1616
2075
|
}
|
|
1617
2076
|
|
|
1618
2077
|
// src/suite/components/ai-panel.tsx
|
|
1619
|
-
import {
|
|
1620
|
-
|
|
1621
|
-
|
|
2078
|
+
import {
|
|
2079
|
+
useCallback as useCallback3,
|
|
2080
|
+
useEffect as useEffect7,
|
|
2081
|
+
useRef as useRef3,
|
|
2082
|
+
useState as useState8
|
|
2083
|
+
} from "react";
|
|
2084
|
+
import { Check as Check2, Copy, Sparks, Xmark as X2 } from "iconoir-react";
|
|
2085
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2086
|
+
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
2087
|
+
function openSuiteAskAi(detail) {
|
|
2088
|
+
if (typeof window === "undefined") return;
|
|
2089
|
+
window.dispatchEvent(
|
|
2090
|
+
new CustomEvent(SUITE_OPEN_ASK_AI_EVENT, {
|
|
2091
|
+
detail: detail != null ? detail : {}
|
|
2092
|
+
})
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
1622
2095
|
function SuiteAiPanel({
|
|
1623
|
-
presets,
|
|
1624
|
-
emptyState,
|
|
1625
|
-
|
|
1626
|
-
|
|
2096
|
+
presets = [],
|
|
2097
|
+
emptyState = "Ask anything about your workspace, or look something up online.",
|
|
2098
|
+
title = "Ask AI",
|
|
2099
|
+
fetchChat,
|
|
2100
|
+
sendMessage,
|
|
2101
|
+
clearChat,
|
|
1627
2102
|
brandIcon: BrandIcon,
|
|
1628
|
-
spinner: Spinner
|
|
2103
|
+
spinner: Spinner,
|
|
2104
|
+
hideLauncher = false
|
|
1629
2105
|
}) {
|
|
1630
|
-
const [open, setOpen] =
|
|
1631
|
-
const [prompt, setPrompt] =
|
|
1632
|
-
const [
|
|
1633
|
-
const [
|
|
1634
|
-
const [
|
|
1635
|
-
const [
|
|
2106
|
+
const [open, setOpen] = useState8(false);
|
|
2107
|
+
const [prompt, setPrompt] = useState8("");
|
|
2108
|
+
const [messages, setMessages] = useState8([]);
|
|
2109
|
+
const [loading, setLoading] = useState8(false);
|
|
2110
|
+
const [hydrating, setHydrating] = useState8(false);
|
|
2111
|
+
const [error, setError] = useState8("");
|
|
2112
|
+
const [copiedId, setCopiedId] = useState8(null);
|
|
2113
|
+
const scrollerRef = useRef3(null);
|
|
2114
|
+
const pendingPromptRef = useRef3(null);
|
|
2115
|
+
const scrollToBottom = useCallback3(() => {
|
|
2116
|
+
const el = scrollerRef.current;
|
|
2117
|
+
if (!el) return;
|
|
2118
|
+
el.scrollTop = el.scrollHeight;
|
|
2119
|
+
}, []);
|
|
2120
|
+
const hydrate = useCallback3(async () => {
|
|
2121
|
+
var _a;
|
|
2122
|
+
setHydrating(true);
|
|
2123
|
+
setError("");
|
|
2124
|
+
try {
|
|
2125
|
+
const data = await fetchChat();
|
|
2126
|
+
setMessages((_a = data.messages) != null ? _a : []);
|
|
2127
|
+
if (!data.configured) {
|
|
2128
|
+
setError("ShellStack AI is not configured for this workspace yet.");
|
|
2129
|
+
}
|
|
2130
|
+
} catch (err) {
|
|
2131
|
+
setError(
|
|
2132
|
+
err instanceof Error ? err.message : "Could not load your Ask AI chat."
|
|
2133
|
+
);
|
|
2134
|
+
} finally {
|
|
2135
|
+
setHydrating(false);
|
|
2136
|
+
}
|
|
2137
|
+
}, [fetchChat]);
|
|
2138
|
+
useEffect7(() => {
|
|
2139
|
+
function onOpen(event) {
|
|
2140
|
+
var _a;
|
|
2141
|
+
const detail = event.detail;
|
|
2142
|
+
setOpen(true);
|
|
2143
|
+
if ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) {
|
|
2144
|
+
pendingPromptRef.current = detail.prompt.trim();
|
|
2145
|
+
setPrompt(detail.prompt.trim());
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2149
|
+
return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
|
|
2150
|
+
}, []);
|
|
2151
|
+
useEffect7(() => {
|
|
2152
|
+
if (!open) return;
|
|
2153
|
+
void hydrate().then(() => {
|
|
2154
|
+
const pending = pendingPromptRef.current;
|
|
2155
|
+
pendingPromptRef.current = null;
|
|
2156
|
+
if (pending) {
|
|
2157
|
+
setPrompt(pending);
|
|
2158
|
+
}
|
|
2159
|
+
});
|
|
2160
|
+
}, [open, hydrate]);
|
|
2161
|
+
useEffect7(() => {
|
|
2162
|
+
if (open) scrollToBottom();
|
|
2163
|
+
}, [messages, loading, open, scrollToBottom]);
|
|
1636
2164
|
async function ask(text) {
|
|
2165
|
+
var _a;
|
|
1637
2166
|
const trimmed = text.trim();
|
|
1638
2167
|
if (!trimmed || loading) return;
|
|
1639
2168
|
setLoading(true);
|
|
1640
2169
|
setError("");
|
|
1641
|
-
|
|
1642
|
-
|
|
2170
|
+
setPrompt("");
|
|
2171
|
+
setMessages((prev) => [...prev, { role: "user", content: trimmed }]);
|
|
1643
2172
|
try {
|
|
1644
|
-
const
|
|
1645
|
-
|
|
1646
|
-
setError("ShellStack AI is not configured for this workspace yet.");
|
|
1647
|
-
return;
|
|
1648
|
-
}
|
|
1649
|
-
const result = await complete({ prompt: trimmed });
|
|
1650
|
-
setAnswer(result.text);
|
|
2173
|
+
const result = await sendMessage({ prompt: trimmed });
|
|
2174
|
+
setMessages((_a = result.messages) != null ? _a : []);
|
|
1651
2175
|
} catch (err) {
|
|
2176
|
+
setMessages(
|
|
2177
|
+
(prev) => {
|
|
2178
|
+
var _a2, _b;
|
|
2179
|
+
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;
|
|
2180
|
+
}
|
|
2181
|
+
);
|
|
2182
|
+
setPrompt(trimmed);
|
|
1652
2183
|
setError(
|
|
1653
2184
|
err instanceof Error ? err.message : "The AI request failed. Try again."
|
|
1654
2185
|
);
|
|
@@ -1656,133 +2187,282 @@ function SuiteAiPanel({
|
|
|
1656
2187
|
setLoading(false);
|
|
1657
2188
|
}
|
|
1658
2189
|
}
|
|
1659
|
-
async function
|
|
1660
|
-
if (
|
|
2190
|
+
async function handleClear() {
|
|
2191
|
+
if (loading) return;
|
|
1661
2192
|
try {
|
|
1662
|
-
await
|
|
1663
|
-
|
|
1664
|
-
|
|
2193
|
+
await clearChat();
|
|
2194
|
+
setMessages([]);
|
|
2195
|
+
setError("");
|
|
2196
|
+
} catch (err) {
|
|
2197
|
+
setError(
|
|
2198
|
+
err instanceof Error ? err.message : "Could not clear this chat."
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
async function copyMessage(index, content) {
|
|
2203
|
+
try {
|
|
2204
|
+
await navigator.clipboard.writeText(content);
|
|
2205
|
+
setCopiedId(index);
|
|
2206
|
+
window.setTimeout(() => setCopiedId(null), 1500);
|
|
1665
2207
|
} catch (e) {
|
|
1666
2208
|
}
|
|
1667
2209
|
}
|
|
1668
|
-
|
|
1669
|
-
|
|
2210
|
+
const Icon = BrandIcon != null ? BrandIcon : Sparks;
|
|
2211
|
+
return /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
2212
|
+
!hideLauncher ? /* @__PURE__ */ jsxs15(
|
|
1670
2213
|
"button",
|
|
1671
2214
|
{
|
|
1672
2215
|
type: "button",
|
|
1673
2216
|
"data-test": "ai-panel-launcher",
|
|
1674
2217
|
onClick: () => setOpen(true),
|
|
1675
2218
|
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",
|
|
1676
|
-
"aria-label": "Open
|
|
2219
|
+
"aria-label": "Open Ask AI",
|
|
1677
2220
|
children: [
|
|
1678
|
-
/* @__PURE__ */
|
|
2221
|
+
/* @__PURE__ */ jsx18(Icon, { className: "h-4 w-4 text-ph-brand" }),
|
|
1679
2222
|
"Ask AI"
|
|
1680
2223
|
]
|
|
1681
2224
|
}
|
|
1682
|
-
),
|
|
1683
|
-
open
|
|
1684
|
-
/* @__PURE__ */
|
|
2225
|
+
) : null,
|
|
2226
|
+
open ? /* @__PURE__ */ jsxs15("div", { className: "fixed inset-0 z-40", role: "dialog", "aria-modal": "true", children: [
|
|
2227
|
+
/* @__PURE__ */ jsx18(
|
|
1685
2228
|
"button",
|
|
1686
2229
|
{
|
|
1687
2230
|
type: "button",
|
|
1688
2231
|
className: "absolute inset-0 bg-black/25",
|
|
1689
2232
|
onClick: () => setOpen(false),
|
|
1690
|
-
"aria-label": "Close AI
|
|
2233
|
+
"aria-label": "Close Ask AI"
|
|
1691
2234
|
}
|
|
1692
2235
|
),
|
|
1693
|
-
/* @__PURE__ */
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
/* @__PURE__ */
|
|
1732
|
-
/* @__PURE__ */ jsxs13(
|
|
2236
|
+
/* @__PURE__ */ jsxs15(
|
|
2237
|
+
"aside",
|
|
2238
|
+
{
|
|
2239
|
+
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",
|
|
2240
|
+
"data-test": "suite-ask-ai-panel",
|
|
2241
|
+
children: [
|
|
2242
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between border-b border-ph-border px-4 py-3", children: [
|
|
2243
|
+
/* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
|
|
2244
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
2245
|
+
/* @__PURE__ */ jsx18(Icon, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2246
|
+
/* @__PURE__ */ jsx18("span", { className: "text-sm font-semibold text-ph-ink", children: title })
|
|
2247
|
+
] }),
|
|
2248
|
+
/* @__PURE__ */ jsx18("p", { className: "mt-0.5 text-[11px] text-ph-mutedtext", children: "Shared across your suite \xB7 same chat in every app" })
|
|
2249
|
+
] }),
|
|
2250
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1", children: [
|
|
2251
|
+
messages.length > 0 ? /* @__PURE__ */ jsx18(
|
|
2252
|
+
"button",
|
|
2253
|
+
{
|
|
2254
|
+
type: "button",
|
|
2255
|
+
onClick: () => void handleClear(),
|
|
2256
|
+
disabled: loading,
|
|
2257
|
+
className: "rounded-md px-2 py-1 text-xs text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink disabled:opacity-50",
|
|
2258
|
+
"data-test": "ask-ai-clear",
|
|
2259
|
+
children: "Clear"
|
|
2260
|
+
}
|
|
2261
|
+
) : null,
|
|
2262
|
+
/* @__PURE__ */ jsx18(
|
|
2263
|
+
"button",
|
|
2264
|
+
{
|
|
2265
|
+
type: "button",
|
|
2266
|
+
onClick: () => setOpen(false),
|
|
2267
|
+
className: "rounded p-1 hover:bg-ph-muted",
|
|
2268
|
+
"aria-label": "Close",
|
|
2269
|
+
children: /* @__PURE__ */ jsx18(X2, { className: "h-4 w-4" })
|
|
2270
|
+
}
|
|
2271
|
+
)
|
|
2272
|
+
] })
|
|
2273
|
+
] }),
|
|
2274
|
+
presets.length > 0 && messages.length === 0 ? /* @__PURE__ */ jsx18("div", { className: "flex flex-wrap gap-1.5 border-b border-ph-border px-4 py-2", children: presets.map((preset) => /* @__PURE__ */ jsx18(
|
|
1733
2275
|
"button",
|
|
1734
2276
|
{
|
|
1735
2277
|
type: "button",
|
|
1736
|
-
onClick: () => void
|
|
1737
|
-
|
|
2278
|
+
onClick: () => void ask(preset.prompt),
|
|
2279
|
+
disabled: loading || hydrating,
|
|
2280
|
+
className: "rounded-full border border-ph-border px-2.5 py-1 text-xs text-ph-ink hover:bg-ph-muted disabled:opacity-50",
|
|
2281
|
+
children: preset.label
|
|
2282
|
+
},
|
|
2283
|
+
preset.label
|
|
2284
|
+
)) }) : null,
|
|
2285
|
+
/* @__PURE__ */ jsxs15(
|
|
2286
|
+
"div",
|
|
2287
|
+
{
|
|
2288
|
+
ref: scrollerRef,
|
|
2289
|
+
className: "flex-1 space-y-3 overflow-y-auto p-4",
|
|
1738
2290
|
children: [
|
|
1739
|
-
|
|
1740
|
-
|
|
2291
|
+
error ? /* @__PURE__ */ jsx18("p", { className: "bg-ph-danger/10 rounded-lg px-3 py-2 text-sm text-ph-danger", children: error }) : null,
|
|
2292
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2293
|
+
/* @__PURE__ */ jsx18(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2294
|
+
"Loading chat\u2026"
|
|
2295
|
+
] }) : null,
|
|
2296
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ jsxs15("div", { className: "mt-10 px-2 text-center", children: [
|
|
2297
|
+
/* @__PURE__ */ jsx18("p", { className: "font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2298
|
+
/* @__PURE__ */ jsx18("p", { className: "mt-2 text-sm leading-relaxed text-ph-subtle", children: emptyState })
|
|
2299
|
+
] }) : null,
|
|
2300
|
+
messages.map((message, index) => {
|
|
2301
|
+
const isUser = message.role === "user";
|
|
2302
|
+
return /* @__PURE__ */ jsxs15(
|
|
2303
|
+
"div",
|
|
2304
|
+
{
|
|
2305
|
+
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",
|
|
2306
|
+
"data-test": isUser ? "ask-ai-user" : "ask-ai-assistant",
|
|
2307
|
+
children: [
|
|
2308
|
+
/* @__PURE__ */ jsx18("p", { className: "whitespace-pre-wrap", children: message.content }),
|
|
2309
|
+
!isUser ? /* @__PURE__ */ jsxs15(
|
|
2310
|
+
"button",
|
|
2311
|
+
{
|
|
2312
|
+
type: "button",
|
|
2313
|
+
onClick: () => void copyMessage(index, message.content),
|
|
2314
|
+
className: "mt-2 inline-flex items-center gap-1 text-xs text-ph-mutedtext hover:text-ph-ink",
|
|
2315
|
+
children: [
|
|
2316
|
+
copiedId === index ? /* @__PURE__ */ jsx18(Check2, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx18(Copy, { className: "h-3 w-3" }),
|
|
2317
|
+
copiedId === index ? "Copied" : "Copy"
|
|
2318
|
+
]
|
|
2319
|
+
}
|
|
2320
|
+
) : null
|
|
2321
|
+
]
|
|
2322
|
+
},
|
|
2323
|
+
`${message.role}-${index}-${message.content.slice(0, 24)}`
|
|
2324
|
+
);
|
|
2325
|
+
}),
|
|
2326
|
+
loading ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 text-sm text-ph-mutedtext", children: [
|
|
2327
|
+
/* @__PURE__ */ jsx18(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2328
|
+
"Thinking\u2026"
|
|
2329
|
+
] }) : null
|
|
1741
2330
|
]
|
|
1742
2331
|
}
|
|
1743
|
-
)
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
2332
|
+
),
|
|
2333
|
+
/* @__PURE__ */ jsx18("div", { className: "border-t border-ph-border p-3", children: /* @__PURE__ */ jsxs15("div", { className: "flex gap-2", children: [
|
|
2334
|
+
/* @__PURE__ */ jsx18(
|
|
2335
|
+
"textarea",
|
|
2336
|
+
{
|
|
2337
|
+
value: prompt,
|
|
2338
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
2339
|
+
onKeyDown: (e) => {
|
|
2340
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
2341
|
+
e.preventDefault();
|
|
2342
|
+
void ask(prompt);
|
|
2343
|
+
}
|
|
2344
|
+
},
|
|
2345
|
+
placeholder: "Ask anything\u2026",
|
|
2346
|
+
rows: 2,
|
|
2347
|
+
disabled: loading,
|
|
2348
|
+
"data-test": "ask-ai-input",
|
|
2349
|
+
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"
|
|
1757
2350
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
] }) })
|
|
1776
|
-
] })
|
|
1777
|
-
] })
|
|
2351
|
+
),
|
|
2352
|
+
/* @__PURE__ */ jsx18(
|
|
2353
|
+
"button",
|
|
2354
|
+
{
|
|
2355
|
+
type: "button",
|
|
2356
|
+
onClick: () => void ask(prompt),
|
|
2357
|
+
disabled: loading || !prompt.trim(),
|
|
2358
|
+
"data-test": "ask-ai-send",
|
|
2359
|
+
className: "self-end rounded-xl bg-ph-brand px-3.5 py-2 text-sm font-medium text-white disabled:opacity-50",
|
|
2360
|
+
children: "Ask"
|
|
2361
|
+
}
|
|
2362
|
+
)
|
|
2363
|
+
] }) })
|
|
2364
|
+
]
|
|
2365
|
+
}
|
|
2366
|
+
)
|
|
2367
|
+
] }) : null
|
|
1778
2368
|
] });
|
|
1779
2369
|
}
|
|
1780
2370
|
|
|
2371
|
+
// src/suite/lib/use-sidebar-width.ts
|
|
2372
|
+
import {
|
|
2373
|
+
useCallback as useCallback4,
|
|
2374
|
+
useEffect as useEffect8,
|
|
2375
|
+
useState as useState9
|
|
2376
|
+
} from "react";
|
|
2377
|
+
var SIDEBAR_RAIL_WIDTH = 56;
|
|
2378
|
+
var SIDEBAR_COLLAPSE_THRESHOLD = 80;
|
|
2379
|
+
var SIDEBAR_MIN_EXPANDED_WIDTH = 180;
|
|
2380
|
+
var SIDEBAR_MAX_WIDTH = 320;
|
|
2381
|
+
var SIDEBAR_DEFAULT_WIDTH = 320;
|
|
2382
|
+
function clampWidth(width) {
|
|
2383
|
+
return Math.min(SIDEBAR_MAX_WIDTH, Math.max(SIDEBAR_RAIL_WIDTH, width));
|
|
2384
|
+
}
|
|
2385
|
+
function snapWidth(width) {
|
|
2386
|
+
if (width <= SIDEBAR_COLLAPSE_THRESHOLD) return SIDEBAR_RAIL_WIDTH;
|
|
2387
|
+
if (width < SIDEBAR_MIN_EXPANDED_WIDTH) return SIDEBAR_MIN_EXPANDED_WIDTH;
|
|
2388
|
+
return Math.min(SIDEBAR_MAX_WIDTH, width);
|
|
2389
|
+
}
|
|
2390
|
+
function useSidebarWidth(storageKey) {
|
|
2391
|
+
const [width, setWidth] = useState9(SIDEBAR_DEFAULT_WIDTH);
|
|
2392
|
+
const [narrowViewport, setNarrowViewport] = useState9(false);
|
|
2393
|
+
const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
|
|
2394
|
+
useEffect8(() => {
|
|
2395
|
+
let stored = null;
|
|
2396
|
+
try {
|
|
2397
|
+
stored = localStorage.getItem(storageKey);
|
|
2398
|
+
} catch (e) {
|
|
2399
|
+
}
|
|
2400
|
+
if (!stored) return;
|
|
2401
|
+
const parsed = Number.parseInt(stored, 10);
|
|
2402
|
+
if (!Number.isNaN(parsed)) {
|
|
2403
|
+
queueMicrotask(() => setWidth(snapWidth(clampWidth(parsed))));
|
|
2404
|
+
}
|
|
2405
|
+
}, [storageKey]);
|
|
2406
|
+
useEffect8(() => {
|
|
2407
|
+
const media = window.matchMedia("(max-width: 639px)");
|
|
2408
|
+
const sync = () => setNarrowViewport(media.matches);
|
|
2409
|
+
sync();
|
|
2410
|
+
media.addEventListener("change", sync);
|
|
2411
|
+
return () => media.removeEventListener("change", sync);
|
|
2412
|
+
}, []);
|
|
2413
|
+
const persist = useCallback4(
|
|
2414
|
+
(value) => {
|
|
2415
|
+
try {
|
|
2416
|
+
localStorage.setItem(storageKey, String(value));
|
|
2417
|
+
} catch (e) {
|
|
2418
|
+
}
|
|
2419
|
+
},
|
|
2420
|
+
[storageKey]
|
|
2421
|
+
);
|
|
2422
|
+
const setCollapsed = useCallback4(
|
|
2423
|
+
(value) => {
|
|
2424
|
+
setWidth((current) => {
|
|
2425
|
+
const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? SIDEBAR_DEFAULT_WIDTH : snapWidth(current);
|
|
2426
|
+
persist(next);
|
|
2427
|
+
return next;
|
|
2428
|
+
});
|
|
2429
|
+
},
|
|
2430
|
+
[persist]
|
|
2431
|
+
);
|
|
2432
|
+
const resetWidth = useCallback4(() => {
|
|
2433
|
+
setWidth(SIDEBAR_DEFAULT_WIDTH);
|
|
2434
|
+
persist(SIDEBAR_DEFAULT_WIDTH);
|
|
2435
|
+
}, [persist]);
|
|
2436
|
+
const startResize = useCallback4(
|
|
2437
|
+
(event) => {
|
|
2438
|
+
event.preventDefault();
|
|
2439
|
+
const startX = event.clientX;
|
|
2440
|
+
const startWidth = width;
|
|
2441
|
+
const onMove = (moveEvent) => {
|
|
2442
|
+
setWidth(clampWidth(startWidth + moveEvent.clientX - startX));
|
|
2443
|
+
};
|
|
2444
|
+
const onUp = () => {
|
|
2445
|
+
document.removeEventListener("pointermove", onMove);
|
|
2446
|
+
document.removeEventListener("pointerup", onUp);
|
|
2447
|
+
setWidth((current) => {
|
|
2448
|
+
const snapped = snapWidth(current);
|
|
2449
|
+
persist(snapped);
|
|
2450
|
+
return snapped;
|
|
2451
|
+
});
|
|
2452
|
+
};
|
|
2453
|
+
document.addEventListener("pointermove", onMove);
|
|
2454
|
+
document.addEventListener("pointerup", onUp);
|
|
2455
|
+
},
|
|
2456
|
+
[persist, width]
|
|
2457
|
+
);
|
|
2458
|
+
return { width, collapsed, setCollapsed, resetWidth, startResize };
|
|
2459
|
+
}
|
|
2460
|
+
|
|
1781
2461
|
// src/suite/lib/motion.tsx
|
|
1782
2462
|
import { LazyMotion, domAnimation, m } from "motion/react";
|
|
1783
|
-
import { jsx as
|
|
2463
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
1784
2464
|
function SuiteMotionProvider({ children }) {
|
|
1785
|
-
return /* @__PURE__ */
|
|
2465
|
+
return /* @__PURE__ */ jsx19(LazyMotion, { features: domAnimation, strict: true, children });
|
|
1786
2466
|
}
|
|
1787
2467
|
var SUITE_SPRINGS = {
|
|
1788
2468
|
/** Snappy panel/sheet entrances — small overshoot. */
|
|
@@ -1793,217 +2473,25 @@ var SUITE_SPRINGS = {
|
|
|
1793
2473
|
press: { type: "spring", stiffness: 600, damping: 35, mass: 0.5 }
|
|
1794
2474
|
};
|
|
1795
2475
|
|
|
1796
|
-
// src/suite/components/suite-layout.tsx
|
|
1797
|
-
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1798
|
-
var WIDTHS = {
|
|
1799
|
-
full: "max-w-none",
|
|
1800
|
-
wide: "max-w-7xl",
|
|
1801
|
-
content: "max-w-6xl",
|
|
1802
|
-
narrow: "max-w-4xl"
|
|
1803
|
-
};
|
|
1804
|
-
function SuiteBreadcrumbs({ items, className }) {
|
|
1805
|
-
return /* @__PURE__ */ jsx18("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx18("ol", { className: "flex min-w-0 items-center gap-1.5", children: items.map((item, index) => {
|
|
1806
|
-
const isLast = index === items.length - 1;
|
|
1807
|
-
return /* @__PURE__ */ jsxs14("li", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1808
|
-
index > 0 ? /* @__PURE__ */ jsx18("span", { className: "select-none text-ph-border", "aria-hidden": "true", children: "/" }) : null,
|
|
1809
|
-
item.href && !isLast ? /* @__PURE__ */ jsx18(
|
|
1810
|
-
"a",
|
|
1811
|
-
{
|
|
1812
|
-
href: item.href,
|
|
1813
|
-
className: "truncate transition hover:text-ph-ink",
|
|
1814
|
-
children: item.label
|
|
1815
|
-
}
|
|
1816
|
-
) : /* @__PURE__ */ jsx18(
|
|
1817
|
-
"span",
|
|
1818
|
-
{
|
|
1819
|
-
className: cn(
|
|
1820
|
-
"truncate",
|
|
1821
|
-
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
1822
|
-
),
|
|
1823
|
-
"aria-current": isLast ? "page" : void 0,
|
|
1824
|
-
children: item.label
|
|
1825
|
-
}
|
|
1826
|
-
)
|
|
1827
|
-
] }, index);
|
|
1828
|
-
}) }) });
|
|
1829
|
-
}
|
|
1830
|
-
function SuitePage({
|
|
1831
|
-
children,
|
|
1832
|
-
width = "wide",
|
|
1833
|
-
inset = true,
|
|
1834
|
-
className,
|
|
1835
|
-
as: Component = "div",
|
|
1836
|
-
dataTest,
|
|
1837
|
-
id,
|
|
1838
|
-
role,
|
|
1839
|
-
"aria-live": ariaLive
|
|
1840
|
-
}) {
|
|
1841
|
-
return /* @__PURE__ */ jsx18(
|
|
1842
|
-
Component,
|
|
1843
|
-
{
|
|
1844
|
-
id,
|
|
1845
|
-
"data-test": dataTest,
|
|
1846
|
-
role,
|
|
1847
|
-
"aria-live": ariaLive,
|
|
1848
|
-
className: cn(
|
|
1849
|
-
"mx-auto flex w-full min-w-0 flex-col",
|
|
1850
|
-
WIDTHS[width],
|
|
1851
|
-
// Tight inset keeps page titles aligned without excessive whitespace.
|
|
1852
|
-
inset && "px-4 pb-6 pt-4 sm:px-6 sm:pb-7 sm:pt-5 lg:px-8",
|
|
1853
|
-
className
|
|
1854
|
-
),
|
|
1855
|
-
children
|
|
1856
|
-
}
|
|
1857
|
-
);
|
|
1858
|
-
}
|
|
1859
|
-
function SuitePageHeader({
|
|
1860
|
-
title,
|
|
1861
|
-
description,
|
|
1862
|
-
eyebrow,
|
|
1863
|
-
actions,
|
|
1864
|
-
className,
|
|
1865
|
-
titleClassName,
|
|
1866
|
-
dataTest,
|
|
1867
|
-
/** Optional icon rendered before the title. */
|
|
1868
|
-
icon,
|
|
1869
|
-
/** Use the animated sun/moon icon from the Today page. */
|
|
1870
|
-
todayIcon,
|
|
1871
|
-
todayIconClassName,
|
|
1872
|
-
/** Small badge/pill next to the title (e.g. "Beta", org name). */
|
|
1873
|
-
badge,
|
|
1874
|
-
/** Breadcrumb line rendered above the title. */
|
|
1875
|
-
breadcrumb
|
|
1876
|
-
}) {
|
|
1877
|
-
const resolvedIcon = todayIcon ? /* @__PURE__ */ jsx18(
|
|
1878
|
-
TodayTimeIcon,
|
|
1879
|
-
{
|
|
1880
|
-
className: cn(
|
|
1881
|
-
"h-6 w-6 sm:h-7 sm:w-7 text-amber-500",
|
|
1882
|
-
todayIconClassName
|
|
1883
|
-
)
|
|
1884
|
-
}
|
|
1885
|
-
) : icon;
|
|
1886
|
-
return /* @__PURE__ */ jsxs14(
|
|
1887
|
-
"header",
|
|
1888
|
-
{
|
|
1889
|
-
"data-test": dataTest,
|
|
1890
|
-
className: cn(
|
|
1891
|
-
"flex items-start justify-between gap-4 pb-4 sm:pb-5",
|
|
1892
|
-
className
|
|
1893
|
-
),
|
|
1894
|
-
children: [
|
|
1895
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 items-start gap-3", children: [
|
|
1896
|
-
resolvedIcon ? /* @__PURE__ */ jsx18(
|
|
1897
|
-
"div",
|
|
1898
|
-
{
|
|
1899
|
-
className: "hidden shrink-0 pt-1 sm:block",
|
|
1900
|
-
"aria-hidden": "true",
|
|
1901
|
-
children: resolvedIcon
|
|
1902
|
-
}
|
|
1903
|
-
) : null,
|
|
1904
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-col gap-1", children: [
|
|
1905
|
-
eyebrow ? /* @__PURE__ */ jsx18("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: eyebrow }) : null,
|
|
1906
|
-
breadcrumb ? /* @__PURE__ */ jsx18("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: breadcrumb }) : null,
|
|
1907
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1908
|
-
/* @__PURE__ */ jsx18(
|
|
1909
|
-
"h1",
|
|
1910
|
-
{
|
|
1911
|
-
className: cn(
|
|
1912
|
-
"font-display text-[1.625rem] font-bold leading-tight tracking-tight text-ph-ink sm:text-[2.25rem]",
|
|
1913
|
-
titleClassName
|
|
1914
|
-
),
|
|
1915
|
-
children: title
|
|
1916
|
-
}
|
|
1917
|
-
),
|
|
1918
|
-
badge ? /* @__PURE__ */ jsx18("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
|
|
1919
|
-
] }),
|
|
1920
|
-
description ? /* @__PURE__ */ jsx18("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
1921
|
-
] })
|
|
1922
|
-
] }),
|
|
1923
|
-
actions ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center gap-2 pt-1", children: actions }) : null
|
|
1924
|
-
]
|
|
1925
|
-
}
|
|
1926
|
-
);
|
|
1927
|
-
}
|
|
1928
|
-
function SuiteToolbar({
|
|
1929
|
-
children,
|
|
1930
|
-
className,
|
|
1931
|
-
label = "Page tools",
|
|
1932
|
-
dataTest
|
|
1933
|
-
}) {
|
|
1934
|
-
return /* @__PURE__ */ jsx18(
|
|
1935
|
-
"div",
|
|
1936
|
-
{
|
|
1937
|
-
role: "toolbar",
|
|
1938
|
-
"aria-label": label,
|
|
1939
|
-
"data-test": dataTest,
|
|
1940
|
-
className: cn("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
1941
|
-
children
|
|
1942
|
-
}
|
|
1943
|
-
);
|
|
1944
|
-
}
|
|
1945
|
-
function SuiteTabList({
|
|
1946
|
-
children,
|
|
1947
|
-
className,
|
|
1948
|
-
label,
|
|
1949
|
-
dataTest
|
|
1950
|
-
}) {
|
|
1951
|
-
return /* @__PURE__ */ jsx18(
|
|
1952
|
-
"nav",
|
|
1953
|
-
{
|
|
1954
|
-
"aria-label": label,
|
|
1955
|
-
"data-test": dataTest,
|
|
1956
|
-
className: cn(
|
|
1957
|
-
"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]",
|
|
1958
|
-
className
|
|
1959
|
-
),
|
|
1960
|
-
children
|
|
1961
|
-
}
|
|
1962
|
-
);
|
|
1963
|
-
}
|
|
1964
|
-
function SuiteSectionHeader({
|
|
1965
|
-
title,
|
|
1966
|
-
description,
|
|
1967
|
-
action,
|
|
1968
|
-
className
|
|
1969
|
-
}) {
|
|
1970
|
-
return /* @__PURE__ */ jsxs14(
|
|
1971
|
-
"div",
|
|
1972
|
-
{
|
|
1973
|
-
className: cn(
|
|
1974
|
-
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
1975
|
-
className
|
|
1976
|
-
),
|
|
1977
|
-
children: [
|
|
1978
|
-
/* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
|
|
1979
|
-
/* @__PURE__ */ jsx18("h2", { className: "font-display text-balance text-lg font-semibold tracking-tight text-ph-ink sm:text-xl", children: title }),
|
|
1980
|
-
description ? /* @__PURE__ */ jsx18("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
1981
|
-
] }),
|
|
1982
|
-
action ? /* @__PURE__ */ jsx18("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
1983
|
-
]
|
|
1984
|
-
}
|
|
1985
|
-
);
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
2476
|
// src/suite/components/suite-skeleton.tsx
|
|
1989
|
-
import { jsx as
|
|
2477
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1990
2478
|
function SuiteSkeleton({
|
|
1991
2479
|
className,
|
|
1992
2480
|
lines = 1,
|
|
1993
2481
|
circle,
|
|
1994
2482
|
width
|
|
1995
2483
|
}) {
|
|
1996
|
-
return /* @__PURE__ */
|
|
2484
|
+
return /* @__PURE__ */ jsx20(
|
|
1997
2485
|
"div",
|
|
1998
2486
|
{
|
|
1999
2487
|
className: cn("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
2000
2488
|
"aria-hidden": true,
|
|
2001
|
-
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */
|
|
2489
|
+
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
2002
2490
|
"div",
|
|
2003
2491
|
{
|
|
2004
2492
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2005
2493
|
style: { animationDelay: `${index * 80}ms` },
|
|
2006
|
-
children: /* @__PURE__ */
|
|
2494
|
+
children: /* @__PURE__ */ jsx20(
|
|
2007
2495
|
"div",
|
|
2008
2496
|
{
|
|
2009
2497
|
className: cn(
|
|
@@ -2027,35 +2515,35 @@ function SuiteSkeletonCard({
|
|
|
2027
2515
|
rows = 3,
|
|
2028
2516
|
header = true
|
|
2029
2517
|
}) {
|
|
2030
|
-
return /* @__PURE__ */
|
|
2518
|
+
return /* @__PURE__ */ jsxs16(
|
|
2031
2519
|
"div",
|
|
2032
2520
|
{
|
|
2033
2521
|
className: cn(
|
|
2034
|
-
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border
|
|
2522
|
+
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border bg-ph-surface p-6 shadow-sm",
|
|
2035
2523
|
className
|
|
2036
2524
|
),
|
|
2037
2525
|
"aria-hidden": true,
|
|
2038
2526
|
children: [
|
|
2039
|
-
header ? /* @__PURE__ */
|
|
2527
|
+
header ? /* @__PURE__ */ jsxs16(
|
|
2040
2528
|
"div",
|
|
2041
2529
|
{
|
|
2042
2530
|
className: "mb-5 flex items-center gap-3 animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2043
2531
|
style: { animationDelay: "100ms" },
|
|
2044
2532
|
children: [
|
|
2045
|
-
/* @__PURE__ */
|
|
2046
|
-
/* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2533
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-10 w-10 rounded-xl" }),
|
|
2534
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex-1 space-y-2", children: [
|
|
2535
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-4 w-1/3" }),
|
|
2536
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2049
2537
|
] })
|
|
2050
2538
|
]
|
|
2051
2539
|
}
|
|
2052
2540
|
) : null,
|
|
2053
|
-
/* @__PURE__ */
|
|
2541
|
+
/* @__PURE__ */ jsx20("div", { className: "space-y-3", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
2054
2542
|
"div",
|
|
2055
2543
|
{
|
|
2056
2544
|
className: "animate-[skeleton-stagger_0.5s_ease-out_both]",
|
|
2057
2545
|
style: { animationDelay: `${200 + index * 80}ms` },
|
|
2058
|
-
children: /* @__PURE__ */
|
|
2546
|
+
children: /* @__PURE__ */ jsx20(
|
|
2059
2547
|
"div",
|
|
2060
2548
|
{
|
|
2061
2549
|
className: "ph-skeleton h-3",
|
|
@@ -2073,16 +2561,16 @@ function SuiteSkeletonList({
|
|
|
2073
2561
|
className,
|
|
2074
2562
|
items = 4
|
|
2075
2563
|
}) {
|
|
2076
|
-
return /* @__PURE__ */
|
|
2564
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("space-y-3", className), "aria-hidden": true, children: Array.from({ length: items }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
2077
2565
|
"div",
|
|
2078
2566
|
{
|
|
2079
2567
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
2080
2568
|
style: { animationDelay: `${index * 100}ms` },
|
|
2081
|
-
children: /* @__PURE__ */
|
|
2082
|
-
/* @__PURE__ */
|
|
2083
|
-
/* @__PURE__ */
|
|
2084
|
-
/* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2569
|
+
children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3 rounded-xl border border-ph-border bg-ph-surface p-4", children: [
|
|
2570
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-10 w-10 rounded-lg" }),
|
|
2571
|
+
/* @__PURE__ */ jsxs16("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
2572
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-3.5 w-3/4" }),
|
|
2573
|
+
/* @__PURE__ */ jsx20("div", { className: "ph-skeleton h-3 w-1/2" })
|
|
2086
2574
|
] })
|
|
2087
2575
|
] })
|
|
2088
2576
|
},
|
|
@@ -2097,22 +2585,22 @@ function SuiteEmptyState({
|
|
|
2097
2585
|
className,
|
|
2098
2586
|
size = "md"
|
|
2099
2587
|
}) {
|
|
2100
|
-
return /* @__PURE__ */
|
|
2588
|
+
return /* @__PURE__ */ jsxs16(
|
|
2101
2589
|
"div",
|
|
2102
2590
|
{
|
|
2103
2591
|
className: cn(
|
|
2104
|
-
"relative overflow-hidden rounded-2xl border border-ph-border
|
|
2592
|
+
"relative overflow-hidden rounded-2xl border border-ph-border bg-ph-surface text-center",
|
|
2105
2593
|
size === "sm" ? "px-5 py-8" : "px-6 py-12 sm:px-10 sm:py-16",
|
|
2106
2594
|
className
|
|
2107
2595
|
),
|
|
2108
2596
|
children: [
|
|
2109
|
-
/* @__PURE__ */
|
|
2110
|
-
/* @__PURE__ */
|
|
2111
|
-
/* @__PURE__ */
|
|
2597
|
+
/* @__PURE__ */ jsxs16("div", { className: "pointer-events-none absolute inset-0 overflow-hidden opacity-60", "aria-hidden": true, children: [
|
|
2598
|
+
/* @__PURE__ */ jsx20("div", { className: "absolute -left-10 -top-10 h-40 w-40 rounded-full bg-ph-brand/10 blur-3xl" }),
|
|
2599
|
+
/* @__PURE__ */ jsx20("div", { className: "absolute -bottom-10 -right-10 h-40 w-40 rounded-full bg-ph-accent/10 blur-3xl" })
|
|
2112
2600
|
] }),
|
|
2113
|
-
/* @__PURE__ */
|
|
2114
|
-
icon ? /* @__PURE__ */
|
|
2115
|
-
/* @__PURE__ */
|
|
2601
|
+
/* @__PURE__ */ jsxs16("div", { className: "relative", children: [
|
|
2602
|
+
icon ? /* @__PURE__ */ jsx20("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,
|
|
2603
|
+
/* @__PURE__ */ jsx20(
|
|
2116
2604
|
"h3",
|
|
2117
2605
|
{
|
|
2118
2606
|
className: cn(
|
|
@@ -2122,8 +2610,8 @@ function SuiteEmptyState({
|
|
|
2122
2610
|
children: title
|
|
2123
2611
|
}
|
|
2124
2612
|
),
|
|
2125
|
-
description ? /* @__PURE__ */
|
|
2126
|
-
action ? /* @__PURE__ */
|
|
2613
|
+
description ? /* @__PURE__ */ jsx20("p", { className: "mx-auto mt-2 max-w-sm text-sm leading-relaxed text-ph-subtle", children: description }) : null,
|
|
2614
|
+
action ? /* @__PURE__ */ jsx20("div", { className: "mt-5 flex flex-wrap items-center justify-center gap-2", children: action }) : null
|
|
2127
2615
|
] })
|
|
2128
2616
|
]
|
|
2129
2617
|
}
|
|
@@ -2132,23 +2620,25 @@ function SuiteEmptyState({
|
|
|
2132
2620
|
|
|
2133
2621
|
// src/suite/components/suite-settings-mobile-nav.tsx
|
|
2134
2622
|
import { isValidElement } from "react";
|
|
2135
|
-
import { jsx as
|
|
2623
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2136
2624
|
function SuiteSettingsMobileNav({
|
|
2137
2625
|
items,
|
|
2138
2626
|
activeHref,
|
|
2139
2627
|
onSelect,
|
|
2140
|
-
dataTest
|
|
2628
|
+
dataTest,
|
|
2629
|
+
ariaLabel = "Settings sections",
|
|
2630
|
+
className
|
|
2141
2631
|
}) {
|
|
2142
|
-
return /* @__PURE__ */
|
|
2632
|
+
return /* @__PURE__ */ jsx21(
|
|
2143
2633
|
"nav",
|
|
2144
2634
|
{
|
|
2145
2635
|
"data-test": dataTest,
|
|
2146
|
-
"aria-label":
|
|
2147
|
-
className: "-
|
|
2148
|
-
children: /* @__PURE__ */
|
|
2636
|
+
"aria-label": ariaLabel,
|
|
2637
|
+
className: cn("suite-settings-mobile-nav lg:hidden", className),
|
|
2638
|
+
children: /* @__PURE__ */ jsx21("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) => {
|
|
2149
2639
|
const Icon = item.icon;
|
|
2150
2640
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
2151
|
-
const iconNode = isValidElement(item.icon) ? item.icon : /* @__PURE__ */
|
|
2641
|
+
const iconNode = isValidElement(item.icon) ? item.icon : /* @__PURE__ */ jsx21(
|
|
2152
2642
|
Icon,
|
|
2153
2643
|
{
|
|
2154
2644
|
className: cn(
|
|
@@ -2158,7 +2648,7 @@ function SuiteSettingsMobileNav({
|
|
|
2158
2648
|
"aria-hidden": true
|
|
2159
2649
|
}
|
|
2160
2650
|
);
|
|
2161
|
-
return /* @__PURE__ */
|
|
2651
|
+
return /* @__PURE__ */ jsxs17(
|
|
2162
2652
|
"button",
|
|
2163
2653
|
{
|
|
2164
2654
|
type: "button",
|
|
@@ -2166,14 +2656,14 @@ function SuiteSettingsMobileNav({
|
|
|
2166
2656
|
onClick: () => onSelect(item.href),
|
|
2167
2657
|
"aria-current": active ? "page" : void 0,
|
|
2168
2658
|
className: cn(
|
|
2169
|
-
"group relative flex shrink-0 snap-start items-center gap-2 rounded-full px-3.5 py-2.5 text-sm font-medium transition",
|
|
2659
|
+
"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",
|
|
2170
2660
|
"min-h-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
2171
2661
|
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"
|
|
2172
2662
|
),
|
|
2173
2663
|
children: [
|
|
2174
2664
|
iconNode,
|
|
2175
|
-
/* @__PURE__ */
|
|
2176
|
-
active ? /* @__PURE__ */
|
|
2665
|
+
/* @__PURE__ */ jsx21("span", { className: "whitespace-nowrap", children: item.label }),
|
|
2666
|
+
active ? /* @__PURE__ */ jsx21("span", { className: "absolute inset-x-0 -bottom-3 h-0.5 rounded-full bg-ph-ink lg:hidden" }) : null
|
|
2177
2667
|
]
|
|
2178
2668
|
},
|
|
2179
2669
|
item.href
|
|
@@ -2185,7 +2675,7 @@ function SuiteSettingsMobileNav({
|
|
|
2185
2675
|
|
|
2186
2676
|
// src/suite/components/suite-sidebar.tsx
|
|
2187
2677
|
import Link2 from "next/link";
|
|
2188
|
-
import { jsx as
|
|
2678
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2189
2679
|
function renderNode(node, collapsed) {
|
|
2190
2680
|
if (typeof node === "function") return node(collapsed);
|
|
2191
2681
|
return node;
|
|
@@ -2202,7 +2692,7 @@ function SuiteSidebar({
|
|
|
2202
2692
|
className,
|
|
2203
2693
|
surface = false
|
|
2204
2694
|
}) {
|
|
2205
|
-
return /* @__PURE__ */
|
|
2695
|
+
return /* @__PURE__ */ jsxs18(
|
|
2206
2696
|
"div",
|
|
2207
2697
|
{
|
|
2208
2698
|
className: cn(
|
|
@@ -2211,7 +2701,7 @@ function SuiteSidebar({
|
|
|
2211
2701
|
className
|
|
2212
2702
|
),
|
|
2213
2703
|
children: [
|
|
2214
|
-
/* @__PURE__ */
|
|
2704
|
+
/* @__PURE__ */ jsxs18(
|
|
2215
2705
|
"div",
|
|
2216
2706
|
{
|
|
2217
2707
|
className: cn(
|
|
@@ -2220,12 +2710,12 @@ function SuiteSidebar({
|
|
|
2220
2710
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
2221
2711
|
),
|
|
2222
2712
|
children: [
|
|
2223
|
-
/* @__PURE__ */
|
|
2224
|
-
collapsed ? null : /* @__PURE__ */
|
|
2713
|
+
/* @__PURE__ */ jsx22("div", { className: cn("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
2714
|
+
collapsed ? null : /* @__PURE__ */ jsx22("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
2225
2715
|
]
|
|
2226
2716
|
}
|
|
2227
2717
|
),
|
|
2228
|
-
/* @__PURE__ */
|
|
2718
|
+
/* @__PURE__ */ jsxs18(
|
|
2229
2719
|
"div",
|
|
2230
2720
|
{
|
|
2231
2721
|
className: cn(
|
|
@@ -2234,17 +2724,17 @@ function SuiteSidebar({
|
|
|
2234
2724
|
collapsed ? "px-1.5 py-2" : "p-2"
|
|
2235
2725
|
),
|
|
2236
2726
|
children: [
|
|
2237
|
-
/* @__PURE__ */
|
|
2727
|
+
/* @__PURE__ */ jsxs18(
|
|
2238
2728
|
"nav",
|
|
2239
2729
|
{
|
|
2240
2730
|
"aria-label": "Pages",
|
|
2241
2731
|
className: "shrink-0 space-y-0.5",
|
|
2242
2732
|
children: [
|
|
2243
|
-
/* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2733
|
+
/* @__PURE__ */ jsx22("div", { className: cn("mb-3", collapsed && "flex justify-center"), children: renderNode(contextSwitcher, collapsed) }),
|
|
2734
|
+
/* @__PURE__ */ jsx22("div", { className: "space-y-0.5", children: navItems.map((item) => {
|
|
2245
2735
|
const Icon = item.icon;
|
|
2246
2736
|
const active = Boolean(item.active);
|
|
2247
|
-
const link = /* @__PURE__ */
|
|
2737
|
+
const link = /* @__PURE__ */ jsxs18(
|
|
2248
2738
|
Link2,
|
|
2249
2739
|
{
|
|
2250
2740
|
href: item.href,
|
|
@@ -2257,7 +2747,7 @@ function SuiteSidebar({
|
|
|
2257
2747
|
collapsed ? "mx-auto size-10 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
2258
2748
|
),
|
|
2259
2749
|
children: [
|
|
2260
|
-
/* @__PURE__ */
|
|
2750
|
+
/* @__PURE__ */ jsx22(
|
|
2261
2751
|
"span",
|
|
2262
2752
|
{
|
|
2263
2753
|
className: cn(
|
|
@@ -2265,7 +2755,7 @@ function SuiteSidebar({
|
|
|
2265
2755
|
item.iconClassName
|
|
2266
2756
|
),
|
|
2267
2757
|
"aria-hidden": true,
|
|
2268
|
-
children: /* @__PURE__ */
|
|
2758
|
+
children: /* @__PURE__ */ jsx22(
|
|
2269
2759
|
Icon,
|
|
2270
2760
|
{
|
|
2271
2761
|
className: "h-full w-full",
|
|
@@ -2274,7 +2764,7 @@ function SuiteSidebar({
|
|
|
2274
2764
|
)
|
|
2275
2765
|
}
|
|
2276
2766
|
),
|
|
2277
|
-
/* @__PURE__ */
|
|
2767
|
+
/* @__PURE__ */ jsx22(
|
|
2278
2768
|
"span",
|
|
2279
2769
|
{
|
|
2280
2770
|
className: cn(
|
|
@@ -2285,17 +2775,17 @@ function SuiteSidebar({
|
|
|
2285
2775
|
children: item.label
|
|
2286
2776
|
}
|
|
2287
2777
|
),
|
|
2288
|
-
!collapsed && item.badge ? /* @__PURE__ */
|
|
2778
|
+
!collapsed && item.badge ? /* @__PURE__ */ jsx22("span", { className: "relative ml-auto shrink-0", children: item.badge }) : null
|
|
2289
2779
|
]
|
|
2290
2780
|
},
|
|
2291
2781
|
item.label
|
|
2292
2782
|
);
|
|
2293
|
-
return collapsed ? /* @__PURE__ */
|
|
2783
|
+
return collapsed ? /* @__PURE__ */ jsx22(Tooltip, { content: item.label, side: "right", children: link }, item.label) : link;
|
|
2294
2784
|
}) })
|
|
2295
2785
|
]
|
|
2296
2786
|
}
|
|
2297
2787
|
),
|
|
2298
|
-
secondaryNav ? /* @__PURE__ */
|
|
2788
|
+
secondaryNav ? /* @__PURE__ */ jsx22(
|
|
2299
2789
|
"div",
|
|
2300
2790
|
{
|
|
2301
2791
|
className: "min-h-0 flex-1",
|
|
@@ -2306,7 +2796,7 @@ function SuiteSidebar({
|
|
|
2306
2796
|
]
|
|
2307
2797
|
}
|
|
2308
2798
|
),
|
|
2309
|
-
/* @__PURE__ */
|
|
2799
|
+
/* @__PURE__ */ jsx22(
|
|
2310
2800
|
"div",
|
|
2311
2801
|
{
|
|
2312
2802
|
className: cn(
|
|
@@ -2314,7 +2804,7 @@ function SuiteSidebar({
|
|
|
2314
2804
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
2315
2805
|
collapsed ? "p-1.5" : "p-3"
|
|
2316
2806
|
),
|
|
2317
|
-
children: /* @__PURE__ */
|
|
2807
|
+
children: /* @__PURE__ */ jsxs18(
|
|
2318
2808
|
"div",
|
|
2319
2809
|
{
|
|
2320
2810
|
className: cn(
|
|
@@ -2323,7 +2813,7 @@ function SuiteSidebar({
|
|
|
2323
2813
|
),
|
|
2324
2814
|
children: [
|
|
2325
2815
|
renderNode(userMenu, collapsed),
|
|
2326
|
-
!collapsed && footerExtras ? /* @__PURE__ */
|
|
2816
|
+
!collapsed && footerExtras ? /* @__PURE__ */ jsx22("div", { className: "ml-auto shrink-0", children: renderNode(footerExtras, collapsed) }) : null
|
|
2327
2817
|
]
|
|
2328
2818
|
}
|
|
2329
2819
|
)
|
|
@@ -2335,7 +2825,7 @@ function SuiteSidebar({
|
|
|
2335
2825
|
}
|
|
2336
2826
|
|
|
2337
2827
|
// src/suite/components/suite-app-layout.tsx
|
|
2338
|
-
import { jsx as
|
|
2828
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2339
2829
|
function SuiteAppLayout({
|
|
2340
2830
|
sidebar,
|
|
2341
2831
|
children,
|
|
@@ -2343,41 +2833,59 @@ function SuiteAppLayout({
|
|
|
2343
2833
|
bottomNav,
|
|
2344
2834
|
sidebarWidth = 240,
|
|
2345
2835
|
collapsed = false,
|
|
2836
|
+
lockMainScroll = false,
|
|
2346
2837
|
onStartResize,
|
|
2347
2838
|
onResetWidth,
|
|
2348
2839
|
className
|
|
2349
2840
|
}) {
|
|
2350
|
-
return /* @__PURE__ */
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2841
|
+
return /* @__PURE__ */ jsxs19(
|
|
2842
|
+
"div",
|
|
2843
|
+
{
|
|
2844
|
+
"data-test": "app-shell",
|
|
2845
|
+
className: cn("flex min-h-dvh lg:h-screen lg:overflow-hidden", className),
|
|
2846
|
+
children: [
|
|
2847
|
+
/* @__PURE__ */ jsxs19(
|
|
2848
|
+
"aside",
|
|
2849
|
+
{
|
|
2850
|
+
className: "relative hidden shrink-0 flex-col overflow-hidden border-r border-ph-border transition-[width] duration-200 ease-out lg:flex",
|
|
2851
|
+
style: { width: `${sidebarWidth}px` },
|
|
2852
|
+
"data-collapsed": collapsed ? "true" : "false",
|
|
2853
|
+
children: [
|
|
2854
|
+
sidebar,
|
|
2855
|
+
onStartResize ? /* @__PURE__ */ jsx23(
|
|
2856
|
+
"div",
|
|
2857
|
+
{
|
|
2858
|
+
role: "separator",
|
|
2859
|
+
"aria-orientation": "vertical",
|
|
2860
|
+
"aria-label": "Resize sidebar",
|
|
2861
|
+
onPointerDown: onStartResize,
|
|
2862
|
+
onDoubleClick: onResetWidth,
|
|
2863
|
+
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)]"
|
|
2864
|
+
}
|
|
2865
|
+
) : null
|
|
2866
|
+
]
|
|
2867
|
+
}
|
|
2868
|
+
),
|
|
2869
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: [
|
|
2870
|
+
mobileHeader ? /* @__PURE__ */ jsx23("div", { className: "shrink-0 lg:hidden", children: mobileHeader }) : null,
|
|
2871
|
+
/* @__PURE__ */ jsx23(
|
|
2872
|
+
"main",
|
|
2873
|
+
{
|
|
2874
|
+
id: "main-content",
|
|
2875
|
+
tabIndex: -1,
|
|
2876
|
+
"data-lock-scroll": lockMainScroll ? "true" : void 0,
|
|
2877
|
+
className: cn(
|
|
2878
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
2879
|
+
lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
|
|
2880
|
+
),
|
|
2881
|
+
children
|
|
2882
|
+
}
|
|
2883
|
+
),
|
|
2884
|
+
bottomNav ? /* @__PURE__ */ jsx23("div", { className: "shrink-0 lg:hidden", children: bottomNav }) : null
|
|
2885
|
+
] })
|
|
2886
|
+
]
|
|
2887
|
+
}
|
|
2888
|
+
);
|
|
2381
2889
|
}
|
|
2382
2890
|
export {
|
|
2383
2891
|
APP_ACCENTS,
|
|
@@ -2389,10 +2897,16 @@ export {
|
|
|
2389
2897
|
AppSwitcherMark,
|
|
2390
2898
|
CommandPaletteHost,
|
|
2391
2899
|
DeferredChrome,
|
|
2900
|
+
SIDEBAR_COLLAPSE_THRESHOLD,
|
|
2901
|
+
SIDEBAR_DEFAULT_WIDTH,
|
|
2902
|
+
SIDEBAR_MAX_WIDTH,
|
|
2903
|
+
SIDEBAR_MIN_EXPANDED_WIDTH,
|
|
2904
|
+
SIDEBAR_RAIL_WIDTH,
|
|
2392
2905
|
SUITE_APPS2 as SUITE_APPS,
|
|
2393
2906
|
SUITE_APP_MAP,
|
|
2394
2907
|
SUITE_GLYPHS,
|
|
2395
2908
|
SUITE_ICON_NAMES,
|
|
2909
|
+
SUITE_OPEN_ASK_AI_EVENT,
|
|
2396
2910
|
SUITE_SPRINGS,
|
|
2397
2911
|
SourceAppGlyph,
|
|
2398
2912
|
SuiteAiPanel,
|
|
@@ -2410,6 +2924,7 @@ export {
|
|
|
2410
2924
|
SuitePage,
|
|
2411
2925
|
SuitePageHeader,
|
|
2412
2926
|
SuiteSectionHeader,
|
|
2927
|
+
SuiteSettingsLayout,
|
|
2413
2928
|
SuiteSettingsMobileNav,
|
|
2414
2929
|
SuiteSidebar,
|
|
2415
2930
|
SuiteSkeleton,
|
|
@@ -2419,11 +2934,15 @@ export {
|
|
|
2419
2934
|
SuiteThemeProvider,
|
|
2420
2935
|
SuiteToolbar,
|
|
2421
2936
|
SuiteUserMenu,
|
|
2937
|
+
TodayAskAiCard,
|
|
2422
2938
|
TodayCalibrating,
|
|
2939
|
+
TodayEmptyAction,
|
|
2423
2940
|
TodayEmptyState,
|
|
2424
2941
|
TodayHero,
|
|
2942
|
+
TodayLayout,
|
|
2425
2943
|
TodayPageFrame,
|
|
2426
2944
|
TodayPanel,
|
|
2945
|
+
TodayPrimaryAction,
|
|
2427
2946
|
TodaySection,
|
|
2428
2947
|
TodayTimeIcon,
|
|
2429
2948
|
TodayTopBar,
|
|
@@ -2433,9 +2952,12 @@ export {
|
|
|
2433
2952
|
cn,
|
|
2434
2953
|
getTodayGreeting,
|
|
2435
2954
|
m,
|
|
2955
|
+
openSuiteAskAi,
|
|
2956
|
+
resolveSuiteNotificationHref,
|
|
2436
2957
|
sourceToSuiteApp,
|
|
2437
2958
|
suiteAppBaseUrl,
|
|
2438
2959
|
suiteAppLabel,
|
|
2439
2960
|
useIdleMount,
|
|
2961
|
+
useSidebarWidth,
|
|
2440
2962
|
useSuiteTheme
|
|
2441
2963
|
};
|