@xenide-io/the-old-ui-theme 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -10
- package/dist/{Chip-Cq3AiAji.d.mts → Chip-BzuNgJIa.d.mts} +81 -23
- package/dist/{Chip-Cq3AiAji.d.ts → Chip-BzuNgJIa.d.ts} +81 -23
- package/dist/{ai-message-blocknote-WABTHFY7.mjs → ai-message-blocknote-D4Z6DUCJ.mjs} +9 -3
- package/dist/{chunk-YB4TBWHV.mjs → chunk-2EO5VCXP.mjs} +688 -388
- package/dist/chunk-APKRZQRO.mjs +251 -0
- package/dist/chunk-BS7BZI5W.mjs +19 -0
- package/dist/chunk-IULORI3A.mjs +8 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +997 -576
- package/dist/index.mjs +7 -1
- package/dist/suite.d.mts +136 -57
- package/dist/suite.d.ts +136 -57
- package/dist/suite.js +3115 -882
- package/dist/suite.mjs +2566 -661
- package/dist/theme-boot-P-oqKVZF.d.mts +74 -0
- package/dist/theme-boot-P-oqKVZF.d.ts +74 -0
- package/dist/theme-boot.d.mts +2 -0
- package/dist/theme-boot.d.ts +2 -0
- package/dist/theme-boot.js +44 -0
- package/dist/theme-boot.mjs +8 -0
- package/dist/ui.d.mts +5 -29
- package/dist/ui.d.ts +5 -29
- package/dist/ui.js +647 -352
- package/dist/ui.mjs +1 -1
- package/docs/README.md +34 -0
- package/docs/ai-quick-reference.md +56 -0
- package/docs/component-library-improvement-plan.md +751 -0
- package/docs/component-reference.md +81 -0
- package/docs/components.md +48 -0
- package/docs/demos.md +19 -0
- package/docs/installation.md +117 -0
- package/docs/suite-audit.md +34 -0
- package/docs/theme-token-reference.md +67 -0
- package/docs/themes.md +164 -0
- package/package.json +22 -21
- package/public/fonts/OpenRunde-Bold.woff2 +0 -0
- package/public/fonts/OpenRunde-Medium.woff2 +0 -0
- package/public/fonts/OpenRunde-Regular.woff2 +0 -0
- package/public/fonts/OpenRunde-Semibold.woff2 +0 -0
- package/scripts/package-smoke.mjs +43 -0
- package/src/app/globals.css +2 -1
- package/src/components/ui/Accordion.tsx +20 -6
- package/src/components/ui/Avatar.tsx +5 -3
- package/src/components/ui/Calendar.tsx +187 -63
- package/src/components/ui/Card.test.tsx +38 -0
- package/src/components/ui/Card.tsx +77 -14
- package/src/components/ui/CollapsibleSection.tsx +12 -4
- package/src/components/ui/CommandPalette.test.tsx +91 -4
- package/src/components/ui/CommandPalette.tsx +138 -128
- package/src/components/ui/EmptyState.tsx +2 -2
- package/src/components/ui/FormField.tsx +1 -1
- package/src/components/ui/Input.tsx +42 -18
- package/src/components/ui/Kbd.tsx +18 -3
- package/src/components/ui/Modal.tsx +3 -1
- package/src/components/ui/Progress.tsx +14 -5
- package/src/components/ui/SegmentedControl.tsx +2 -2
- package/src/components/ui/SettingsLayout.tsx +1 -1
- package/src/components/ui/Stat.tsx +3 -2
- package/src/components/ui/Table.tsx +8 -3
- package/src/components/ui/Tooltip.test.tsx +70 -1
- package/src/components/ui/Tooltip.tsx +53 -29
- package/src/components/ui/Typography.tsx +103 -49
- package/src/components/ui/avatar-stat.test.tsx +23 -0
- package/src/components/ui/calendar.test.tsx +88 -0
- package/src/components/ui/disclosure.test.tsx +39 -0
- package/src/components/ui/index.ts +44 -6
- package/src/components/ui/progress.test.tsx +15 -0
- package/src/components/ui/typography.test.tsx +26 -1
- package/src/styles/suite-skin.css +8 -2
- package/src/styles/themes.css +184 -68
- package/src/suite/components/ai-message-blocknote.tsx +13 -2
- package/src/suite/components/ai-panel.tsx +41 -10
- package/src/suite/components/app-switcher.test.tsx +21 -6
- package/src/suite/components/app-switcher.tsx +7 -11
- package/src/suite/components/suite-app-layout.tsx +12 -3
- package/src/suite/components/suite-bottom-nav.tsx +0 -1
- package/src/suite/components/suite-clients-projects-directory.test.tsx +71 -0
- package/src/suite/components/suite-clients-projects-directory.tsx +943 -0
- package/src/suite/components/suite-integration-picker.test.tsx +224 -0
- package/src/suite/components/suite-integration-picker.tsx +889 -18
- package/src/suite/components/suite-integration-rules.test.tsx +157 -0
- package/src/suite/components/suite-integration-rules.tsx +471 -0
- package/src/suite/components/suite-mobile-drawer.test.tsx +18 -2
- package/src/suite/components/suite-mobile-drawer.tsx +65 -98
- package/src/suite/components/suite-notification-bell.tsx +29 -4
- package/src/suite/components/suite-sidebar.tsx +25 -25
- package/src/suite/components/suite-skeleton.tsx +2 -2
- package/src/suite/components/suite-user-menu.tsx +9 -8
- package/src/suite/components/theme-provider.test.tsx +87 -3
- package/src/suite/components/theme-provider.tsx +144 -23
- package/src/suite/components/today-ui.tsx +79 -68
- package/src/suite/components/workspace-switcher.test.tsx +56 -0
- package/src/suite/components/workspace-switcher.tsx +3 -3
- package/src/suite/icons/app-accents.ts +12 -12
- package/src/suite/icons/glyphs.ts +6 -12
- package/src/suite/index.ts +22 -0
- package/src/suite/lib/apps.test.ts +9 -1
- package/src/suite/lib/apps.ts +14 -8
- package/src/suite/lib/cookies.ts +53 -0
- package/src/suite/lib/theme-boot.ts +32 -0
- package/src/suite/lib/theme-cookie.ts +7 -0
- package/src/suite/lib/use-sidebar-width.ts +5 -51
- package/dist/chunk-NOI42JNZ.mjs +0 -151
- package/src/suite/lib/use-lock-mobile-page-zoom.test.tsx +0 -65
- package/src/suite/lib/use-lock-mobile-page-zoom.ts +0 -51
package/dist/suite.mjs
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Alert,
|
|
3
|
+
Badge,
|
|
2
4
|
Button,
|
|
5
|
+
Card,
|
|
3
6
|
DropdownItem,
|
|
4
7
|
DropdownMenu,
|
|
8
|
+
FileUpload,
|
|
5
9
|
Input,
|
|
6
10
|
Modal,
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
Select,
|
|
12
|
+
Toggle,
|
|
13
|
+
Tooltip,
|
|
14
|
+
cn
|
|
15
|
+
} from "./chunk-2EO5VCXP.mjs";
|
|
16
|
+
import {
|
|
17
|
+
suiteThemeBootScript
|
|
18
|
+
} from "./chunk-BS7BZI5W.mjs";
|
|
9
19
|
import {
|
|
10
20
|
SuiteThemeProvider,
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
clearCookie,
|
|
22
|
+
readCookie,
|
|
23
|
+
useSuiteTheme,
|
|
24
|
+
writeCookie
|
|
25
|
+
} from "./chunk-APKRZQRO.mjs";
|
|
26
|
+
import {
|
|
27
|
+
SUITE_THEME_COOKIE
|
|
28
|
+
} from "./chunk-IULORI3A.mjs";
|
|
13
29
|
import {
|
|
14
30
|
__spreadProps,
|
|
15
31
|
__spreadValues
|
|
@@ -59,7 +75,7 @@ import { Refresh as RefreshCw } from "iconoir-react";
|
|
|
59
75
|
// src/suite/lib/cn.ts
|
|
60
76
|
import { clsx } from "clsx";
|
|
61
77
|
import { twMerge } from "tailwind-merge";
|
|
62
|
-
function
|
|
78
|
+
function cn2(...inputs) {
|
|
63
79
|
return twMerge(clsx(inputs));
|
|
64
80
|
}
|
|
65
81
|
|
|
@@ -88,10 +104,10 @@ var APP_ACCENTS = {
|
|
|
88
104
|
},
|
|
89
105
|
shellstack: {
|
|
90
106
|
label: "ShellStack",
|
|
91
|
-
accent: "#
|
|
92
|
-
tile: "#
|
|
93
|
-
onTile: "#
|
|
94
|
-
onTileAccent: "#
|
|
107
|
+
accent: "#0078D4",
|
|
108
|
+
tile: "#FFFFFF",
|
|
109
|
+
onTile: "#111114",
|
|
110
|
+
onTileAccent: "#0078D4"
|
|
95
111
|
},
|
|
96
112
|
crew: {
|
|
97
113
|
label: "Crew",
|
|
@@ -100,12 +116,12 @@ var APP_ACCENTS = {
|
|
|
100
116
|
onTile: "#ffffff",
|
|
101
117
|
onTileAccent: "#a5f3fc"
|
|
102
118
|
},
|
|
103
|
-
|
|
104
|
-
label: "
|
|
105
|
-
accent: "#
|
|
106
|
-
tile: "#
|
|
107
|
-
onTile: "#
|
|
108
|
-
onTileAccent: "#
|
|
119
|
+
shelly: {
|
|
120
|
+
label: "Shelly",
|
|
121
|
+
accent: "#0078D4",
|
|
122
|
+
tile: "#1B1B1F",
|
|
123
|
+
onTile: "#ECECF1",
|
|
124
|
+
onTileAccent: "#00BCF2"
|
|
109
125
|
}
|
|
110
126
|
};
|
|
111
127
|
var APP_GLYPHS = {
|
|
@@ -114,7 +130,7 @@ var APP_GLYPHS = {
|
|
|
114
130
|
kraken: "squid-doc",
|
|
115
131
|
shellstack: "stack-hex",
|
|
116
132
|
crew: "crew-bot",
|
|
117
|
-
|
|
133
|
+
shelly: "shelly-snail"
|
|
118
134
|
};
|
|
119
135
|
|
|
120
136
|
// src/suite/icons/glyph-parts.tsx
|
|
@@ -237,22 +253,15 @@ var SUITE_GLYPHS = {
|
|
|
237
253
|
{ kind: "path", d: "M9.6 14.6q2.4 1.7 4.8 0", accent: true }
|
|
238
254
|
]
|
|
239
255
|
},
|
|
240
|
-
"
|
|
241
|
-
description: "
|
|
256
|
+
"shelly-snail": {
|
|
257
|
+
description: "Shelly \u2014 smiling snail with spiral shell and ball-tipped antennae",
|
|
242
258
|
elements: [
|
|
243
259
|
{
|
|
244
260
|
kind: "path",
|
|
245
|
-
d: "
|
|
261
|
+
d: "M2931 37263 c-1542 -737 -1730 -2870 -339 -3838 427 -297 339 1 1730 -5802 102 -425 101 -430 -391 -950 -1003 -1062 -1175 -1507 -1834 -4748 -1525 -7505 -1398 -10142 668 -13875 2061 -3724 4835 -5715 9185 -6592 2869 -579 4928 -582 8750 -15 1293 192 3408 506 4700 697 6839 1012 8768 1422 9385 1993 1103 1021 425 2357 -1733 3414 l-944 462 916 620 c5469 3705 5358 13657 -209 18536 -2592 2272 -5133 3185 -8865 3185 -3361 0 -5965 -948 -8226 -2994 -501 -453 -824 -546 -824 -235 0 70 301 1416 668 2991 668 2863 668 2863 1053 3101 1156 713 1317 2506 305 3395 -1583 1390 -3787 234 -3592 -1885 61 -673 61 -673 -1165 -3013 l-1227 -2340 -1303 -10 -1303 -10 -1267 2463 c-1202 2337 -1261 2480 -1155 2784 610 1750 -1309 3465 -2983 2666z m1743 -1216 c309 -354 379 -713 232 -1191 -205 -669 -183 -731 1300 -3583 1821 -3503 1488 -3127 2631 -2970 816 112 1053 109 1729 -25 587 -117 813 -127 901 -42 64 63 778 1394 1586 2958 1470 2844 1470 2844 1345 3365 -208 868 106 1458 852 1598 1380 258 1829 -1605 545 -2260 -501 -255 -427 -36 -1292 -3813 l-725 -3166 513 -617 c1210 -1453 1328 -2014 1709 -8068 224 -3562 368 -4603 790 -5688 820 -2113 2775 -3739 5643 -4695 2847 -948 5589 -1186 7567 -654 l850 228 1070 -471 c2352 -1034 2946 -1824 1719 -2288 -1707 -647 -14950 -2665 -17489 -2665 -5500 0 -9506 1872 -11922 5573 -2564 3926 -2753 6473 -1075 14490 542 2586 754 3104 1682 4102 778 837 757 677 322 2415 -188 754 -529 2180 -757 3170 -228 990 -436 1878 -463 1973 -27 95 -246 260 -486 366 -685 303 -961 1115 -610 1795 335 647 1332 736 1833 163z m21523 -6801 c6385 -1036 10732 -7090 9753 -13583 -628 -4167 -2948 -6812 -6688 -7626 -6108 -1329 -10963 4878 -8256 10556 1608 3373 6202 4320 8566 1766 2055 -2219 1699 -6037 -662 -7096 -2082 -935 -4058 98 -4184 2187 -93 1553 1143 2685 2287 2093 607 -313 709 -1340 148 -1481 -564 -142 -462 -962 120 -962 1033 2 1610 1420 1015 2496 -814 1471 -2971 1452 -3972 -37 -1601 -2380 159 -5650 3046 -5658 2778 -8 4680 2269 4503 5390 -265 4668 -5206 7028 -9332 4457 -3911 -2438 -4439 -8515 -1057 -12167 l561 -607 -647 327 c-2556 1290 -3718 2796 -4088 5301 -61 411 -201 2166 -311 3898 -312 4898 -436 5802 -952 6962 l-261 588 532 493 c1419 1314 3729 2427 5782 2786 639 112 3218 59 4097 -83z M5574 23846 c-476 -475 -431 -1229 97 -1644 835 -658 1687 739 970 1590 -326 388 -715 407 -1067 54z M12075 23992 c-669 -390 -584 -1598 134 -1896 608 -252 1135 289 1057 1085 -72 728 -654 1124 -1191 811z M7801 22451 c-626 -754 1585 -1648 2460 -995 485 362 676 688 546 932 -155 288 -335 267 -719 -84 -549 -502 -1237 -469 -1728 82 -224 251 -389 271 -559 65z",
|
|
246
262
|
filled: true,
|
|
247
|
-
transform: "translate(
|
|
248
|
-
}
|
|
249
|
-
{ kind: "path", d: "M7 18h3.5M12.2 18h3M8.5 19.5h6", accent: true },
|
|
250
|
-
{
|
|
251
|
-
kind: "path",
|
|
252
|
-
d: "M4.8 5.8h2.7M4.8 7.4h1.4M18.5 17.1h1.7",
|
|
253
|
-
accent: true
|
|
254
|
-
},
|
|
255
|
-
{ kind: "circle", cx: 18.5, cy: 4.5, r: 0.8, accent: true, filled: true }
|
|
263
|
+
transform: "translate(0.88 22.8) scale(0.0005714 -0.0005714)"
|
|
264
|
+
}
|
|
256
265
|
]
|
|
257
266
|
},
|
|
258
267
|
workspace: {
|
|
@@ -366,7 +375,7 @@ function SuiteAppIcon({
|
|
|
366
375
|
width: px,
|
|
367
376
|
height: px,
|
|
368
377
|
viewBox: "0 0 24 24",
|
|
369
|
-
className:
|
|
378
|
+
className: cn2("shrink-0", className),
|
|
370
379
|
style,
|
|
371
380
|
role: label ? "img" : void 0,
|
|
372
381
|
"aria-label": label,
|
|
@@ -394,104 +403,55 @@ function SuiteAppIcon({
|
|
|
394
403
|
);
|
|
395
404
|
}
|
|
396
405
|
|
|
397
|
-
// src/suite/icons/suite-icon.tsx
|
|
398
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
399
|
-
var TODAY_SUN_STYLE = `
|
|
400
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
401
|
-
.suite-icon-today-sun-rays {
|
|
402
|
-
animation: suite-icon-today-sun-spin 18s linear infinite;
|
|
403
|
-
transform-box: fill-box;
|
|
404
|
-
transform-origin: center;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
@keyframes suite-icon-today-sun-spin {
|
|
408
|
-
to { transform: rotate(360deg); }
|
|
409
|
-
}
|
|
410
|
-
`;
|
|
411
|
-
function SuiteIcon({
|
|
412
|
-
name,
|
|
413
|
-
size = 24,
|
|
414
|
-
accent,
|
|
415
|
-
strokeWidth = 2,
|
|
416
|
-
animated = true,
|
|
417
|
-
label,
|
|
418
|
-
className,
|
|
419
|
-
style
|
|
420
|
-
}) {
|
|
421
|
-
const glyph = SUITE_GLYPHS[name];
|
|
422
|
-
const accentHex = accent ? APP_ACCENTS[accent].accent : void 0;
|
|
423
|
-
const mergedStyle = accentHex ? __spreadProps(__spreadValues({}, style), { "--suite-icon-accent": accentHex }) : style;
|
|
424
|
-
return /* @__PURE__ */ jsxs4(
|
|
425
|
-
"svg",
|
|
426
|
-
{
|
|
427
|
-
width: size,
|
|
428
|
-
height: size,
|
|
429
|
-
viewBox: "0 0 24 24",
|
|
430
|
-
fill: "none",
|
|
431
|
-
stroke: "currentColor",
|
|
432
|
-
strokeWidth,
|
|
433
|
-
strokeLinecap: "round",
|
|
434
|
-
strokeLinejoin: "round",
|
|
435
|
-
className: cn("shrink-0", className),
|
|
436
|
-
style: mergedStyle,
|
|
437
|
-
role: label ? "img" : void 0,
|
|
438
|
-
"aria-label": label,
|
|
439
|
-
"aria-hidden": label ? void 0 : true,
|
|
440
|
-
children: [
|
|
441
|
-
glyph.animatedAccent && animated ? /* @__PURE__ */ jsx4("style", { children: TODAY_SUN_STYLE }) : null,
|
|
442
|
-
/* @__PURE__ */ jsx4(
|
|
443
|
-
GlyphParts,
|
|
444
|
-
{
|
|
445
|
-
elements: glyph.elements,
|
|
446
|
-
accentClassName: glyph.animatedAccent && animated ? "suite-icon-today-sun-rays" : void 0
|
|
447
|
-
}
|
|
448
|
-
)
|
|
449
|
-
]
|
|
450
|
-
}
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
406
|
// src/suite/components/today-ui.tsx
|
|
455
|
-
import { Fragment as Fragment2, jsx as
|
|
407
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
456
408
|
var APP_META = {
|
|
457
409
|
shellstack: { name: "ShellStack" },
|
|
458
410
|
tides: { name: "Tides" },
|
|
459
411
|
turtletime: { name: "TurtleTime" },
|
|
460
|
-
kraken: { name: "Kraken" }
|
|
412
|
+
kraken: { name: "Kraken" },
|
|
413
|
+
shelly: { name: "Shelly" }
|
|
461
414
|
};
|
|
462
415
|
var SUITE_APPS = [
|
|
463
416
|
"shellstack",
|
|
464
417
|
"tides",
|
|
465
418
|
"turtletime",
|
|
466
|
-
"kraken"
|
|
419
|
+
"kraken",
|
|
420
|
+
"shelly"
|
|
467
421
|
];
|
|
468
422
|
function sourceToSuiteApp(source) {
|
|
469
|
-
|
|
470
|
-
|
|
423
|
+
const normalised = source.trim().toLowerCase();
|
|
424
|
+
if (normalised === "tides" || normalised === "turtletime" || normalised === "kraken" || normalised === "shelly") {
|
|
425
|
+
return normalised;
|
|
471
426
|
}
|
|
472
427
|
return "shellstack";
|
|
473
428
|
}
|
|
474
429
|
function suiteAppLabel(source) {
|
|
475
430
|
return APP_META[sourceToSuiteApp(source)].name;
|
|
476
431
|
}
|
|
477
|
-
var
|
|
478
|
-
shellstack: "
|
|
479
|
-
tides: "
|
|
480
|
-
turtletime: "
|
|
481
|
-
kraken: "
|
|
432
|
+
var SOURCE_APP_LOGOS = {
|
|
433
|
+
shellstack: "/icon-shellstack.svg",
|
|
434
|
+
tides: "/tides-icon.svg",
|
|
435
|
+
turtletime: "/turtletime-icon.svg",
|
|
436
|
+
kraken: "/kraken-icon.svg",
|
|
437
|
+
shelly: "/shelly-icon.svg"
|
|
482
438
|
};
|
|
483
439
|
function SourceAppGlyph({
|
|
484
440
|
source,
|
|
485
441
|
className
|
|
486
442
|
}) {
|
|
487
443
|
const app = sourceToSuiteApp(source);
|
|
488
|
-
return
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
444
|
+
return (
|
|
445
|
+
// These assets are copied into each product's public directory.
|
|
446
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
447
|
+
/* @__PURE__ */ jsx4(
|
|
448
|
+
"img",
|
|
449
|
+
{
|
|
450
|
+
src: SOURCE_APP_LOGOS[app],
|
|
451
|
+
alt: "",
|
|
452
|
+
className: cn2("h-7 w-7 shrink-0 rounded-lg object-contain", className)
|
|
453
|
+
}
|
|
454
|
+
)
|
|
495
455
|
);
|
|
496
456
|
}
|
|
497
457
|
function formatLongDate(date = /* @__PURE__ */ new Date()) {
|
|
@@ -504,23 +464,23 @@ function SuiteAppStrip({
|
|
|
504
464
|
className,
|
|
505
465
|
icons
|
|
506
466
|
}) {
|
|
507
|
-
return /* @__PURE__ */
|
|
467
|
+
return /* @__PURE__ */ jsx4(
|
|
508
468
|
"div",
|
|
509
469
|
{
|
|
510
|
-
className:
|
|
470
|
+
className: cn2(
|
|
511
471
|
"flex flex-wrap items-center justify-center gap-2.5",
|
|
512
472
|
className
|
|
513
473
|
),
|
|
514
474
|
"aria-label": "ShellStack suite apps",
|
|
515
475
|
children: SUITE_APPS.map((app) => {
|
|
516
476
|
var _a;
|
|
517
|
-
return /* @__PURE__ */
|
|
477
|
+
return /* @__PURE__ */ jsxs4(
|
|
518
478
|
"div",
|
|
519
479
|
{
|
|
520
480
|
className: "flex items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-2.5 py-1.5 shadow-sm",
|
|
521
481
|
children: [
|
|
522
|
-
(_a = icons == null ? void 0 : icons[app]) != null ? _a : /* @__PURE__ */
|
|
523
|
-
/* @__PURE__ */
|
|
482
|
+
(_a = icons == null ? void 0 : icons[app]) != null ? _a : /* @__PURE__ */ jsx4(SuiteAppIcon, { app, size: "sm" }),
|
|
483
|
+
/* @__PURE__ */ jsx4("span", { className: "text-xs font-medium text-ph-subtle", children: APP_META[app].name })
|
|
524
484
|
]
|
|
525
485
|
},
|
|
526
486
|
app
|
|
@@ -530,7 +490,7 @@ function SuiteAppStrip({
|
|
|
530
490
|
);
|
|
531
491
|
}
|
|
532
492
|
function AnimatedSun({ className }) {
|
|
533
|
-
return /* @__PURE__ */
|
|
493
|
+
return /* @__PURE__ */ jsxs4(
|
|
534
494
|
"svg",
|
|
535
495
|
{
|
|
536
496
|
width: "40",
|
|
@@ -538,14 +498,14 @@ function AnimatedSun({ className }) {
|
|
|
538
498
|
viewBox: "0 0 40 40",
|
|
539
499
|
fill: "none",
|
|
540
500
|
xmlns: "http://www.w3.org/2000/svg",
|
|
541
|
-
className:
|
|
501
|
+
className: cn2(className),
|
|
542
502
|
"aria-hidden": "true",
|
|
543
503
|
children: [
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
504
|
+
/* @__PURE__ */ jsx4("defs", { children: /* @__PURE__ */ jsxs4("linearGradient", { id: "animatedSunCenter", x1: "0", y1: "0", x2: "40", y2: "40", children: [
|
|
505
|
+
/* @__PURE__ */ jsx4("stop", { stopColor: "#f59e0b" }),
|
|
506
|
+
/* @__PURE__ */ jsx4("stop", { offset: "1", stopColor: "#fb923c" })
|
|
547
507
|
] }) }),
|
|
548
|
-
/* @__PURE__ */
|
|
508
|
+
/* @__PURE__ */ jsx4("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__ */ jsx4(
|
|
549
509
|
"line",
|
|
550
510
|
{
|
|
551
511
|
x1: "20",
|
|
@@ -559,13 +519,13 @@ function AnimatedSun({ className }) {
|
|
|
559
519
|
},
|
|
560
520
|
angle
|
|
561
521
|
)) }),
|
|
562
|
-
/* @__PURE__ */
|
|
522
|
+
/* @__PURE__ */ jsx4("circle", { cx: "20", cy: "20", r: "9", fill: "url(#animatedSunCenter)" })
|
|
563
523
|
]
|
|
564
524
|
}
|
|
565
525
|
);
|
|
566
526
|
}
|
|
567
527
|
function AnimatedMoon({ className }) {
|
|
568
|
-
return /* @__PURE__ */
|
|
528
|
+
return /* @__PURE__ */ jsxs4(
|
|
569
529
|
"svg",
|
|
570
530
|
{
|
|
571
531
|
width: "40",
|
|
@@ -573,23 +533,23 @@ function AnimatedMoon({ className }) {
|
|
|
573
533
|
viewBox: "0 0 40 40",
|
|
574
534
|
fill: "none",
|
|
575
535
|
xmlns: "http://www.w3.org/2000/svg",
|
|
576
|
-
className:
|
|
536
|
+
className: cn2(className),
|
|
577
537
|
"aria-hidden": "true",
|
|
578
538
|
children: [
|
|
579
|
-
/* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
581
|
-
/* @__PURE__ */
|
|
539
|
+
/* @__PURE__ */ jsx4("defs", { children: /* @__PURE__ */ jsxs4("linearGradient", { id: "animatedMoonBody", x1: "0", y1: "0", x2: "40", y2: "40", children: [
|
|
540
|
+
/* @__PURE__ */ jsx4("stop", { stopColor: "#a5b4fc" }),
|
|
541
|
+
/* @__PURE__ */ jsx4("stop", { offset: "1", stopColor: "#818cf8" })
|
|
582
542
|
] }) }),
|
|
583
|
-
/* @__PURE__ */
|
|
543
|
+
/* @__PURE__ */ jsx4(
|
|
584
544
|
"path",
|
|
585
545
|
{
|
|
586
546
|
d: "M27.5 25.5A11 11 0 1 1 14.5 9.6a9 9 0 1 0 13 15.9Z",
|
|
587
547
|
fill: "url(#animatedMoonBody)"
|
|
588
548
|
}
|
|
589
549
|
),
|
|
590
|
-
/* @__PURE__ */
|
|
591
|
-
/* @__PURE__ */
|
|
592
|
-
/* @__PURE__ */
|
|
550
|
+
/* @__PURE__ */ jsxs4("g", { className: "opacity-70 motion-safe:animate-[pulse_10s_ease-in-out_infinite] motion-reduce:animate-none", children: [
|
|
551
|
+
/* @__PURE__ */ jsx4("circle", { cx: "29", cy: "10", r: "1.2", fill: "#c7d2fe" }),
|
|
552
|
+
/* @__PURE__ */ jsx4("circle", { cx: "34", cy: "16", r: "0.9", fill: "#c7d2fe" })
|
|
593
553
|
] })
|
|
594
554
|
]
|
|
595
555
|
}
|
|
@@ -598,7 +558,7 @@ function AnimatedMoon({ className }) {
|
|
|
598
558
|
function TodayTimeIcon({ className }) {
|
|
599
559
|
const hour = (/* @__PURE__ */ new Date()).getHours();
|
|
600
560
|
const isNight = hour >= 18 || hour < 6;
|
|
601
|
-
return isNight ? /* @__PURE__ */
|
|
561
|
+
return isNight ? /* @__PURE__ */ jsx4(AnimatedMoon, { className }) : /* @__PURE__ */ jsx4(AnimatedSun, { className });
|
|
602
562
|
}
|
|
603
563
|
function TodayTopBar({
|
|
604
564
|
refreshing,
|
|
@@ -607,17 +567,17 @@ function TodayTopBar({
|
|
|
607
567
|
appIcon,
|
|
608
568
|
appName
|
|
609
569
|
}) {
|
|
610
|
-
const icon = appIcon != null ? appIcon : /* @__PURE__ */
|
|
611
|
-
return /* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
/* @__PURE__ */
|
|
615
|
-
/* @__PURE__ */
|
|
616
|
-
appName ? /* @__PURE__ */
|
|
617
|
-
/* @__PURE__ */
|
|
570
|
+
const icon = appIcon != null ? appIcon : /* @__PURE__ */ jsx4(TodayTimeIcon, { className: "h-6 w-6 sm:h-7 sm:w-7 text-amber-500" });
|
|
571
|
+
return /* @__PURE__ */ jsxs4("header", { className: "flex items-center justify-between gap-4", children: [
|
|
572
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
573
|
+
/* @__PURE__ */ jsx4("div", { className: "hidden shrink-0 sm:block", "aria-hidden": "true", children: icon }),
|
|
574
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
575
|
+
/* @__PURE__ */ jsx4("h1", { className: "font-display text-[1.625rem] font-bold leading-tight tracking-tight text-ph-ink sm:text-[2.25rem]", children: "Today" }),
|
|
576
|
+
appName ? /* @__PURE__ */ jsx4("span", { className: "rounded-md bg-ph-muted px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-ph-subtle", children: appName }) : null,
|
|
577
|
+
/* @__PURE__ */ jsx4("span", { className: "text-sm text-ph-subtle", children: formatLongDate() })
|
|
618
578
|
] })
|
|
619
579
|
] }),
|
|
620
|
-
/* @__PURE__ */
|
|
580
|
+
/* @__PURE__ */ jsx4("div", { className: "flex shrink-0 items-center", children: /* @__PURE__ */ jsx4(
|
|
621
581
|
"button",
|
|
622
582
|
{
|
|
623
583
|
type: "button",
|
|
@@ -626,10 +586,10 @@ function TodayTopBar({
|
|
|
626
586
|
className: "press-subtle inline-flex h-10 w-10 items-center justify-center rounded-lg text-ph-subtle transition hover:bg-ph-surface hover:text-ph-ink disabled:opacity-50",
|
|
627
587
|
"data-test": "today-refresh",
|
|
628
588
|
"aria-label": "Refresh today",
|
|
629
|
-
children: /* @__PURE__ */
|
|
589
|
+
children: /* @__PURE__ */ jsx4(
|
|
630
590
|
RefreshCw,
|
|
631
591
|
{
|
|
632
|
-
className:
|
|
592
|
+
className: cn2("h-4 w-4", refreshing && "animate-spin"),
|
|
633
593
|
"aria-hidden": true
|
|
634
594
|
}
|
|
635
595
|
)
|
|
@@ -669,8 +629,8 @@ function TodayHero({
|
|
|
669
629
|
brief,
|
|
670
630
|
briefMeta
|
|
671
631
|
}) {
|
|
672
|
-
return /* @__PURE__ */
|
|
673
|
-
/* @__PURE__ */
|
|
632
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mt-4 sm:mt-6", children: [
|
|
633
|
+
/* @__PURE__ */ jsx4(
|
|
674
634
|
"p",
|
|
675
635
|
{
|
|
676
636
|
className: "today-hero max-w-2xl font-display text-lg font-semibold tracking-tight text-ph-ink sm:text-xl sm:leading-snug",
|
|
@@ -678,9 +638,9 @@ function TodayHero({
|
|
|
678
638
|
},
|
|
679
639
|
typeof message === "string" ? message : "hero"
|
|
680
640
|
),
|
|
681
|
-
brief ? /* @__PURE__ */
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
briefMeta ? /* @__PURE__ */
|
|
641
|
+
brief ? /* @__PURE__ */ jsxs4("div", { className: "mt-4 max-w-2xl", "data-test": "today-focus-brief", children: [
|
|
642
|
+
/* @__PURE__ */ jsx4("p", { className: "text-[15px] leading-[1.65] text-ph-ink", children: brief }),
|
|
643
|
+
briefMeta ? /* @__PURE__ */ jsx4("p", { className: "mt-1.5 text-xs text-ph-mutedtext", children: briefMeta }) : null
|
|
684
644
|
] }) : null
|
|
685
645
|
] });
|
|
686
646
|
}
|
|
@@ -696,20 +656,20 @@ function TodayPrimaryAction({
|
|
|
696
656
|
className,
|
|
697
657
|
dataTest = "today-primary-action"
|
|
698
658
|
}) {
|
|
699
|
-
const classes =
|
|
659
|
+
const classes = cn2(
|
|
700
660
|
"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",
|
|
701
661
|
`today-primary-action--${accent}`,
|
|
702
662
|
active && "today-primary-action--active",
|
|
703
663
|
loading && "pointer-events-none opacity-70",
|
|
704
664
|
className
|
|
705
665
|
);
|
|
706
|
-
const body = /* @__PURE__ */
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
709
|
-
/* @__PURE__ */
|
|
710
|
-
description ? /* @__PURE__ */
|
|
666
|
+
const body = /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
667
|
+
/* @__PURE__ */ jsx4("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 }),
|
|
668
|
+
/* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1", children: [
|
|
669
|
+
/* @__PURE__ */ jsx4("span", { className: "block text-sm font-semibold tracking-tight sm:text-base", children: label }),
|
|
670
|
+
description ? /* @__PURE__ */ jsx4("span", { className: "mt-0.5 block text-xs opacity-80 sm:text-sm", children: description }) : null
|
|
711
671
|
] }),
|
|
712
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx4(
|
|
713
673
|
"span",
|
|
714
674
|
{
|
|
715
675
|
className: "today-primary-action__chevron shrink-0 text-base opacity-60 transition group-hover:translate-x-0.5 group-hover:opacity-100",
|
|
@@ -719,7 +679,7 @@ function TodayPrimaryAction({
|
|
|
719
679
|
)
|
|
720
680
|
] });
|
|
721
681
|
if (href && !onClick) {
|
|
722
|
-
return /* @__PURE__ */
|
|
682
|
+
return /* @__PURE__ */ jsx4(
|
|
723
683
|
"a",
|
|
724
684
|
{
|
|
725
685
|
href,
|
|
@@ -730,7 +690,7 @@ function TodayPrimaryAction({
|
|
|
730
690
|
}
|
|
731
691
|
);
|
|
732
692
|
}
|
|
733
|
-
return /* @__PURE__ */
|
|
693
|
+
return /* @__PURE__ */ jsx4(
|
|
734
694
|
"button",
|
|
735
695
|
{
|
|
736
696
|
type: "button",
|
|
@@ -746,33 +706,33 @@ function TodayPrimaryAction({
|
|
|
746
706
|
function TodayEmptyAction({
|
|
747
707
|
title,
|
|
748
708
|
description,
|
|
749
|
-
actionLabel,
|
|
709
|
+
actionLabel: actionLabel2,
|
|
750
710
|
href,
|
|
751
711
|
onClick,
|
|
752
712
|
dataTest
|
|
753
713
|
}) {
|
|
754
|
-
return /* @__PURE__ */
|
|
714
|
+
return /* @__PURE__ */ jsxs4(
|
|
755
715
|
"div",
|
|
756
716
|
{
|
|
757
717
|
className: "rounded-lg border border-dashed border-ph-border/80 bg-ph-muted/30 px-4 py-4 text-center",
|
|
758
718
|
"data-test": dataTest,
|
|
759
719
|
children: [
|
|
760
|
-
/* @__PURE__ */
|
|
761
|
-
description ? /* @__PURE__ */
|
|
762
|
-
|
|
720
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm font-semibold text-ph-ink", children: title }),
|
|
721
|
+
description ? /* @__PURE__ */ jsx4("p", { className: "mx-auto mt-1 max-w-sm text-xs leading-relaxed text-ph-subtle sm:text-sm", children: description }) : null,
|
|
722
|
+
actionLabel2 && (href || onClick) ? href ? /* @__PURE__ */ jsx4(
|
|
763
723
|
"a",
|
|
764
724
|
{
|
|
765
725
|
href,
|
|
766
726
|
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
767
|
-
children:
|
|
727
|
+
children: actionLabel2
|
|
768
728
|
}
|
|
769
|
-
) : /* @__PURE__ */
|
|
729
|
+
) : /* @__PURE__ */ jsx4(
|
|
770
730
|
"button",
|
|
771
731
|
{
|
|
772
732
|
type: "button",
|
|
773
733
|
onClick,
|
|
774
734
|
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
775
|
-
children:
|
|
735
|
+
children: actionLabel2
|
|
776
736
|
}
|
|
777
737
|
) : null
|
|
778
738
|
]
|
|
@@ -785,16 +745,16 @@ function TodayLayout({
|
|
|
785
745
|
aside,
|
|
786
746
|
className
|
|
787
747
|
}) {
|
|
788
|
-
return /* @__PURE__ */
|
|
748
|
+
return /* @__PURE__ */ jsxs4(
|
|
789
749
|
"div",
|
|
790
750
|
{
|
|
791
|
-
className:
|
|
751
|
+
className: cn2("mt-5 space-y-6 sm:mt-6", className),
|
|
792
752
|
"data-test": "today-layout",
|
|
793
753
|
children: [
|
|
794
|
-
primary ? /* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
/* @__PURE__ */
|
|
797
|
-
aside ? /* @__PURE__ */
|
|
754
|
+
primary ? /* @__PURE__ */ jsx4("div", { className: "max-w-md", children: primary }) : null,
|
|
755
|
+
/* @__PURE__ */ jsxs4("div", { className: "grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(16rem,20rem)] lg:items-start lg:gap-8", children: [
|
|
756
|
+
/* @__PURE__ */ jsx4("div", { className: "min-w-0 space-y-8", children: main }),
|
|
757
|
+
aside ? /* @__PURE__ */ jsx4("aside", { className: "space-y-3 lg:sticky lg:top-6 lg:self-start", children: aside }) : null
|
|
798
758
|
] })
|
|
799
759
|
]
|
|
800
760
|
}
|
|
@@ -808,22 +768,30 @@ function TodayAskAiCard({
|
|
|
808
768
|
onClick,
|
|
809
769
|
href
|
|
810
770
|
}) {
|
|
811
|
-
const classes =
|
|
771
|
+
const classes = cn2(
|
|
812
772
|
"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",
|
|
813
773
|
className
|
|
814
774
|
);
|
|
815
|
-
const body = /* @__PURE__ */
|
|
816
|
-
/* @__PURE__ */
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
775
|
+
const body = /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
776
|
+
/* @__PURE__ */ jsx4(
|
|
777
|
+
"img",
|
|
778
|
+
{
|
|
779
|
+
src: "/shelly-icon.svg",
|
|
780
|
+
alt: "",
|
|
781
|
+
"aria-hidden": true,
|
|
782
|
+
className: "h-5 w-5 shrink-0 object-contain"
|
|
783
|
+
}
|
|
784
|
+
),
|
|
785
|
+
/* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1", children: [
|
|
786
|
+
/* @__PURE__ */ jsxs4("span", { className: "flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1", children: [
|
|
787
|
+
/* @__PURE__ */ jsx4("span", { className: "font-display text-sm font-bold tracking-tight text-ph-ink", children: title }),
|
|
788
|
+
/* @__PURE__ */ jsx4("span", { className: "text-sm font-medium text-ph-brand transition group-hover:underline", children: cta })
|
|
821
789
|
] }),
|
|
822
|
-
/* @__PURE__ */
|
|
790
|
+
/* @__PURE__ */ jsx4("span", { className: "mt-1 block text-sm leading-relaxed text-ph-subtle", children: description })
|
|
823
791
|
] })
|
|
824
792
|
] });
|
|
825
793
|
if (onClick) {
|
|
826
|
-
return /* @__PURE__ */
|
|
794
|
+
return /* @__PURE__ */ jsx4(
|
|
827
795
|
"button",
|
|
828
796
|
{
|
|
829
797
|
type: "button",
|
|
@@ -835,9 +803,9 @@ function TodayAskAiCard({
|
|
|
835
803
|
);
|
|
836
804
|
}
|
|
837
805
|
if (href) {
|
|
838
|
-
return /* @__PURE__ */
|
|
806
|
+
return /* @__PURE__ */ jsx4("a", { href, className: classes, "data-test": "today-ask-ai", children: body });
|
|
839
807
|
}
|
|
840
|
-
return /* @__PURE__ */
|
|
808
|
+
return /* @__PURE__ */ jsx4("div", { className: classes, "data-test": "today-ask-ai", children: body });
|
|
841
809
|
}
|
|
842
810
|
function TodaySection({
|
|
843
811
|
icon: Icon,
|
|
@@ -848,22 +816,22 @@ function TodaySection({
|
|
|
848
816
|
testId,
|
|
849
817
|
children
|
|
850
818
|
}) {
|
|
851
|
-
return /* @__PURE__ */
|
|
852
|
-
/* @__PURE__ */
|
|
853
|
-
/* @__PURE__ */
|
|
854
|
-
/* @__PURE__ */
|
|
819
|
+
return /* @__PURE__ */ jsxs4("section", { "data-test": testId, className: "space-y-5", children: [
|
|
820
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-start justify-between gap-4", children: [
|
|
821
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-start gap-3.5", children: [
|
|
822
|
+
/* @__PURE__ */ jsx4(
|
|
855
823
|
"span",
|
|
856
824
|
{
|
|
857
|
-
className:
|
|
825
|
+
className: cn2(
|
|
858
826
|
"inline-flex h-10 w-10 sm:h-11 sm:w-11 shrink-0 items-center justify-center rounded-2xl shadow-sm ring-1 ring-black/[0.06]",
|
|
859
827
|
iconClassName != null ? iconClassName : "bg-ph-muted text-ph-ink"
|
|
860
828
|
),
|
|
861
|
-
children: /* @__PURE__ */
|
|
829
|
+
children: /* @__PURE__ */ jsx4(Icon, { className: "h-5 w-5", "aria-hidden": true })
|
|
862
830
|
}
|
|
863
831
|
),
|
|
864
|
-
/* @__PURE__ */
|
|
865
|
-
/* @__PURE__ */
|
|
866
|
-
description ? /* @__PURE__ */
|
|
832
|
+
/* @__PURE__ */ jsxs4("div", { className: "min-w-0 pt-0.5", children: [
|
|
833
|
+
/* @__PURE__ */ jsx4("h2", { className: "font-display text-lg font-bold tracking-tight text-ph-ink", children: title }),
|
|
834
|
+
description ? /* @__PURE__ */ jsx4("p", { className: "mt-1 max-w-xl text-sm leading-relaxed text-ph-subtle", children: description }) : null
|
|
867
835
|
] })
|
|
868
836
|
] }),
|
|
869
837
|
action
|
|
@@ -875,10 +843,10 @@ function TodayPanel({
|
|
|
875
843
|
children,
|
|
876
844
|
className
|
|
877
845
|
}) {
|
|
878
|
-
return /* @__PURE__ */
|
|
846
|
+
return /* @__PURE__ */ jsx4(
|
|
879
847
|
"div",
|
|
880
848
|
{
|
|
881
|
-
className:
|
|
849
|
+
className: cn2(
|
|
882
850
|
"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",
|
|
883
851
|
className
|
|
884
852
|
),
|
|
@@ -890,41 +858,38 @@ function TodayEmptyState({
|
|
|
890
858
|
title,
|
|
891
859
|
description
|
|
892
860
|
}) {
|
|
893
|
-
return /* @__PURE__ */
|
|
894
|
-
/* @__PURE__ */
|
|
895
|
-
description ? /* @__PURE__ */
|
|
861
|
+
return /* @__PURE__ */ jsxs4("div", { className: "border-ph-border/80 rounded-xl border border-dashed px-5 py-8 text-center", children: [
|
|
862
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm font-semibold text-ph-ink", children: title }),
|
|
863
|
+
description ? /* @__PURE__ */ jsx4("p", { className: "mt-1.5 text-sm leading-relaxed text-ph-subtle", children: description }) : null
|
|
896
864
|
] });
|
|
897
865
|
}
|
|
898
866
|
|
|
899
867
|
// src/suite/components/app-switcher.tsx
|
|
900
868
|
import Image from "next/image";
|
|
901
869
|
import { useState } from "react";
|
|
902
|
-
import {
|
|
903
|
-
|
|
904
|
-
OpenNewWindow
|
|
905
|
-
} from "iconoir-react";
|
|
906
|
-
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
870
|
+
import { NavArrowDown as ChevronDown, OpenNewWindow } from "iconoir-react";
|
|
871
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
907
872
|
function appSwitcherTriggerClass(open, collapsed = false) {
|
|
908
|
-
return
|
|
873
|
+
return cn2(
|
|
909
874
|
"group flex min-w-0 items-center gap-2 rounded-lg border px-2 py-1.5 text-left transition-all duration-200",
|
|
910
875
|
collapsed ? "h-11 w-11 justify-center px-0 py-0" : "w-full",
|
|
911
876
|
open ? "border-ph-brand/30 bg-ph-muted shadow-[0_1px_2px_rgba(0,0,0,0.06)] ring-1 ring-ph-brand/15" : "border-transparent hover:border-ph-border hover:bg-ph-muted/80 hover:shadow-sm"
|
|
912
877
|
);
|
|
913
878
|
}
|
|
914
879
|
function appSwitcherMarkClass() {
|
|
915
|
-
return "h-8 w-8 shrink-0 rounded-lg
|
|
880
|
+
return "h-8 w-8 shrink-0 rounded-lg";
|
|
916
881
|
}
|
|
917
882
|
function appSwitcherMenuItemClass() {
|
|
918
|
-
return "rounded-lg px-2 py-2 data-[highlighted]:bg-transparent hover:bg-ph-muted/80";
|
|
883
|
+
return "rounded-lg px-2 py-2 data-[highlighted]:bg-transparent hover:bg-ph-muted/80 focus-visible:shadow-none";
|
|
919
884
|
}
|
|
920
885
|
function AppSwitcherMark({
|
|
921
886
|
children,
|
|
922
887
|
collapsed
|
|
923
888
|
}) {
|
|
924
|
-
return /* @__PURE__ */
|
|
889
|
+
return /* @__PURE__ */ jsx5(
|
|
925
890
|
"span",
|
|
926
891
|
{
|
|
927
|
-
className:
|
|
892
|
+
className: cn2(
|
|
928
893
|
"relative shrink-0",
|
|
929
894
|
collapsed && "group-hover:scale-[1.02]"
|
|
930
895
|
),
|
|
@@ -937,18 +902,18 @@ function AppSwitcherChevron({
|
|
|
937
902
|
collapsed = false
|
|
938
903
|
}) {
|
|
939
904
|
if (collapsed) {
|
|
940
|
-
return /* @__PURE__ */
|
|
905
|
+
return /* @__PURE__ */ jsx5(
|
|
941
906
|
"span",
|
|
942
907
|
{
|
|
943
|
-
className:
|
|
908
|
+
className: cn2(
|
|
944
909
|
"absolute bottom-0 right-0 flex h-3 w-3 items-center justify-center rounded-full border border-ph-border bg-ph-surface shadow-sm transition-colors",
|
|
945
910
|
open && "border-ph-brand/40 bg-ph-brand/10"
|
|
946
911
|
),
|
|
947
912
|
"aria-hidden": true,
|
|
948
|
-
children: /* @__PURE__ */
|
|
913
|
+
children: /* @__PURE__ */ jsx5(
|
|
949
914
|
ChevronDown,
|
|
950
915
|
{
|
|
951
|
-
className:
|
|
916
|
+
className: cn2(
|
|
952
917
|
"h-2 w-2 text-ph-mutedtext transition-transform duration-200",
|
|
953
918
|
open && "rotate-180 text-ph-brand"
|
|
954
919
|
)
|
|
@@ -957,18 +922,18 @@ function AppSwitcherChevron({
|
|
|
957
922
|
}
|
|
958
923
|
);
|
|
959
924
|
}
|
|
960
|
-
return /* @__PURE__ */
|
|
925
|
+
return /* @__PURE__ */ jsx5(
|
|
961
926
|
"span",
|
|
962
927
|
{
|
|
963
|
-
className:
|
|
928
|
+
className: cn2(
|
|
964
929
|
"border-ph-border/80 flex h-5 w-5 shrink-0 items-center justify-center rounded-lg border bg-ph-canvas shadow-sm transition-all duration-200",
|
|
965
930
|
open ? "border-ph-brand/35 bg-ph-brand/10 text-ph-brand" : "text-ph-mutedtext group-hover:border-ph-border group-hover:bg-ph-surface"
|
|
966
931
|
),
|
|
967
932
|
"aria-hidden": true,
|
|
968
|
-
children: /* @__PURE__ */
|
|
933
|
+
children: /* @__PURE__ */ jsx5(
|
|
969
934
|
ChevronDown,
|
|
970
935
|
{
|
|
971
|
-
className:
|
|
936
|
+
className: cn2(
|
|
972
937
|
"h-3 w-3 transition-transform duration-200",
|
|
973
938
|
open && "rotate-180"
|
|
974
939
|
)
|
|
@@ -990,7 +955,7 @@ function AppSwitcher({
|
|
|
990
955
|
triggerDataTest
|
|
991
956
|
}) {
|
|
992
957
|
const [open, setOpen] = useState(false);
|
|
993
|
-
return /* @__PURE__ */
|
|
958
|
+
return /* @__PURE__ */ jsx5(
|
|
994
959
|
DropdownMenu2,
|
|
995
960
|
{
|
|
996
961
|
"aria-label": "Switch application",
|
|
@@ -1001,26 +966,25 @@ function AppSwitcher({
|
|
|
1001
966
|
align: "start",
|
|
1002
967
|
open,
|
|
1003
968
|
onOpenChange: setOpen,
|
|
1004
|
-
trigger: /* @__PURE__ */
|
|
969
|
+
trigger: /* @__PURE__ */ jsxs5(
|
|
1005
970
|
"span",
|
|
1006
971
|
{
|
|
1007
972
|
className: appSwitcherTriggerClass(open, collapsed),
|
|
1008
973
|
"data-test": "app-switcher-trigger",
|
|
1009
|
-
"aria-expanded": open,
|
|
1010
974
|
children: [
|
|
1011
|
-
/* @__PURE__ */
|
|
975
|
+
/* @__PURE__ */ jsxs5(AppSwitcherMark, { collapsed, children: [
|
|
1012
976
|
mark,
|
|
1013
|
-
collapsed ? /* @__PURE__ */
|
|
977
|
+
collapsed ? /* @__PURE__ */ jsx5(AppSwitcherChevron, { open, collapsed: true }) : null
|
|
1014
978
|
] }),
|
|
1015
979
|
!collapsed ? title : null,
|
|
1016
|
-
!collapsed ? /* @__PURE__ */
|
|
980
|
+
!collapsed ? /* @__PURE__ */ jsx5(AppSwitcherChevron, { open }) : null
|
|
1017
981
|
]
|
|
1018
982
|
}
|
|
1019
983
|
),
|
|
1020
|
-
children: /* @__PURE__ */
|
|
1021
|
-
/* @__PURE__ */
|
|
1022
|
-
apps.filter((app) => app.slug !== currentApp).map((app) => /* @__PURE__ */
|
|
1023
|
-
/* @__PURE__ */
|
|
984
|
+
children: /* @__PURE__ */ jsxs5("div", { id: "app-switcher-menu", className: "p-1", "data-test": "app-switcher-menu", children: [
|
|
985
|
+
/* @__PURE__ */ jsx5("p", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-ph-mutedtext", children: "Switch application" }),
|
|
986
|
+
apps.filter((app) => app.slug !== currentApp).map((app) => /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
|
|
987
|
+
/* @__PURE__ */ jsx5(
|
|
1024
988
|
DropdownItem2,
|
|
1025
989
|
{
|
|
1026
990
|
id: `switch-app-${app.slug}`,
|
|
@@ -1030,9 +994,9 @@ function AppSwitcher({
|
|
|
1030
994
|
setOpen(false);
|
|
1031
995
|
onSelect(app);
|
|
1032
996
|
},
|
|
1033
|
-
className:
|
|
1034
|
-
children: /* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
997
|
+
className: cn2(appSwitcherMenuItemClass(), "pr-11"),
|
|
998
|
+
children: /* @__PURE__ */ jsxs5("span", { className: "flex min-w-0 items-center gap-3", children: [
|
|
999
|
+
/* @__PURE__ */ jsx5(
|
|
1036
1000
|
Image,
|
|
1037
1001
|
{
|
|
1038
1002
|
src: app.icon,
|
|
@@ -1042,17 +1006,16 @@ function AppSwitcher({
|
|
|
1042
1006
|
className: "h-7 w-7 shrink-0 rounded-md object-contain"
|
|
1043
1007
|
}
|
|
1044
1008
|
),
|
|
1045
|
-
/* @__PURE__ */
|
|
1046
|
-
/* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1009
|
+
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
1010
|
+
/* @__PURE__ */ jsx5("span", { className: "block truncate text-sm font-medium text-ph-ink", children: app.name }),
|
|
1011
|
+
/* @__PURE__ */ jsx5("span", { className: "block truncate text-xs text-ph-mutedtext", children: app.description })
|
|
1048
1012
|
] })
|
|
1049
1013
|
] })
|
|
1050
1014
|
}
|
|
1051
1015
|
),
|
|
1052
|
-
/* @__PURE__ */
|
|
1053
|
-
|
|
1016
|
+
/* @__PURE__ */ jsx5(
|
|
1017
|
+
DropdownItem2,
|
|
1054
1018
|
{
|
|
1055
|
-
type: "button",
|
|
1056
1019
|
id: `switch-app-${app.slug}-new-tab`,
|
|
1057
1020
|
"data-test": `switch-app-${app.slug}-new-tab`,
|
|
1058
1021
|
"aria-label": `Open ${app.name} in a new tab`,
|
|
@@ -1061,8 +1024,9 @@ function AppSwitcher({
|
|
|
1061
1024
|
setOpen(false);
|
|
1062
1025
|
onSelect(app, { newTab: true });
|
|
1063
1026
|
},
|
|
1064
|
-
className: "absolute right-1.5 top-1/2 z-[1] flex h-8
|
|
1065
|
-
|
|
1027
|
+
className: "absolute right-1.5 top-1/2 z-[1] flex h-8 -translate-y-1/2 justify-center rounded-md p-0 text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:shadow-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ph-brand/35",
|
|
1028
|
+
style: { width: "2rem" },
|
|
1029
|
+
children: /* @__PURE__ */ jsx5(OpenNewWindow, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
1066
1030
|
}
|
|
1067
1031
|
)
|
|
1068
1032
|
] }, app.slug))
|
|
@@ -1084,7 +1048,7 @@ var SUITE_APPS2 = [
|
|
|
1084
1048
|
description: "Organisation and billing",
|
|
1085
1049
|
icon: "/icon-shellstack.svg",
|
|
1086
1050
|
landing: "/home",
|
|
1087
|
-
baseUrlEnv: "
|
|
1051
|
+
baseUrlEnv: "NEXT_PUBLIC_PORTAL_URL",
|
|
1088
1052
|
baseUrlFallback: "http://localhost:3002"
|
|
1089
1053
|
},
|
|
1090
1054
|
{
|
|
@@ -1115,12 +1079,12 @@ var SUITE_APPS2 = [
|
|
|
1115
1079
|
baseUrlFallback: "http://localhost:3003"
|
|
1116
1080
|
},
|
|
1117
1081
|
{
|
|
1118
|
-
slug: "
|
|
1119
|
-
name: "
|
|
1082
|
+
slug: "shelly",
|
|
1083
|
+
name: "Shelly",
|
|
1120
1084
|
description: "AI teammates",
|
|
1121
|
-
icon: "/
|
|
1085
|
+
icon: "/shelly-icon.svg",
|
|
1122
1086
|
landing: "/today",
|
|
1123
|
-
baseUrlEnv: "
|
|
1087
|
+
baseUrlEnv: "NEXT_PUBLIC_SHELLY_URL",
|
|
1124
1088
|
baseUrlFallback: "http://localhost:3004"
|
|
1125
1089
|
}
|
|
1126
1090
|
];
|
|
@@ -1134,16 +1098,20 @@ var SOURCE_APP_SLUG = {
|
|
|
1134
1098
|
turtletime: "turtletime",
|
|
1135
1099
|
tides: "tides",
|
|
1136
1100
|
kraken: "kraken",
|
|
1137
|
-
|
|
1101
|
+
shelly: "shelly",
|
|
1138
1102
|
portal: "shellstack",
|
|
1139
1103
|
shellstack: "shellstack"
|
|
1140
1104
|
};
|
|
1105
|
+
function suiteAppSlugForNotificationSource(sourceApp) {
|
|
1106
|
+
var _a;
|
|
1107
|
+
return (_a = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a : null;
|
|
1108
|
+
}
|
|
1141
1109
|
function resolveSuiteNotificationHref(href, sourceApp) {
|
|
1142
1110
|
const value = (href || "").trim();
|
|
1143
1111
|
if (!value) return "";
|
|
1144
1112
|
if (/^(https?:|mailto:|\/\/)/i.test(value)) return value;
|
|
1145
1113
|
const path = value.startsWith("/") ? value : `/${value}`;
|
|
1146
|
-
const slug =
|
|
1114
|
+
const slug = suiteAppSlugForNotificationSource(sourceApp);
|
|
1147
1115
|
if (!slug) return path;
|
|
1148
1116
|
return `${suiteAppBaseUrl(slug)}${path}`;
|
|
1149
1117
|
}
|
|
@@ -1174,7 +1142,7 @@ function classifySuiteHref(href, bases, currentOrigin = "") {
|
|
|
1174
1142
|
}
|
|
1175
1143
|
|
|
1176
1144
|
// src/suite/components/suite-notification-bell.tsx
|
|
1177
|
-
import { jsx as
|
|
1145
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1178
1146
|
var POLL_MS = 6e4;
|
|
1179
1147
|
function timeAgo(iso) {
|
|
1180
1148
|
const then = new Date(iso).getTime();
|
|
@@ -1270,6 +1238,28 @@ function SuiteNotificationBell({
|
|
|
1270
1238
|
const target = resolveSuiteNotificationHref(n.href, n.source_app);
|
|
1271
1239
|
if (!target) return;
|
|
1272
1240
|
if (/^https?:\/\//i.test(target)) {
|
|
1241
|
+
try {
|
|
1242
|
+
const url = new URL(target);
|
|
1243
|
+
const sourceApp = suiteAppSlugForNotificationSource(n.source_app);
|
|
1244
|
+
const path = `${url.pathname}${url.search}${url.hash}`;
|
|
1245
|
+
if (url.origin === window.location.origin) {
|
|
1246
|
+
router.push(path);
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
if (sourceApp && sourceApp !== "shellstack") {
|
|
1250
|
+
const sourceOrigin = new URL(suiteAppBaseUrl(sourceApp)).origin;
|
|
1251
|
+
if (url.origin === sourceOrigin) {
|
|
1252
|
+
const launchUrl = new URL(
|
|
1253
|
+
`/launch/${sourceApp}`,
|
|
1254
|
+
suiteAppBaseUrl("shellstack")
|
|
1255
|
+
);
|
|
1256
|
+
launchUrl.searchParams.set("next", path);
|
|
1257
|
+
window.location.assign(launchUrl.toString());
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
} catch (e) {
|
|
1262
|
+
}
|
|
1273
1263
|
window.location.assign(target);
|
|
1274
1264
|
return;
|
|
1275
1265
|
}
|
|
@@ -1292,7 +1282,7 @@ function SuiteNotificationBell({
|
|
|
1292
1282
|
} catch (e) {
|
|
1293
1283
|
}
|
|
1294
1284
|
}, [markAllRead]);
|
|
1295
|
-
return /* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsxs6(
|
|
1296
1286
|
DropdownMenu2,
|
|
1297
1287
|
{
|
|
1298
1288
|
"aria-label": unread > 0 ? `Notifications, ${unread} unread` : "Notifications",
|
|
@@ -1302,14 +1292,14 @@ function SuiteNotificationBell({
|
|
|
1302
1292
|
panelClassName: "w-80 overflow-hidden p-0",
|
|
1303
1293
|
open,
|
|
1304
1294
|
onOpenChange,
|
|
1305
|
-
trigger: /* @__PURE__ */
|
|
1306
|
-
/* @__PURE__ */
|
|
1307
|
-
unread > 0 ? /* @__PURE__ */
|
|
1295
|
+
trigger: /* @__PURE__ */ jsx6("span", { className: "relative inline-flex h-11 w-11 items-center justify-center overflow-visible rounded-full text-ph-mutedtext transition hover:bg-ph-muted hover:text-ph-ink", children: /* @__PURE__ */ jsxs6("span", { className: "relative inline-flex h-5 w-5", children: [
|
|
1296
|
+
/* @__PURE__ */ jsx6(Bell, { className: "h-5 w-5", strokeWidth: 1.75, "aria-hidden": true }),
|
|
1297
|
+
unread > 0 ? /* @__PURE__ */ jsx6("span", { className: "pointer-events-none absolute -right-2 -top-2 z-[1] flex h-4 min-w-4 items-center justify-center rounded-full bg-ph-brand px-1 text-[9px] font-semibold leading-none text-[var(--ph-on-accent)] ring-2 ring-ph-surface", children: unread > 9 ? "9+" : unread }) : null
|
|
1308
1298
|
] }) }),
|
|
1309
1299
|
children: [
|
|
1310
|
-
/* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1312
|
-
unread > 0 ? /* @__PURE__ */
|
|
1300
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between border-b border-ph-border px-3 py-2", children: [
|
|
1301
|
+
/* @__PURE__ */ jsx6("span", { className: "text-sm font-semibold text-ph-ink", children: "Notifications" }),
|
|
1302
|
+
unread > 0 ? /* @__PURE__ */ jsx6(
|
|
1313
1303
|
"button",
|
|
1314
1304
|
{
|
|
1315
1305
|
type: "button",
|
|
@@ -1321,27 +1311,26 @@ function SuiteNotificationBell({
|
|
|
1321
1311
|
}
|
|
1322
1312
|
) : null
|
|
1323
1313
|
] }),
|
|
1324
|
-
/* @__PURE__ */
|
|
1314
|
+
/* @__PURE__ */ jsx6("div", { className: "max-h-80 overflow-y-auto py-1", children: items.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "px-3 py-6 text-center text-sm text-ph-mutedtext", children: "You're all caught up." }) : items.map((n) => /* @__PURE__ */ jsxs6(
|
|
1325
1315
|
"button",
|
|
1326
1316
|
{
|
|
1327
|
-
type: "button",
|
|
1328
1317
|
id: `${dataTest}-item-${n.id}`,
|
|
1329
1318
|
"data-test": `${dataTest}-item-${n.id}`,
|
|
1330
1319
|
onClick: () => void openItem(n),
|
|
1331
1320
|
className: "flex w-full flex-col gap-0.5 px-3 py-2 text-left transition hover:bg-ph-muted",
|
|
1332
1321
|
children: [
|
|
1333
|
-
/* @__PURE__ */
|
|
1334
|
-
!n.read_at ? /* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-2", children: [
|
|
1323
|
+
!n.read_at ? /* @__PURE__ */ jsx6(
|
|
1335
1324
|
"span",
|
|
1336
1325
|
{
|
|
1337
1326
|
className: "h-1.5 w-1.5 shrink-0 rounded-full bg-ph-brand",
|
|
1338
1327
|
"aria-hidden": true
|
|
1339
1328
|
}
|
|
1340
1329
|
) : null,
|
|
1341
|
-
/* @__PURE__ */
|
|
1330
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate text-sm font-medium text-ph-ink", children: n.title })
|
|
1342
1331
|
] }),
|
|
1343
|
-
n.body ? /* @__PURE__ */
|
|
1344
|
-
/* @__PURE__ */
|
|
1332
|
+
n.body ? /* @__PURE__ */ jsx6("span", { className: "line-clamp-2 text-xs text-ph-mutedtext", children: n.body }) : null,
|
|
1333
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-[11px] uppercase tracking-wide text-ph-subtle", children: [
|
|
1345
1334
|
n.source_app,
|
|
1346
1335
|
" \xB7 ",
|
|
1347
1336
|
timeAgo(n.created_at)
|
|
@@ -1357,7 +1346,7 @@ function SuiteNotificationBell({
|
|
|
1357
1346
|
|
|
1358
1347
|
// src/suite/components/command-palette-host.tsx
|
|
1359
1348
|
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
1360
|
-
import { jsx as
|
|
1349
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1361
1350
|
function isEditableTarget() {
|
|
1362
1351
|
if (typeof document === "undefined") return false;
|
|
1363
1352
|
const el = document.activeElement;
|
|
@@ -1389,7 +1378,7 @@ function CommandPaletteHost({
|
|
|
1389
1378
|
return () => window.removeEventListener("keydown", onKey);
|
|
1390
1379
|
}, [open]);
|
|
1391
1380
|
if (!isAuthenticated) return null;
|
|
1392
|
-
return /* @__PURE__ */
|
|
1381
|
+
return /* @__PURE__ */ jsx7(
|
|
1393
1382
|
CommandPalette,
|
|
1394
1383
|
{
|
|
1395
1384
|
items,
|
|
@@ -1423,17 +1412,18 @@ function useIdleMount(timeoutMs = 1200) {
|
|
|
1423
1412
|
}
|
|
1424
1413
|
|
|
1425
1414
|
// src/suite/components/deferred-chrome.tsx
|
|
1426
|
-
import { Fragment as Fragment3, jsx as
|
|
1415
|
+
import { Fragment as Fragment3, jsx as jsx8 } from "react/jsx-runtime";
|
|
1427
1416
|
function DeferredChrome({ children }) {
|
|
1428
1417
|
const ready = useIdleMount();
|
|
1429
1418
|
if (!ready) return null;
|
|
1430
|
-
return /* @__PURE__ */
|
|
1419
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children });
|
|
1431
1420
|
}
|
|
1432
1421
|
|
|
1433
1422
|
// src/suite/components/suite-mobile-drawer.tsx
|
|
1434
|
-
import
|
|
1423
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
1424
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
1435
1425
|
import { Xmark as X } from "iconoir-react";
|
|
1436
|
-
import { jsx as
|
|
1426
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1437
1427
|
function SuiteMobileDrawer({
|
|
1438
1428
|
open,
|
|
1439
1429
|
onClose,
|
|
@@ -1455,11 +1445,6 @@ function SuiteMobileDrawer({
|
|
|
1455
1445
|
}) {
|
|
1456
1446
|
const [rendered, setRendered] = useState5(open);
|
|
1457
1447
|
const [shown, setShown] = useState5(open);
|
|
1458
|
-
const panelRef = useRef(null);
|
|
1459
|
-
const onCloseRef = useRef(onClose);
|
|
1460
|
-
useEffect4(() => {
|
|
1461
|
-
onCloseRef.current = onClose;
|
|
1462
|
-
}, [onClose]);
|
|
1463
1448
|
useEffect4(() => {
|
|
1464
1449
|
if (open) {
|
|
1465
1450
|
queueMicrotask(() => setRendered(true));
|
|
@@ -1476,86 +1461,61 @@ function SuiteMobileDrawer({
|
|
|
1476
1461
|
const timeout = window.setTimeout(() => setRendered(false), durationMs);
|
|
1477
1462
|
return () => window.clearTimeout(timeout);
|
|
1478
1463
|
}, [open, durationMs]);
|
|
1479
|
-
useEffect4(() => {
|
|
1480
|
-
if (!open) return;
|
|
1481
|
-
const onKeyDown = (event) => {
|
|
1482
|
-
if (event.key === "Escape") onCloseRef.current();
|
|
1483
|
-
};
|
|
1484
|
-
window.addEventListener("keydown", onKeyDown);
|
|
1485
|
-
const previousOverflow = document.body.style.overflow;
|
|
1486
|
-
document.body.style.overflow = "hidden";
|
|
1487
|
-
const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1488
|
-
const frame = requestAnimationFrame(() => {
|
|
1489
|
-
var _a;
|
|
1490
|
-
return (_a = panelRef.current) == null ? void 0 : _a.focus();
|
|
1491
|
-
});
|
|
1492
|
-
return () => {
|
|
1493
|
-
window.removeEventListener("keydown", onKeyDown);
|
|
1494
|
-
document.body.style.overflow = previousOverflow;
|
|
1495
|
-
cancelAnimationFrame(frame);
|
|
1496
|
-
if (previouslyFocused == null ? void 0 : previouslyFocused.isConnected) previouslyFocused.focus();
|
|
1497
|
-
};
|
|
1498
|
-
}, [open]);
|
|
1499
1464
|
if (!rendered) return null;
|
|
1500
|
-
return /* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
|
|
1465
|
+
return /* @__PURE__ */ jsx9(Dialog.Root, { open, onOpenChange: (nextOpen) => !nextOpen && onClose(), children: /* @__PURE__ */ jsxs7(Dialog.Portal, { forceMount: true, children: [
|
|
1466
|
+
/* @__PURE__ */ jsx9(
|
|
1467
|
+
Dialog.Overlay,
|
|
1503
1468
|
{
|
|
1504
|
-
|
|
1469
|
+
forceMount: true,
|
|
1505
1470
|
id: backdropId,
|
|
1506
|
-
"data-test": backdropDataTest,
|
|
1507
|
-
|
|
1508
|
-
className:
|
|
1509
|
-
"
|
|
1471
|
+
"data-test": backdropDataTest != null ? backdropDataTest : dataTest,
|
|
1472
|
+
"aria-label": backdropLabel,
|
|
1473
|
+
className: cn2(
|
|
1474
|
+
"no-print fixed inset-0 z-50 bg-black/25 backdrop-blur-sm motion-safe:transition-opacity motion-safe:ease-spring-subtle lg:hidden",
|
|
1510
1475
|
shown ? "opacity-100" : "opacity-0"
|
|
1511
1476
|
),
|
|
1512
|
-
style: { transitionDuration: `${durationMs}ms` }
|
|
1513
|
-
onClick: onClose,
|
|
1514
|
-
"aria-label": backdropLabel
|
|
1477
|
+
style: { transitionDuration: `${durationMs}ms` }
|
|
1515
1478
|
}
|
|
1516
1479
|
),
|
|
1517
|
-
/* @__PURE__ */
|
|
1480
|
+
/* @__PURE__ */ jsx9(Dialog.Content, { forceMount: true, asChild: true, children: /* @__PURE__ */ jsxs7(
|
|
1518
1481
|
"aside",
|
|
1519
1482
|
{
|
|
1520
|
-
ref: panelRef,
|
|
1521
1483
|
role: "dialog",
|
|
1522
|
-
"aria-modal": "true",
|
|
1523
|
-
"aria-label": dialogLabel,
|
|
1524
|
-
tabIndex: -1,
|
|
1525
1484
|
"data-test": panelDataTest,
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1485
|
+
"aria-modal": "true",
|
|
1486
|
+
className: cn2(
|
|
1487
|
+
"fixed inset-y-0 left-0 z-50 flex h-dvh max-h-dvh 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 lg:hidden",
|
|
1488
|
+
side === "right" && "left-auto right-0",
|
|
1529
1489
|
shown ? "translate-x-0" : side === "right" ? "translate-x-full" : "-translate-x-full",
|
|
1530
1490
|
panelClassName
|
|
1531
1491
|
),
|
|
1532
1492
|
style: { transitionDuration: `${durationMs}ms` },
|
|
1533
1493
|
children: [
|
|
1534
|
-
|
|
1494
|
+
/* @__PURE__ */ jsx9(Dialog.Title, { className: "sr-only", children: dialogLabel }),
|
|
1495
|
+
showCloseButton ? /* @__PURE__ */ jsxs7(
|
|
1535
1496
|
"div",
|
|
1536
1497
|
{
|
|
1537
|
-
className:
|
|
1498
|
+
className: cn2(
|
|
1538
1499
|
"flex h-14 shrink-0 items-center border-b border-ph-border px-3",
|
|
1539
1500
|
title ? "justify-between" : "justify-end"
|
|
1540
1501
|
),
|
|
1541
1502
|
children: [
|
|
1542
|
-
title ? /* @__PURE__ */
|
|
1543
|
-
/* @__PURE__ */
|
|
1503
|
+
title ? /* @__PURE__ */ jsx9("span", { className: "truncate text-sm font-semibold text-ph-ink", children: title }) : null,
|
|
1504
|
+
/* @__PURE__ */ jsx9(Dialog.Close, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
1544
1505
|
"button",
|
|
1545
1506
|
{
|
|
1546
1507
|
type: "button",
|
|
1547
1508
|
id: closeButtonId,
|
|
1548
1509
|
"data-test": closeButtonDataTest,
|
|
1549
|
-
onClick: onClose,
|
|
1550
1510
|
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",
|
|
1551
1511
|
"aria-label": closeLabel,
|
|
1552
|
-
children: /* @__PURE__ */
|
|
1512
|
+
children: /* @__PURE__ */ jsx9(X, { className: "h-4 w-4", "aria-hidden": true })
|
|
1553
1513
|
}
|
|
1554
|
-
)
|
|
1514
|
+
) })
|
|
1555
1515
|
]
|
|
1556
1516
|
}
|
|
1557
1517
|
) : null,
|
|
1558
|
-
/* @__PURE__ */
|
|
1518
|
+
/* @__PURE__ */ jsx9(
|
|
1559
1519
|
"div",
|
|
1560
1520
|
{
|
|
1561
1521
|
"data-test": "suite-mobile-drawer-body",
|
|
@@ -1565,13 +1525,13 @@ function SuiteMobileDrawer({
|
|
|
1565
1525
|
)
|
|
1566
1526
|
]
|
|
1567
1527
|
}
|
|
1568
|
-
)
|
|
1569
|
-
] });
|
|
1528
|
+
) })
|
|
1529
|
+
] }) });
|
|
1570
1530
|
}
|
|
1571
1531
|
|
|
1572
1532
|
// src/suite/components/suite-mobile-header.tsx
|
|
1573
1533
|
import { Menu } from "iconoir-react";
|
|
1574
|
-
import { jsx as
|
|
1534
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1575
1535
|
function SuiteMobileHeader({
|
|
1576
1536
|
onMenuClick,
|
|
1577
1537
|
menuIcon: MenuIcon = Menu,
|
|
@@ -1583,16 +1543,16 @@ function SuiteMobileHeader({
|
|
|
1583
1543
|
dataTest,
|
|
1584
1544
|
className
|
|
1585
1545
|
}) {
|
|
1586
|
-
return /* @__PURE__ */
|
|
1546
|
+
return /* @__PURE__ */ jsxs8(
|
|
1587
1547
|
"header",
|
|
1588
1548
|
{
|
|
1589
1549
|
"data-test": dataTest,
|
|
1590
|
-
className:
|
|
1550
|
+
className: cn2(
|
|
1591
1551
|
"suite-app-bar no-print sticky top-0 z-30 flex min-h-[56px] shrink-0 items-center gap-1 border-b border-ph-border px-2 lg:hidden",
|
|
1592
1552
|
className
|
|
1593
1553
|
),
|
|
1594
1554
|
children: [
|
|
1595
|
-
onMenuClick ? /* @__PURE__ */
|
|
1555
|
+
onMenuClick ? /* @__PURE__ */ jsx10(
|
|
1596
1556
|
"button",
|
|
1597
1557
|
{
|
|
1598
1558
|
type: "button",
|
|
@@ -1601,20 +1561,20 @@ function SuiteMobileHeader({
|
|
|
1601
1561
|
className: "suite-press inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-xl text-ph-ink transition-colors hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
1602
1562
|
onClick: onMenuClick,
|
|
1603
1563
|
"aria-label": menuLabel,
|
|
1604
|
-
children: /* @__PURE__ */
|
|
1564
|
+
children: /* @__PURE__ */ jsx10(MenuIcon, { className: "h-5 w-5", "aria-hidden": true })
|
|
1605
1565
|
}
|
|
1606
1566
|
) : null,
|
|
1607
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsx10(
|
|
1608
1568
|
"div",
|
|
1609
1569
|
{
|
|
1610
|
-
className:
|
|
1570
|
+
className: cn2(
|
|
1611
1571
|
"flex min-w-0 flex-1 items-center",
|
|
1612
1572
|
!onMenuClick && "pl-2"
|
|
1613
1573
|
),
|
|
1614
1574
|
children: title
|
|
1615
1575
|
}
|
|
1616
1576
|
),
|
|
1617
|
-
actions ? /* @__PURE__ */
|
|
1577
|
+
actions ? /* @__PURE__ */ jsx10("div", { className: "flex shrink-0 items-center gap-1", children: actions }) : null
|
|
1618
1578
|
]
|
|
1619
1579
|
}
|
|
1620
1580
|
);
|
|
@@ -1623,26 +1583,26 @@ function SuiteMobileHeader({
|
|
|
1623
1583
|
// src/suite/components/suite-layout.tsx
|
|
1624
1584
|
import {
|
|
1625
1585
|
useEffect as useEffect5,
|
|
1626
|
-
useRef
|
|
1586
|
+
useRef,
|
|
1627
1587
|
useState as useState6
|
|
1628
1588
|
} from "react";
|
|
1629
|
-
import { jsx as
|
|
1589
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1630
1590
|
function SuiteBreadcrumbs({ items, className }) {
|
|
1631
|
-
return /* @__PURE__ */
|
|
1591
|
+
return /* @__PURE__ */ jsx11("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx11("ol", { className: "flex min-w-0 items-center gap-1.5", children: items.map((item, index) => {
|
|
1632
1592
|
const isLast = index === items.length - 1;
|
|
1633
|
-
return /* @__PURE__ */
|
|
1634
|
-
index > 0 ? /* @__PURE__ */
|
|
1635
|
-
item.href && !isLast ? /* @__PURE__ */
|
|
1593
|
+
return /* @__PURE__ */ jsxs9("li", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1594
|
+
index > 0 ? /* @__PURE__ */ jsx11("span", { className: "select-none text-ph-border", "aria-hidden": "true", children: "/" }) : null,
|
|
1595
|
+
item.href && !isLast ? /* @__PURE__ */ jsx11(
|
|
1636
1596
|
"a",
|
|
1637
1597
|
{
|
|
1638
1598
|
href: item.href,
|
|
1639
1599
|
className: "truncate transition hover:text-ph-ink",
|
|
1640
1600
|
children: item.label
|
|
1641
1601
|
}
|
|
1642
|
-
) : /* @__PURE__ */
|
|
1602
|
+
) : /* @__PURE__ */ jsx11(
|
|
1643
1603
|
"span",
|
|
1644
1604
|
{
|
|
1645
|
-
className:
|
|
1605
|
+
className: cn2(
|
|
1646
1606
|
"truncate",
|
|
1647
1607
|
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
1648
1608
|
),
|
|
@@ -1664,7 +1624,7 @@ function SuitePage({
|
|
|
1664
1624
|
role,
|
|
1665
1625
|
"aria-live": ariaLive
|
|
1666
1626
|
}) {
|
|
1667
|
-
return /* @__PURE__ */
|
|
1627
|
+
return /* @__PURE__ */ jsx11(
|
|
1668
1628
|
Component,
|
|
1669
1629
|
{
|
|
1670
1630
|
id,
|
|
@@ -1672,7 +1632,7 @@ function SuitePage({
|
|
|
1672
1632
|
"data-width": width,
|
|
1673
1633
|
role,
|
|
1674
1634
|
"aria-live": ariaLive,
|
|
1675
|
-
className:
|
|
1635
|
+
className: cn2(
|
|
1676
1636
|
"suite-page-stage relative flex w-full min-w-0 flex-col",
|
|
1677
1637
|
inset && "suite-page-inset",
|
|
1678
1638
|
className
|
|
@@ -1704,7 +1664,7 @@ function SuitePageHeader({
|
|
|
1704
1664
|
*/
|
|
1705
1665
|
sticky = true
|
|
1706
1666
|
}) {
|
|
1707
|
-
const headerRef =
|
|
1667
|
+
const headerRef = useRef(null);
|
|
1708
1668
|
const [stuck, setStuck] = useState6(false);
|
|
1709
1669
|
useEffect5(() => {
|
|
1710
1670
|
if (!sticky) return;
|
|
@@ -1732,33 +1692,33 @@ function SuitePageHeader({
|
|
|
1732
1692
|
sentinel.remove();
|
|
1733
1693
|
};
|
|
1734
1694
|
}, [sticky]);
|
|
1735
|
-
const resolvedIcon = todayIcon ? /* @__PURE__ */
|
|
1695
|
+
const resolvedIcon = todayIcon ? /* @__PURE__ */ jsx11(
|
|
1736
1696
|
TodayTimeIcon,
|
|
1737
1697
|
{
|
|
1738
|
-
className:
|
|
1698
|
+
className: cn2(
|
|
1739
1699
|
"h-6 w-6 text-amber-500",
|
|
1740
1700
|
todayIconClassName
|
|
1741
1701
|
)
|
|
1742
1702
|
}
|
|
1743
1703
|
) : icon;
|
|
1744
|
-
return /* @__PURE__ */
|
|
1704
|
+
return /* @__PURE__ */ jsxs9(
|
|
1745
1705
|
"header",
|
|
1746
1706
|
{
|
|
1747
1707
|
ref: headerRef,
|
|
1748
1708
|
"data-test": dataTest,
|
|
1749
1709
|
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1750
|
-
className:
|
|
1710
|
+
className: cn2(
|
|
1751
1711
|
"flex min-w-0 shrink-0 flex-col items-start gap-3 pb-2 sm:flex-row sm:justify-between sm:gap-4 sm:pb-3",
|
|
1752
1712
|
// No extra pt here — page inset sets the shared title baseline.
|
|
1753
1713
|
sticky && "suite-page-header-sticky",
|
|
1754
1714
|
className
|
|
1755
1715
|
),
|
|
1756
1716
|
children: [
|
|
1757
|
-
/* @__PURE__ */
|
|
1758
|
-
eyebrow ? /* @__PURE__ */
|
|
1759
|
-
breadcrumb ? /* @__PURE__ */
|
|
1760
|
-
/* @__PURE__ */
|
|
1761
|
-
resolvedIcon ? /* @__PURE__ */
|
|
1717
|
+
/* @__PURE__ */ jsxs9("div", { className: "min-w-0 flex-1", children: [
|
|
1718
|
+
eyebrow ? /* @__PURE__ */ jsx11("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: eyebrow }) : null,
|
|
1719
|
+
breadcrumb ? /* @__PURE__ */ jsx11("div", { className: "mb-0.5 flex min-w-0 items-center gap-1.5 text-xs text-ph-subtle", children: breadcrumb }) : null,
|
|
1720
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
1721
|
+
resolvedIcon ? /* @__PURE__ */ jsx11(
|
|
1762
1722
|
"div",
|
|
1763
1723
|
{
|
|
1764
1724
|
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-6 [&_svg]:w-6",
|
|
@@ -1766,24 +1726,24 @@ function SuitePageHeader({
|
|
|
1766
1726
|
children: resolvedIcon
|
|
1767
1727
|
}
|
|
1768
1728
|
) : null,
|
|
1769
|
-
/* @__PURE__ */
|
|
1770
|
-
/* @__PURE__ */
|
|
1729
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1730
|
+
/* @__PURE__ */ jsx11(
|
|
1771
1731
|
"h1",
|
|
1772
1732
|
{
|
|
1773
|
-
className:
|
|
1733
|
+
className: cn2(
|
|
1774
1734
|
"min-w-0 break-words font-display text-[1.375rem] font-semibold leading-tight tracking-tight text-ph-ink text-balance sm:text-2xl",
|
|
1775
1735
|
titleClassName
|
|
1776
1736
|
),
|
|
1777
1737
|
children: title
|
|
1778
1738
|
}
|
|
1779
1739
|
),
|
|
1780
|
-
badge ? /* @__PURE__ */
|
|
1740
|
+
badge ? /* @__PURE__ */ jsx11("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
|
|
1781
1741
|
] })
|
|
1782
1742
|
] }),
|
|
1783
|
-
description ? /* @__PURE__ */
|
|
1743
|
+
description ? /* @__PURE__ */ jsx11(
|
|
1784
1744
|
"div",
|
|
1785
1745
|
{
|
|
1786
|
-
className:
|
|
1746
|
+
className: cn2(
|
|
1787
1747
|
"mt-1.5 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle",
|
|
1788
1748
|
resolvedIcon && "sm:pl-9"
|
|
1789
1749
|
),
|
|
@@ -1791,7 +1751,7 @@ function SuitePageHeader({
|
|
|
1791
1751
|
}
|
|
1792
1752
|
) : null
|
|
1793
1753
|
] }),
|
|
1794
|
-
actions ? /* @__PURE__ */
|
|
1754
|
+
actions ? /* @__PURE__ */ jsx11("div", { className: "flex max-w-full items-center gap-2 self-stretch overflow-x-auto pb-1 sm:shrink-0 sm:self-center sm:overflow-visible sm:pb-0", children: actions }) : null
|
|
1795
1755
|
]
|
|
1796
1756
|
}
|
|
1797
1757
|
);
|
|
@@ -1802,13 +1762,13 @@ function SuiteToolbar({
|
|
|
1802
1762
|
label = "Page tools",
|
|
1803
1763
|
dataTest
|
|
1804
1764
|
}) {
|
|
1805
|
-
return /* @__PURE__ */
|
|
1765
|
+
return /* @__PURE__ */ jsx11(
|
|
1806
1766
|
"div",
|
|
1807
1767
|
{
|
|
1808
1768
|
role: "toolbar",
|
|
1809
1769
|
"aria-label": label,
|
|
1810
1770
|
"data-test": dataTest,
|
|
1811
|
-
className:
|
|
1771
|
+
className: cn2("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
1812
1772
|
children
|
|
1813
1773
|
}
|
|
1814
1774
|
);
|
|
@@ -1819,12 +1779,12 @@ function SuiteTabList({
|
|
|
1819
1779
|
label,
|
|
1820
1780
|
dataTest
|
|
1821
1781
|
}) {
|
|
1822
|
-
return /* @__PURE__ */
|
|
1782
|
+
return /* @__PURE__ */ jsx11(
|
|
1823
1783
|
"nav",
|
|
1824
1784
|
{
|
|
1825
1785
|
"aria-label": label,
|
|
1826
1786
|
"data-test": dataTest,
|
|
1827
|
-
className:
|
|
1787
|
+
className: cn2(
|
|
1828
1788
|
"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]",
|
|
1829
1789
|
className
|
|
1830
1790
|
),
|
|
@@ -1838,26 +1798,26 @@ function SuiteSectionHeader({
|
|
|
1838
1798
|
action,
|
|
1839
1799
|
className
|
|
1840
1800
|
}) {
|
|
1841
|
-
return /* @__PURE__ */
|
|
1801
|
+
return /* @__PURE__ */ jsxs9(
|
|
1842
1802
|
"div",
|
|
1843
1803
|
{
|
|
1844
|
-
className:
|
|
1804
|
+
className: cn2(
|
|
1845
1805
|
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
1846
1806
|
className
|
|
1847
1807
|
),
|
|
1848
1808
|
children: [
|
|
1849
|
-
/* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
1851
|
-
description ? /* @__PURE__ */
|
|
1809
|
+
/* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
|
|
1810
|
+
/* @__PURE__ */ jsx11("h2", { className: "font-display text-balance text-lg font-semibold tracking-tight text-ph-ink sm:text-xl", children: title }),
|
|
1811
|
+
description ? /* @__PURE__ */ jsx11("div", { className: "mt-1 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle", children: description }) : null
|
|
1852
1812
|
] }),
|
|
1853
|
-
action ? /* @__PURE__ */
|
|
1813
|
+
action ? /* @__PURE__ */ jsx11("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
1854
1814
|
]
|
|
1855
1815
|
}
|
|
1856
1816
|
);
|
|
1857
1817
|
}
|
|
1858
1818
|
|
|
1859
1819
|
// src/suite/components/suite-settings-layout.tsx
|
|
1860
|
-
import { jsx as
|
|
1820
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1861
1821
|
function SuiteSettingsLayout({
|
|
1862
1822
|
children,
|
|
1863
1823
|
sidebar,
|
|
@@ -1871,13 +1831,13 @@ function SuiteSettingsLayout({
|
|
|
1871
1831
|
className,
|
|
1872
1832
|
contentClassName
|
|
1873
1833
|
}) {
|
|
1874
|
-
return /* @__PURE__ */
|
|
1834
|
+
return /* @__PURE__ */ jsxs10(
|
|
1875
1835
|
SuitePage,
|
|
1876
1836
|
{
|
|
1877
1837
|
dataTest,
|
|
1878
|
-
className:
|
|
1838
|
+
className: cn2("flex h-full flex-col overflow-hidden", className),
|
|
1879
1839
|
children: [
|
|
1880
|
-
header != null ? header : /* @__PURE__ */
|
|
1840
|
+
header != null ? header : /* @__PURE__ */ jsx12(
|
|
1881
1841
|
SuitePageHeader,
|
|
1882
1842
|
{
|
|
1883
1843
|
sticky: true,
|
|
@@ -1886,10 +1846,10 @@ function SuiteSettingsLayout({
|
|
|
1886
1846
|
description
|
|
1887
1847
|
}
|
|
1888
1848
|
),
|
|
1889
|
-
loading != null ? loading : /* @__PURE__ */
|
|
1890
|
-
mobileNav ? /* @__PURE__ */
|
|
1891
|
-
/* @__PURE__ */
|
|
1892
|
-
/* @__PURE__ */
|
|
1849
|
+
loading != null ? loading : /* @__PURE__ */ jsxs10("div", { className: "suite-page-body mt-6 flex min-h-0 flex-1 flex-col", children: [
|
|
1850
|
+
mobileNav ? /* @__PURE__ */ jsx12("div", { className: "sticky top-0 z-20 mb-2 shrink-0 bg-ph-canvas/95 backdrop-blur lg:hidden", children: mobileNav }) : null,
|
|
1851
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex min-h-0 flex-1 flex-col gap-6 lg:flex-row lg:gap-8", children: [
|
|
1852
|
+
/* @__PURE__ */ jsx12(
|
|
1893
1853
|
"aside",
|
|
1894
1854
|
{
|
|
1895
1855
|
"aria-label": "Settings",
|
|
@@ -1897,10 +1857,10 @@ function SuiteSettingsLayout({
|
|
|
1897
1857
|
children: sidebar
|
|
1898
1858
|
}
|
|
1899
1859
|
),
|
|
1900
|
-
/* @__PURE__ */
|
|
1860
|
+
/* @__PURE__ */ jsx12(
|
|
1901
1861
|
"div",
|
|
1902
1862
|
{
|
|
1903
|
-
className:
|
|
1863
|
+
className: cn2(
|
|
1904
1864
|
"min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain pb-6",
|
|
1905
1865
|
contentClassName
|
|
1906
1866
|
),
|
|
@@ -1918,24 +1878,25 @@ function SuiteSettingsLayout({
|
|
|
1918
1878
|
import Image2 from "next/image";
|
|
1919
1879
|
import { useRouter as useRouter2 } from "next/navigation";
|
|
1920
1880
|
import { LogOut, Settings } from "iconoir-react";
|
|
1921
|
-
import { jsx as
|
|
1881
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1922
1882
|
function computeInitials(name, email) {
|
|
1923
1883
|
const source = (name || email || "?").trim();
|
|
1924
1884
|
return source.split(/[\s@]+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
1925
1885
|
}
|
|
1926
1886
|
var AVATAR_TOKENS = [
|
|
1927
|
-
"bg-ph-brand",
|
|
1928
|
-
"bg-ph-violet",
|
|
1929
|
-
"bg-ph-info",
|
|
1930
|
-
"bg-ph-success",
|
|
1931
|
-
"bg-ph-danger"
|
|
1887
|
+
["bg-ph-brand", "text-[var(--ph-on-accent)]"],
|
|
1888
|
+
["bg-ph-violet", "text-[var(--ph-on-violet)]"],
|
|
1889
|
+
["bg-ph-info", "text-[var(--ph-on-info)]"],
|
|
1890
|
+
["bg-ph-success", "text-[var(--ph-on-success)]"],
|
|
1891
|
+
["bg-ph-danger", "text-[var(--ph-on-danger)]"]
|
|
1932
1892
|
];
|
|
1933
1893
|
function avatarColorClass(seed) {
|
|
1934
1894
|
let hash = 0;
|
|
1935
1895
|
for (let i = 0; i < seed.length; i += 1) {
|
|
1936
1896
|
hash = seed.charCodeAt(i) + ((hash << 5) - hash);
|
|
1937
1897
|
}
|
|
1938
|
-
|
|
1898
|
+
const [bg, ink] = AVATAR_TOKENS[Math.abs(hash) % AVATAR_TOKENS.length];
|
|
1899
|
+
return `${bg} ${ink}`;
|
|
1939
1900
|
}
|
|
1940
1901
|
function SuiteUserMenu({
|
|
1941
1902
|
name,
|
|
@@ -1953,7 +1914,7 @@ function SuiteUserMenu({
|
|
|
1953
1914
|
const router = useRouter2();
|
|
1954
1915
|
const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
|
|
1955
1916
|
const fallbackColor = avatarColorClass(email || name || "?");
|
|
1956
|
-
const avatar = /* @__PURE__ */
|
|
1917
|
+
const avatar = /* @__PURE__ */ jsx13("span", { className: "inline-flex h-10 w-10 items-center justify-center overflow-hidden rounded-full border border-ph-border", children: image ? /* @__PURE__ */ jsx13(
|
|
1957
1918
|
Image2,
|
|
1958
1919
|
{
|
|
1959
1920
|
src: image,
|
|
@@ -1963,17 +1924,17 @@ function SuiteUserMenu({
|
|
|
1963
1924
|
className: "h-full w-full object-cover",
|
|
1964
1925
|
unoptimized: true
|
|
1965
1926
|
}
|
|
1966
|
-
) : /* @__PURE__ */
|
|
1927
|
+
) : /* @__PURE__ */ jsx13(
|
|
1967
1928
|
"span",
|
|
1968
1929
|
{
|
|
1969
|
-
className:
|
|
1970
|
-
"flex h-full w-full items-center justify-center text-sm font-semibold
|
|
1930
|
+
className: cn2(
|
|
1931
|
+
"flex h-full w-full items-center justify-center text-sm font-semibold",
|
|
1971
1932
|
fallbackColor
|
|
1972
1933
|
),
|
|
1973
1934
|
children: initials
|
|
1974
1935
|
}
|
|
1975
1936
|
) });
|
|
1976
|
-
const accountMenu = /* @__PURE__ */
|
|
1937
|
+
const accountMenu = /* @__PURE__ */ jsxs11(
|
|
1977
1938
|
DropdownMenu,
|
|
1978
1939
|
{
|
|
1979
1940
|
trigger: avatar,
|
|
@@ -1985,30 +1946,30 @@ function SuiteUserMenu({
|
|
|
1985
1946
|
sideOffset: 6,
|
|
1986
1947
|
collisionPadding: 16,
|
|
1987
1948
|
modal: false,
|
|
1988
|
-
className:
|
|
1949
|
+
className: cn2(
|
|
1989
1950
|
"[&_.ph-dropdown-trigger]:rounded-full",
|
|
1990
1951
|
showSignOutAction ? void 0 : className
|
|
1991
1952
|
),
|
|
1992
1953
|
"data-test": dataTest,
|
|
1993
1954
|
children: [
|
|
1994
|
-
/* @__PURE__ */
|
|
1995
|
-
/* @__PURE__ */
|
|
1996
|
-
email ? /* @__PURE__ */
|
|
1955
|
+
/* @__PURE__ */ jsxs11("div", { className: "px-2 py-1.5", children: [
|
|
1956
|
+
/* @__PURE__ */ jsx13("p", { className: "truncate text-sm font-medium text-ph-ink", children: name || email || "Account" }),
|
|
1957
|
+
email ? /* @__PURE__ */ jsx13("p", { className: "truncate text-xs text-ph-mutedtext", children: email }) : null
|
|
1997
1958
|
] }),
|
|
1998
|
-
/* @__PURE__ */
|
|
1999
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsx13("div", { className: "my-1 border-t border-ph-border" }),
|
|
1960
|
+
/* @__PURE__ */ jsxs11(
|
|
2000
1961
|
DropdownItem,
|
|
2001
1962
|
{
|
|
2002
1963
|
"data-test": `${dataTest}-settings`,
|
|
2003
1964
|
onClick: () => router.push(settingsHref),
|
|
2004
1965
|
children: [
|
|
2005
|
-
/* @__PURE__ */
|
|
1966
|
+
/* @__PURE__ */ jsx13(Settings, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
2006
1967
|
"Profile settings"
|
|
2007
1968
|
]
|
|
2008
1969
|
}
|
|
2009
1970
|
),
|
|
2010
|
-
/* @__PURE__ */
|
|
2011
|
-
/* @__PURE__ */
|
|
1971
|
+
/* @__PURE__ */ jsxs11(DropdownItem, { "data-test": `${dataTest}-sign-out`, onClick: onSignOut, children: [
|
|
1972
|
+
/* @__PURE__ */ jsx13(LogOut, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
2012
1973
|
"Sign out"
|
|
2013
1974
|
] })
|
|
2014
1975
|
]
|
|
@@ -2017,16 +1978,16 @@ function SuiteUserMenu({
|
|
|
2017
1978
|
if (!showSignOutAction) {
|
|
2018
1979
|
return accountMenu;
|
|
2019
1980
|
}
|
|
2020
|
-
return /* @__PURE__ */
|
|
1981
|
+
return /* @__PURE__ */ jsxs11(
|
|
2021
1982
|
"div",
|
|
2022
1983
|
{
|
|
2023
|
-
className:
|
|
1984
|
+
className: cn2(
|
|
2024
1985
|
"flex w-full min-w-0 flex-1 items-center justify-between gap-2",
|
|
2025
1986
|
className
|
|
2026
1987
|
),
|
|
2027
1988
|
children: [
|
|
2028
|
-
/* @__PURE__ */
|
|
2029
|
-
/* @__PURE__ */
|
|
1989
|
+
/* @__PURE__ */ jsx13("div", { className: "shrink-0", children: accountMenu }),
|
|
1990
|
+
/* @__PURE__ */ jsx13(
|
|
2030
1991
|
"button",
|
|
2031
1992
|
{
|
|
2032
1993
|
type: "button",
|
|
@@ -2035,7 +1996,7 @@ function SuiteUserMenu({
|
|
|
2035
1996
|
"aria-label": "Sign out",
|
|
2036
1997
|
className: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-ph-mutedtext transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-focus-ring",
|
|
2037
1998
|
onClick: onSignOut,
|
|
2038
|
-
children: /* @__PURE__ */
|
|
1999
|
+
children: /* @__PURE__ */ jsx13(LogOut, { className: "h-4 w-4", "aria-hidden": true })
|
|
2039
2000
|
}
|
|
2040
2001
|
)
|
|
2041
2002
|
]
|
|
@@ -2045,7 +2006,7 @@ function SuiteUserMenu({
|
|
|
2045
2006
|
|
|
2046
2007
|
// src/suite/components/suite-bottom-nav.tsx
|
|
2047
2008
|
import Link from "next/link";
|
|
2048
|
-
import { Fragment as Fragment4, jsx as
|
|
2009
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2049
2010
|
function SuiteBottomNav({
|
|
2050
2011
|
items,
|
|
2051
2012
|
ariaLabel = "Primary navigation",
|
|
@@ -2058,8 +2019,8 @@ function SuiteBottomNav({
|
|
|
2058
2019
|
);
|
|
2059
2020
|
}
|
|
2060
2021
|
const activeIndex = items.findIndex((item) => item.active);
|
|
2061
|
-
return /* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
2022
|
+
return /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2023
|
+
/* @__PURE__ */ jsx14(
|
|
2063
2024
|
"div",
|
|
2064
2025
|
{
|
|
2065
2026
|
"aria-hidden": true,
|
|
@@ -2067,12 +2028,12 @@ function SuiteBottomNav({
|
|
|
2067
2028
|
style: { height: "calc(60px + env(safe-area-inset-bottom))" }
|
|
2068
2029
|
}
|
|
2069
2030
|
),
|
|
2070
|
-
/* @__PURE__ */
|
|
2031
|
+
/* @__PURE__ */ jsxs12(
|
|
2071
2032
|
"nav",
|
|
2072
2033
|
{
|
|
2073
2034
|
"aria-label": ariaLabel,
|
|
2074
2035
|
"data-test": dataTest,
|
|
2075
|
-
className:
|
|
2036
|
+
className: cn2(
|
|
2076
2037
|
"suite-bottom-nav no-print z-40 grid auto-cols-fr grid-flow-col lg:hidden",
|
|
2077
2038
|
className
|
|
2078
2039
|
),
|
|
@@ -2082,31 +2043,31 @@ function SuiteBottomNav({
|
|
|
2082
2043
|
"--suite-nav-active": activeIndex >= 0 ? activeIndex : 0
|
|
2083
2044
|
},
|
|
2084
2045
|
children: [
|
|
2085
|
-
activeIndex >= 0 ? /* @__PURE__ */
|
|
2046
|
+
activeIndex >= 0 ? /* @__PURE__ */ jsx14("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
|
|
2086
2047
|
items.map((item) => {
|
|
2087
2048
|
var _a;
|
|
2088
2049
|
const Icon = item.icon;
|
|
2089
2050
|
const active = Boolean(item.active);
|
|
2090
|
-
return /* @__PURE__ */
|
|
2051
|
+
return /* @__PURE__ */ jsxs12(
|
|
2091
2052
|
Link,
|
|
2092
2053
|
{
|
|
2093
2054
|
href: item.href,
|
|
2094
2055
|
id: item.id,
|
|
2095
2056
|
"data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
2096
2057
|
"aria-current": active ? "page" : void 0,
|
|
2097
|
-
className:
|
|
2058
|
+
className: cn2(
|
|
2098
2059
|
"suite-bottom-nav__item relative flex min-h-[60px] min-w-0 flex-col items-center justify-center gap-1 px-1 pb-1.5 pt-2 text-[10px] font-medium leading-none text-ph-mutedtext transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ph-brand motion-reduce:transition-none",
|
|
2099
2060
|
active && "font-semibold text-ph-brand"
|
|
2100
2061
|
),
|
|
2101
2062
|
children: [
|
|
2102
|
-
/* @__PURE__ */
|
|
2063
|
+
/* @__PURE__ */ jsx14(
|
|
2103
2064
|
"span",
|
|
2104
2065
|
{
|
|
2105
|
-
className:
|
|
2066
|
+
className: cn2(
|
|
2106
2067
|
"suite-bottom-nav__icon relative z-10 inline-flex items-center justify-center",
|
|
2107
2068
|
active && "suite-bottom-nav__icon--active"
|
|
2108
2069
|
),
|
|
2109
|
-
children: /* @__PURE__ */
|
|
2070
|
+
children: /* @__PURE__ */ jsx14(
|
|
2110
2071
|
Icon,
|
|
2111
2072
|
{
|
|
2112
2073
|
className: "h-6 w-6",
|
|
@@ -2116,7 +2077,7 @@ function SuiteBottomNav({
|
|
|
2116
2077
|
)
|
|
2117
2078
|
}
|
|
2118
2079
|
),
|
|
2119
|
-
/* @__PURE__ */
|
|
2080
|
+
/* @__PURE__ */ jsx14("span", { className: "relative z-10 max-w-full truncate", children: item.label })
|
|
2120
2081
|
]
|
|
2121
2082
|
},
|
|
2122
2083
|
item.href
|
|
@@ -2130,7 +2091,7 @@ function SuiteBottomNav({
|
|
|
2130
2091
|
|
|
2131
2092
|
// src/suite/components/today-calibrating.tsx
|
|
2132
2093
|
import { Refresh as RefreshCw2, SunLight as Sun } from "iconoir-react";
|
|
2133
|
-
import { jsx as
|
|
2094
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2134
2095
|
function TodayCalibrating({
|
|
2135
2096
|
onRetry,
|
|
2136
2097
|
retrying = false,
|
|
@@ -2140,27 +2101,27 @@ function TodayCalibrating({
|
|
|
2140
2101
|
retrySpinnerClassName = "text-ph-brand"
|
|
2141
2102
|
}) {
|
|
2142
2103
|
void _variant;
|
|
2143
|
-
return /* @__PURE__ */
|
|
2104
|
+
return /* @__PURE__ */ jsxs13(
|
|
2144
2105
|
"div",
|
|
2145
2106
|
{
|
|
2146
|
-
className:
|
|
2107
|
+
className: cn2(
|
|
2147
2108
|
"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",
|
|
2148
2109
|
className
|
|
2149
2110
|
),
|
|
2150
2111
|
"data-test": "today-calibrating",
|
|
2151
2112
|
children: [
|
|
2152
|
-
/* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsx15(
|
|
2153
2114
|
"div",
|
|
2154
2115
|
{
|
|
2155
2116
|
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.1),transparent_55%)]",
|
|
2156
2117
|
"aria-hidden": true
|
|
2157
2118
|
}
|
|
2158
2119
|
),
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
2163
|
-
onRetry ? /* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsx15("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__ */ jsx15(Sun, { className: "h-8 w-8", strokeWidth: 2, "aria-hidden": true }) }),
|
|
2121
|
+
/* @__PURE__ */ jsx15("h2", { className: "relative text-base font-semibold tracking-tight text-ph-ink sm:text-lg md:text-xl", children: "Calibrating your day" }),
|
|
2122
|
+
/* @__PURE__ */ jsx15("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" }),
|
|
2123
|
+
/* @__PURE__ */ jsx15("div", { className: "relative mt-5 flex justify-center", children: /* @__PURE__ */ jsx15(Spinner, { size: "sm", className: "opacity-70", label: "Loading today" }) }),
|
|
2124
|
+
onRetry ? /* @__PURE__ */ jsxs13(
|
|
2164
2125
|
"button",
|
|
2165
2126
|
{
|
|
2166
2127
|
type: "button",
|
|
@@ -2168,7 +2129,7 @@ function TodayCalibrating({
|
|
|
2168
2129
|
disabled: retrying,
|
|
2169
2130
|
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",
|
|
2170
2131
|
children: [
|
|
2171
|
-
retrying ? /* @__PURE__ */
|
|
2132
|
+
retrying ? /* @__PURE__ */ jsx15(Spinner, { size: "sm", className: retrySpinnerClassName }) : /* @__PURE__ */ jsx15(RefreshCw2, { className: "h-4 w-4", "aria-hidden": true }),
|
|
2172
2133
|
"Try again"
|
|
2173
2134
|
]
|
|
2174
2135
|
}
|
|
@@ -2186,7 +2147,7 @@ import {
|
|
|
2186
2147
|
useEffect as useEffect6,
|
|
2187
2148
|
useId,
|
|
2188
2149
|
useLayoutEffect,
|
|
2189
|
-
useRef as
|
|
2150
|
+
useRef as useRef2,
|
|
2190
2151
|
useState as useState7
|
|
2191
2152
|
} from "react";
|
|
2192
2153
|
import {
|
|
@@ -2197,8 +2158,8 @@ import {
|
|
|
2197
2158
|
Square,
|
|
2198
2159
|
WarningTriangle
|
|
2199
2160
|
} from "iconoir-react";
|
|
2200
|
-
import { Fragment as Fragment5, jsx as
|
|
2201
|
-
var SuiteAiBlockNoteMessage = lazy(() => import("./ai-message-blocknote-
|
|
2161
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2162
|
+
var SuiteAiBlockNoteMessage = lazy(() => import("./ai-message-blocknote-D4Z6DUCJ.mjs"));
|
|
2202
2163
|
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
2203
2164
|
var SUITE_ASK_AI_OPEN_KEY = "shellstack:shelly-open";
|
|
2204
2165
|
var SUITE_ASK_AI_OPEN_QUERY = "shelly";
|
|
@@ -2280,7 +2241,8 @@ function SuiteAiPanel({
|
|
|
2280
2241
|
suiteAppBases,
|
|
2281
2242
|
onSwitchApp,
|
|
2282
2243
|
onSameAppNavigate,
|
|
2283
|
-
resolveAction
|
|
2244
|
+
resolveAction,
|
|
2245
|
+
isWaitingForReply = false
|
|
2284
2246
|
}) {
|
|
2285
2247
|
const inputId = useId();
|
|
2286
2248
|
const [uncontrolledOpen, setUncontrolledOpen] = useState7(false);
|
|
@@ -2300,10 +2262,11 @@ function SuiteAiPanel({
|
|
|
2300
2262
|
const [hydrating, setHydrating] = useState7(false);
|
|
2301
2263
|
const [error, setError] = useState7("");
|
|
2302
2264
|
const [atBottom, setAtBottom] = useState7(true);
|
|
2303
|
-
const scrollerRef =
|
|
2304
|
-
const textareaRef =
|
|
2305
|
-
const abortRef =
|
|
2306
|
-
const pendingPromptRef =
|
|
2265
|
+
const scrollerRef = useRef2(null);
|
|
2266
|
+
const textareaRef = useRef2(null);
|
|
2267
|
+
const abortRef = useRef2(null);
|
|
2268
|
+
const pendingPromptRef = useRef2(null);
|
|
2269
|
+
const waiting = loading || isWaitingForReply;
|
|
2307
2270
|
useEffect6(() => {
|
|
2308
2271
|
function onOpen(event) {
|
|
2309
2272
|
var _a;
|
|
@@ -2331,7 +2294,7 @@ function SuiteAiPanel({
|
|
|
2331
2294
|
setAtBottom(distance < 64);
|
|
2332
2295
|
}, []);
|
|
2333
2296
|
const hydrate = useCallback2(async () => {
|
|
2334
|
-
var _a;
|
|
2297
|
+
var _a, _b, _c;
|
|
2335
2298
|
setHydrating(true);
|
|
2336
2299
|
setError("");
|
|
2337
2300
|
try {
|
|
@@ -2339,6 +2302,11 @@ function SuiteAiPanel({
|
|
|
2339
2302
|
setMessages((_a = data.messages) != null ? _a : []);
|
|
2340
2303
|
if (!data.configured) {
|
|
2341
2304
|
setError("ShellStack AI is not configured for this workspace yet.");
|
|
2305
|
+
} else {
|
|
2306
|
+
const latestJob = (_b = data.jobs) == null ? void 0 : _b[0];
|
|
2307
|
+
if ((latestJob == null ? void 0 : latestJob.status) === "failed" && latestJob.error && latestJob.error !== "Chat cleared." && ((_c = data.messages.at(-1)) == null ? void 0 : _c.role) !== "assistant") {
|
|
2308
|
+
setError(latestJob.error);
|
|
2309
|
+
}
|
|
2342
2310
|
}
|
|
2343
2311
|
} catch (err) {
|
|
2344
2312
|
setError(
|
|
@@ -2361,7 +2329,7 @@ function SuiteAiPanel({
|
|
|
2361
2329
|
}, [open, hydrate]);
|
|
2362
2330
|
useEffect6(() => {
|
|
2363
2331
|
if (open && atBottom) scrollToBottom();
|
|
2364
|
-
}, [messages,
|
|
2332
|
+
}, [messages, waiting, open, atBottom, scrollToBottom]);
|
|
2365
2333
|
useEffect6(() => {
|
|
2366
2334
|
var _a;
|
|
2367
2335
|
if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
@@ -2375,7 +2343,7 @@ function SuiteAiPanel({
|
|
|
2375
2343
|
async function ask(text) {
|
|
2376
2344
|
var _a;
|
|
2377
2345
|
const trimmed = text.trim();
|
|
2378
|
-
if (!trimmed ||
|
|
2346
|
+
if (!trimmed || waiting) return;
|
|
2379
2347
|
const controller = new AbortController();
|
|
2380
2348
|
abortRef.current = controller;
|
|
2381
2349
|
setLoading(true);
|
|
@@ -2491,32 +2459,32 @@ function SuiteAiPanel({
|
|
|
2491
2459
|
}
|
|
2492
2460
|
if (!open) return null;
|
|
2493
2461
|
const Icon = BrandIcon != null ? BrandIcon : Sparks;
|
|
2494
|
-
return /* @__PURE__ */
|
|
2462
|
+
return /* @__PURE__ */ jsxs14(
|
|
2495
2463
|
"aside",
|
|
2496
2464
|
{
|
|
2497
2465
|
className: "flex h-full min-h-0 flex-col bg-ph-canvas",
|
|
2498
2466
|
"data-test": "suite-ask-ai-panel",
|
|
2499
2467
|
"aria-label": title,
|
|
2500
2468
|
children: [
|
|
2501
|
-
/* @__PURE__ */
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
messages.length > 0 ? /* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsxs14("header", { className: "flex items-center gap-2 px-2 pb-2", children: [
|
|
2470
|
+
/* @__PURE__ */ jsx16("h2", { className: "sr-only", children: title }),
|
|
2471
|
+
messages.length > 0 ? /* @__PURE__ */ jsxs14(
|
|
2504
2472
|
"button",
|
|
2505
2473
|
{
|
|
2506
2474
|
type: "button",
|
|
2507
2475
|
onClick: () => void handleClear(),
|
|
2508
|
-
disabled:
|
|
2476
|
+
disabled: waiting,
|
|
2509
2477
|
className: "ml-auto inline-flex h-9 items-center gap-1.5 rounded-lg px-2 text-xs font-medium text-ph-subtle transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2510
2478
|
"data-test": "ask-ai-clear",
|
|
2511
2479
|
children: [
|
|
2512
|
-
/* @__PURE__ */
|
|
2480
|
+
/* @__PURE__ */ jsx16(Erase, { className: "h-3.5 w-3.5" }),
|
|
2513
2481
|
"Clear"
|
|
2514
2482
|
]
|
|
2515
2483
|
}
|
|
2516
2484
|
) : null
|
|
2517
2485
|
] }),
|
|
2518
|
-
/* @__PURE__ */
|
|
2519
|
-
/* @__PURE__ */
|
|
2486
|
+
/* @__PURE__ */ jsxs14("div", { className: "relative min-h-0 flex-1", children: [
|
|
2487
|
+
/* @__PURE__ */ jsxs14(
|
|
2520
2488
|
"div",
|
|
2521
2489
|
{
|
|
2522
2490
|
ref: scrollerRef,
|
|
@@ -2527,25 +2495,25 @@ function SuiteAiPanel({
|
|
|
2527
2495
|
"aria-label": "Conversation",
|
|
2528
2496
|
className: "suite-scroll-lock h-full space-y-5 overflow-y-auto px-2 py-3",
|
|
2529
2497
|
children: [
|
|
2530
|
-
hydrating && messages.length === 0 ? /* @__PURE__ */
|
|
2531
|
-
/* @__PURE__ */
|
|
2498
|
+
hydrating && messages.length === 0 ? /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 text-sm text-ph-subtle", children: [
|
|
2499
|
+
/* @__PURE__ */ jsx16(Spinner, { className: "h-4 w-4 animate-spin" }),
|
|
2532
2500
|
"Loading your chat\u2026"
|
|
2533
2501
|
] }) : null,
|
|
2534
|
-
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */
|
|
2535
|
-
/* @__PURE__ */
|
|
2536
|
-
/* @__PURE__ */
|
|
2537
|
-
/* @__PURE__ */
|
|
2538
|
-
presets.length > 0 ? /* @__PURE__ */
|
|
2502
|
+
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */ jsxs14("div", { className: "mx-auto mt-4 flex max-w-sm flex-col items-center px-1 text-center", children: [
|
|
2503
|
+
/* @__PURE__ */ jsx16("span", { className: "flex h-10 w-10 items-center justify-center rounded-2xl bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ jsx16(Icon, { className: "h-5 w-5" }) }),
|
|
2504
|
+
/* @__PURE__ */ jsx16("p", { className: "mt-3 font-display text-base font-semibold text-ph-ink", children: "How can I help?" }),
|
|
2505
|
+
/* @__PURE__ */ jsx16("p", { className: "mt-1 text-sm leading-relaxed text-ph-subtle", children: emptyState }),
|
|
2506
|
+
presets.length > 0 ? /* @__PURE__ */ jsx16("div", { className: "mt-4 flex w-full flex-col gap-2", children: presets.map((preset) => /* @__PURE__ */ jsxs14(
|
|
2539
2507
|
"button",
|
|
2540
2508
|
{
|
|
2541
2509
|
type: "button",
|
|
2542
2510
|
onClick: () => void ask(preset.prompt),
|
|
2543
|
-
disabled:
|
|
2511
|
+
disabled: waiting || hydrating,
|
|
2544
2512
|
className: "group flex w-full items-center gap-2 rounded-xl border border-ph-border bg-ph-surface px-3 py-2 text-left text-sm text-ph-ink transition-colors hover:border-ph-brand/40 hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2545
2513
|
children: [
|
|
2546
|
-
/* @__PURE__ */
|
|
2547
|
-
/* @__PURE__ */
|
|
2548
|
-
/* @__PURE__ */
|
|
2514
|
+
/* @__PURE__ */ jsx16(Sparks, { className: "h-4 w-4 shrink-0 text-ph-brand" }),
|
|
2515
|
+
/* @__PURE__ */ jsx16("span", { className: "min-w-0 flex-1 truncate", children: preset.label }),
|
|
2516
|
+
/* @__PURE__ */ jsx16(ArrowUp, { className: "h-3.5 w-3.5 shrink-0 rotate-45 text-ph-mutedtext transition-transform group-hover:translate-x-0.5" })
|
|
2549
2517
|
]
|
|
2550
2518
|
},
|
|
2551
2519
|
preset.label
|
|
@@ -2555,48 +2523,61 @@ function SuiteAiPanel({
|
|
|
2555
2523
|
var _a;
|
|
2556
2524
|
const isUser = message.role === "user";
|
|
2557
2525
|
if (isUser) {
|
|
2558
|
-
return /* @__PURE__ */
|
|
2526
|
+
return /* @__PURE__ */ jsx16(
|
|
2559
2527
|
"div",
|
|
2560
2528
|
{
|
|
2561
2529
|
className: "flex justify-end",
|
|
2562
2530
|
"data-test": "ask-ai-user",
|
|
2563
|
-
children: /* @__PURE__ */
|
|
2531
|
+
children: /* @__PURE__ */ jsx16("div", { className: "w-fit max-w-[85%] whitespace-pre-wrap break-words rounded-2xl rounded-br-md bg-ph-brand px-3 py-2 text-sm leading-relaxed text-[var(--ph-on-accent)] [overflow-wrap:anywhere]", children: message.content })
|
|
2564
2532
|
},
|
|
2565
2533
|
`user-${index}`
|
|
2566
2534
|
);
|
|
2567
2535
|
}
|
|
2568
|
-
return /* @__PURE__ */
|
|
2536
|
+
return /* @__PURE__ */ jsxs14(
|
|
2569
2537
|
"div",
|
|
2570
2538
|
{
|
|
2571
2539
|
className: "flex items-end gap-2",
|
|
2572
2540
|
"data-test": "ask-ai-assistant",
|
|
2573
2541
|
children: [
|
|
2574
|
-
/* @__PURE__ */
|
|
2542
|
+
/* @__PURE__ */ jsx16(
|
|
2575
2543
|
"span",
|
|
2576
2544
|
{
|
|
2577
2545
|
className: "mb-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand",
|
|
2578
2546
|
"aria-hidden": true,
|
|
2579
|
-
children: /* @__PURE__ */
|
|
2547
|
+
children: /* @__PURE__ */ jsx16(Icon, { className: "h-3.5 w-3.5" })
|
|
2580
2548
|
}
|
|
2581
2549
|
),
|
|
2582
|
-
/* @__PURE__ */
|
|
2583
|
-
/* @__PURE__ */
|
|
2550
|
+
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 max-w-[85%] space-y-2", children: [
|
|
2551
|
+
/* @__PURE__ */ jsx16("div", { className: "rounded-2xl rounded-bl-md bg-ph-muted px-3 py-2 text-sm leading-relaxed text-ph-ink", children: /* @__PURE__ */ jsx16(
|
|
2584
2552
|
Suspense,
|
|
2585
2553
|
{
|
|
2586
|
-
fallback: /* @__PURE__ */
|
|
2587
|
-
|
|
2554
|
+
fallback: /* @__PURE__ */ jsxs14(
|
|
2555
|
+
"div",
|
|
2556
|
+
{
|
|
2557
|
+
className: "space-y-2 py-0.5",
|
|
2558
|
+
role: "status",
|
|
2559
|
+
"aria-label": "Rendering response",
|
|
2560
|
+
children: [
|
|
2561
|
+
/* @__PURE__ */ jsx16("span", { className: "sr-only", children: "Rendering response\u2026" }),
|
|
2562
|
+
/* @__PURE__ */ jsx16("div", { className: "h-3 w-11/12 rounded bg-ph-mutedtext/20 motion-safe:animate-pulse" }),
|
|
2563
|
+
/* @__PURE__ */ jsx16("div", { className: "h-3 w-full rounded bg-ph-mutedtext/20 motion-safe:animate-pulse" }),
|
|
2564
|
+
/* @__PURE__ */ jsx16("div", { className: "h-3 w-3/5 rounded bg-ph-mutedtext/20 motion-safe:animate-pulse" })
|
|
2565
|
+
]
|
|
2566
|
+
}
|
|
2567
|
+
),
|
|
2568
|
+
children: /* @__PURE__ */ jsx16(SuiteAiBlockNoteMessage, { markdown: message.content })
|
|
2588
2569
|
}
|
|
2589
2570
|
) }),
|
|
2590
|
-
((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */
|
|
2571
|
+
((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */ jsxs14(
|
|
2591
2572
|
"div",
|
|
2592
2573
|
{
|
|
2593
2574
|
"data-test": "ask-ai-action",
|
|
2594
2575
|
"data-status": action.status,
|
|
2595
2576
|
className: "rounded-xl border border-ph-border bg-ph-surface px-3 py-2 text-sm text-ph-ink",
|
|
2596
2577
|
children: [
|
|
2597
|
-
/* @__PURE__ */
|
|
2598
|
-
action.status === "proposed" ? /* @__PURE__ */
|
|
2599
|
-
/* @__PURE__ */
|
|
2578
|
+
/* @__PURE__ */ jsx16("p", { className: "font-medium", children: action.summary }),
|
|
2579
|
+
action.status === "proposed" ? /* @__PURE__ */ jsxs14("div", { className: "mt-2 flex flex-wrap gap-2", children: [
|
|
2580
|
+
/* @__PURE__ */ jsx16(
|
|
2600
2581
|
"button",
|
|
2601
2582
|
{
|
|
2602
2583
|
type: "button",
|
|
@@ -2607,7 +2588,7 @@ function SuiteAiPanel({
|
|
|
2607
2588
|
children: resolvingId === action.id ? "Working\u2026" : "Confirm"
|
|
2608
2589
|
}
|
|
2609
2590
|
),
|
|
2610
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ jsx16(
|
|
2611
2592
|
"button",
|
|
2612
2593
|
{
|
|
2613
2594
|
type: "button",
|
|
@@ -2619,11 +2600,11 @@ function SuiteAiPanel({
|
|
|
2619
2600
|
}
|
|
2620
2601
|
)
|
|
2621
2602
|
] }) : null,
|
|
2622
|
-
action.status === "applied" ? /* @__PURE__ */
|
|
2603
|
+
action.status === "applied" ? /* @__PURE__ */ jsxs14("p", { className: "mt-1 text-xs text-ph-subtle", children: [
|
|
2623
2604
|
"Done",
|
|
2624
|
-
action.href ? /* @__PURE__ */
|
|
2605
|
+
action.href ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
2625
2606
|
" \xB7 ",
|
|
2626
|
-
/* @__PURE__ */
|
|
2607
|
+
/* @__PURE__ */ jsx16(
|
|
2627
2608
|
"a",
|
|
2628
2609
|
{
|
|
2629
2610
|
href: action.href,
|
|
@@ -2633,8 +2614,8 @@ function SuiteAiPanel({
|
|
|
2633
2614
|
)
|
|
2634
2615
|
] }) : null
|
|
2635
2616
|
] }) : null,
|
|
2636
|
-
action.status === "cancelled" ? /* @__PURE__ */
|
|
2637
|
-
action.status === "failed" ? /* @__PURE__ */
|
|
2617
|
+
action.status === "cancelled" ? /* @__PURE__ */ jsx16("p", { className: "mt-1 text-xs text-ph-subtle", children: "Cancelled" }) : null,
|
|
2618
|
+
action.status === "failed" ? /* @__PURE__ */ jsx16("p", { className: "mt-1 text-xs text-ph-danger", children: action.error || "Could not apply that." }) : null
|
|
2638
2619
|
]
|
|
2639
2620
|
},
|
|
2640
2621
|
action.id
|
|
@@ -2645,31 +2626,31 @@ function SuiteAiPanel({
|
|
|
2645
2626
|
`assistant-${index}`
|
|
2646
2627
|
);
|
|
2647
2628
|
}),
|
|
2648
|
-
|
|
2649
|
-
/* @__PURE__ */
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
2653
|
-
/* @__PURE__ */
|
|
2629
|
+
waiting ? /* @__PURE__ */ jsxs14("div", { className: "flex items-end gap-2", "aria-hidden": true, children: [
|
|
2630
|
+
/* @__PURE__ */ jsx16("span", { className: "mb-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-ph-brand/10 text-ph-brand", children: /* @__PURE__ */ jsx16(Icon, { className: "h-3.5 w-3.5" }) }),
|
|
2631
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1.5 rounded-2xl rounded-bl-md bg-ph-muted px-3 py-2.5", children: [
|
|
2632
|
+
/* @__PURE__ */ jsx16("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce" }),
|
|
2633
|
+
/* @__PURE__ */ jsx16("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.15s]" }),
|
|
2634
|
+
/* @__PURE__ */ jsx16("span", { className: "h-1.5 w-1.5 rounded-full bg-ph-mutedtext motion-safe:animate-bounce [animation-delay:0.3s]" })
|
|
2654
2635
|
] })
|
|
2655
2636
|
] }) : null,
|
|
2656
|
-
|
|
2657
|
-
error ? /* @__PURE__ */
|
|
2637
|
+
waiting ? /* @__PURE__ */ jsx16("span", { className: "sr-only", "aria-live": "polite", children: "Assistant is responding\u2026" }) : null,
|
|
2638
|
+
error ? /* @__PURE__ */ jsxs14(
|
|
2658
2639
|
"div",
|
|
2659
2640
|
{
|
|
2660
2641
|
role: "alert",
|
|
2661
2642
|
className: "flex items-start gap-2 rounded-xl border border-ph-danger/30 bg-ph-danger/10 px-3 py-2.5 text-sm text-ph-ink",
|
|
2662
2643
|
children: [
|
|
2663
|
-
/* @__PURE__ */
|
|
2664
|
-
/* @__PURE__ */
|
|
2665
|
-
/* @__PURE__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2644
|
+
/* @__PURE__ */ jsx16(WarningTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-ph-danger" }),
|
|
2645
|
+
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
|
|
2646
|
+
/* @__PURE__ */ jsx16("p", { className: "font-medium text-ph-danger", children: "Something went wrong" }),
|
|
2647
|
+
/* @__PURE__ */ jsx16("p", { className: "mt-0.5 text-ph-subtle", children: error }),
|
|
2648
|
+
/* @__PURE__ */ jsx16(
|
|
2668
2649
|
"button",
|
|
2669
2650
|
{
|
|
2670
2651
|
type: "button",
|
|
2671
2652
|
onClick: retry,
|
|
2672
|
-
disabled:
|
|
2653
|
+
disabled: waiting,
|
|
2673
2654
|
className: "mt-2 inline-flex min-h-8 items-center gap-1.5 rounded-lg border border-ph-border bg-ph-surface px-2.5 text-xs font-medium text-ph-ink transition-colors hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2674
2655
|
children: "Try again"
|
|
2675
2656
|
}
|
|
@@ -2681,20 +2662,20 @@ function SuiteAiPanel({
|
|
|
2681
2662
|
]
|
|
2682
2663
|
}
|
|
2683
2664
|
),
|
|
2684
|
-
!atBottom ? /* @__PURE__ */
|
|
2665
|
+
!atBottom ? /* @__PURE__ */ jsx16("div", { className: "absolute bottom-3 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx16(Tooltip, { content: "Scroll to latest", children: /* @__PURE__ */ jsx16(
|
|
2685
2666
|
"button",
|
|
2686
2667
|
{
|
|
2687
2668
|
type: "button",
|
|
2688
2669
|
onClick: () => scrollToBottom("smooth"),
|
|
2689
2670
|
className: "flex h-9 w-9 items-center justify-center rounded-full border border-ph-border bg-ph-surface text-ph-subtle shadow-ph-md transition-colors hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus",
|
|
2690
2671
|
"aria-label": "Scroll to latest",
|
|
2691
|
-
children: /* @__PURE__ */
|
|
2672
|
+
children: /* @__PURE__ */ jsx16(ArrowDown, { className: "h-4 w-4" })
|
|
2692
2673
|
}
|
|
2693
2674
|
) }) }) : null
|
|
2694
2675
|
] }),
|
|
2695
|
-
/* @__PURE__ */
|
|
2696
|
-
/* @__PURE__ */
|
|
2697
|
-
/* @__PURE__ */
|
|
2676
|
+
/* @__PURE__ */ jsx16("div", { className: "px-2 pt-2 pb-[max(2rem,calc(env(safe-area-inset-bottom)+1rem))]", children: /* @__PURE__ */ jsxs14("div", { className: "flex items-end gap-1.5 rounded-2xl border border-ph-border bg-ph-surface px-1.5 py-1 transition-colors focus-within:border-ph-brand/45 focus-within:ring-2 focus-within:ring-ph-focus/35", children: [
|
|
2677
|
+
/* @__PURE__ */ jsx16("label", { htmlFor: inputId, className: "sr-only", children: "Ask a question" }),
|
|
2678
|
+
/* @__PURE__ */ jsx16(
|
|
2698
2679
|
"textarea",
|
|
2699
2680
|
{
|
|
2700
2681
|
id: inputId,
|
|
@@ -2713,7 +2694,7 @@ function SuiteAiPanel({
|
|
|
2713
2694
|
className: "max-h-36 min-h-10 flex-1 resize-none bg-transparent px-1.5 py-2 text-sm leading-relaxed text-ph-ink outline-none placeholder:text-ph-mutedtext"
|
|
2714
2695
|
}
|
|
2715
2696
|
),
|
|
2716
|
-
loading ? /* @__PURE__ */
|
|
2697
|
+
loading ? /* @__PURE__ */ jsx16(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ jsx16(
|
|
2717
2698
|
"button",
|
|
2718
2699
|
{
|
|
2719
2700
|
type: "button",
|
|
@@ -2721,9 +2702,18 @@ function SuiteAiPanel({
|
|
|
2721
2702
|
"data-test": "ask-ai-stop",
|
|
2722
2703
|
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-ph-muted text-ph-ink transition-colors hover:bg-ph-border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus",
|
|
2723
2704
|
"aria-label": "Stop generating",
|
|
2724
|
-
children: /* @__PURE__ */
|
|
2705
|
+
children: /* @__PURE__ */ jsx16(Square, { className: "h-3.5 w-3.5 fill-current" })
|
|
2706
|
+
}
|
|
2707
|
+
) }) : isWaitingForReply ? /* @__PURE__ */ jsx16(
|
|
2708
|
+
"span",
|
|
2709
|
+
{
|
|
2710
|
+
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-ph-muted text-ph-subtle",
|
|
2711
|
+
"data-test": "ask-ai-waiting",
|
|
2712
|
+
role: "status",
|
|
2713
|
+
"aria-label": "Shelly is responding",
|
|
2714
|
+
children: /* @__PURE__ */ jsx16(Spinner, { className: "h-4 w-4 animate-spin" })
|
|
2725
2715
|
}
|
|
2726
|
-
)
|
|
2716
|
+
) : /* @__PURE__ */ jsx16(Tooltip, { content: "Send message", children: /* @__PURE__ */ jsx16(
|
|
2727
2717
|
"button",
|
|
2728
2718
|
{
|
|
2729
2719
|
type: "button",
|
|
@@ -2732,7 +2722,7 @@ function SuiteAiPanel({
|
|
|
2732
2722
|
"data-test": "ask-ai-send",
|
|
2733
2723
|
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-ph-brand text-[color:var(--ph-on-accent)] transition-opacity hover:bg-ph-brand-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-focus disabled:opacity-40",
|
|
2734
2724
|
"aria-label": "Send message",
|
|
2735
|
-
children: /* @__PURE__ */
|
|
2725
|
+
children: /* @__PURE__ */ jsx16(ArrowUp, { className: "h-4 w-4" })
|
|
2736
2726
|
}
|
|
2737
2727
|
) })
|
|
2738
2728
|
] }) })
|
|
@@ -2744,7 +2734,7 @@ function SuiteAiPanel({
|
|
|
2744
2734
|
// src/suite/components/workspace-switcher.tsx
|
|
2745
2735
|
import { useState as useState8 } from "react";
|
|
2746
2736
|
import { Building, Check, NavArrowDown } from "iconoir-react";
|
|
2747
|
-
import { Fragment as Fragment6, jsx as
|
|
2737
|
+
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2748
2738
|
function SuiteWorkspaceSwitcher({
|
|
2749
2739
|
workspaces = [],
|
|
2750
2740
|
groups,
|
|
@@ -2762,7 +2752,7 @@ function SuiteWorkspaceSwitcher({
|
|
|
2762
2752
|
var _a;
|
|
2763
2753
|
const [open, setOpen] = useState8(false);
|
|
2764
2754
|
const sections = (_a = groups == null ? void 0 : groups.filter((group) => group.workspaces.length > 0)) != null ? _a : workspaces.length > 0 ? [{ id: "workspaces", label: "Switch workspace", workspaces }] : [];
|
|
2765
|
-
return /* @__PURE__ */
|
|
2755
|
+
return /* @__PURE__ */ jsx17(
|
|
2766
2756
|
DropdownMenu2,
|
|
2767
2757
|
{
|
|
2768
2758
|
"aria-label": "Switch workspace",
|
|
@@ -2773,24 +2763,23 @@ function SuiteWorkspaceSwitcher({
|
|
|
2773
2763
|
align: "start",
|
|
2774
2764
|
open,
|
|
2775
2765
|
onOpenChange: setOpen,
|
|
2776
|
-
trigger: /* @__PURE__ */
|
|
2766
|
+
trigger: /* @__PURE__ */ jsxs15(
|
|
2777
2767
|
"span",
|
|
2778
2768
|
{
|
|
2779
|
-
className:
|
|
2769
|
+
className: cn2(
|
|
2780
2770
|
"flex min-w-0 max-w-full items-center gap-2 rounded-lg border border-ph-border bg-ph-muted text-left transition-colors hover:bg-ph-muted",
|
|
2781
2771
|
collapsed ? "h-10 w-10 justify-center p-0" : "w-full px-3 py-2",
|
|
2782
2772
|
open && "border-ph-brand/40"
|
|
2783
2773
|
),
|
|
2784
2774
|
"data-test": "workspace-switcher-trigger",
|
|
2785
|
-
"aria-expanded": open,
|
|
2786
2775
|
children: [
|
|
2787
|
-
/* @__PURE__ */
|
|
2788
|
-
!collapsed ? /* @__PURE__ */
|
|
2789
|
-
/* @__PURE__ */
|
|
2790
|
-
/* @__PURE__ */
|
|
2776
|
+
/* @__PURE__ */ jsx17(Building, { className: "h-4 w-4 shrink-0 text-ph-ink", "aria-hidden": true }),
|
|
2777
|
+
!collapsed ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
2778
|
+
/* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: name }),
|
|
2779
|
+
/* @__PURE__ */ jsx17(
|
|
2791
2780
|
NavArrowDown,
|
|
2792
2781
|
{
|
|
2793
|
-
className:
|
|
2782
|
+
className: cn2(
|
|
2794
2783
|
"h-3.5 w-3.5 shrink-0 text-ph-mutedtext transition-transform",
|
|
2795
2784
|
open && "rotate-180"
|
|
2796
2785
|
),
|
|
@@ -2801,21 +2790,20 @@ function SuiteWorkspaceSwitcher({
|
|
|
2801
2790
|
]
|
|
2802
2791
|
}
|
|
2803
2792
|
),
|
|
2804
|
-
children: /* @__PURE__ */
|
|
2793
|
+
children: /* @__PURE__ */ jsxs15(
|
|
2805
2794
|
"div",
|
|
2806
2795
|
{
|
|
2807
2796
|
id: "workspace-switcher-menu",
|
|
2808
2797
|
className: "p-1",
|
|
2809
2798
|
"data-test": "workspace-switcher-menu",
|
|
2810
2799
|
children: [
|
|
2811
|
-
sections.length === 0 ? /* @__PURE__ */
|
|
2812
|
-
/* @__PURE__ */
|
|
2813
|
-
section.workspaces.map((workspace) => /* @__PURE__ */
|
|
2800
|
+
sections.length === 0 ? /* @__PURE__ */ jsx17("p", { className: "px-3 py-2 text-sm text-ph-mutedtext", children: emptyLabel }) : sections.map((section) => /* @__PURE__ */ jsxs15("div", { children: [
|
|
2801
|
+
/* @__PURE__ */ jsx17("p", { className: "px-3 py-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-ph-mutedtext", children: section.label }),
|
|
2802
|
+
section.workspaces.map((workspace) => /* @__PURE__ */ jsx17(
|
|
2814
2803
|
DropdownItem2,
|
|
2815
2804
|
{
|
|
2816
2805
|
id: `workspace-option-${workspace.id}`,
|
|
2817
|
-
|
|
2818
|
-
"aria-selected": workspace.id === currentId,
|
|
2806
|
+
"aria-current": workspace.id === currentId ? "true" : void 0,
|
|
2819
2807
|
"data-test": "workspace-option",
|
|
2820
2808
|
"data-workspace-id": workspace.id,
|
|
2821
2809
|
onMouseDown: (event) => event.preventDefault(),
|
|
@@ -2824,12 +2812,12 @@ function SuiteWorkspaceSwitcher({
|
|
|
2824
2812
|
onSelect(workspace);
|
|
2825
2813
|
},
|
|
2826
2814
|
className: appSwitcherMenuItemClass(),
|
|
2827
|
-
children: /* @__PURE__ */
|
|
2828
|
-
/* @__PURE__ */
|
|
2829
|
-
/* @__PURE__ */
|
|
2830
|
-
workspace.description ? /* @__PURE__ */
|
|
2815
|
+
children: /* @__PURE__ */ jsxs15("span", { className: "flex min-w-0 w-full items-center gap-3", children: [
|
|
2816
|
+
/* @__PURE__ */ jsxs15("span", { className: "min-w-0 flex-1", children: [
|
|
2817
|
+
/* @__PURE__ */ jsx17("span", { className: "block truncate text-sm font-medium text-ph-ink", children: workspace.name }),
|
|
2818
|
+
workspace.description ? /* @__PURE__ */ jsx17("span", { className: "block truncate text-xs text-ph-mutedtext", children: workspace.description }) : null
|
|
2831
2819
|
] }),
|
|
2832
|
-
workspace.id === currentId ? /* @__PURE__ */
|
|
2820
|
+
workspace.id === currentId ? /* @__PURE__ */ jsx17(
|
|
2833
2821
|
Check,
|
|
2834
2822
|
{
|
|
2835
2823
|
className: "h-4 w-4 shrink-0 text-ph-brand",
|
|
@@ -2841,7 +2829,7 @@ function SuiteWorkspaceSwitcher({
|
|
|
2841
2829
|
workspace.id
|
|
2842
2830
|
))
|
|
2843
2831
|
] }, section.id)),
|
|
2844
|
-
footer ? /* @__PURE__ */
|
|
2832
|
+
footer ? /* @__PURE__ */ jsx17("div", { className: "mt-1 border-t border-ph-border pt-1", children: footer }) : null
|
|
2845
2833
|
]
|
|
2846
2834
|
}
|
|
2847
2835
|
)
|
|
@@ -2849,6 +2837,63 @@ function SuiteWorkspaceSwitcher({
|
|
|
2849
2837
|
);
|
|
2850
2838
|
}
|
|
2851
2839
|
|
|
2840
|
+
// src/suite/icons/suite-icon.tsx
|
|
2841
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2842
|
+
var TODAY_SUN_STYLE = `
|
|
2843
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2844
|
+
.suite-icon-today-sun-rays {
|
|
2845
|
+
animation: suite-icon-today-sun-spin 18s linear infinite;
|
|
2846
|
+
transform-box: fill-box;
|
|
2847
|
+
transform-origin: center;
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
@keyframes suite-icon-today-sun-spin {
|
|
2851
|
+
to { transform: rotate(360deg); }
|
|
2852
|
+
}
|
|
2853
|
+
`;
|
|
2854
|
+
function SuiteIcon({
|
|
2855
|
+
name,
|
|
2856
|
+
size = 24,
|
|
2857
|
+
accent,
|
|
2858
|
+
strokeWidth = 2,
|
|
2859
|
+
animated = true,
|
|
2860
|
+
label,
|
|
2861
|
+
className,
|
|
2862
|
+
style
|
|
2863
|
+
}) {
|
|
2864
|
+
const glyph = SUITE_GLYPHS[name];
|
|
2865
|
+
const accentHex = accent ? APP_ACCENTS[accent].accent : void 0;
|
|
2866
|
+
const mergedStyle = accentHex ? __spreadProps(__spreadValues({}, style), { "--suite-icon-accent": accentHex }) : style;
|
|
2867
|
+
return /* @__PURE__ */ jsxs16(
|
|
2868
|
+
"svg",
|
|
2869
|
+
{
|
|
2870
|
+
width: size,
|
|
2871
|
+
height: size,
|
|
2872
|
+
viewBox: "0 0 24 24",
|
|
2873
|
+
fill: "none",
|
|
2874
|
+
stroke: "currentColor",
|
|
2875
|
+
strokeWidth,
|
|
2876
|
+
strokeLinecap: "round",
|
|
2877
|
+
strokeLinejoin: "round",
|
|
2878
|
+
className: cn2("shrink-0", className),
|
|
2879
|
+
style: mergedStyle,
|
|
2880
|
+
role: label ? "img" : void 0,
|
|
2881
|
+
"aria-label": label,
|
|
2882
|
+
"aria-hidden": label ? void 0 : true,
|
|
2883
|
+
children: [
|
|
2884
|
+
glyph.animatedAccent && animated ? /* @__PURE__ */ jsx18("style", { children: TODAY_SUN_STYLE }) : null,
|
|
2885
|
+
/* @__PURE__ */ jsx18(
|
|
2886
|
+
GlyphParts,
|
|
2887
|
+
{
|
|
2888
|
+
elements: glyph.elements,
|
|
2889
|
+
accentClassName: glyph.animatedAccent && animated ? "suite-icon-today-sun-rays" : void 0
|
|
2890
|
+
}
|
|
2891
|
+
)
|
|
2892
|
+
]
|
|
2893
|
+
}
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2852
2897
|
// src/suite/lib/use-sidebar-width.ts
|
|
2853
2898
|
import {
|
|
2854
2899
|
useCallback as useCallback3,
|
|
@@ -2866,8 +2911,7 @@ var LEGACY_SIDEBAR_WIDTH_KEYS = [
|
|
|
2866
2911
|
"tides-sidebar-width",
|
|
2867
2912
|
"tt-sidebar-width",
|
|
2868
2913
|
"kraken-sidebar-width",
|
|
2869
|
-
"shellstack-sidebar-width"
|
|
2870
|
-
"nakama-sidebar-width"
|
|
2914
|
+
"shellstack-sidebar-width"
|
|
2871
2915
|
];
|
|
2872
2916
|
function isSuiteSidebarKey(storageKey) {
|
|
2873
2917
|
return storageKey === SUITE_SIDEBAR_WIDTH_KEY || LEGACY_SIDEBAR_WIDTH_KEYS.includes(
|
|
@@ -2875,6 +2919,7 @@ function isSuiteSidebarKey(storageKey) {
|
|
|
2875
2919
|
);
|
|
2876
2920
|
}
|
|
2877
2921
|
function sidebarColumnWidth(width, collapsed, _chatOpen = false) {
|
|
2922
|
+
void _chatOpen;
|
|
2878
2923
|
if (collapsed) return SIDEBAR_RAIL_WIDTH;
|
|
2879
2924
|
return width;
|
|
2880
2925
|
}
|
|
@@ -2891,50 +2936,6 @@ function parseWidth(raw) {
|
|
|
2891
2936
|
const parsed = Number.parseInt(raw, 10);
|
|
2892
2937
|
return Number.isNaN(parsed) ? null : parsed;
|
|
2893
2938
|
}
|
|
2894
|
-
function suiteCookieDomainAttr() {
|
|
2895
|
-
var _a;
|
|
2896
|
-
const host = window.location.hostname;
|
|
2897
|
-
if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
|
|
2898
|
-
return "";
|
|
2899
|
-
}
|
|
2900
|
-
if (host.endsWith(".localhost")) {
|
|
2901
|
-
return "; Domain=.localhost";
|
|
2902
|
-
}
|
|
2903
|
-
const known = /* @__PURE__ */ new Set([
|
|
2904
|
-
"tides",
|
|
2905
|
-
"kraken",
|
|
2906
|
-
"turtletime",
|
|
2907
|
-
"time",
|
|
2908
|
-
"nakama",
|
|
2909
|
-
"app",
|
|
2910
|
-
"shellstack",
|
|
2911
|
-
"portal"
|
|
2912
|
-
]);
|
|
2913
|
-
const parts = host.split(".");
|
|
2914
|
-
if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
|
|
2915
|
-
return `; Domain=.${parts.slice(1).join(".")}`;
|
|
2916
|
-
}
|
|
2917
|
-
if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
|
|
2918
|
-
return "";
|
|
2919
|
-
}
|
|
2920
|
-
function readCookie(name) {
|
|
2921
|
-
const prefix = `${name}=`;
|
|
2922
|
-
for (const part of document.cookie.split(";")) {
|
|
2923
|
-
const trimmed = part.trim();
|
|
2924
|
-
if (trimmed.startsWith(prefix)) {
|
|
2925
|
-
return decodeURIComponent(trimmed.slice(prefix.length));
|
|
2926
|
-
}
|
|
2927
|
-
}
|
|
2928
|
-
return null;
|
|
2929
|
-
}
|
|
2930
|
-
function writeCookie(name, value) {
|
|
2931
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2932
|
-
document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
2933
|
-
}
|
|
2934
|
-
function clearCookie(name) {
|
|
2935
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2936
|
-
document.cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
2937
|
-
}
|
|
2938
2939
|
function readSidebarWidth(storageKey) {
|
|
2939
2940
|
try {
|
|
2940
2941
|
if (isSuiteSidebarKey(storageKey)) {
|
|
@@ -3090,7 +3091,7 @@ function SuiteSkeleton({
|
|
|
3090
3091
|
return /* @__PURE__ */ jsx20(
|
|
3091
3092
|
"div",
|
|
3092
3093
|
{
|
|
3093
|
-
className:
|
|
3094
|
+
className: cn2("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
3094
3095
|
"aria-hidden": true,
|
|
3095
3096
|
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
3096
3097
|
"div",
|
|
@@ -3100,7 +3101,7 @@ function SuiteSkeleton({
|
|
|
3100
3101
|
children: /* @__PURE__ */ jsx20(
|
|
3101
3102
|
"div",
|
|
3102
3103
|
{
|
|
3103
|
-
className:
|
|
3104
|
+
className: cn2(
|
|
3104
3105
|
"ph-skeleton",
|
|
3105
3106
|
circle ? "h-10 w-10 rounded-full" : "h-3",
|
|
3106
3107
|
className
|
|
@@ -3124,7 +3125,7 @@ function SuiteSkeletonCard({
|
|
|
3124
3125
|
return /* @__PURE__ */ jsxs17(
|
|
3125
3126
|
"div",
|
|
3126
3127
|
{
|
|
3127
|
-
className:
|
|
3128
|
+
className: cn2(
|
|
3128
3129
|
"ph-skeleton-card animate-[skeleton-stagger_0.5s_ease-out_both] rounded-2xl border border-ph-border bg-ph-surface p-6 shadow-sm",
|
|
3129
3130
|
className
|
|
3130
3131
|
),
|
|
@@ -3167,7 +3168,7 @@ function SuiteSkeletonList({
|
|
|
3167
3168
|
className,
|
|
3168
3169
|
items = 4
|
|
3169
3170
|
}) {
|
|
3170
|
-
return /* @__PURE__ */ jsx20("div", { className:
|
|
3171
|
+
return /* @__PURE__ */ jsx20("div", { className: cn2("space-y-3", className), "aria-hidden": true, children: Array.from({ length: items }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
3171
3172
|
"div",
|
|
3172
3173
|
{
|
|
3173
3174
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
@@ -3194,7 +3195,7 @@ function SuiteEmptyState({
|
|
|
3194
3195
|
return /* @__PURE__ */ jsxs17(
|
|
3195
3196
|
"div",
|
|
3196
3197
|
{
|
|
3197
|
-
className:
|
|
3198
|
+
className: cn2(
|
|
3198
3199
|
"relative overflow-hidden rounded-2xl border border-ph-border bg-ph-surface text-center",
|
|
3199
3200
|
size === "sm" ? "px-5 py-8" : "px-6 py-12 sm:px-10 sm:py-16",
|
|
3200
3201
|
className
|
|
@@ -3207,9 +3208,9 @@ function SuiteEmptyState({
|
|
|
3207
3208
|
/* @__PURE__ */ jsxs17("div", { className: "relative", children: [
|
|
3208
3209
|
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,
|
|
3209
3210
|
/* @__PURE__ */ jsx20(
|
|
3210
|
-
"
|
|
3211
|
+
"h2",
|
|
3211
3212
|
{
|
|
3212
|
-
className:
|
|
3213
|
+
className: cn2(
|
|
3213
3214
|
"font-semibold text-ph-ink",
|
|
3214
3215
|
size === "sm" ? "text-base" : "text-lg"
|
|
3215
3216
|
),
|
|
@@ -3240,14 +3241,14 @@ function SuiteSettingsMobileNav({
|
|
|
3240
3241
|
{
|
|
3241
3242
|
"data-test": dataTest,
|
|
3242
3243
|
"aria-label": ariaLabel,
|
|
3243
|
-
className:
|
|
3244
|
+
className: cn2("suite-settings-mobile-nav lg:hidden", className),
|
|
3244
3245
|
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) => {
|
|
3245
3246
|
const Icon = item.icon;
|
|
3246
3247
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
3247
3248
|
const iconNode = isValidElement(item.icon) ? item.icon : /* @__PURE__ */ jsx21(
|
|
3248
3249
|
Icon,
|
|
3249
3250
|
{
|
|
3250
|
-
className:
|
|
3251
|
+
className: cn2(
|
|
3251
3252
|
"h-4 w-4 shrink-0 transition",
|
|
3252
3253
|
active ? "text-ph-surface" : "text-ph-mutedtext"
|
|
3253
3254
|
),
|
|
@@ -3262,7 +3263,7 @@ function SuiteSettingsMobileNav({
|
|
|
3262
3263
|
"data-test": item.testId,
|
|
3263
3264
|
onClick: () => onSelect(item.href),
|
|
3264
3265
|
"aria-current": active ? "page" : void 0,
|
|
3265
|
-
className:
|
|
3266
|
+
className: cn2(
|
|
3266
3267
|
"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",
|
|
3267
3268
|
"min-h-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
3268
3269
|
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"
|
|
@@ -3347,7 +3348,7 @@ function SuiteSidebar({
|
|
|
3347
3348
|
"aria-pressed": askAiOpen,
|
|
3348
3349
|
"aria-label": askAiOpen ? "Back to navigation" : "Shelly AI",
|
|
3349
3350
|
onClick: toggleAskAi,
|
|
3350
|
-
className:
|
|
3351
|
+
className: cn2(
|
|
3351
3352
|
"inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-focus-ring",
|
|
3352
3353
|
askAiOpen ? "bg-ph-brand/10 text-ph-brand" : "text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink"
|
|
3353
3354
|
),
|
|
@@ -3359,7 +3360,7 @@ function SuiteSidebar({
|
|
|
3359
3360
|
"div",
|
|
3360
3361
|
{
|
|
3361
3362
|
"data-suite-chat-open": "",
|
|
3362
|
-
className:
|
|
3363
|
+
className: cn2(
|
|
3363
3364
|
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
3364
3365
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3365
3366
|
className
|
|
@@ -3368,12 +3369,12 @@ function SuiteSidebar({
|
|
|
3368
3369
|
/* @__PURE__ */ jsxs19(
|
|
3369
3370
|
"div",
|
|
3370
3371
|
{
|
|
3371
|
-
className:
|
|
3372
|
+
className: cn2(
|
|
3372
3373
|
"flex h-14 shrink-0 items-center gap-1 border-b border-ph-border px-2",
|
|
3373
3374
|
surface ? "bg-ph-surface" : "bg-ph-canvas"
|
|
3374
3375
|
),
|
|
3375
3376
|
children: [
|
|
3376
|
-
/* @__PURE__ */ jsx22(
|
|
3377
|
+
/* @__PURE__ */ jsx22(
|
|
3377
3378
|
"button",
|
|
3378
3379
|
{
|
|
3379
3380
|
type: "button",
|
|
@@ -3383,7 +3384,7 @@ function SuiteSidebar({
|
|
|
3383
3384
|
className: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-ph-subtle transition-colors hover:bg-ph-muted hover:text-ph-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
3384
3385
|
children: /* @__PURE__ */ jsx22(NavArrowLeft, { className: "h-4 w-4", "aria-hidden": true })
|
|
3385
3386
|
}
|
|
3386
|
-
)
|
|
3387
|
+
),
|
|
3387
3388
|
/* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: "Shelly AI" })
|
|
3388
3389
|
]
|
|
3389
3390
|
}
|
|
@@ -3396,7 +3397,7 @@ function SuiteSidebar({
|
|
|
3396
3397
|
return /* @__PURE__ */ jsxs19(
|
|
3397
3398
|
"div",
|
|
3398
3399
|
{
|
|
3399
|
-
className:
|
|
3400
|
+
className: cn2(
|
|
3400
3401
|
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
3401
3402
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3402
3403
|
className
|
|
@@ -3405,13 +3406,13 @@ function SuiteSidebar({
|
|
|
3405
3406
|
appSwitcher || notificationBell ? /* @__PURE__ */ jsxs19(
|
|
3406
3407
|
"div",
|
|
3407
3408
|
{
|
|
3408
|
-
className:
|
|
3409
|
+
className: cn2(
|
|
3409
3410
|
"flex shrink-0 border-b border-ph-border",
|
|
3410
3411
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3411
3412
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
3412
3413
|
),
|
|
3413
3414
|
children: [
|
|
3414
|
-
/* @__PURE__ */ jsx22("div", { className:
|
|
3415
|
+
/* @__PURE__ */ jsx22("div", { className: cn2("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
3415
3416
|
collapsed ? null : /* @__PURE__ */ jsx22("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
3416
3417
|
]
|
|
3417
3418
|
}
|
|
@@ -3419,14 +3420,23 @@ function SuiteSidebar({
|
|
|
3419
3420
|
/* @__PURE__ */ jsxs19(
|
|
3420
3421
|
"div",
|
|
3421
3422
|
{
|
|
3422
|
-
className:
|
|
3423
|
+
className: cn2(
|
|
3423
3424
|
"flex min-h-0 flex-1 flex-col",
|
|
3424
3425
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3425
3426
|
chatOpen ? "min-h-0" : "overflow-y-auto",
|
|
3426
|
-
collapsed ? "px-1.5 py-2" : "p-
|
|
3427
|
+
collapsed ? "px-1.5 py-2" : "p-3"
|
|
3427
3428
|
),
|
|
3428
3429
|
children: [
|
|
3429
|
-
/* @__PURE__ */ jsx22(
|
|
3430
|
+
contextSwitcher ? /* @__PURE__ */ jsx22(
|
|
3431
|
+
"div",
|
|
3432
|
+
{
|
|
3433
|
+
className: cn2(
|
|
3434
|
+
"mb-4 w-full shrink-0",
|
|
3435
|
+
collapsed && "flex justify-center"
|
|
3436
|
+
),
|
|
3437
|
+
children: renderNode(contextSwitcher, collapsed)
|
|
3438
|
+
}
|
|
3439
|
+
) : null,
|
|
3430
3440
|
chatOpen ? /* @__PURE__ */ jsxs19("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3431
3441
|
/* @__PURE__ */ jsxs19("div", { className: "mb-2 flex shrink-0 items-center gap-1", children: [
|
|
3432
3442
|
/* @__PURE__ */ jsxs19(
|
|
@@ -3446,7 +3456,7 @@ function SuiteSidebar({
|
|
|
3446
3456
|
] }),
|
|
3447
3457
|
/* @__PURE__ */ jsx22("div", { className: "min-h-0 flex-1", children: askAi })
|
|
3448
3458
|
] }) : /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
3449
|
-
/* @__PURE__ */ jsx22("nav", { "aria-label": "Pages", className: "shrink-0 space-y-
|
|
3459
|
+
/* @__PURE__ */ jsx22("nav", { "aria-label": "Pages", className: "shrink-0 space-y-1", children: /* @__PURE__ */ jsx22("div", { className: "space-y-1", children: navItems.map((item) => {
|
|
3450
3460
|
var _a;
|
|
3451
3461
|
const Icon = item.icon;
|
|
3452
3462
|
const active = Boolean(item.active);
|
|
@@ -3458,7 +3468,7 @@ function SuiteSidebar({
|
|
|
3458
3468
|
"data-test": (_a = item.dataTest) != null ? _a : "nav-link",
|
|
3459
3469
|
"aria-current": active ? "page" : void 0,
|
|
3460
3470
|
onClick: item.onClick,
|
|
3461
|
-
className:
|
|
3471
|
+
className: cn2(
|
|
3462
3472
|
"group relative flex min-h-11 touch-manipulation items-center gap-2.5 rounded-[var(--ph-radius-app)] text-sm font-medium transition-colors",
|
|
3463
3473
|
active ? "bg-ph-muted" : "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
|
|
3464
3474
|
collapsed ? "mx-auto size-11 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
@@ -3467,7 +3477,7 @@ function SuiteSidebar({
|
|
|
3467
3477
|
/* @__PURE__ */ jsx22(
|
|
3468
3478
|
"span",
|
|
3469
3479
|
{
|
|
3470
|
-
className:
|
|
3480
|
+
className: cn2(
|
|
3471
3481
|
"relative flex h-4 w-4 shrink-0 items-center justify-center",
|
|
3472
3482
|
item.iconClassName
|
|
3473
3483
|
),
|
|
@@ -3484,7 +3494,7 @@ function SuiteSidebar({
|
|
|
3484
3494
|
/* @__PURE__ */ jsx22(
|
|
3485
3495
|
"span",
|
|
3486
3496
|
{
|
|
3487
|
-
className:
|
|
3497
|
+
className: cn2(
|
|
3488
3498
|
"relative truncate",
|
|
3489
3499
|
active ? "text-ph-ink" : "text-ph-subtle group-hover:text-ph-ink",
|
|
3490
3500
|
collapsed && "sr-only"
|
|
@@ -3514,7 +3524,7 @@ function SuiteSidebar({
|
|
|
3514
3524
|
/* @__PURE__ */ jsx22(
|
|
3515
3525
|
"div",
|
|
3516
3526
|
{
|
|
3517
|
-
className:
|
|
3527
|
+
className: cn2(
|
|
3518
3528
|
"shrink-0 border-t border-ph-border",
|
|
3519
3529
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3520
3530
|
collapsed ? "p-1.5" : "p-3"
|
|
@@ -3522,20 +3532,14 @@ function SuiteSidebar({
|
|
|
3522
3532
|
children: /* @__PURE__ */ jsxs19(
|
|
3523
3533
|
"div",
|
|
3524
3534
|
{
|
|
3525
|
-
className:
|
|
3535
|
+
className: cn2(
|
|
3526
3536
|
"flex items-center gap-2",
|
|
3527
3537
|
collapsed ? "flex-col items-center justify-center [&>div]:w-auto" : "w-full min-w-0"
|
|
3528
3538
|
),
|
|
3529
3539
|
children: [
|
|
3530
3540
|
renderNode(userMenu, collapsed),
|
|
3531
|
-
showAskAi ? /* @__PURE__ */ jsx22(
|
|
3532
|
-
|
|
3533
|
-
{
|
|
3534
|
-
className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"),
|
|
3535
|
-
children: /* @__PURE__ */ jsx22(Tooltip, { content: "Shelly AI", side: collapsed ? "right" : "top", children: askAiButton })
|
|
3536
|
-
}
|
|
3537
|
-
) : footerExtras ? /* @__PURE__ */ jsx22("div", { className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: renderNode(footerExtras, collapsed) }) : null,
|
|
3538
|
-
showAskAi && footerExtras ? /* @__PURE__ */ jsx22("div", { className: cn("shrink-0", collapsed && "mt-2"), children: renderNode(footerExtras, collapsed) }) : null
|
|
3541
|
+
showAskAi ? /* @__PURE__ */ jsx22("div", { className: cn2("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: /* @__PURE__ */ jsx22(Tooltip, { content: "Shelly AI", side: collapsed ? "right" : "top", children: askAiButton }) }) : footerExtras ? /* @__PURE__ */ jsx22("div", { className: cn2("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: renderNode(footerExtras, collapsed) }) : null,
|
|
3542
|
+
showAskAi && footerExtras ? /* @__PURE__ */ jsx22("div", { className: cn2("shrink-0", collapsed && "mt-2"), children: renderNode(footerExtras, collapsed) }) : null
|
|
3539
3543
|
]
|
|
3540
3544
|
}
|
|
3541
3545
|
)
|
|
@@ -3565,7 +3569,7 @@ function SuiteAppLayout({
|
|
|
3565
3569
|
"div",
|
|
3566
3570
|
{
|
|
3567
3571
|
"data-test": "app-shell",
|
|
3568
|
-
className:
|
|
3572
|
+
className: cn2(
|
|
3569
3573
|
"suite-app-layout flex h-dvh overflow-hidden",
|
|
3570
3574
|
className
|
|
3571
3575
|
),
|
|
@@ -3573,6 +3577,7 @@ function SuiteAppLayout({
|
|
|
3573
3577
|
/* @__PURE__ */ jsxs20(
|
|
3574
3578
|
"aside",
|
|
3575
3579
|
{
|
|
3580
|
+
"aria-label": "Sidebar",
|
|
3576
3581
|
className: "relative hidden shrink-0 flex-col overflow-visible border-r border-ph-border ease-out lg:flex",
|
|
3577
3582
|
style: { width: `${sidebarWidth}px` },
|
|
3578
3583
|
"data-collapsed": collapsed ? "true" : "false",
|
|
@@ -3584,6 +3589,10 @@ function SuiteAppLayout({
|
|
|
3584
3589
|
role: "separator",
|
|
3585
3590
|
"aria-orientation": "vertical",
|
|
3586
3591
|
"aria-label": "Resize sidebar",
|
|
3592
|
+
"aria-valuenow": sidebarWidth,
|
|
3593
|
+
"aria-valuemin": SIDEBAR_RAIL_WIDTH,
|
|
3594
|
+
"aria-valuemax": SIDEBAR_MAX_WIDTH,
|
|
3595
|
+
"aria-valuetext": `${sidebarWidth} pixels`,
|
|
3587
3596
|
"data-test": "sidebar-resize-handle",
|
|
3588
3597
|
tabIndex: onResizeBy ? 0 : void 0,
|
|
3589
3598
|
onPointerDown: onStartResize,
|
|
@@ -3600,7 +3609,7 @@ function SuiteAppLayout({
|
|
|
3600
3609
|
onResizeBy == null ? void 0 : onResizeBy(16);
|
|
3601
3610
|
}
|
|
3602
3611
|
},
|
|
3603
|
-
className: "absolute inset-y-0 right-0 z-20 w-2 cursor-col-resize touch-none transition-colors hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
|
|
3612
|
+
className: "absolute inset-y-0 right-0 z-20 w-2 cursor-col-resize touch-none transition-colors before:absolute before:-left-2 before:-right-2 before:inset-y-0 before:content-[''] hover:bg-[color-mix(in_oklab,var(--ph-accent)_30%,transparent)]"
|
|
3604
3613
|
}
|
|
3605
3614
|
) : null
|
|
3606
3615
|
]
|
|
@@ -3612,10 +3621,10 @@ function SuiteAppLayout({
|
|
|
3612
3621
|
"main",
|
|
3613
3622
|
{
|
|
3614
3623
|
id: "main-content",
|
|
3615
|
-
tabIndex:
|
|
3624
|
+
tabIndex: 0,
|
|
3616
3625
|
"data-lock-scroll": lockMainScroll ? "true" : void 0,
|
|
3617
|
-
className:
|
|
3618
|
-
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none",
|
|
3626
|
+
className: cn2(
|
|
3627
|
+
"flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden overscroll-contain bg-ph-canvas focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ph-focus",
|
|
3619
3628
|
"suite-app-layout__main",
|
|
3620
3629
|
lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
|
|
3621
3630
|
),
|
|
@@ -3630,78 +3639,1970 @@ function SuiteAppLayout({
|
|
|
3630
3639
|
}
|
|
3631
3640
|
|
|
3632
3641
|
// src/suite/components/suite-integration-picker.tsx
|
|
3633
|
-
import {
|
|
3634
|
-
|
|
3635
|
-
|
|
3642
|
+
import {
|
|
3643
|
+
useEffect as useEffect8,
|
|
3644
|
+
useMemo,
|
|
3645
|
+
useRef as useRef3,
|
|
3646
|
+
useState as useState10
|
|
3647
|
+
} from "react";
|
|
3648
|
+
import {
|
|
3649
|
+
EvPlug as Plug,
|
|
3650
|
+
Filter,
|
|
3651
|
+
NavArrowDown as NavArrowDown2,
|
|
3652
|
+
NavArrowUp,
|
|
3653
|
+
Search,
|
|
3654
|
+
Xmark
|
|
3655
|
+
} from "iconoir-react";
|
|
3656
|
+
import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3636
3657
|
var DESCRIPTION_LIMIT = 90;
|
|
3637
|
-
function
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
})
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
+
function IntegrationSkeletonCard() {
|
|
3659
|
+
return /* @__PURE__ */ jsxs21(
|
|
3660
|
+
"div",
|
|
3661
|
+
{
|
|
3662
|
+
className: "flex min-h-36 min-w-0 animate-pulse flex-col justify-between rounded-xl border border-ph-border bg-ph-surface p-4",
|
|
3663
|
+
"aria-hidden": "true",
|
|
3664
|
+
children: [
|
|
3665
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-start gap-3", children: [
|
|
3666
|
+
/* @__PURE__ */ jsx24("div", { className: "h-10 w-10 shrink-0 rounded-lg bg-ph-muted" }),
|
|
3667
|
+
/* @__PURE__ */ jsxs21("div", { className: "min-w-0 flex-1 space-y-2 pt-1", children: [
|
|
3668
|
+
/* @__PURE__ */ jsx24("div", { className: "h-4 w-3/5 rounded bg-ph-muted" }),
|
|
3669
|
+
/* @__PURE__ */ jsx24("div", { className: "h-3 w-full rounded bg-ph-muted" }),
|
|
3670
|
+
/* @__PURE__ */ jsx24("div", { className: "h-3 w-4/5 rounded bg-ph-muted" })
|
|
3671
|
+
] })
|
|
3672
|
+
] }),
|
|
3673
|
+
/* @__PURE__ */ jsx24("div", { className: "mt-3 h-9 w-20 rounded bg-ph-muted" })
|
|
3674
|
+
]
|
|
3675
|
+
}
|
|
3676
|
+
);
|
|
3677
|
+
}
|
|
3678
|
+
var SKELETON_COUNT = 6;
|
|
3679
|
+
var AUTH_SCHEME_LABELS = {
|
|
3680
|
+
API_KEY: "API key",
|
|
3681
|
+
BASIC_AUTH: "Basic auth",
|
|
3682
|
+
BEARER_TOKEN: "Bearer token",
|
|
3683
|
+
OAUTH2: "OAuth 2.0"
|
|
3684
|
+
};
|
|
3685
|
+
function authSchemeLabel(scheme) {
|
|
3686
|
+
var _a;
|
|
3687
|
+
const normalised = scheme.trim().toUpperCase();
|
|
3688
|
+
return (_a = AUTH_SCHEME_LABELS[normalised]) != null ? _a : normalised.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
3689
|
+
}
|
|
3690
|
+
function authSchemesFor(item) {
|
|
3691
|
+
var _a;
|
|
3692
|
+
return Array.from(
|
|
3693
|
+
new Set(
|
|
3694
|
+
((_a = item.authSchemes) != null ? _a : []).map((scheme) => scheme.trim().toUpperCase()).filter(Boolean)
|
|
3695
|
+
)
|
|
3696
|
+
);
|
|
3697
|
+
}
|
|
3698
|
+
var CATEGORY_APP_AFFINITY = {
|
|
3699
|
+
calendar: ["turtletime", "tides"],
|
|
3700
|
+
email: ["turtletime", "tides"],
|
|
3701
|
+
code: ["tides", "kraken"],
|
|
3702
|
+
chat: ["tides", "kraken"],
|
|
3703
|
+
documents: ["kraken"],
|
|
3704
|
+
notes: ["kraken"],
|
|
3705
|
+
knowledge: ["kraken"],
|
|
3706
|
+
file_storage: ["kraken"],
|
|
3707
|
+
crm: ["shellstack", "tides"],
|
|
3708
|
+
finance: ["shellstack", "tides"],
|
|
3709
|
+
payment: ["shellstack", "tides"],
|
|
3710
|
+
monitoring: ["tides", "kraken"],
|
|
3711
|
+
design: ["tides", "kraken"],
|
|
3712
|
+
support: ["tides", "shellstack"],
|
|
3713
|
+
ticketing: ["tides", "kraken"]
|
|
3714
|
+
};
|
|
3715
|
+
var DEFAULT_APP_AFFINITY = ["tides", "kraken"];
|
|
3716
|
+
function suiteAppsForIntegration(categories) {
|
|
3717
|
+
var _a;
|
|
3718
|
+
const apps = /* @__PURE__ */ new Set();
|
|
3719
|
+
for (const category of categories != null ? categories : []) {
|
|
3720
|
+
for (const app of (_a = CATEGORY_APP_AFFINITY[category.trim().toLowerCase()]) != null ? _a : []) {
|
|
3721
|
+
apps.add(app);
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
return apps.size > 0 ? SUITE_APPS2.filter((app) => apps.has(app.slug)).map((app) => app.slug) : [...DEFAULT_APP_AFFINITY];
|
|
3725
|
+
}
|
|
3726
|
+
function SuiteIntegrationPicker({
|
|
3727
|
+
open,
|
|
3728
|
+
items,
|
|
3729
|
+
connectedItems = [],
|
|
3730
|
+
loading = false,
|
|
3731
|
+
catalogLoading = false,
|
|
3732
|
+
loadingMore = false,
|
|
3733
|
+
hasMore = false,
|
|
3734
|
+
onEndReached,
|
|
3735
|
+
search: controlledSearch,
|
|
3736
|
+
onSearchChange,
|
|
3737
|
+
category: controlledCategory,
|
|
3738
|
+
categories: controlledCategories,
|
|
3739
|
+
onCategoryChange,
|
|
3740
|
+
onClose,
|
|
3741
|
+
onConnect,
|
|
3742
|
+
onFetchAuthFields,
|
|
3743
|
+
onDisconnect,
|
|
3744
|
+
title = "Integrate an app",
|
|
3745
|
+
description = "Connect an app to this workspace securely.",
|
|
3746
|
+
dataTest = "suite-integration-picker"
|
|
3747
|
+
}) {
|
|
3748
|
+
const [query, setQuery] = useState10("");
|
|
3749
|
+
const [category, setCategory] = useState10("all");
|
|
3750
|
+
const [categoryQuery, setCategoryQuery] = useState10("");
|
|
3751
|
+
const [categoryMenuOpen, setCategoryMenuOpen] = useState10(false);
|
|
3752
|
+
const [expanded, setExpanded] = useState10(null);
|
|
3753
|
+
const categoryMenuRef = useRef3(null);
|
|
3754
|
+
const categoryTriggerRef = useRef3(null);
|
|
3755
|
+
const categorySearchRef = useRef3(null);
|
|
3756
|
+
const categoryOptionRefs = useRef3({});
|
|
3757
|
+
const pendingCategoryFocus = useRef3(
|
|
3758
|
+
null
|
|
3759
|
+
);
|
|
3760
|
+
const scrollViewportRef = useRef3(null);
|
|
3761
|
+
const loadMoreSentinelRef = useRef3(null);
|
|
3762
|
+
const loadMoreInFlightRef = useRef3(false);
|
|
3763
|
+
const authRequestRef = useRef3(0);
|
|
3764
|
+
const [methodItem, setMethodItem] = useState10(null);
|
|
3765
|
+
const [authItem, setAuthItem] = useState10(null);
|
|
3766
|
+
const [authValues, setAuthValues] = useState10({});
|
|
3767
|
+
const [authLoading, setAuthLoading] = useState10(false);
|
|
3768
|
+
const [authSubmitting, setAuthSubmitting] = useState10(false);
|
|
3769
|
+
const [authError, setAuthError] = useState10(null);
|
|
3770
|
+
const [connectionError, setConnectionError] = useState10(null);
|
|
3771
|
+
const [itemToDisconnect, setItemToDisconnect] = useState10(null);
|
|
3772
|
+
const [disconnecting, setDisconnecting] = useState10(false);
|
|
3773
|
+
const [disconnectError, setDisconnectError] = useState10(null);
|
|
3774
|
+
const itemCategories = useMemo(
|
|
3775
|
+
() => Array.from(
|
|
3776
|
+
new Set(items.flatMap((item) => {
|
|
3777
|
+
var _a;
|
|
3778
|
+
return (_a = item.categories) != null ? _a : [];
|
|
3779
|
+
}))
|
|
3780
|
+
).sort(),
|
|
3781
|
+
[items]
|
|
3658
3782
|
);
|
|
3659
|
-
const
|
|
3783
|
+
const categories = controlledCategories != null ? controlledCategories : itemCategories;
|
|
3784
|
+
const activeSearch = controlledSearch != null ? controlledSearch : query;
|
|
3785
|
+
const activeCategory = controlledCategory != null ? controlledCategory : category;
|
|
3786
|
+
const categoryLabel = (value) => value.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
3787
|
+
const filtered = onSearchChange || onCategoryChange ? items : items.filter((item) => {
|
|
3660
3788
|
var _a;
|
|
3661
|
-
|
|
3662
|
-
return haystack.includes(query.trim().toLowerCase()) && (category === "all" || ((_a = item.categories) != null ? _a : []).includes(category));
|
|
3789
|
+
return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a = item.categories) != null ? _a : []).includes(activeCategory));
|
|
3663
3790
|
});
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3791
|
+
const visibleCategories = categories.filter(
|
|
3792
|
+
(value) => categoryLabel(value).toLowerCase().includes(categoryQuery.trim().toLowerCase())
|
|
3793
|
+
);
|
|
3794
|
+
const categoryValues = ["all", ...visibleCategories];
|
|
3795
|
+
const focusableCategory = categoryValues.includes(activeCategory) ? activeCategory : "all";
|
|
3796
|
+
function focusCategory(value) {
|
|
3797
|
+
pendingCategoryFocus.current = value;
|
|
3798
|
+
}
|
|
3799
|
+
function openCategoryMenu(focus = null) {
|
|
3800
|
+
setCategoryQuery("");
|
|
3801
|
+
if (focus) focusCategory(focus);
|
|
3802
|
+
setCategoryMenuOpen(true);
|
|
3803
|
+
}
|
|
3804
|
+
function closeCategoryMenu(restoreFocus = false) {
|
|
3805
|
+
if (restoreFocus) focusCategory("trigger");
|
|
3806
|
+
setCategoryMenuOpen(false);
|
|
3807
|
+
}
|
|
3808
|
+
function selectCategory(value) {
|
|
3809
|
+
setCategory(value);
|
|
3810
|
+
onCategoryChange == null ? void 0 : onCategoryChange(value);
|
|
3811
|
+
closeCategoryMenu(true);
|
|
3812
|
+
}
|
|
3813
|
+
function moveCategoryFocus(event, value) {
|
|
3814
|
+
var _a;
|
|
3815
|
+
const index = categoryValues.indexOf(value);
|
|
3816
|
+
let nextIndex = null;
|
|
3817
|
+
if (event.key === "ArrowDown") nextIndex = (index + 1) % categoryValues.length;
|
|
3818
|
+
else if (event.key === "ArrowUp")
|
|
3819
|
+
nextIndex = (index - 1 + categoryValues.length) % categoryValues.length;
|
|
3820
|
+
else if (event.key === "Home") nextIndex = 0;
|
|
3821
|
+
else if (event.key === "End") nextIndex = categoryValues.length - 1;
|
|
3822
|
+
if (nextIndex === null) return;
|
|
3823
|
+
event.preventDefault();
|
|
3824
|
+
(_a = categoryOptionRefs.current[categoryValues[nextIndex]]) == null ? void 0 : _a.focus();
|
|
3825
|
+
}
|
|
3826
|
+
function handleCategoryTriggerKeyDown(event) {
|
|
3827
|
+
var _a;
|
|
3828
|
+
if (event.key === "ArrowDown") {
|
|
3829
|
+
event.preventDefault();
|
|
3830
|
+
openCategoryMenu(activeCategory === "all" ? "all" : activeCategory);
|
|
3831
|
+
} else if (event.key === "ArrowUp") {
|
|
3832
|
+
event.preventDefault();
|
|
3833
|
+
openCategoryMenu((_a = categoryValues.at(-1)) != null ? _a : "all");
|
|
3834
|
+
} else if (event.key === "Enter" || event.key === " ") {
|
|
3835
|
+
event.preventDefault();
|
|
3836
|
+
openCategoryMenu("search");
|
|
3837
|
+
}
|
|
3838
|
+
}
|
|
3839
|
+
function resetAuthForm() {
|
|
3840
|
+
authRequestRef.current += 1;
|
|
3841
|
+
setAuthItem(null);
|
|
3842
|
+
setAuthValues({});
|
|
3843
|
+
setAuthLoading(false);
|
|
3844
|
+
setAuthError(null);
|
|
3845
|
+
}
|
|
3846
|
+
function closeAuthForm() {
|
|
3847
|
+
if (authSubmitting) return;
|
|
3848
|
+
resetAuthForm();
|
|
3849
|
+
}
|
|
3850
|
+
async function prepareConnection(item, scheme) {
|
|
3851
|
+
var _a;
|
|
3852
|
+
setMethodItem(null);
|
|
3853
|
+
setAuthError(null);
|
|
3854
|
+
setConnectionError(null);
|
|
3855
|
+
setAuthValues({});
|
|
3856
|
+
if (!onFetchAuthFields) {
|
|
3857
|
+
try {
|
|
3858
|
+
await onConnect(item, { auth_scheme: scheme });
|
|
3859
|
+
} catch (cause) {
|
|
3860
|
+
setConnectionError(
|
|
3861
|
+
cause instanceof Error ? cause.message : "Could not connect the app."
|
|
3862
|
+
);
|
|
3863
|
+
}
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
const requestId = authRequestRef.current + 1;
|
|
3867
|
+
authRequestRef.current = requestId;
|
|
3868
|
+
setAuthItem({ item, scheme, fields: [] });
|
|
3869
|
+
setAuthLoading(true);
|
|
3870
|
+
try {
|
|
3871
|
+
const details = await onFetchAuthFields(item, scheme);
|
|
3872
|
+
if (requestId !== authRequestRef.current) return;
|
|
3873
|
+
const resolvedScheme = (_a = details.auth_scheme) != null ? _a : scheme;
|
|
3874
|
+
if (details.managed) {
|
|
3875
|
+
setAuthItem(null);
|
|
3876
|
+
await onConnect(item, { auth_scheme: resolvedScheme });
|
|
3877
|
+
} else if (details.fields.length === 0) {
|
|
3878
|
+
setAuthItem(null);
|
|
3879
|
+
await onConnect(item, {
|
|
3880
|
+
auth_scheme: resolvedScheme,
|
|
3881
|
+
auth_fields: {}
|
|
3882
|
+
});
|
|
3883
|
+
} else {
|
|
3884
|
+
setAuthItem({ item, scheme: resolvedScheme, fields: details.fields });
|
|
3885
|
+
}
|
|
3886
|
+
} catch (cause) {
|
|
3887
|
+
if (requestId === authRequestRef.current) {
|
|
3888
|
+
const message = cause instanceof Error ? cause.message : "Could not load authentication details.";
|
|
3889
|
+
setAuthError(message);
|
|
3890
|
+
setConnectionError(message);
|
|
3891
|
+
}
|
|
3892
|
+
} finally {
|
|
3893
|
+
if (requestId === authRequestRef.current) setAuthLoading(false);
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
function connectItem(item) {
|
|
3897
|
+
setConnectionError(null);
|
|
3898
|
+
const schemes = authSchemesFor(item);
|
|
3899
|
+
if (schemes.length > 1) {
|
|
3900
|
+
setMethodItem(item);
|
|
3901
|
+
return;
|
|
3902
|
+
}
|
|
3903
|
+
if (schemes.length === 1) {
|
|
3904
|
+
void prepareConnection(item, schemes[0]);
|
|
3905
|
+
return;
|
|
3906
|
+
}
|
|
3907
|
+
void (async () => {
|
|
3908
|
+
try {
|
|
3909
|
+
await onConnect(item);
|
|
3910
|
+
} catch (cause) {
|
|
3911
|
+
setConnectionError(
|
|
3912
|
+
cause instanceof Error ? cause.message : "Could not connect the app."
|
|
3913
|
+
);
|
|
3914
|
+
}
|
|
3915
|
+
})();
|
|
3916
|
+
}
|
|
3917
|
+
function requestDisconnect(item) {
|
|
3918
|
+
setDisconnectError(null);
|
|
3919
|
+
setItemToDisconnect(item);
|
|
3920
|
+
}
|
|
3921
|
+
async function disconnectItem() {
|
|
3922
|
+
if (!onDisconnect || !itemToDisconnect) return;
|
|
3923
|
+
setDisconnecting(true);
|
|
3924
|
+
setDisconnectError(null);
|
|
3925
|
+
try {
|
|
3926
|
+
await onDisconnect(itemToDisconnect);
|
|
3927
|
+
setItemToDisconnect(null);
|
|
3928
|
+
} catch (cause) {
|
|
3929
|
+
setDisconnectError(
|
|
3930
|
+
cause instanceof Error ? cause.message : "Could not disconnect the app."
|
|
3931
|
+
);
|
|
3932
|
+
} finally {
|
|
3933
|
+
setDisconnecting(false);
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
async function submitAuthForm(event) {
|
|
3937
|
+
event.preventDefault();
|
|
3938
|
+
if (!authItem) return;
|
|
3939
|
+
setAuthSubmitting(true);
|
|
3940
|
+
setAuthError(null);
|
|
3941
|
+
try {
|
|
3942
|
+
await onConnect(authItem.item, {
|
|
3943
|
+
auth_scheme: authItem.scheme,
|
|
3944
|
+
auth_fields: authValues
|
|
3945
|
+
});
|
|
3946
|
+
resetAuthForm();
|
|
3947
|
+
} catch (cause) {
|
|
3948
|
+
setAuthError(
|
|
3949
|
+
cause instanceof Error ? cause.message : "Could not connect the app."
|
|
3950
|
+
);
|
|
3951
|
+
} finally {
|
|
3952
|
+
setAuthSubmitting(false);
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
useEffect8(() => {
|
|
3956
|
+
if (!categoryMenuOpen) return;
|
|
3957
|
+
const handlePointerDown = (event) => {
|
|
3958
|
+
var _a;
|
|
3959
|
+
if (!((_a = categoryMenuRef.current) == null ? void 0 : _a.contains(event.target))) {
|
|
3960
|
+
closeCategoryMenu();
|
|
3961
|
+
}
|
|
3962
|
+
};
|
|
3963
|
+
const handleKeyDown = (event) => {
|
|
3964
|
+
if (event.key === "Escape") closeCategoryMenu(true);
|
|
3965
|
+
};
|
|
3966
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
3967
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
3968
|
+
return () => {
|
|
3969
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
3970
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
3971
|
+
};
|
|
3972
|
+
}, [categoryMenuOpen]);
|
|
3973
|
+
useEffect8(() => {
|
|
3974
|
+
var _a, _b, _c;
|
|
3975
|
+
const target = pendingCategoryFocus.current;
|
|
3976
|
+
if (!target) return;
|
|
3977
|
+
pendingCategoryFocus.current = null;
|
|
3978
|
+
if (target === "trigger") (_a = categoryTriggerRef.current) == null ? void 0 : _a.focus();
|
|
3979
|
+
else if (target === "search") (_b = categorySearchRef.current) == null ? void 0 : _b.focus();
|
|
3980
|
+
else (_c = categoryOptionRefs.current[target]) == null ? void 0 : _c.focus();
|
|
3981
|
+
}, [activeCategory, categoryMenuOpen, categoryQuery, visibleCategories]);
|
|
3982
|
+
useEffect8(() => {
|
|
3983
|
+
if (!loadingMore) loadMoreInFlightRef.current = false;
|
|
3984
|
+
}, [loadingMore]);
|
|
3985
|
+
useEffect8(() => {
|
|
3986
|
+
const root = scrollViewportRef.current;
|
|
3987
|
+
const sentinel = loadMoreSentinelRef.current;
|
|
3988
|
+
if (!open || !root || !sentinel || !hasMore || !onEndReached || loading || catalogLoading || loadingMore) {
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const observer = new IntersectionObserver(
|
|
3992
|
+
([entry]) => {
|
|
3993
|
+
if (!entry.isIntersecting || loadMoreInFlightRef.current) return;
|
|
3994
|
+
loadMoreInFlightRef.current = true;
|
|
3995
|
+
observer.unobserve(entry.target);
|
|
3996
|
+
onEndReached();
|
|
3997
|
+
},
|
|
3998
|
+
{ root, rootMargin: "0px 0px 80px", threshold: 0 }
|
|
3999
|
+
);
|
|
4000
|
+
observer.observe(sentinel);
|
|
4001
|
+
return () => observer.disconnect();
|
|
4002
|
+
}, [catalogLoading, hasMore, loading, loadingMore, onEndReached, open]);
|
|
4003
|
+
return /* @__PURE__ */ jsxs21(Fragment8, { children: [
|
|
4004
|
+
/* @__PURE__ */ jsx24(
|
|
4005
|
+
Modal,
|
|
4006
|
+
{
|
|
4007
|
+
open,
|
|
4008
|
+
onClose,
|
|
4009
|
+
title,
|
|
4010
|
+
description,
|
|
4011
|
+
size: "xl",
|
|
4012
|
+
dataTest,
|
|
4013
|
+
bodyClassName: "!overflow-hidden",
|
|
4014
|
+
children: /* @__PURE__ */ jsxs21("div", { className: "space-y-4", children: [
|
|
4015
|
+
connectionError ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-ph-danger", role: "alert", children: connectionError }) : null,
|
|
4016
|
+
/* @__PURE__ */ jsxs21("div", { className: "grid gap-4 md:grid-cols-2", children: [
|
|
4017
|
+
/* @__PURE__ */ jsxs21("div", { className: "relative", children: [
|
|
4018
|
+
/* @__PURE__ */ jsx24(
|
|
4019
|
+
Search,
|
|
4020
|
+
{
|
|
4021
|
+
className: "pointer-events-none absolute left-3 top-1/2 z-10 h-4 w-4 -translate-y-1/2 text-ph-subtle",
|
|
4022
|
+
"aria-hidden": true
|
|
4023
|
+
}
|
|
4024
|
+
),
|
|
4025
|
+
/* @__PURE__ */ jsx24(
|
|
4026
|
+
Input,
|
|
4027
|
+
{
|
|
4028
|
+
value: activeSearch,
|
|
4029
|
+
onChange: (event) => {
|
|
4030
|
+
setQuery(event.target.value);
|
|
4031
|
+
onSearchChange == null ? void 0 : onSearchChange(event.target.value);
|
|
4032
|
+
},
|
|
4033
|
+
placeholder: "Search apps...",
|
|
4034
|
+
"aria-label": "Search apps",
|
|
4035
|
+
className: "pl-10"
|
|
4036
|
+
}
|
|
4037
|
+
)
|
|
4038
|
+
] }),
|
|
4039
|
+
/* @__PURE__ */ jsxs21("div", { ref: categoryMenuRef, className: "relative", children: [
|
|
4040
|
+
/* @__PURE__ */ jsxs21(
|
|
4041
|
+
"button",
|
|
4042
|
+
{
|
|
4043
|
+
ref: categoryTriggerRef,
|
|
4044
|
+
id: `${dataTest}-category`,
|
|
4045
|
+
type: "button",
|
|
4046
|
+
className: "ph-input flex w-full items-center justify-between text-left",
|
|
4047
|
+
"aria-haspopup": "listbox",
|
|
4048
|
+
"aria-expanded": categoryMenuOpen,
|
|
4049
|
+
"aria-controls": categoryMenuOpen ? `${dataTest}-category-options` : void 0,
|
|
4050
|
+
"aria-label": "Filter by category",
|
|
4051
|
+
onClick: () => {
|
|
4052
|
+
if (categoryMenuOpen) closeCategoryMenu();
|
|
4053
|
+
else openCategoryMenu();
|
|
4054
|
+
},
|
|
4055
|
+
onKeyDown: handleCategoryTriggerKeyDown,
|
|
4056
|
+
children: [
|
|
4057
|
+
/* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-2", children: [
|
|
4058
|
+
/* @__PURE__ */ jsx24(
|
|
4059
|
+
Filter,
|
|
4060
|
+
{
|
|
4061
|
+
className: "h-4 w-4 shrink-0 text-ph-subtle",
|
|
4062
|
+
"aria-hidden": true
|
|
4063
|
+
}
|
|
4064
|
+
),
|
|
4065
|
+
/* @__PURE__ */ jsx24("span", { children: activeCategory === "all" ? "All apps" : categoryLabel(activeCategory) })
|
|
4066
|
+
] }),
|
|
4067
|
+
/* @__PURE__ */ jsx24(
|
|
4068
|
+
NavArrowDown2,
|
|
4069
|
+
{
|
|
4070
|
+
className: `h-4 w-4 transition-transform ${categoryMenuOpen ? "rotate-180" : ""}`,
|
|
4071
|
+
"aria-hidden": true
|
|
4072
|
+
}
|
|
4073
|
+
)
|
|
4074
|
+
]
|
|
4075
|
+
}
|
|
4076
|
+
),
|
|
4077
|
+
categoryMenuOpen ? /* @__PURE__ */ jsxs21(
|
|
4078
|
+
"div",
|
|
4079
|
+
{
|
|
4080
|
+
className: "absolute z-20 mt-2 max-h-[min(22rem,calc(100dvh-12rem))] w-full max-w-full overflow-hidden rounded-lg border border-ph-border bg-ph-surface p-2 shadow-lg",
|
|
4081
|
+
children: [
|
|
4082
|
+
/* @__PURE__ */ jsx24(
|
|
4083
|
+
Input,
|
|
4084
|
+
{
|
|
4085
|
+
ref: categorySearchRef,
|
|
4086
|
+
value: categoryQuery,
|
|
4087
|
+
onChange: (event) => setCategoryQuery(event.target.value),
|
|
4088
|
+
placeholder: "Search categories...",
|
|
4089
|
+
"aria-label": "Search categories",
|
|
4090
|
+
onKeyDown: (event) => {
|
|
4091
|
+
var _a;
|
|
4092
|
+
if (event.key === "ArrowDown") {
|
|
4093
|
+
event.preventDefault();
|
|
4094
|
+
(_a = categoryOptionRefs.current[categoryValues[0]]) == null ? void 0 : _a.focus();
|
|
4095
|
+
} else if (event.key === "Escape") {
|
|
4096
|
+
event.preventDefault();
|
|
4097
|
+
closeCategoryMenu(true);
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
),
|
|
4102
|
+
/* @__PURE__ */ jsx24(
|
|
4103
|
+
"div",
|
|
4104
|
+
{
|
|
4105
|
+
id: `${dataTest}-category-options`,
|
|
4106
|
+
role: "listbox",
|
|
4107
|
+
"aria-label": "Integration categories",
|
|
4108
|
+
className: "mt-2 max-h-52 overflow-y-auto",
|
|
4109
|
+
"data-test": "integration-category-options",
|
|
4110
|
+
children: categoryValues.map((value) => /* @__PURE__ */ jsx24(
|
|
4111
|
+
"button",
|
|
4112
|
+
{
|
|
4113
|
+
type: "button",
|
|
4114
|
+
role: "option",
|
|
4115
|
+
"aria-selected": activeCategory === value,
|
|
4116
|
+
tabIndex: value === focusableCategory ? 0 : -1,
|
|
4117
|
+
ref: (element) => {
|
|
4118
|
+
categoryOptionRefs.current[value] = element;
|
|
4119
|
+
},
|
|
4120
|
+
className: `flex w-full min-w-0 items-center rounded-md px-3 py-2 text-left text-sm break-words ${activeCategory === value ? "bg-ph-brand text-[var(--ph-on-accent)]" : "text-ph-ink hover:bg-ph-muted"}`,
|
|
4121
|
+
onClick: () => selectCategory(value),
|
|
4122
|
+
onKeyDown: (event) => {
|
|
4123
|
+
if (event.key === "Escape") {
|
|
4124
|
+
event.preventDefault();
|
|
4125
|
+
closeCategoryMenu(true);
|
|
4126
|
+
} else if (event.key === "Enter" || event.key === " ") {
|
|
4127
|
+
event.preventDefault();
|
|
4128
|
+
selectCategory(value);
|
|
4129
|
+
} else moveCategoryFocus(event, value);
|
|
4130
|
+
},
|
|
4131
|
+
children: value === "all" ? "All apps" : categoryLabel(value)
|
|
4132
|
+
},
|
|
4133
|
+
value
|
|
4134
|
+
))
|
|
4135
|
+
}
|
|
4136
|
+
)
|
|
4137
|
+
]
|
|
4138
|
+
}
|
|
4139
|
+
) : null
|
|
4140
|
+
] })
|
|
4141
|
+
] }),
|
|
4142
|
+
/* @__PURE__ */ jsxs21(
|
|
4143
|
+
"div",
|
|
4144
|
+
{
|
|
4145
|
+
ref: scrollViewportRef,
|
|
4146
|
+
className: "min-h-0 max-h-[min(60vh,32rem)] w-full overflow-y-auto pr-1",
|
|
4147
|
+
children: [
|
|
4148
|
+
loading || catalogLoading ? /* @__PURE__ */ jsx24(
|
|
4149
|
+
"div",
|
|
4150
|
+
{
|
|
4151
|
+
className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3",
|
|
4152
|
+
"aria-label": "Loading apps",
|
|
4153
|
+
children: Array.from({ length: SKELETON_COUNT }, (_, index) => /* @__PURE__ */ jsx24(IntegrationSkeletonCard, {}, index))
|
|
4154
|
+
}
|
|
4155
|
+
) : /* @__PURE__ */ jsxs21("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: [
|
|
4156
|
+
filtered.map((item) => {
|
|
4157
|
+
var _a, _b;
|
|
4158
|
+
const isExpanded = expanded === item.id;
|
|
4159
|
+
const longDescription = item.description.length > DESCRIPTION_LIMIT;
|
|
4160
|
+
const text = isExpanded || !longDescription ? item.description : `${item.description.slice(0, DESCRIPTION_LIMIT).trimEnd()}...`;
|
|
4161
|
+
return /* @__PURE__ */ jsxs21(
|
|
4162
|
+
"div",
|
|
4163
|
+
{
|
|
4164
|
+
className: "flex min-h-36 min-w-0 flex-col justify-between rounded-xl border border-ph-border bg-ph-surface p-4",
|
|
4165
|
+
children: [
|
|
4166
|
+
/* @__PURE__ */ jsx24(
|
|
4167
|
+
"button",
|
|
4168
|
+
{
|
|
4169
|
+
type: "button",
|
|
4170
|
+
className: "min-w-0 text-left",
|
|
4171
|
+
onClick: () => longDescription && setExpanded(isExpanded ? null : item.id),
|
|
4172
|
+
"aria-expanded": isExpanded,
|
|
4173
|
+
children: /* @__PURE__ */ jsxs21("span", { className: "flex items-start gap-3", children: [
|
|
4174
|
+
/* @__PURE__ */ jsx24("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-ph-muted text-ph-ink", children: (_a = item.icon) != null ? _a : /* @__PURE__ */ jsx24(Plug, { className: "h-5 w-5", "aria-hidden": true }) }),
|
|
4175
|
+
/* @__PURE__ */ jsxs21("span", { className: "min-w-0", children: [
|
|
4176
|
+
/* @__PURE__ */ jsx24("span", { className: "block truncate font-medium text-ph-ink", children: item.label }),
|
|
4177
|
+
/* @__PURE__ */ jsx24("span", { className: "mt-1 block text-xs text-ph-subtle", children: text }),
|
|
4178
|
+
longDescription ? /* @__PURE__ */ jsxs21("span", { className: "mt-1 block text-xs font-medium text-ph-brand", children: [
|
|
4179
|
+
isExpanded ? "See less" : "See more",
|
|
4180
|
+
" ",
|
|
4181
|
+
isExpanded ? /* @__PURE__ */ jsx24(NavArrowUp, { className: "inline h-3 w-3" }) : /* @__PURE__ */ jsx24(NavArrowDown2, { className: "inline h-3 w-3" })
|
|
4182
|
+
] }) : null
|
|
4183
|
+
] })
|
|
4184
|
+
] })
|
|
4185
|
+
}
|
|
4186
|
+
),
|
|
4187
|
+
suiteAppsForIntegration(item.categories).length > 0 ? /* @__PURE__ */ jsx24(
|
|
4188
|
+
"div",
|
|
4189
|
+
{
|
|
4190
|
+
className: "mt-3 flex flex-wrap items-center gap-1.5",
|
|
4191
|
+
"aria-label": "Works with ShellStack apps",
|
|
4192
|
+
children: suiteAppsForIntegration(item.categories).map(
|
|
4193
|
+
(app) => /* @__PURE__ */ jsx24(
|
|
4194
|
+
"span",
|
|
4195
|
+
{
|
|
4196
|
+
"data-test": `${dataTest}-${item.id}-app-${app}`,
|
|
4197
|
+
children: /* @__PURE__ */ jsx24(
|
|
4198
|
+
SuiteAppIcon,
|
|
4199
|
+
{
|
|
4200
|
+
app,
|
|
4201
|
+
size: 16,
|
|
4202
|
+
label: `Works with ${SUITE_APP_MAP[app].name}`,
|
|
4203
|
+
className: "rounded-[4px]"
|
|
4204
|
+
}
|
|
4205
|
+
)
|
|
4206
|
+
},
|
|
4207
|
+
app
|
|
4208
|
+
)
|
|
4209
|
+
)
|
|
4210
|
+
}
|
|
4211
|
+
) : null,
|
|
4212
|
+
authSchemesFor(item).length > 0 ? /* @__PURE__ */ jsx24(
|
|
4213
|
+
"div",
|
|
4214
|
+
{
|
|
4215
|
+
className: "mt-3 flex flex-wrap gap-1.5",
|
|
4216
|
+
"aria-label": "Connection methods",
|
|
4217
|
+
children: authSchemesFor(item).map((scheme) => /* @__PURE__ */ jsx24(
|
|
4218
|
+
"span",
|
|
4219
|
+
{
|
|
4220
|
+
className: "rounded-full border border-ph-border bg-ph-muted px-2 py-1 text-[0.6875rem] font-medium text-ph-subtle",
|
|
4221
|
+
"data-test": `${dataTest}-${item.id}-auth-${scheme.toLowerCase()}`,
|
|
4222
|
+
children: authSchemeLabel(scheme)
|
|
4223
|
+
},
|
|
4224
|
+
scheme
|
|
4225
|
+
))
|
|
4226
|
+
}
|
|
4227
|
+
) : null,
|
|
4228
|
+
/* @__PURE__ */ jsx24(
|
|
4229
|
+
Button,
|
|
4230
|
+
{
|
|
4231
|
+
type: "button",
|
|
4232
|
+
variant: "primary",
|
|
4233
|
+
className: "mt-3 self-start",
|
|
4234
|
+
disabled: Boolean(item.unavailableReason) || item.connecting,
|
|
4235
|
+
onClick: () => connectItem(item),
|
|
4236
|
+
children: /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1.5", children: [
|
|
4237
|
+
/* @__PURE__ */ jsx24(Plug, { className: "h-3.5 w-3.5", "aria-hidden": true }),
|
|
4238
|
+
item.connecting ? "Connecting..." : (_b = item.unavailableReason) != null ? _b : "Connect"
|
|
4239
|
+
] })
|
|
4240
|
+
}
|
|
4241
|
+
)
|
|
4242
|
+
]
|
|
4243
|
+
},
|
|
4244
|
+
item.id
|
|
4245
|
+
);
|
|
4246
|
+
}),
|
|
4247
|
+
loadingMore ? Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsx24(IntegrationSkeletonCard, {}, `loading-${index}`)) : null
|
|
4248
|
+
] }),
|
|
4249
|
+
/* @__PURE__ */ jsx24("div", { ref: loadMoreSentinelRef, className: "h-1", "aria-hidden": "true" })
|
|
4250
|
+
]
|
|
4251
|
+
}
|
|
4252
|
+
),
|
|
4253
|
+
connectedItems.length > 0 && onDisconnect ? /* @__PURE__ */ jsxs21("div", { className: "space-y-2 border-t border-ph-border pt-4", children: [
|
|
4254
|
+
/* @__PURE__ */ jsx24("h3", { className: "font-medium text-ph-ink", children: "Connected apps" }),
|
|
4255
|
+
connectedItems.map((item) => /* @__PURE__ */ jsxs21(
|
|
4256
|
+
"div",
|
|
4257
|
+
{
|
|
4258
|
+
className: "flex items-center justify-between gap-3 rounded-lg border border-ph-border bg-ph-muted p-3",
|
|
4259
|
+
children: [
|
|
4260
|
+
/* @__PURE__ */ jsxs21("span", { className: "flex min-w-0 items-center gap-2 text-sm text-ph-ink", children: [
|
|
4261
|
+
item.icon,
|
|
4262
|
+
/* @__PURE__ */ jsx24("span", { className: "truncate", children: item.label })
|
|
4263
|
+
] }),
|
|
4264
|
+
/* @__PURE__ */ jsx24(
|
|
4265
|
+
Button,
|
|
4266
|
+
{
|
|
4267
|
+
type: "button",
|
|
4268
|
+
variant: "danger",
|
|
4269
|
+
onClick: () => requestDisconnect(item),
|
|
4270
|
+
children: /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1.5", children: [
|
|
4271
|
+
/* @__PURE__ */ jsx24(Xmark, { className: "h-4 w-4", "aria-hidden": true }),
|
|
4272
|
+
"Disconnect"
|
|
4273
|
+
] })
|
|
4274
|
+
}
|
|
4275
|
+
)
|
|
4276
|
+
]
|
|
4277
|
+
},
|
|
4278
|
+
item.id
|
|
4279
|
+
))
|
|
4280
|
+
] }) : null
|
|
4281
|
+
] })
|
|
4282
|
+
}
|
|
4283
|
+
),
|
|
4284
|
+
/* @__PURE__ */ jsxs21(
|
|
4285
|
+
Modal,
|
|
4286
|
+
{
|
|
4287
|
+
open: itemToDisconnect !== null,
|
|
4288
|
+
onClose: () => {
|
|
4289
|
+
if (!disconnecting) setItemToDisconnect(null);
|
|
4290
|
+
},
|
|
4291
|
+
title: "Disconnect app",
|
|
4292
|
+
description: "This will stop syncing data from this app.",
|
|
4293
|
+
size: "sm",
|
|
4294
|
+
zIndex: 220,
|
|
4295
|
+
dataTest: `${dataTest}-disconnect-confirmation`,
|
|
4296
|
+
footer: /* @__PURE__ */ jsxs21("div", { className: "flex justify-end gap-2", children: [
|
|
4297
|
+
/* @__PURE__ */ jsx24(
|
|
4298
|
+
Button,
|
|
4299
|
+
{
|
|
4300
|
+
type: "button",
|
|
4301
|
+
variant: "tertiary",
|
|
4302
|
+
onClick: () => setItemToDisconnect(null),
|
|
4303
|
+
disabled: disconnecting,
|
|
4304
|
+
children: "Cancel"
|
|
4305
|
+
}
|
|
4306
|
+
),
|
|
4307
|
+
/* @__PURE__ */ jsx24(
|
|
4308
|
+
Button,
|
|
4309
|
+
{
|
|
4310
|
+
type: "button",
|
|
4311
|
+
variant: "danger",
|
|
4312
|
+
onClick: () => void disconnectItem(),
|
|
4313
|
+
disabled: disconnecting,
|
|
4314
|
+
"data-test": `${dataTest}-disconnect-confirm`,
|
|
4315
|
+
children: disconnecting ? "Disconnecting..." : "Disconnect app"
|
|
4316
|
+
}
|
|
4317
|
+
)
|
|
3697
4318
|
] }),
|
|
3698
|
-
|
|
3699
|
-
/* @__PURE__ */ jsx24(
|
|
3700
|
-
"
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
4319
|
+
children: [
|
|
4320
|
+
disconnectError ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-ph-danger", role: "alert", children: disconnectError }) : null,
|
|
4321
|
+
/* @__PURE__ */ jsxs21("p", { className: "text-sm text-ph-ink", children: [
|
|
4322
|
+
"Disconnect ",
|
|
4323
|
+
itemToDisconnect == null ? void 0 : itemToDisconnect.label,
|
|
4324
|
+
"? You can reconnect it later."
|
|
4325
|
+
] })
|
|
4326
|
+
]
|
|
4327
|
+
}
|
|
4328
|
+
),
|
|
4329
|
+
/* @__PURE__ */ jsx24(
|
|
4330
|
+
Modal,
|
|
4331
|
+
{
|
|
4332
|
+
open: Boolean(methodItem),
|
|
4333
|
+
onClose: () => setMethodItem(null),
|
|
4334
|
+
title: methodItem ? `Connect ${methodItem.label}` : "Choose connection method",
|
|
4335
|
+
description: "Choose how you want to connect this app.",
|
|
4336
|
+
size: "sm",
|
|
4337
|
+
zIndex: 200,
|
|
4338
|
+
dataTest: `${dataTest}-auth-method`,
|
|
4339
|
+
children: methodItem ? /* @__PURE__ */ jsx24("div", { className: "space-y-2", children: authSchemesFor(methodItem).map((scheme) => /* @__PURE__ */ jsxs21(
|
|
4340
|
+
"button",
|
|
4341
|
+
{
|
|
4342
|
+
type: "button",
|
|
4343
|
+
className: "flex w-full items-center justify-between rounded-lg border border-ph-border bg-ph-surface px-3 py-3 text-left text-sm text-ph-ink transition hover:border-ph-brand hover:bg-ph-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
4344
|
+
onClick: () => void prepareConnection(methodItem, scheme),
|
|
4345
|
+
"data-test": `${dataTest}-choose-${scheme.toLowerCase()}`,
|
|
4346
|
+
children: [
|
|
4347
|
+
/* @__PURE__ */ jsx24("span", { className: "font-medium", children: authSchemeLabel(scheme) }),
|
|
4348
|
+
/* @__PURE__ */ jsx24("span", { className: "text-xs text-ph-subtle", children: "Select" })
|
|
4349
|
+
]
|
|
4350
|
+
},
|
|
4351
|
+
scheme
|
|
4352
|
+
)) }) : null
|
|
4353
|
+
}
|
|
4354
|
+
),
|
|
4355
|
+
/* @__PURE__ */ jsx24(
|
|
4356
|
+
Modal,
|
|
4357
|
+
{
|
|
4358
|
+
open: Boolean(authItem),
|
|
4359
|
+
onClose: closeAuthForm,
|
|
4360
|
+
title: authItem ? `${authItem.item.label} authentication` : "Authentication",
|
|
4361
|
+
description: "Enter the credentials required by Composio. They are sent securely to the ShellStack API.",
|
|
4362
|
+
size: "md",
|
|
4363
|
+
zIndex: 210,
|
|
4364
|
+
dataTest: `${dataTest}-auth-form`,
|
|
4365
|
+
children: authLoading ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-ph-subtle", children: "Loading authentication fields..." }) : authItem ? /* @__PURE__ */ jsxs21(
|
|
4366
|
+
"form",
|
|
4367
|
+
{
|
|
4368
|
+
className: "space-y-4",
|
|
4369
|
+
onSubmit: (event) => void submitAuthForm(event),
|
|
4370
|
+
children: [
|
|
4371
|
+
authError ? /* @__PURE__ */ jsx24("p", { className: "text-sm text-ph-danger", role: "alert", children: authError }) : null,
|
|
4372
|
+
authItem.fields.length === 0 && authError ? /* @__PURE__ */ jsx24(
|
|
4373
|
+
Button,
|
|
4374
|
+
{
|
|
4375
|
+
type: "button",
|
|
4376
|
+
variant: "tertiary",
|
|
4377
|
+
onClick: () => void prepareConnection(authItem.item, authItem.scheme),
|
|
4378
|
+
children: "Try again"
|
|
4379
|
+
}
|
|
4380
|
+
) : null,
|
|
4381
|
+
authItem.fields.map((field) => {
|
|
4382
|
+
var _a, _b;
|
|
4383
|
+
return /* @__PURE__ */ jsx24(
|
|
4384
|
+
Input,
|
|
4385
|
+
{
|
|
4386
|
+
label: field.label,
|
|
4387
|
+
type: (_a = field.type) != null ? _a : "password",
|
|
4388
|
+
required: true,
|
|
4389
|
+
value: (_b = authValues[field.name]) != null ? _b : "",
|
|
4390
|
+
onChange: (event) => setAuthValues((current) => __spreadProps(__spreadValues({}, current), {
|
|
4391
|
+
[field.name]: event.target.value
|
|
4392
|
+
})),
|
|
4393
|
+
autoComplete: "off",
|
|
4394
|
+
"data-test": `${dataTest}-auth-field-${field.name}`
|
|
4395
|
+
},
|
|
4396
|
+
field.name
|
|
4397
|
+
);
|
|
4398
|
+
}),
|
|
4399
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex justify-end gap-2 border-t border-ph-border pt-4", children: [
|
|
4400
|
+
/* @__PURE__ */ jsx24(
|
|
4401
|
+
Button,
|
|
4402
|
+
{
|
|
4403
|
+
type: "button",
|
|
4404
|
+
variant: "tertiary",
|
|
4405
|
+
onClick: closeAuthForm,
|
|
4406
|
+
disabled: authSubmitting,
|
|
4407
|
+
children: "Cancel"
|
|
4408
|
+
}
|
|
4409
|
+
),
|
|
4410
|
+
/* @__PURE__ */ jsx24(Button, { type: "submit", variant: "primary", disabled: authSubmitting, children: authSubmitting ? "Connecting..." : "Connect" })
|
|
4411
|
+
] })
|
|
4412
|
+
]
|
|
4413
|
+
}
|
|
4414
|
+
) : null
|
|
4415
|
+
}
|
|
4416
|
+
)
|
|
4417
|
+
] });
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4420
|
+
// src/suite/components/suite-integration-rules.tsx
|
|
4421
|
+
import { useState as useState11 } from "react";
|
|
4422
|
+
import { Plus, Xmark as Xmark2 } from "iconoir-react";
|
|
4423
|
+
import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4424
|
+
var ACTION_LABELS = {
|
|
4425
|
+
create_tides_task: "Create a Tides task",
|
|
4426
|
+
draft_time_entry: "Draft a time entry",
|
|
4427
|
+
create_suite_notification: "Send a suite notification"
|
|
4428
|
+
};
|
|
4429
|
+
function actionLabel(actionType) {
|
|
4430
|
+
var _a;
|
|
4431
|
+
return (_a = ACTION_LABELS[actionType]) != null ? _a : actionType;
|
|
4432
|
+
}
|
|
4433
|
+
function formatDateTime(value) {
|
|
4434
|
+
if (!value) return "\u2014";
|
|
4435
|
+
return new Date(value).toLocaleString(void 0, {
|
|
4436
|
+
dateStyle: "medium",
|
|
4437
|
+
timeStyle: "short"
|
|
4438
|
+
});
|
|
4439
|
+
}
|
|
4440
|
+
function SuiteIntegrationRules({
|
|
4441
|
+
canManage,
|
|
4442
|
+
projects,
|
|
4443
|
+
rules,
|
|
4444
|
+
events,
|
|
4445
|
+
loading = false,
|
|
4446
|
+
error = null,
|
|
4447
|
+
onCreate,
|
|
4448
|
+
onUpdate,
|
|
4449
|
+
onDelete,
|
|
4450
|
+
onRefresh,
|
|
4451
|
+
dataTest = "integration-rules"
|
|
4452
|
+
}) {
|
|
4453
|
+
const [formOpen, setFormOpen] = useState11(false);
|
|
4454
|
+
const [name, setName] = useState11("");
|
|
4455
|
+
const [trigger, setTrigger] = useState11("");
|
|
4456
|
+
const [actionType, setActionType] = useState11("create_tides_task");
|
|
4457
|
+
const [projectId, setProjectId] = useState11("");
|
|
4458
|
+
const [minutes, setMinutes] = useState11("");
|
|
4459
|
+
const [priority, setPriority] = useState11("low");
|
|
4460
|
+
const [submitting, setSubmitting] = useState11(false);
|
|
4461
|
+
const [formError, setFormError] = useState11(null);
|
|
4462
|
+
const [busyId, setBusyId] = useState11(null);
|
|
4463
|
+
const [ruleToDelete, setRuleToDelete] = useState11(null);
|
|
4464
|
+
const [deleteError, setDeleteError] = useState11(null);
|
|
4465
|
+
const needsProject = actionType === "create_tides_task" || actionType === "draft_time_entry";
|
|
4466
|
+
async function submitForm(event) {
|
|
4467
|
+
event.preventDefault();
|
|
4468
|
+
if (!onCreate) return;
|
|
4469
|
+
setSubmitting(true);
|
|
4470
|
+
setFormError(null);
|
|
4471
|
+
try {
|
|
4472
|
+
const actionConfig = {};
|
|
4473
|
+
if (projectId) actionConfig.project_id = projectId;
|
|
4474
|
+
if (actionType === "draft_time_entry" && minutes)
|
|
4475
|
+
actionConfig.minutes = minutes;
|
|
4476
|
+
if (actionType === "create_tides_task" && priority !== "low")
|
|
4477
|
+
actionConfig.priority = priority;
|
|
4478
|
+
await onCreate({
|
|
4479
|
+
name: name.trim(),
|
|
4480
|
+
trigger_event_type: trigger.trim(),
|
|
4481
|
+
action_type: actionType,
|
|
4482
|
+
action_config: actionConfig
|
|
4483
|
+
});
|
|
4484
|
+
setName("");
|
|
4485
|
+
setTrigger("");
|
|
4486
|
+
setProjectId("");
|
|
4487
|
+
setMinutes("");
|
|
4488
|
+
setPriority("low");
|
|
4489
|
+
setFormOpen(false);
|
|
4490
|
+
onRefresh == null ? void 0 : onRefresh();
|
|
4491
|
+
} catch (cause) {
|
|
4492
|
+
setFormError(
|
|
4493
|
+
cause instanceof Error ? cause.message : "Could not create the rule."
|
|
4494
|
+
);
|
|
4495
|
+
} finally {
|
|
4496
|
+
setSubmitting(false);
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
async function toggleRule(rule) {
|
|
4500
|
+
if (!onUpdate) return;
|
|
4501
|
+
setBusyId(rule.id);
|
|
4502
|
+
try {
|
|
4503
|
+
await onUpdate(rule.id, { enabled: !rule.enabled });
|
|
4504
|
+
onRefresh == null ? void 0 : onRefresh();
|
|
4505
|
+
} finally {
|
|
4506
|
+
setBusyId(null);
|
|
4507
|
+
}
|
|
4508
|
+
}
|
|
4509
|
+
function requestDelete(rule) {
|
|
4510
|
+
setDeleteError(null);
|
|
4511
|
+
setRuleToDelete(rule);
|
|
4512
|
+
}
|
|
4513
|
+
async function deleteRule() {
|
|
4514
|
+
if (!onDelete || !ruleToDelete) return;
|
|
4515
|
+
setBusyId(ruleToDelete.id);
|
|
4516
|
+
setDeleteError(null);
|
|
4517
|
+
try {
|
|
4518
|
+
await onDelete(ruleToDelete.id);
|
|
4519
|
+
onRefresh == null ? void 0 : onRefresh();
|
|
4520
|
+
setRuleToDelete(null);
|
|
4521
|
+
} catch (cause) {
|
|
4522
|
+
setDeleteError(
|
|
4523
|
+
cause instanceof Error ? cause.message : "Could not delete the rule."
|
|
4524
|
+
);
|
|
4525
|
+
} finally {
|
|
4526
|
+
setBusyId(null);
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
return /* @__PURE__ */ jsxs22("section", { className: "space-y-4", "data-test": dataTest, children: [
|
|
4530
|
+
/* @__PURE__ */ jsxs22(
|
|
4531
|
+
Card,
|
|
4532
|
+
{
|
|
4533
|
+
variant: "outlined",
|
|
4534
|
+
bodyClassName: "p-5",
|
|
4535
|
+
"data-test": `${dataTest}-card`,
|
|
4536
|
+
children: [
|
|
4537
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
4538
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4539
|
+
/* @__PURE__ */ jsx25("h3", { className: "font-medium text-ph-ink", children: "Automation rules" }),
|
|
4540
|
+
/* @__PURE__ */ jsx25("p", { className: "mt-1 text-sm text-ph-subtle", children: "Turn incoming integration events into tasks, time entries, or notifications for this workspace." })
|
|
4541
|
+
] }),
|
|
4542
|
+
canManage && onCreate ? /* @__PURE__ */ jsx25(
|
|
4543
|
+
Button,
|
|
4544
|
+
{
|
|
4545
|
+
type: "button",
|
|
4546
|
+
variant: "tertiary",
|
|
4547
|
+
size: "sm",
|
|
4548
|
+
onClick: () => setFormOpen((open) => !open),
|
|
4549
|
+
"data-test": `${dataTest}-new`,
|
|
4550
|
+
children: /* @__PURE__ */ jsxs22("span", { className: "flex items-center gap-1.5", children: [
|
|
4551
|
+
/* @__PURE__ */ jsx25(Plus, { className: "h-4 w-4", "aria-hidden": true }),
|
|
4552
|
+
"New rule"
|
|
4553
|
+
] })
|
|
4554
|
+
}
|
|
4555
|
+
) : null
|
|
4556
|
+
] }),
|
|
4557
|
+
error ? /* @__PURE__ */ jsx25(
|
|
4558
|
+
Alert,
|
|
4559
|
+
{
|
|
4560
|
+
status: "danger",
|
|
4561
|
+
title: "Could not load rules",
|
|
4562
|
+
description: error
|
|
4563
|
+
}
|
|
4564
|
+
) : null,
|
|
4565
|
+
loading ? /* @__PURE__ */ jsx25("p", { className: "mt-4 text-sm text-ph-subtle", children: "Loading rules..." }) : rules.length === 0 ? /* @__PURE__ */ jsx25(
|
|
4566
|
+
"div",
|
|
4567
|
+
{
|
|
4568
|
+
className: "mt-4 rounded-lg border border-dashed border-ph-border px-4 py-6 text-center",
|
|
4569
|
+
"data-test": `${dataTest}-empty`,
|
|
4570
|
+
children: /* @__PURE__ */ jsxs22("p", { className: "text-sm text-ph-subtle", children: [
|
|
4571
|
+
"No automation rules yet.",
|
|
4572
|
+
canManage ? " Create one to get started." : ""
|
|
4573
|
+
] })
|
|
4574
|
+
}
|
|
4575
|
+
) : /* @__PURE__ */ jsx25("ul", { className: "mt-4 space-y-2", "data-test": `${dataTest}-list`, children: rules.map((rule) => /* @__PURE__ */ jsxs22(
|
|
4576
|
+
"li",
|
|
4577
|
+
{
|
|
4578
|
+
className: "flex items-center justify-between gap-3 rounded-lg border border-ph-border bg-ph-muted px-3 py-3",
|
|
4579
|
+
"data-test": `${dataTest}-rule-${rule.id}`,
|
|
4580
|
+
children: [
|
|
4581
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
|
|
4582
|
+
/* @__PURE__ */ jsx25("p", { className: "truncate text-sm font-medium text-ph-ink", children: rule.name }),
|
|
4583
|
+
/* @__PURE__ */ jsxs22("p", { className: "mt-0.5 truncate text-xs text-ph-subtle", children: [
|
|
4584
|
+
rule.trigger_event_type,
|
|
4585
|
+
" \u2192 ",
|
|
4586
|
+
actionLabel(rule.action_type)
|
|
4587
|
+
] }),
|
|
4588
|
+
/* @__PURE__ */ jsxs22("p", { className: "mt-0.5 truncate text-xs text-ph-subtle", children: [
|
|
4589
|
+
"Last fired: ",
|
|
4590
|
+
formatDateTime(rule.last_fired_at)
|
|
4591
|
+
] })
|
|
4592
|
+
] }),
|
|
4593
|
+
canManage ? /* @__PURE__ */ jsxs22("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
4594
|
+
/* @__PURE__ */ jsx25(
|
|
4595
|
+
Toggle,
|
|
4596
|
+
{
|
|
4597
|
+
checked: rule.enabled,
|
|
4598
|
+
disabled: busyId === rule.id,
|
|
4599
|
+
onChange: () => void toggleRule(rule),
|
|
4600
|
+
"aria-label": `Enable ${rule.name}`
|
|
4601
|
+
}
|
|
4602
|
+
),
|
|
4603
|
+
/* @__PURE__ */ jsx25(
|
|
4604
|
+
Button,
|
|
4605
|
+
{
|
|
4606
|
+
type: "button",
|
|
4607
|
+
variant: "tertiary",
|
|
4608
|
+
size: "sm",
|
|
4609
|
+
disabled: busyId === rule.id,
|
|
4610
|
+
onClick: () => requestDelete(rule),
|
|
4611
|
+
"aria-label": `Delete ${rule.name}`,
|
|
4612
|
+
children: /* @__PURE__ */ jsx25(Xmark2, { className: "h-4 w-4", "aria-hidden": true })
|
|
4613
|
+
}
|
|
4614
|
+
)
|
|
4615
|
+
] }) : /* @__PURE__ */ jsx25(
|
|
4616
|
+
Badge,
|
|
4617
|
+
{
|
|
4618
|
+
variant: rule.enabled ? "success" : "neutral",
|
|
4619
|
+
size: "sm",
|
|
4620
|
+
children: rule.enabled ? "Enabled" : "Disabled"
|
|
4621
|
+
}
|
|
4622
|
+
)
|
|
4623
|
+
]
|
|
4624
|
+
},
|
|
4625
|
+
rule.id
|
|
4626
|
+
)) }),
|
|
4627
|
+
canManage && formOpen && onCreate ? /* @__PURE__ */ jsxs22(
|
|
4628
|
+
"form",
|
|
4629
|
+
{
|
|
4630
|
+
className: "mt-4 space-y-3 rounded-lg border border-ph-border bg-ph-surface p-4",
|
|
4631
|
+
onSubmit: (event) => void submitForm(event),
|
|
4632
|
+
"data-test": `${dataTest}-form`,
|
|
4633
|
+
children: [
|
|
4634
|
+
formError ? /* @__PURE__ */ jsx25("p", { className: "text-sm text-ph-danger", role: "alert", children: formError }) : null,
|
|
4635
|
+
/* @__PURE__ */ jsx25(
|
|
4636
|
+
Input,
|
|
4637
|
+
{
|
|
4638
|
+
label: "Rule name",
|
|
4639
|
+
required: true,
|
|
4640
|
+
value: name,
|
|
4641
|
+
onChange: (event) => setName(event.target.value),
|
|
4642
|
+
placeholder: "GitHub issues to tasks",
|
|
4643
|
+
"data-test": `${dataTest}-name`
|
|
4644
|
+
}
|
|
4645
|
+
),
|
|
4646
|
+
/* @__PURE__ */ jsx25(
|
|
4647
|
+
Input,
|
|
4648
|
+
{
|
|
4649
|
+
label: "Trigger event type",
|
|
4650
|
+
required: true,
|
|
4651
|
+
value: trigger,
|
|
4652
|
+
onChange: (event) => setTrigger(event.target.value),
|
|
4653
|
+
placeholder: "github.issue_assigned",
|
|
4654
|
+
helperText: "Provider event type, for example github.issue_assigned or googlecalendar.event_ended.",
|
|
4655
|
+
"data-test": `${dataTest}-trigger`
|
|
4656
|
+
}
|
|
4657
|
+
),
|
|
4658
|
+
/* @__PURE__ */ jsx25(
|
|
4659
|
+
Select,
|
|
4660
|
+
{
|
|
4661
|
+
label: "Action",
|
|
4662
|
+
value: actionType,
|
|
4663
|
+
onChange: (event) => setActionType(
|
|
4664
|
+
event.target.value
|
|
4665
|
+
),
|
|
4666
|
+
"data-test": `${dataTest}-action`,
|
|
4667
|
+
children: Object.entries(ACTION_LABELS).map(([value, label]) => /* @__PURE__ */ jsx25("option", { value, children: label }, value))
|
|
4668
|
+
}
|
|
4669
|
+
),
|
|
4670
|
+
needsProject ? /* @__PURE__ */ jsxs22(
|
|
4671
|
+
Select,
|
|
4672
|
+
{
|
|
4673
|
+
label: "Project",
|
|
4674
|
+
value: projectId,
|
|
4675
|
+
onChange: (event) => setProjectId(event.target.value),
|
|
4676
|
+
"data-test": `${dataTest}-project`,
|
|
4677
|
+
children: [
|
|
4678
|
+
/* @__PURE__ */ jsx25("option", { value: "", children: "Choose a project..." }),
|
|
4679
|
+
projects.map((project) => /* @__PURE__ */ jsx25("option", { value: project.id, children: project.name }, project.id))
|
|
4680
|
+
]
|
|
4681
|
+
}
|
|
4682
|
+
) : null,
|
|
4683
|
+
actionType === "draft_time_entry" ? /* @__PURE__ */ jsx25(
|
|
4684
|
+
Input,
|
|
4685
|
+
{
|
|
4686
|
+
label: "Minutes (optional)",
|
|
4687
|
+
type: "number",
|
|
4688
|
+
min: "1",
|
|
4689
|
+
value: minutes,
|
|
4690
|
+
onChange: (event) => setMinutes(event.target.value),
|
|
4691
|
+
"data-test": `${dataTest}-minutes`
|
|
4692
|
+
}
|
|
4693
|
+
) : null,
|
|
4694
|
+
actionType === "create_tides_task" ? /* @__PURE__ */ jsxs22(
|
|
4695
|
+
Select,
|
|
4696
|
+
{
|
|
4697
|
+
label: "Priority",
|
|
4698
|
+
value: priority,
|
|
4699
|
+
onChange: (event) => setPriority(event.target.value),
|
|
4700
|
+
"data-test": `${dataTest}-priority`,
|
|
4701
|
+
children: [
|
|
4702
|
+
/* @__PURE__ */ jsx25("option", { value: "low", children: "Low" }),
|
|
4703
|
+
/* @__PURE__ */ jsx25("option", { value: "medium", children: "Medium" }),
|
|
4704
|
+
/* @__PURE__ */ jsx25("option", { value: "high", children: "High" }),
|
|
4705
|
+
/* @__PURE__ */ jsx25("option", { value: "urgent", children: "Urgent" })
|
|
4706
|
+
]
|
|
4707
|
+
}
|
|
4708
|
+
) : null,
|
|
4709
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-2 border-t border-ph-border pt-3", children: [
|
|
4710
|
+
/* @__PURE__ */ jsx25(
|
|
4711
|
+
Button,
|
|
4712
|
+
{
|
|
4713
|
+
type: "button",
|
|
4714
|
+
variant: "tertiary",
|
|
4715
|
+
onClick: () => setFormOpen(false),
|
|
4716
|
+
disabled: submitting,
|
|
4717
|
+
children: "Cancel"
|
|
4718
|
+
}
|
|
4719
|
+
),
|
|
4720
|
+
/* @__PURE__ */ jsx25(Button, { type: "submit", variant: "primary", disabled: submitting, children: submitting ? "Creating..." : "Create rule" })
|
|
4721
|
+
] })
|
|
4722
|
+
]
|
|
4723
|
+
}
|
|
4724
|
+
) : null
|
|
4725
|
+
]
|
|
4726
|
+
}
|
|
4727
|
+
),
|
|
4728
|
+
/* @__PURE__ */ jsxs22(
|
|
4729
|
+
Modal,
|
|
4730
|
+
{
|
|
4731
|
+
open: ruleToDelete !== null,
|
|
4732
|
+
onClose: () => {
|
|
4733
|
+
if (busyId !== (ruleToDelete == null ? void 0 : ruleToDelete.id)) setRuleToDelete(null);
|
|
4734
|
+
},
|
|
4735
|
+
title: "Delete automation rule",
|
|
4736
|
+
description: "This action cannot be undone.",
|
|
4737
|
+
dataTest: `${dataTest}-delete-confirmation`,
|
|
4738
|
+
footer: /* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-2", children: [
|
|
4739
|
+
/* @__PURE__ */ jsx25(
|
|
4740
|
+
Button,
|
|
4741
|
+
{
|
|
4742
|
+
type: "button",
|
|
4743
|
+
variant: "tertiary",
|
|
4744
|
+
onClick: () => setRuleToDelete(null),
|
|
4745
|
+
disabled: busyId === (ruleToDelete == null ? void 0 : ruleToDelete.id),
|
|
4746
|
+
children: "Cancel"
|
|
4747
|
+
}
|
|
4748
|
+
),
|
|
4749
|
+
/* @__PURE__ */ jsx25(
|
|
4750
|
+
Button,
|
|
4751
|
+
{
|
|
4752
|
+
type: "button",
|
|
4753
|
+
variant: "danger",
|
|
4754
|
+
onClick: () => void deleteRule(),
|
|
4755
|
+
disabled: busyId === (ruleToDelete == null ? void 0 : ruleToDelete.id),
|
|
4756
|
+
"data-test": `${dataTest}-delete-confirm`,
|
|
4757
|
+
children: busyId === (ruleToDelete == null ? void 0 : ruleToDelete.id) ? "Deleting..." : "Delete rule"
|
|
4758
|
+
}
|
|
4759
|
+
)
|
|
4760
|
+
] }),
|
|
4761
|
+
children: [
|
|
4762
|
+
deleteError ? /* @__PURE__ */ jsx25("p", { className: "text-sm text-ph-danger", role: "alert", children: deleteError }) : null,
|
|
4763
|
+
/* @__PURE__ */ jsxs22("p", { className: "text-sm text-ph-ink", children: [
|
|
4764
|
+
"Delete ",
|
|
4765
|
+
ruleToDelete == null ? void 0 : ruleToDelete.name,
|
|
4766
|
+
"? This cannot be undone."
|
|
4767
|
+
] })
|
|
4768
|
+
]
|
|
4769
|
+
}
|
|
4770
|
+
),
|
|
4771
|
+
/* @__PURE__ */ jsxs22(
|
|
4772
|
+
Card,
|
|
4773
|
+
{
|
|
4774
|
+
variant: "outlined",
|
|
4775
|
+
bodyClassName: "p-5",
|
|
4776
|
+
"data-test": `${dataTest}-events-card`,
|
|
4777
|
+
children: [
|
|
4778
|
+
/* @__PURE__ */ jsx25("h3", { className: "font-medium text-ph-ink", children: "Recent events" }),
|
|
4779
|
+
/* @__PURE__ */ jsx25("p", { className: "mt-1 text-sm text-ph-subtle", children: "The latest events received from your connected apps." }),
|
|
4780
|
+
events.length === 0 ? /* @__PURE__ */ jsx25(
|
|
4781
|
+
"p",
|
|
4782
|
+
{
|
|
4783
|
+
className: "mt-4 rounded-lg border border-dashed border-ph-border px-4 py-6 text-center text-sm text-ph-subtle",
|
|
4784
|
+
"data-test": `${dataTest}-events-empty`,
|
|
4785
|
+
children: "No integration events yet."
|
|
4786
|
+
}
|
|
4787
|
+
) : /* @__PURE__ */ jsx25("ul", { className: "mt-4 space-y-2", "data-test": `${dataTest}-events-list`, children: events.map((event) => /* @__PURE__ */ jsxs22(
|
|
4788
|
+
"li",
|
|
4789
|
+
{
|
|
4790
|
+
className: "flex items-center justify-between gap-3 rounded-lg border border-ph-border bg-ph-muted px-3 py-2",
|
|
4791
|
+
children: [
|
|
4792
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
|
|
4793
|
+
/* @__PURE__ */ jsxs22("p", { className: "truncate text-sm text-ph-ink", children: [
|
|
4794
|
+
event.provider,
|
|
4795
|
+
" \xB7 ",
|
|
4796
|
+
event.event_type
|
|
4797
|
+
] }),
|
|
4798
|
+
/* @__PURE__ */ jsx25("p", { className: "mt-0.5 text-xs text-ph-subtle", children: formatDateTime(event.created_at) })
|
|
4799
|
+
] }),
|
|
4800
|
+
/* @__PURE__ */ jsx25(
|
|
4801
|
+
Badge,
|
|
4802
|
+
{
|
|
4803
|
+
variant: event.processed_at ? "success" : "warning",
|
|
4804
|
+
size: "sm",
|
|
4805
|
+
children: event.processed_at ? "Processed" : "Pending"
|
|
4806
|
+
}
|
|
4807
|
+
)
|
|
4808
|
+
]
|
|
4809
|
+
},
|
|
4810
|
+
event.id
|
|
4811
|
+
)) })
|
|
4812
|
+
]
|
|
4813
|
+
}
|
|
4814
|
+
)
|
|
4815
|
+
] });
|
|
4816
|
+
}
|
|
4817
|
+
|
|
4818
|
+
// src/suite/components/suite-clients-projects-directory.tsx
|
|
4819
|
+
import {
|
|
4820
|
+
useEffect as useEffect9,
|
|
4821
|
+
useMemo as useMemo2,
|
|
4822
|
+
useRef as useRef4,
|
|
4823
|
+
useState as useState12
|
|
4824
|
+
} from "react";
|
|
4825
|
+
import {
|
|
4826
|
+
ArrowLeft,
|
|
4827
|
+
MediaImagePlus as ImagePlus,
|
|
4828
|
+
MoreHoriz as MoreHorizontal,
|
|
4829
|
+
Plus as Plus2,
|
|
4830
|
+
Search as Search2,
|
|
4831
|
+
Trash
|
|
4832
|
+
} from "iconoir-react";
|
|
4833
|
+
import { Fragment as Fragment9, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
4834
|
+
var DEFAULT_ICON = "castle-emblem";
|
|
4835
|
+
var DEFAULT_COLOR = "#6366f1";
|
|
4836
|
+
var DIRECTORY_ICON_OPTIONS = [
|
|
4837
|
+
["arena", "Arena"],
|
|
4838
|
+
["bridge", "Bridge"],
|
|
4839
|
+
["capitol", "Capitol"],
|
|
4840
|
+
["castle-emblem", "Castle"],
|
|
4841
|
+
["castle-flag", "Castle flag"],
|
|
4842
|
+
["lighthouse", "Lighthouse"],
|
|
4843
|
+
["tower", "Tower"],
|
|
4844
|
+
["wooden-sign", "Sign"],
|
|
4845
|
+
["anvil", "Anvil"],
|
|
4846
|
+
["book", "Book"],
|
|
4847
|
+
["chessboard", "Chessboard"],
|
|
4848
|
+
["cog", "Settings"],
|
|
4849
|
+
["hammer", "Build"],
|
|
4850
|
+
["light-bulb", "Idea"],
|
|
4851
|
+
["microphone", "Communication"],
|
|
4852
|
+
["quill-ink", "Writing"],
|
|
4853
|
+
["scroll-unfurled", "Notes"],
|
|
4854
|
+
["hourglass", "Planning"],
|
|
4855
|
+
["wrench", "Tools"],
|
|
4856
|
+
["archer", "Archer"],
|
|
4857
|
+
["archery-target", "Target"],
|
|
4858
|
+
["axe", "Axe"],
|
|
4859
|
+
["campfire", "Campfire"],
|
|
4860
|
+
["compass", "Compass"],
|
|
4861
|
+
["crossed-swords", "Battle"],
|
|
4862
|
+
["knight-helmet", "Knight"],
|
|
4863
|
+
["mountains", "Mountains"],
|
|
4864
|
+
["shield", "Shield"],
|
|
4865
|
+
["ship-emblem", "Voyage"],
|
|
4866
|
+
["sword", "Sword"],
|
|
4867
|
+
["trophy", "Trophy"],
|
|
4868
|
+
["apple", "Apple"],
|
|
4869
|
+
["butterfly", "Butterfly"],
|
|
4870
|
+
["clover", "Clover"],
|
|
4871
|
+
["dragon", "Dragon"],
|
|
4872
|
+
["fire", "Fire"],
|
|
4873
|
+
["flower", "Flower"],
|
|
4874
|
+
["flowers", "Flowers"],
|
|
4875
|
+
["grass", "Grass"],
|
|
4876
|
+
["leaf", "Leaf"],
|
|
4877
|
+
["pine-tree", "Pine tree"],
|
|
4878
|
+
["sun", "Sun"],
|
|
4879
|
+
["water-drop", "Water"],
|
|
4880
|
+
["aura", "Aura"],
|
|
4881
|
+
["crystal-ball", "Crystal ball"],
|
|
4882
|
+
["diamond", "Diamond"],
|
|
4883
|
+
["explosion", "Explosion"],
|
|
4884
|
+
["fire-symbol", "Fire symbol"],
|
|
4885
|
+
["gem", "Gem"],
|
|
4886
|
+
["lightning-trio", "Lightning"],
|
|
4887
|
+
["potion", "Potion"],
|
|
4888
|
+
["rune-stone", "Rune stone"],
|
|
4889
|
+
["skull", "Skull"],
|
|
4890
|
+
["tentacle", "Tentacle"],
|
|
4891
|
+
["wolf-head", "Wolf"],
|
|
4892
|
+
["anchor", "Anchor"],
|
|
4893
|
+
["beer", "Beer"],
|
|
4894
|
+
["carrot", "Carrot"],
|
|
4895
|
+
["cat", "Cat"],
|
|
4896
|
+
["crown", "Crown"],
|
|
4897
|
+
["gold-bar", "Gold bar"],
|
|
4898
|
+
["helmet", "Helmet"],
|
|
4899
|
+
["key", "Key"],
|
|
4900
|
+
["three-keys", "Keys"]
|
|
4901
|
+
];
|
|
4902
|
+
function isDirectoryIcon(value) {
|
|
4903
|
+
return DIRECTORY_ICON_OPTIONS.some(([name]) => name === value);
|
|
4904
|
+
}
|
|
4905
|
+
function DirectoryIconPicker({
|
|
4906
|
+
value,
|
|
4907
|
+
preview,
|
|
4908
|
+
onFileChange,
|
|
4909
|
+
onClear,
|
|
4910
|
+
onChange
|
|
4911
|
+
}) {
|
|
4912
|
+
const iconRefs = useRef4({});
|
|
4913
|
+
function moveSelection(event, index) {
|
|
4914
|
+
var _a;
|
|
4915
|
+
let nextIndex = null;
|
|
4916
|
+
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
|
4917
|
+
nextIndex = (index + 1) % DIRECTORY_ICON_OPTIONS.length;
|
|
4918
|
+
} else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
|
4919
|
+
nextIndex = (index - 1 + DIRECTORY_ICON_OPTIONS.length) % DIRECTORY_ICON_OPTIONS.length;
|
|
4920
|
+
} else if (event.key === "Home") {
|
|
4921
|
+
nextIndex = 0;
|
|
4922
|
+
} else if (event.key === "End") {
|
|
4923
|
+
nextIndex = DIRECTORY_ICON_OPTIONS.length - 1;
|
|
4924
|
+
}
|
|
4925
|
+
if (nextIndex === null) return;
|
|
4926
|
+
event.preventDefault();
|
|
4927
|
+
const [nextIcon] = DIRECTORY_ICON_OPTIONS[nextIndex];
|
|
4928
|
+
onChange(nextIcon);
|
|
4929
|
+
(_a = iconRefs.current[nextIcon]) == null ? void 0 : _a.focus();
|
|
4930
|
+
}
|
|
4931
|
+
return /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
|
|
4932
|
+
/* @__PURE__ */ jsx26("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Icon" }),
|
|
4933
|
+
/* @__PURE__ */ jsx26(
|
|
4934
|
+
"div",
|
|
4935
|
+
{
|
|
4936
|
+
role: "radiogroup",
|
|
4937
|
+
"aria-label": "Icon",
|
|
4938
|
+
className: "grid grid-cols-6 gap-1.5 rounded-lg border border-ph-border p-1.5 sm:grid-cols-8",
|
|
4939
|
+
children: DIRECTORY_ICON_OPTIONS.map(([name, label], index) => {
|
|
4940
|
+
const selected = value === name;
|
|
4941
|
+
return /* @__PURE__ */ jsx26(
|
|
4942
|
+
"button",
|
|
4943
|
+
{
|
|
4944
|
+
type: "button",
|
|
4945
|
+
role: "radio",
|
|
4946
|
+
"aria-label": label,
|
|
4947
|
+
"aria-checked": selected,
|
|
4948
|
+
tabIndex: selected ? 0 : -1,
|
|
4949
|
+
title: label,
|
|
4950
|
+
onClick: () => onChange(name),
|
|
4951
|
+
onKeyDown: (event) => moveSelection(event, index),
|
|
4952
|
+
ref: (element) => {
|
|
4953
|
+
iconRefs.current[name] = element;
|
|
4954
|
+
},
|
|
4955
|
+
className: cn(
|
|
4956
|
+
"flex h-9 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink",
|
|
4957
|
+
selected && "bg-ph-muted text-ph-ink ring-2 ring-ph-brand ring-inset"
|
|
4958
|
+
),
|
|
4959
|
+
children: /* @__PURE__ */ jsx26(
|
|
4960
|
+
"i",
|
|
4961
|
+
{
|
|
4962
|
+
className: cn("ra", `ra-${name}`, "text-base leading-none"),
|
|
4963
|
+
"aria-hidden": true
|
|
4964
|
+
}
|
|
4965
|
+
)
|
|
4966
|
+
},
|
|
4967
|
+
name
|
|
4968
|
+
);
|
|
4969
|
+
})
|
|
4970
|
+
}
|
|
4971
|
+
),
|
|
4972
|
+
/* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-ph-border bg-ph-muted p-2", children: [
|
|
4973
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 text-sm font-medium text-ph-ink", children: [
|
|
4974
|
+
/* @__PURE__ */ jsx26(ImagePlus, { className: "h-4 w-4", "aria-hidden": true }),
|
|
4975
|
+
" Custom image"
|
|
4976
|
+
] }),
|
|
4977
|
+
/* @__PURE__ */ jsx26("p", { className: "mt-1 text-xs text-ph-mutedtext", children: "PNG, JPG, GIF, WebP, or SVG \u2014 max 512 KB." }),
|
|
4978
|
+
/* @__PURE__ */ jsx26(
|
|
4979
|
+
FileUpload,
|
|
4980
|
+
{
|
|
4981
|
+
accept: "image/png,image/jpeg,image/gif,image/webp,image/svg+xml,.svg",
|
|
4982
|
+
onChange: (event) => {
|
|
4983
|
+
var _a, _b;
|
|
4984
|
+
return onFileChange((_b = (_a = event.target.files) == null ? void 0 : _a[0]) != null ? _b : null);
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
),
|
|
4988
|
+
preview ? /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex items-center gap-2", children: [
|
|
4989
|
+
/* @__PURE__ */ jsx26(
|
|
4990
|
+
"img",
|
|
4991
|
+
{
|
|
4992
|
+
src: preview,
|
|
4993
|
+
alt: "",
|
|
4994
|
+
className: "h-8 w-8 rounded object-cover"
|
|
4995
|
+
}
|
|
4996
|
+
),
|
|
4997
|
+
/* @__PURE__ */ jsxs23(
|
|
4998
|
+
"button",
|
|
4999
|
+
{
|
|
5000
|
+
type: "button",
|
|
5001
|
+
className: "text-xs text-ph-mutedtext hover:text-ph-ink",
|
|
5002
|
+
onClick: onClear,
|
|
5003
|
+
children: [
|
|
5004
|
+
/* @__PURE__ */ jsx26(Trash, { className: "mr-1 inline h-3.5 w-3.5", "aria-hidden": true }),
|
|
5005
|
+
" Remove custom image"
|
|
5006
|
+
]
|
|
5007
|
+
}
|
|
5008
|
+
)
|
|
5009
|
+
] }) : null
|
|
5010
|
+
] })
|
|
5011
|
+
] });
|
|
5012
|
+
}
|
|
5013
|
+
function DirectoryIcon({
|
|
5014
|
+
item
|
|
5015
|
+
}) {
|
|
5016
|
+
const icon = item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON;
|
|
5017
|
+
return /* @__PURE__ */ jsx26(
|
|
5018
|
+
"span",
|
|
5019
|
+
{
|
|
5020
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-white",
|
|
5021
|
+
style: { backgroundColor: item.color || "var(--ph-brand)" },
|
|
5022
|
+
children: item.icon_image ? (
|
|
5023
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
5024
|
+
/* @__PURE__ */ jsx26(
|
|
5025
|
+
"img",
|
|
5026
|
+
{
|
|
5027
|
+
src: item.icon_image,
|
|
5028
|
+
alt: "",
|
|
5029
|
+
className: "h-full w-full rounded-lg object-cover"
|
|
5030
|
+
}
|
|
5031
|
+
)
|
|
5032
|
+
) : /* @__PURE__ */ jsx26(
|
|
5033
|
+
"i",
|
|
5034
|
+
{
|
|
5035
|
+
className: cn("ra", `ra-${icon}`, "text-base leading-none"),
|
|
5036
|
+
"aria-hidden": true
|
|
5037
|
+
}
|
|
5038
|
+
)
|
|
5039
|
+
}
|
|
5040
|
+
);
|
|
5041
|
+
}
|
|
5042
|
+
function SuiteClientsProjectsDirectory({
|
|
5043
|
+
clients,
|
|
5044
|
+
projects,
|
|
5045
|
+
canEdit = false,
|
|
5046
|
+
loading = false,
|
|
5047
|
+
error,
|
|
5048
|
+
onCreateClient,
|
|
5049
|
+
onUpdateClient,
|
|
5050
|
+
onDeleteClient,
|
|
5051
|
+
onCreateProject,
|
|
5052
|
+
onUpdateProject,
|
|
5053
|
+
onDeleteProject,
|
|
5054
|
+
dataTest = "suite-clients-projects-directory"
|
|
5055
|
+
}) {
|
|
5056
|
+
var _a;
|
|
5057
|
+
const [query, setQuery] = useState12("");
|
|
5058
|
+
const [selectedClientId, setSelectedClientId] = useState12(null);
|
|
5059
|
+
const [mobileDetail, setMobileDetail] = useState12(false);
|
|
5060
|
+
const [editing, setEditing] = useState12(null);
|
|
5061
|
+
const [draft, setDraft] = useState12({
|
|
5062
|
+
name: "",
|
|
5063
|
+
icon: DEFAULT_ICON,
|
|
5064
|
+
color: DEFAULT_COLOR
|
|
5065
|
+
});
|
|
5066
|
+
const [draftClientId, setDraftClientId] = useState12(null);
|
|
5067
|
+
const [preview, setPreview] = useState12(null);
|
|
5068
|
+
const [draftArchived, setDraftArchived] = useState12(false);
|
|
5069
|
+
const [confirming, setConfirming] = useState12(null);
|
|
5070
|
+
const [saving, setSaving] = useState12(false);
|
|
5071
|
+
const [mutationError, setMutationError] = useState12(null);
|
|
5072
|
+
const clientButtonRefs = useRef4({});
|
|
5073
|
+
const backToClientsRef = useRef4(null);
|
|
5074
|
+
const mobileFocusTarget = useRef4(null);
|
|
5075
|
+
useEffect9(() => {
|
|
5076
|
+
var _a2, _b;
|
|
5077
|
+
if (selectedClientId && clients.some((client) => client.id === selectedClientId))
|
|
5078
|
+
return;
|
|
5079
|
+
setSelectedClientId((_b = (_a2 = clients[0]) == null ? void 0 : _a2.id) != null ? _b : null);
|
|
5080
|
+
}, [clients, selectedClientId]);
|
|
5081
|
+
useEffect9(() => {
|
|
5082
|
+
var _a2, _b;
|
|
5083
|
+
const target = mobileFocusTarget.current;
|
|
5084
|
+
if (!target) return;
|
|
5085
|
+
mobileFocusTarget.current = null;
|
|
5086
|
+
if (target === "detail") (_a2 = backToClientsRef.current) == null ? void 0 : _a2.focus();
|
|
5087
|
+
else if (selectedClientId)
|
|
5088
|
+
(_b = clientButtonRefs.current[selectedClientId]) == null ? void 0 : _b.focus();
|
|
5089
|
+
}, [mobileDetail, selectedClientId]);
|
|
5090
|
+
const filteredClients = useMemo2(() => {
|
|
5091
|
+
const value = query.trim().toLowerCase();
|
|
5092
|
+
return [...clients].sort((a, b) => a.name.localeCompare(b.name)).filter((client) => !value || client.name.toLowerCase().includes(value));
|
|
5093
|
+
}, [clients, query]);
|
|
5094
|
+
const selectedClient = (_a = clients.find((client) => client.id === selectedClientId)) != null ? _a : null;
|
|
5095
|
+
const selectedProjects = projects.filter((project) => project.clientId === selectedClientId).sort((a, b) => a.name.localeCompare(b.name));
|
|
5096
|
+
function isMobileDirectoryView() {
|
|
5097
|
+
var _a2, _b;
|
|
5098
|
+
return (_b = (_a2 = window.matchMedia) == null ? void 0 : _a2.call(window, "(max-width: 1023px)").matches) != null ? _b : false;
|
|
5099
|
+
}
|
|
5100
|
+
function selectClient(client) {
|
|
5101
|
+
setSelectedClientId(client.id);
|
|
5102
|
+
setMobileDetail(true);
|
|
5103
|
+
if (isMobileDirectoryView()) mobileFocusTarget.current = "detail";
|
|
5104
|
+
}
|
|
5105
|
+
function moveClientSelection(event, index) {
|
|
5106
|
+
var _a2;
|
|
5107
|
+
let nextIndex = null;
|
|
5108
|
+
if (event.key === "ArrowDown") {
|
|
5109
|
+
nextIndex = (index + 1) % filteredClients.length;
|
|
5110
|
+
} else if (event.key === "ArrowUp") {
|
|
5111
|
+
nextIndex = (index - 1 + filteredClients.length) % filteredClients.length;
|
|
5112
|
+
} else if (event.key === "Home") {
|
|
5113
|
+
nextIndex = 0;
|
|
5114
|
+
} else if (event.key === "End") {
|
|
5115
|
+
nextIndex = filteredClients.length - 1;
|
|
5116
|
+
}
|
|
5117
|
+
if (nextIndex === null) return;
|
|
5118
|
+
event.preventDefault();
|
|
5119
|
+
const client = filteredClients[nextIndex];
|
|
5120
|
+
selectClient(client);
|
|
5121
|
+
if (!isMobileDirectoryView()) (_a2 = clientButtonRefs.current[client.id]) == null ? void 0 : _a2.focus();
|
|
5122
|
+
}
|
|
5123
|
+
function openNew(kind) {
|
|
5124
|
+
setMutationError(null);
|
|
5125
|
+
setDraft({
|
|
5126
|
+
name: "",
|
|
5127
|
+
icon: DEFAULT_ICON,
|
|
5128
|
+
color: DEFAULT_COLOR,
|
|
5129
|
+
iconImageFile: null,
|
|
5130
|
+
clearIconImage: false
|
|
5131
|
+
});
|
|
5132
|
+
setPreview(null);
|
|
5133
|
+
setDraftArchived(false);
|
|
5134
|
+
setDraftClientId(kind === "project" ? selectedClientId : null);
|
|
5135
|
+
setEditing({ kind: kind === "client" ? "new-client" : "new-project" });
|
|
5136
|
+
}
|
|
5137
|
+
function openEdit(item, kind) {
|
|
5138
|
+
var _a2;
|
|
5139
|
+
setMutationError(null);
|
|
5140
|
+
setDraft({
|
|
5141
|
+
name: item.name,
|
|
5142
|
+
icon: item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON,
|
|
5143
|
+
color: item.color || DEFAULT_COLOR,
|
|
5144
|
+
iconImageFile: null,
|
|
5145
|
+
clearIconImage: false
|
|
5146
|
+
});
|
|
5147
|
+
setPreview(item.icon_image || null);
|
|
5148
|
+
setDraftArchived(
|
|
5149
|
+
kind === "project" && Boolean(item.isArchived)
|
|
5150
|
+
);
|
|
5151
|
+
setDraftClientId(
|
|
5152
|
+
kind === "project" ? (_a2 = item.clientId) != null ? _a2 : null : null
|
|
5153
|
+
);
|
|
5154
|
+
setEditing({ kind, item });
|
|
5155
|
+
}
|
|
5156
|
+
function chooseImage(file) {
|
|
5157
|
+
if (!file) return;
|
|
5158
|
+
if (file.size > 512 * 1024) {
|
|
5159
|
+
setMutationError("Icon must be 512 KB or smaller.");
|
|
5160
|
+
return;
|
|
5161
|
+
}
|
|
5162
|
+
setMutationError(null);
|
|
5163
|
+
if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
|
|
5164
|
+
setDraft((current) => __spreadProps(__spreadValues({}, current), {
|
|
5165
|
+
iconImageFile: file,
|
|
5166
|
+
clearIconImage: false
|
|
5167
|
+
}));
|
|
5168
|
+
setPreview(URL.createObjectURL(file));
|
|
5169
|
+
}
|
|
5170
|
+
function clearImage() {
|
|
5171
|
+
if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
|
|
5172
|
+
setPreview(null);
|
|
5173
|
+
setDraft((current) => __spreadProps(__spreadValues({}, current), {
|
|
5174
|
+
iconImageFile: null,
|
|
5175
|
+
clearIconImage: true
|
|
5176
|
+
}));
|
|
5177
|
+
}
|
|
5178
|
+
function closeEditor() {
|
|
5179
|
+
if (!saving) setEditing(null);
|
|
5180
|
+
}
|
|
5181
|
+
async function save() {
|
|
5182
|
+
if (!editing || !draft.name.trim() || saving) return;
|
|
5183
|
+
setSaving(true);
|
|
5184
|
+
setMutationError(null);
|
|
5185
|
+
try {
|
|
5186
|
+
const fields = __spreadProps(__spreadValues({}, draft), { name: draft.name.trim() });
|
|
5187
|
+
if (editing.kind === "new-client") await (onCreateClient == null ? void 0 : onCreateClient(fields));
|
|
5188
|
+
else if (editing.kind === "new-project")
|
|
5189
|
+
await (onCreateProject == null ? void 0 : onCreateProject(__spreadProps(__spreadValues({}, fields), {
|
|
5190
|
+
clientId: draftClientId,
|
|
5191
|
+
isArchived: draftArchived
|
|
5192
|
+
})));
|
|
5193
|
+
else if (editing.kind === "client")
|
|
5194
|
+
await (onUpdateClient == null ? void 0 : onUpdateClient(editing.item, fields));
|
|
5195
|
+
else
|
|
5196
|
+
await (onUpdateProject == null ? void 0 : onUpdateProject(editing.item, __spreadProps(__spreadValues({}, fields), {
|
|
5197
|
+
clientId: draftClientId,
|
|
5198
|
+
isArchived: draftArchived
|
|
5199
|
+
})));
|
|
5200
|
+
setEditing(null);
|
|
5201
|
+
} catch (err) {
|
|
5202
|
+
setMutationError(
|
|
5203
|
+
err instanceof Error ? err.message : "Failed to save directory item."
|
|
5204
|
+
);
|
|
5205
|
+
} finally {
|
|
5206
|
+
setSaving(false);
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
function remove(item, kind) {
|
|
5210
|
+
setConfirming({ item, kind });
|
|
5211
|
+
}
|
|
5212
|
+
async function toggleArchive(project) {
|
|
5213
|
+
var _a2;
|
|
5214
|
+
if (!onUpdateProject) return;
|
|
5215
|
+
try {
|
|
5216
|
+
await onUpdateProject(project, {
|
|
5217
|
+
name: project.name,
|
|
5218
|
+
icon: project.icon && isDirectoryIcon(project.icon) ? project.icon : DEFAULT_ICON,
|
|
5219
|
+
color: project.color || DEFAULT_COLOR,
|
|
5220
|
+
clientId: (_a2 = project.clientId) != null ? _a2 : null,
|
|
5221
|
+
isArchived: !project.isArchived
|
|
5222
|
+
});
|
|
5223
|
+
} catch (err) {
|
|
5224
|
+
setMutationError(
|
|
5225
|
+
err instanceof Error ? err.message : "Failed to update project."
|
|
5226
|
+
);
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
async function confirmRemove() {
|
|
5230
|
+
if (!confirming) return;
|
|
5231
|
+
const { item, kind } = confirming;
|
|
5232
|
+
setConfirming(null);
|
|
5233
|
+
try {
|
|
5234
|
+
if (kind === "client")
|
|
5235
|
+
await (onDeleteClient == null ? void 0 : onDeleteClient(item));
|
|
5236
|
+
else await (onDeleteProject == null ? void 0 : onDeleteProject(item));
|
|
5237
|
+
} catch (err) {
|
|
5238
|
+
setMutationError(
|
|
5239
|
+
err instanceof Error ? err.message : "Failed to delete directory item."
|
|
5240
|
+
);
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
return /* @__PURE__ */ jsxs23("div", { "data-test": dataTest, className: "space-y-3", children: [
|
|
5244
|
+
error || mutationError ? /* @__PURE__ */ jsx26(Alert, { status: "danger", live: "assertive", children: error || mutationError }) : null,
|
|
5245
|
+
loading ? /* @__PURE__ */ jsx26("p", { className: "text-sm text-ph-mutedtext", children: "Loading directory..." }) : /* @__PURE__ */ jsxs23("div", { className: "overflow-hidden rounded-xl border border-ph-border bg-ph-surface lg:grid lg:min-h-[22rem] lg:grid-cols-[minmax(14rem,18rem)_1fr]", children: [
|
|
5246
|
+
/* @__PURE__ */ jsxs23(
|
|
5247
|
+
"section",
|
|
5248
|
+
{
|
|
5249
|
+
className: cn(
|
|
5250
|
+
"border-ph-border lg:border-r",
|
|
5251
|
+
mobileDetail ? "hidden lg:block" : "block"
|
|
5252
|
+
),
|
|
5253
|
+
children: [
|
|
5254
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex h-14 items-center gap-2 border-b border-ph-border px-3", children: [
|
|
5255
|
+
/* @__PURE__ */ jsxs23("div", { className: "relative min-w-0 flex-1", children: [
|
|
5256
|
+
/* @__PURE__ */ jsx26(
|
|
5257
|
+
Search2,
|
|
5258
|
+
{
|
|
5259
|
+
className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
|
|
5260
|
+
"aria-hidden": true
|
|
5261
|
+
}
|
|
5262
|
+
),
|
|
5263
|
+
/* @__PURE__ */ jsx26(
|
|
5264
|
+
Input,
|
|
5265
|
+
{
|
|
5266
|
+
hideLabel: true,
|
|
5267
|
+
"aria-label": "Search clients",
|
|
5268
|
+
placeholder: "Search clients...",
|
|
5269
|
+
value: query,
|
|
5270
|
+
onChange: (event) => setQuery(event.target.value),
|
|
5271
|
+
className: "pl-9"
|
|
5272
|
+
}
|
|
5273
|
+
)
|
|
5274
|
+
] }),
|
|
5275
|
+
canEdit && onCreateClient ? /* @__PURE__ */ jsx26(
|
|
5276
|
+
Button,
|
|
5277
|
+
{
|
|
5278
|
+
size: "sm",
|
|
5279
|
+
variant: "primary",
|
|
5280
|
+
icon: /* @__PURE__ */ jsx26(Plus2, { className: "h-4 w-4" }),
|
|
5281
|
+
onClick: () => openNew("client"),
|
|
5282
|
+
children: "New client"
|
|
5283
|
+
}
|
|
5284
|
+
) : null
|
|
5285
|
+
] }),
|
|
5286
|
+
/* @__PURE__ */ jsx26(
|
|
5287
|
+
"ul",
|
|
5288
|
+
{
|
|
5289
|
+
role: "listbox",
|
|
5290
|
+
"aria-label": "Clients",
|
|
5291
|
+
className: "max-h-[28rem] overflow-y-auto p-1.5",
|
|
5292
|
+
children: filteredClients.length ? filteredClients.map((client, index) => {
|
|
5293
|
+
const selected = client.id === selectedClientId;
|
|
5294
|
+
const count = projects.filter(
|
|
5295
|
+
(project) => project.clientId === client.id
|
|
5296
|
+
).length;
|
|
5297
|
+
return /* @__PURE__ */ jsx26("li", { role: "none", children: /* @__PURE__ */ jsxs23(
|
|
5298
|
+
"button",
|
|
5299
|
+
{
|
|
5300
|
+
type: "button",
|
|
5301
|
+
role: "option",
|
|
5302
|
+
"aria-selected": selected,
|
|
5303
|
+
tabIndex: selected ? 0 : -1,
|
|
5304
|
+
onClick: () => selectClient(client),
|
|
5305
|
+
onKeyDown: (event) => moveClientSelection(event, index),
|
|
5306
|
+
ref: (element) => {
|
|
5307
|
+
clientButtonRefs.current[client.id] = element;
|
|
5308
|
+
},
|
|
5309
|
+
className: cn(
|
|
5310
|
+
"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left",
|
|
5311
|
+
selected ? "bg-ph-muted" : "hover:bg-ph-canvas"
|
|
5312
|
+
),
|
|
5313
|
+
children: [
|
|
5314
|
+
/* @__PURE__ */ jsx26(DirectoryIcon, { item: client }),
|
|
5315
|
+
/* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex-1", children: [
|
|
5316
|
+
/* @__PURE__ */ jsx26("span", { className: "block truncate text-sm font-medium text-ph-ink", children: client.name }),
|
|
5317
|
+
/* @__PURE__ */ jsxs23("span", { className: "text-xs text-ph-mutedtext", children: [
|
|
5318
|
+
count,
|
|
5319
|
+
" project",
|
|
5320
|
+
count === 1 ? "" : "s"
|
|
5321
|
+
] })
|
|
5322
|
+
] })
|
|
5323
|
+
]
|
|
5324
|
+
}
|
|
5325
|
+
) }, client.id);
|
|
5326
|
+
}) : /* @__PURE__ */ jsx26("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: clients.length ? "No matches." : "Add a client to get started." })
|
|
5327
|
+
}
|
|
5328
|
+
)
|
|
5329
|
+
]
|
|
5330
|
+
}
|
|
5331
|
+
),
|
|
5332
|
+
/* @__PURE__ */ jsxs23(
|
|
5333
|
+
"section",
|
|
5334
|
+
{
|
|
5335
|
+
className: cn(
|
|
5336
|
+
"flex min-w-0 flex-col",
|
|
5337
|
+
mobileDetail ? "flex" : "hidden lg:flex"
|
|
5338
|
+
),
|
|
5339
|
+
children: [
|
|
5340
|
+
/* @__PURE__ */ jsx26("div", { className: "flex min-h-14 items-center gap-2 border-b border-ph-border px-3 py-2", children: selectedClient ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
|
|
5341
|
+
/* @__PURE__ */ jsx26(
|
|
5342
|
+
"button",
|
|
5343
|
+
{
|
|
5344
|
+
type: "button",
|
|
5345
|
+
ref: backToClientsRef,
|
|
5346
|
+
className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted lg:hidden",
|
|
5347
|
+
onClick: () => {
|
|
5348
|
+
mobileFocusTarget.current = "list";
|
|
5349
|
+
setMobileDetail(false);
|
|
5350
|
+
},
|
|
5351
|
+
"aria-label": "Back to clients",
|
|
5352
|
+
children: /* @__PURE__ */ jsx26(ArrowLeft, { className: "h-4 w-4" })
|
|
5353
|
+
}
|
|
5354
|
+
),
|
|
5355
|
+
/* @__PURE__ */ jsx26(DirectoryIcon, { item: selectedClient }),
|
|
5356
|
+
/* @__PURE__ */ jsxs23("div", { className: "min-w-0 flex-1", children: [
|
|
5357
|
+
/* @__PURE__ */ jsx26("h3", { className: "truncate text-sm font-semibold text-ph-ink", children: selectedClient.name }),
|
|
5358
|
+
/* @__PURE__ */ jsxs23("p", { className: "text-xs text-ph-mutedtext", children: [
|
|
5359
|
+
selectedProjects.length,
|
|
5360
|
+
" project",
|
|
5361
|
+
selectedProjects.length === 1 ? "" : "s"
|
|
5362
|
+
] })
|
|
5363
|
+
] }),
|
|
5364
|
+
canEdit && (onUpdateClient || onDeleteClient) ? /* @__PURE__ */ jsx26("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx26(
|
|
5365
|
+
DropdownMenu,
|
|
5366
|
+
{
|
|
5367
|
+
"aria-label": `Actions for ${selectedClient.name}`,
|
|
5368
|
+
align: "end",
|
|
5369
|
+
trigger: /* @__PURE__ */ jsxs23("span", { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink", children: [
|
|
5370
|
+
/* @__PURE__ */ jsx26(MoreHorizontal, { className: "h-4 w-4", "aria-hidden": true }),
|
|
5371
|
+
/* @__PURE__ */ jsx26("span", { className: "sr-only", children: "Client actions" })
|
|
5372
|
+
] }),
|
|
5373
|
+
children: /* @__PURE__ */ jsxs23("div", { className: "p-1", children: [
|
|
5374
|
+
onUpdateClient ? /* @__PURE__ */ jsx26(
|
|
5375
|
+
DropdownItem,
|
|
5376
|
+
{
|
|
5377
|
+
onClick: () => openEdit(selectedClient, "client"),
|
|
5378
|
+
children: "Edit client"
|
|
5379
|
+
}
|
|
5380
|
+
) : null,
|
|
5381
|
+
onDeleteClient ? /* @__PURE__ */ jsx26(
|
|
5382
|
+
DropdownItem,
|
|
5383
|
+
{
|
|
5384
|
+
className: "text-red-600",
|
|
5385
|
+
onClick: () => void remove(selectedClient, "client"),
|
|
5386
|
+
children: "Delete client"
|
|
5387
|
+
}
|
|
5388
|
+
) : null
|
|
5389
|
+
] })
|
|
5390
|
+
}
|
|
5391
|
+
) }) : null
|
|
5392
|
+
] }) : /* @__PURE__ */ jsx26("p", { className: "text-sm text-ph-mutedtext", children: "Select a client" }) }),
|
|
5393
|
+
canEdit && onCreateProject ? /* @__PURE__ */ jsx26("div", { className: "border-b border-ph-border p-3", children: /* @__PURE__ */ jsx26(
|
|
5394
|
+
Button,
|
|
5395
|
+
{
|
|
5396
|
+
variant: "primary",
|
|
5397
|
+
icon: /* @__PURE__ */ jsx26(Plus2, { className: "h-4 w-4" }),
|
|
5398
|
+
onClick: () => openNew("project"),
|
|
5399
|
+
children: "Add project"
|
|
5400
|
+
}
|
|
5401
|
+
) }) : null,
|
|
5402
|
+
/* @__PURE__ */ jsx26("ul", { className: "flex-1 p-2", children: selectedClient && selectedProjects.length ? selectedProjects.map((project) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsxs23(
|
|
5403
|
+
"div",
|
|
5404
|
+
{
|
|
5405
|
+
className: "flex items-center gap-3 rounded-lg px-2 py-1 hover:bg-ph-canvas",
|
|
5406
|
+
onClick: () => openEdit(project, "project"),
|
|
5407
|
+
children: [
|
|
5408
|
+
/* @__PURE__ */ jsxs23(
|
|
5409
|
+
"button",
|
|
5410
|
+
{
|
|
5411
|
+
type: "button",
|
|
5412
|
+
className: "flex min-w-0 flex-1 items-center gap-3 rounded-lg py-1 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
5413
|
+
onClick: () => openEdit(project, "project"),
|
|
5414
|
+
children: [
|
|
5415
|
+
/* @__PURE__ */ jsx26(DirectoryIcon, { item: project }),
|
|
5416
|
+
/* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex-1", children: [
|
|
5417
|
+
/* @__PURE__ */ jsx26(
|
|
5418
|
+
"span",
|
|
5419
|
+
{
|
|
5420
|
+
className: cn(
|
|
5421
|
+
"block truncate text-sm font-medium",
|
|
5422
|
+
project.isArchived ? "text-ph-mutedtext line-through" : "text-ph-ink"
|
|
5423
|
+
),
|
|
5424
|
+
children: project.name
|
|
5425
|
+
}
|
|
5426
|
+
),
|
|
5427
|
+
/* @__PURE__ */ jsx26("span", { className: "text-xs text-ph-mutedtext", children: project.isArchived ? "Archived" : "Active" })
|
|
5428
|
+
] })
|
|
5429
|
+
]
|
|
5430
|
+
}
|
|
5431
|
+
),
|
|
5432
|
+
canEdit && (onUpdateProject || onDeleteProject) ? /* @__PURE__ */ jsx26("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx26(
|
|
5433
|
+
DropdownMenu,
|
|
5434
|
+
{
|
|
5435
|
+
"aria-label": `Actions for ${project.name}`,
|
|
5436
|
+
align: "end",
|
|
5437
|
+
trigger: /* @__PURE__ */ jsxs23("span", { className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink", children: [
|
|
5438
|
+
/* @__PURE__ */ jsx26(
|
|
5439
|
+
MoreHorizontal,
|
|
5440
|
+
{
|
|
5441
|
+
className: "h-4 w-4",
|
|
5442
|
+
"aria-hidden": true
|
|
5443
|
+
}
|
|
5444
|
+
),
|
|
5445
|
+
/* @__PURE__ */ jsx26("span", { className: "sr-only", children: "Project actions" })
|
|
5446
|
+
] }),
|
|
5447
|
+
children: /* @__PURE__ */ jsxs23("div", { className: "p-1", children: [
|
|
5448
|
+
onUpdateProject ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
|
|
5449
|
+
/* @__PURE__ */ jsx26(
|
|
5450
|
+
DropdownItem,
|
|
5451
|
+
{
|
|
5452
|
+
onClick: () => openEdit(project, "project"),
|
|
5453
|
+
children: "Edit project"
|
|
5454
|
+
}
|
|
5455
|
+
),
|
|
5456
|
+
/* @__PURE__ */ jsx26(
|
|
5457
|
+
DropdownItem,
|
|
5458
|
+
{
|
|
5459
|
+
onClick: () => void toggleArchive(project),
|
|
5460
|
+
children: project.isArchived ? "Unarchive project" : "Archive project"
|
|
5461
|
+
}
|
|
5462
|
+
)
|
|
5463
|
+
] }) : null,
|
|
5464
|
+
onDeleteProject ? /* @__PURE__ */ jsx26(
|
|
5465
|
+
DropdownItem,
|
|
5466
|
+
{
|
|
5467
|
+
className: "text-red-600",
|
|
5468
|
+
onClick: () => void remove(project, "project"),
|
|
5469
|
+
children: "Delete project"
|
|
5470
|
+
}
|
|
5471
|
+
) : null
|
|
5472
|
+
] })
|
|
5473
|
+
}
|
|
5474
|
+
) }) : null
|
|
5475
|
+
]
|
|
5476
|
+
}
|
|
5477
|
+
) }, project.id)) : /* @__PURE__ */ jsx26("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: selectedClient ? "No projects yet." : "Select a client to see its projects." }) })
|
|
5478
|
+
]
|
|
5479
|
+
}
|
|
5480
|
+
)
|
|
5481
|
+
] }),
|
|
5482
|
+
/* @__PURE__ */ jsx26(
|
|
5483
|
+
Modal,
|
|
5484
|
+
{
|
|
5485
|
+
open: editing !== null,
|
|
5486
|
+
onClose: closeEditor,
|
|
5487
|
+
title: (editing == null ? void 0 : editing.kind.includes("project")) ? editing.kind === "new-project" ? "New project" : "Edit project" : (editing == null ? void 0 : editing.kind) === "new-client" ? "New client" : "Edit client",
|
|
5488
|
+
footer: /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
|
|
5489
|
+
/* @__PURE__ */ jsx26(Button, { variant: "tertiary", onClick: closeEditor, disabled: saving, children: "Cancel" }),
|
|
5490
|
+
/* @__PURE__ */ jsx26(
|
|
5491
|
+
Button,
|
|
5492
|
+
{
|
|
5493
|
+
variant: "primary",
|
|
5494
|
+
onClick: () => void save(),
|
|
5495
|
+
disabled: saving || !draft.name.trim(),
|
|
5496
|
+
children: saving ? "Saving..." : "Save"
|
|
5497
|
+
}
|
|
5498
|
+
)
|
|
5499
|
+
] }),
|
|
5500
|
+
children: /* @__PURE__ */ jsxs23("div", { className: "space-y-3", children: [
|
|
5501
|
+
/* @__PURE__ */ jsx26(
|
|
5502
|
+
Input,
|
|
5503
|
+
{
|
|
5504
|
+
label: "Name",
|
|
5505
|
+
autoFocus: true,
|
|
5506
|
+
value: draft.name,
|
|
5507
|
+
onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { name: event.target.value }))
|
|
5508
|
+
}
|
|
5509
|
+
),
|
|
5510
|
+
/* @__PURE__ */ jsx26(
|
|
5511
|
+
DirectoryIconPicker,
|
|
5512
|
+
{
|
|
5513
|
+
value: isDirectoryIcon(draft.icon) ? draft.icon : DEFAULT_ICON,
|
|
5514
|
+
preview,
|
|
5515
|
+
onFileChange: chooseImage,
|
|
5516
|
+
onClear: clearImage,
|
|
5517
|
+
onChange: (icon) => {
|
|
5518
|
+
if (preview) clearImage();
|
|
5519
|
+
setDraft((current) => __spreadProps(__spreadValues({}, current), { icon }));
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
),
|
|
5523
|
+
/* @__PURE__ */ jsxs23("div", { children: [
|
|
5524
|
+
/* @__PURE__ */ jsx26("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Colour" }),
|
|
5525
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex flex-wrap gap-2", children: [
|
|
5526
|
+
[
|
|
5527
|
+
"#6366f1",
|
|
5528
|
+
"#0ea5e9",
|
|
5529
|
+
"#10b981",
|
|
5530
|
+
"#f59e0b",
|
|
5531
|
+
"#ef4444",
|
|
5532
|
+
"#a855f7",
|
|
5533
|
+
"#64748b"
|
|
5534
|
+
].map((color) => /* @__PURE__ */ jsx26(
|
|
5535
|
+
"button",
|
|
5536
|
+
{
|
|
5537
|
+
type: "button",
|
|
5538
|
+
"aria-label": `Colour ${color}`,
|
|
5539
|
+
"aria-pressed": draft.color === color,
|
|
5540
|
+
onClick: () => setDraft(__spreadProps(__spreadValues({}, draft), { color })),
|
|
5541
|
+
className: cn(
|
|
5542
|
+
"h-8 w-8 rounded-full ring-offset-2",
|
|
5543
|
+
draft.color === color && "ring-2 ring-ph-brand"
|
|
5544
|
+
),
|
|
5545
|
+
style: { backgroundColor: color }
|
|
5546
|
+
},
|
|
5547
|
+
color
|
|
5548
|
+
)),
|
|
5549
|
+
/* @__PURE__ */ jsx26(
|
|
5550
|
+
Input,
|
|
5551
|
+
{
|
|
5552
|
+
hideLabel: true,
|
|
5553
|
+
label: "Custom colour",
|
|
5554
|
+
type: "color",
|
|
5555
|
+
value: draft.color,
|
|
5556
|
+
onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { color: event.target.value })),
|
|
5557
|
+
className: "h-8 w-8 p-0"
|
|
5558
|
+
}
|
|
5559
|
+
)
|
|
5560
|
+
] })
|
|
5561
|
+
] }),
|
|
5562
|
+
(editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs23(
|
|
5563
|
+
Select,
|
|
5564
|
+
{
|
|
5565
|
+
label: "Client",
|
|
5566
|
+
value: draftClientId != null ? draftClientId : "",
|
|
5567
|
+
onChange: (event) => setDraftClientId(event.target.value || null),
|
|
5568
|
+
children: [
|
|
5569
|
+
/* @__PURE__ */ jsx26("option", { value: "", children: "No client" }),
|
|
5570
|
+
clients.map((client) => /* @__PURE__ */ jsx26("option", { value: client.id, children: client.name }, client.id))
|
|
5571
|
+
]
|
|
5572
|
+
}
|
|
5573
|
+
) : null,
|
|
5574
|
+
(editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs23("label", { className: "flex items-center gap-2 text-sm text-ph-ink", children: [
|
|
5575
|
+
/* @__PURE__ */ jsx26(
|
|
5576
|
+
"input",
|
|
5577
|
+
{
|
|
5578
|
+
type: "checkbox",
|
|
5579
|
+
checked: draftArchived,
|
|
5580
|
+
onChange: (event) => setDraftArchived(event.target.checked)
|
|
5581
|
+
}
|
|
5582
|
+
),
|
|
5583
|
+
"Archived"
|
|
5584
|
+
] }) : null
|
|
5585
|
+
] })
|
|
5586
|
+
}
|
|
5587
|
+
),
|
|
5588
|
+
/* @__PURE__ */ jsx26(
|
|
5589
|
+
Modal,
|
|
5590
|
+
{
|
|
5591
|
+
open: confirming !== null,
|
|
5592
|
+
onClose: () => setConfirming(null),
|
|
5593
|
+
title: "Confirm deletion",
|
|
5594
|
+
footer: /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
|
|
5595
|
+
/* @__PURE__ */ jsx26(Button, { variant: "tertiary", onClick: () => setConfirming(null), children: "Cancel" }),
|
|
5596
|
+
/* @__PURE__ */ jsx26(Button, { variant: "primary", onClick: () => void confirmRemove(), children: "Delete" })
|
|
5597
|
+
] }),
|
|
5598
|
+
children: /* @__PURE__ */ jsxs23("p", { className: "text-sm text-ph-ink", children: [
|
|
5599
|
+
"Delete ",
|
|
5600
|
+
confirming == null ? void 0 : confirming.item.name,
|
|
5601
|
+
"? This cannot be undone."
|
|
5602
|
+
] })
|
|
5603
|
+
}
|
|
5604
|
+
)
|
|
5605
|
+
] });
|
|
3705
5606
|
}
|
|
3706
5607
|
export {
|
|
3707
5608
|
APP_ACCENTS,
|
|
@@ -3729,6 +5630,7 @@ export {
|
|
|
3729
5630
|
SUITE_SIDEBAR_WIDTH_COOKIE,
|
|
3730
5631
|
SUITE_SIDEBAR_WIDTH_KEY,
|
|
3731
5632
|
SUITE_SPRINGS,
|
|
5633
|
+
SUITE_THEME_COOKIE,
|
|
3732
5634
|
SourceAppGlyph,
|
|
3733
5635
|
SuiteAiPanel,
|
|
3734
5636
|
SuiteAppIcon,
|
|
@@ -3736,9 +5638,11 @@ export {
|
|
|
3736
5638
|
SuiteAppStrip,
|
|
3737
5639
|
SuiteBottomNav,
|
|
3738
5640
|
SuiteBreadcrumbs,
|
|
5641
|
+
SuiteClientsProjectsDirectory,
|
|
3739
5642
|
SuiteEmptyState,
|
|
3740
5643
|
SuiteIcon,
|
|
3741
5644
|
SuiteIntegrationPicker,
|
|
5645
|
+
SuiteIntegrationRules,
|
|
3742
5646
|
SuiteMobileDrawer,
|
|
3743
5647
|
SuiteMobileHeader,
|
|
3744
5648
|
SuiteMotionProvider,
|
|
@@ -3774,7 +5678,7 @@ export {
|
|
|
3774
5678
|
appSwitcherMenuItemClass,
|
|
3775
5679
|
appSwitcherTriggerClass,
|
|
3776
5680
|
classifySuiteHref,
|
|
3777
|
-
cn,
|
|
5681
|
+
cn2 as cn,
|
|
3778
5682
|
consumePendingAskAiPrompt,
|
|
3779
5683
|
consumeSuiteAskAiOpenFromLocation,
|
|
3780
5684
|
getTodayGreeting,
|
|
@@ -3791,6 +5695,7 @@ export {
|
|
|
3791
5695
|
sourceToSuiteApp,
|
|
3792
5696
|
suiteAppBaseUrl,
|
|
3793
5697
|
suiteAppLabel,
|
|
5698
|
+
suiteThemeBootScript,
|
|
3794
5699
|
useIdleMount,
|
|
3795
5700
|
useSidebarWidth,
|
|
3796
5701
|
useSuiteTheme
|