@xenide-io/the-old-ui-theme 0.7.0 → 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-2EO5VCXP.mjs +3912 -0
- 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 +49 -45
- package/dist/suite.d.mts +157 -55
- package/dist/suite.d.ts +157 -55
- package/dist/suite.js +4249 -801
- package/dist/suite.mjs +2578 -594
- 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 +10 -12
- 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 +939 -0
- 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 +27 -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-KDR6HI6F.mjs +0 -1075
- package/dist/chunk-NOI42JNZ.mjs +0 -151
- package/dist/chunk-VXISSXTB.mjs +0 -2564
- 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,12 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Alert,
|
|
3
|
+
Badge,
|
|
4
|
+
Button,
|
|
5
|
+
Card,
|
|
2
6
|
DropdownItem,
|
|
3
7
|
DropdownMenu,
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
FileUpload,
|
|
9
|
+
Input,
|
|
10
|
+
Modal,
|
|
11
|
+
Select,
|
|
12
|
+
Toggle,
|
|
13
|
+
Tooltip,
|
|
14
|
+
cn
|
|
15
|
+
} from "./chunk-2EO5VCXP.mjs";
|
|
16
|
+
import {
|
|
17
|
+
suiteThemeBootScript
|
|
18
|
+
} from "./chunk-BS7BZI5W.mjs";
|
|
6
19
|
import {
|
|
7
20
|
SuiteThemeProvider,
|
|
8
|
-
|
|
9
|
-
|
|
21
|
+
clearCookie,
|
|
22
|
+
readCookie,
|
|
23
|
+
useSuiteTheme,
|
|
24
|
+
writeCookie
|
|
25
|
+
} from "./chunk-APKRZQRO.mjs";
|
|
26
|
+
import {
|
|
27
|
+
SUITE_THEME_COOKIE
|
|
28
|
+
} from "./chunk-IULORI3A.mjs";
|
|
10
29
|
import {
|
|
11
30
|
__spreadProps,
|
|
12
31
|
__spreadValues
|
|
@@ -56,7 +75,7 @@ import { Refresh as RefreshCw } from "iconoir-react";
|
|
|
56
75
|
// src/suite/lib/cn.ts
|
|
57
76
|
import { clsx } from "clsx";
|
|
58
77
|
import { twMerge } from "tailwind-merge";
|
|
59
|
-
function
|
|
78
|
+
function cn2(...inputs) {
|
|
60
79
|
return twMerge(clsx(inputs));
|
|
61
80
|
}
|
|
62
81
|
|
|
@@ -85,10 +104,10 @@ var APP_ACCENTS = {
|
|
|
85
104
|
},
|
|
86
105
|
shellstack: {
|
|
87
106
|
label: "ShellStack",
|
|
88
|
-
accent: "#
|
|
89
|
-
tile: "#
|
|
90
|
-
onTile: "#
|
|
91
|
-
onTileAccent: "#
|
|
107
|
+
accent: "#0078D4",
|
|
108
|
+
tile: "#FFFFFF",
|
|
109
|
+
onTile: "#111114",
|
|
110
|
+
onTileAccent: "#0078D4"
|
|
92
111
|
},
|
|
93
112
|
crew: {
|
|
94
113
|
label: "Crew",
|
|
@@ -97,12 +116,12 @@ var APP_ACCENTS = {
|
|
|
97
116
|
onTile: "#ffffff",
|
|
98
117
|
onTileAccent: "#a5f3fc"
|
|
99
118
|
},
|
|
100
|
-
|
|
101
|
-
label: "
|
|
102
|
-
accent: "#
|
|
103
|
-
tile: "#
|
|
104
|
-
onTile: "#
|
|
105
|
-
onTileAccent: "#
|
|
119
|
+
shelly: {
|
|
120
|
+
label: "Shelly",
|
|
121
|
+
accent: "#0078D4",
|
|
122
|
+
tile: "#1B1B1F",
|
|
123
|
+
onTile: "#ECECF1",
|
|
124
|
+
onTileAccent: "#00BCF2"
|
|
106
125
|
}
|
|
107
126
|
};
|
|
108
127
|
var APP_GLYPHS = {
|
|
@@ -111,7 +130,7 @@ var APP_GLYPHS = {
|
|
|
111
130
|
kraken: "squid-doc",
|
|
112
131
|
shellstack: "stack-hex",
|
|
113
132
|
crew: "crew-bot",
|
|
114
|
-
|
|
133
|
+
shelly: "shelly-snail"
|
|
115
134
|
};
|
|
116
135
|
|
|
117
136
|
// src/suite/icons/glyph-parts.tsx
|
|
@@ -234,22 +253,15 @@ var SUITE_GLYPHS = {
|
|
|
234
253
|
{ kind: "path", d: "M9.6 14.6q2.4 1.7 4.8 0", accent: true }
|
|
235
254
|
]
|
|
236
255
|
},
|
|
237
|
-
"
|
|
238
|
-
description: "
|
|
256
|
+
"shelly-snail": {
|
|
257
|
+
description: "Shelly \u2014 smiling snail with spiral shell and ball-tipped antennae",
|
|
239
258
|
elements: [
|
|
240
259
|
{
|
|
241
260
|
kind: "path",
|
|
242
|
-
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",
|
|
243
262
|
filled: true,
|
|
244
|
-
transform: "translate(
|
|
245
|
-
}
|
|
246
|
-
{ kind: "path", d: "M7 18h3.5M12.2 18h3M8.5 19.5h6", accent: true },
|
|
247
|
-
{
|
|
248
|
-
kind: "path",
|
|
249
|
-
d: "M4.8 5.8h2.7M4.8 7.4h1.4M18.5 17.1h1.7",
|
|
250
|
-
accent: true
|
|
251
|
-
},
|
|
252
|
-
{ 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
|
+
}
|
|
253
265
|
]
|
|
254
266
|
},
|
|
255
267
|
workspace: {
|
|
@@ -363,7 +375,7 @@ function SuiteAppIcon({
|
|
|
363
375
|
width: px,
|
|
364
376
|
height: px,
|
|
365
377
|
viewBox: "0 0 24 24",
|
|
366
|
-
className:
|
|
378
|
+
className: cn2("shrink-0", className),
|
|
367
379
|
style,
|
|
368
380
|
role: label ? "img" : void 0,
|
|
369
381
|
"aria-label": label,
|
|
@@ -391,104 +403,55 @@ function SuiteAppIcon({
|
|
|
391
403
|
);
|
|
392
404
|
}
|
|
393
405
|
|
|
394
|
-
// src/suite/icons/suite-icon.tsx
|
|
395
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
396
|
-
var TODAY_SUN_STYLE = `
|
|
397
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
398
|
-
.suite-icon-today-sun-rays {
|
|
399
|
-
animation: suite-icon-today-sun-spin 18s linear infinite;
|
|
400
|
-
transform-box: fill-box;
|
|
401
|
-
transform-origin: center;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
@keyframes suite-icon-today-sun-spin {
|
|
405
|
-
to { transform: rotate(360deg); }
|
|
406
|
-
}
|
|
407
|
-
`;
|
|
408
|
-
function SuiteIcon({
|
|
409
|
-
name,
|
|
410
|
-
size = 24,
|
|
411
|
-
accent,
|
|
412
|
-
strokeWidth = 2,
|
|
413
|
-
animated = true,
|
|
414
|
-
label,
|
|
415
|
-
className,
|
|
416
|
-
style
|
|
417
|
-
}) {
|
|
418
|
-
const glyph = SUITE_GLYPHS[name];
|
|
419
|
-
const accentHex = accent ? APP_ACCENTS[accent].accent : void 0;
|
|
420
|
-
const mergedStyle = accentHex ? __spreadProps(__spreadValues({}, style), { "--suite-icon-accent": accentHex }) : style;
|
|
421
|
-
return /* @__PURE__ */ jsxs4(
|
|
422
|
-
"svg",
|
|
423
|
-
{
|
|
424
|
-
width: size,
|
|
425
|
-
height: size,
|
|
426
|
-
viewBox: "0 0 24 24",
|
|
427
|
-
fill: "none",
|
|
428
|
-
stroke: "currentColor",
|
|
429
|
-
strokeWidth,
|
|
430
|
-
strokeLinecap: "round",
|
|
431
|
-
strokeLinejoin: "round",
|
|
432
|
-
className: cn("shrink-0", className),
|
|
433
|
-
style: mergedStyle,
|
|
434
|
-
role: label ? "img" : void 0,
|
|
435
|
-
"aria-label": label,
|
|
436
|
-
"aria-hidden": label ? void 0 : true,
|
|
437
|
-
children: [
|
|
438
|
-
glyph.animatedAccent && animated ? /* @__PURE__ */ jsx4("style", { children: TODAY_SUN_STYLE }) : null,
|
|
439
|
-
/* @__PURE__ */ jsx4(
|
|
440
|
-
GlyphParts,
|
|
441
|
-
{
|
|
442
|
-
elements: glyph.elements,
|
|
443
|
-
accentClassName: glyph.animatedAccent && animated ? "suite-icon-today-sun-rays" : void 0
|
|
444
|
-
}
|
|
445
|
-
)
|
|
446
|
-
]
|
|
447
|
-
}
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
406
|
// src/suite/components/today-ui.tsx
|
|
452
|
-
import { Fragment as Fragment2, jsx as
|
|
407
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
453
408
|
var APP_META = {
|
|
454
409
|
shellstack: { name: "ShellStack" },
|
|
455
410
|
tides: { name: "Tides" },
|
|
456
411
|
turtletime: { name: "TurtleTime" },
|
|
457
|
-
kraken: { name: "Kraken" }
|
|
412
|
+
kraken: { name: "Kraken" },
|
|
413
|
+
shelly: { name: "Shelly" }
|
|
458
414
|
};
|
|
459
415
|
var SUITE_APPS = [
|
|
460
416
|
"shellstack",
|
|
461
417
|
"tides",
|
|
462
418
|
"turtletime",
|
|
463
|
-
"kraken"
|
|
419
|
+
"kraken",
|
|
420
|
+
"shelly"
|
|
464
421
|
];
|
|
465
422
|
function sourceToSuiteApp(source) {
|
|
466
|
-
|
|
467
|
-
|
|
423
|
+
const normalised = source.trim().toLowerCase();
|
|
424
|
+
if (normalised === "tides" || normalised === "turtletime" || normalised === "kraken" || normalised === "shelly") {
|
|
425
|
+
return normalised;
|
|
468
426
|
}
|
|
469
427
|
return "shellstack";
|
|
470
428
|
}
|
|
471
429
|
function suiteAppLabel(source) {
|
|
472
430
|
return APP_META[sourceToSuiteApp(source)].name;
|
|
473
431
|
}
|
|
474
|
-
var
|
|
475
|
-
shellstack: "
|
|
476
|
-
tides: "
|
|
477
|
-
turtletime: "
|
|
478
|
-
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"
|
|
479
438
|
};
|
|
480
439
|
function SourceAppGlyph({
|
|
481
440
|
source,
|
|
482
441
|
className
|
|
483
442
|
}) {
|
|
484
443
|
const app = sourceToSuiteApp(source);
|
|
485
|
-
return
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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
|
+
)
|
|
492
455
|
);
|
|
493
456
|
}
|
|
494
457
|
function formatLongDate(date = /* @__PURE__ */ new Date()) {
|
|
@@ -501,23 +464,23 @@ function SuiteAppStrip({
|
|
|
501
464
|
className,
|
|
502
465
|
icons
|
|
503
466
|
}) {
|
|
504
|
-
return /* @__PURE__ */
|
|
467
|
+
return /* @__PURE__ */ jsx4(
|
|
505
468
|
"div",
|
|
506
469
|
{
|
|
507
|
-
className:
|
|
470
|
+
className: cn2(
|
|
508
471
|
"flex flex-wrap items-center justify-center gap-2.5",
|
|
509
472
|
className
|
|
510
473
|
),
|
|
511
474
|
"aria-label": "ShellStack suite apps",
|
|
512
475
|
children: SUITE_APPS.map((app) => {
|
|
513
476
|
var _a;
|
|
514
|
-
return /* @__PURE__ */
|
|
477
|
+
return /* @__PURE__ */ jsxs4(
|
|
515
478
|
"div",
|
|
516
479
|
{
|
|
517
480
|
className: "flex items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-2.5 py-1.5 shadow-sm",
|
|
518
481
|
children: [
|
|
519
|
-
(_a = icons == null ? void 0 : icons[app]) != null ? _a : /* @__PURE__ */
|
|
520
|
-
/* @__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 })
|
|
521
484
|
]
|
|
522
485
|
},
|
|
523
486
|
app
|
|
@@ -527,7 +490,7 @@ function SuiteAppStrip({
|
|
|
527
490
|
);
|
|
528
491
|
}
|
|
529
492
|
function AnimatedSun({ className }) {
|
|
530
|
-
return /* @__PURE__ */
|
|
493
|
+
return /* @__PURE__ */ jsxs4(
|
|
531
494
|
"svg",
|
|
532
495
|
{
|
|
533
496
|
width: "40",
|
|
@@ -535,14 +498,14 @@ function AnimatedSun({ className }) {
|
|
|
535
498
|
viewBox: "0 0 40 40",
|
|
536
499
|
fill: "none",
|
|
537
500
|
xmlns: "http://www.w3.org/2000/svg",
|
|
538
|
-
className:
|
|
501
|
+
className: cn2(className),
|
|
539
502
|
"aria-hidden": "true",
|
|
540
503
|
children: [
|
|
541
|
-
/* @__PURE__ */
|
|
542
|
-
/* @__PURE__ */
|
|
543
|
-
/* @__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" })
|
|
544
507
|
] }) }),
|
|
545
|
-
/* @__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(
|
|
546
509
|
"line",
|
|
547
510
|
{
|
|
548
511
|
x1: "20",
|
|
@@ -556,13 +519,13 @@ function AnimatedSun({ className }) {
|
|
|
556
519
|
},
|
|
557
520
|
angle
|
|
558
521
|
)) }),
|
|
559
|
-
/* @__PURE__ */
|
|
522
|
+
/* @__PURE__ */ jsx4("circle", { cx: "20", cy: "20", r: "9", fill: "url(#animatedSunCenter)" })
|
|
560
523
|
]
|
|
561
524
|
}
|
|
562
525
|
);
|
|
563
526
|
}
|
|
564
527
|
function AnimatedMoon({ className }) {
|
|
565
|
-
return /* @__PURE__ */
|
|
528
|
+
return /* @__PURE__ */ jsxs4(
|
|
566
529
|
"svg",
|
|
567
530
|
{
|
|
568
531
|
width: "40",
|
|
@@ -570,23 +533,23 @@ function AnimatedMoon({ className }) {
|
|
|
570
533
|
viewBox: "0 0 40 40",
|
|
571
534
|
fill: "none",
|
|
572
535
|
xmlns: "http://www.w3.org/2000/svg",
|
|
573
|
-
className:
|
|
536
|
+
className: cn2(className),
|
|
574
537
|
"aria-hidden": "true",
|
|
575
538
|
children: [
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
578
|
-
/* @__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" })
|
|
579
542
|
] }) }),
|
|
580
|
-
/* @__PURE__ */
|
|
543
|
+
/* @__PURE__ */ jsx4(
|
|
581
544
|
"path",
|
|
582
545
|
{
|
|
583
546
|
d: "M27.5 25.5A11 11 0 1 1 14.5 9.6a9 9 0 1 0 13 15.9Z",
|
|
584
547
|
fill: "url(#animatedMoonBody)"
|
|
585
548
|
}
|
|
586
549
|
),
|
|
587
|
-
/* @__PURE__ */
|
|
588
|
-
/* @__PURE__ */
|
|
589
|
-
/* @__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" })
|
|
590
553
|
] })
|
|
591
554
|
]
|
|
592
555
|
}
|
|
@@ -595,7 +558,7 @@ function AnimatedMoon({ className }) {
|
|
|
595
558
|
function TodayTimeIcon({ className }) {
|
|
596
559
|
const hour = (/* @__PURE__ */ new Date()).getHours();
|
|
597
560
|
const isNight = hour >= 18 || hour < 6;
|
|
598
|
-
return isNight ? /* @__PURE__ */
|
|
561
|
+
return isNight ? /* @__PURE__ */ jsx4(AnimatedMoon, { className }) : /* @__PURE__ */ jsx4(AnimatedSun, { className });
|
|
599
562
|
}
|
|
600
563
|
function TodayTopBar({
|
|
601
564
|
refreshing,
|
|
@@ -604,17 +567,17 @@ function TodayTopBar({
|
|
|
604
567
|
appIcon,
|
|
605
568
|
appName
|
|
606
569
|
}) {
|
|
607
|
-
const icon = appIcon != null ? appIcon : /* @__PURE__ */
|
|
608
|
-
return /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
613
|
-
appName ? /* @__PURE__ */
|
|
614
|
-
/* @__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() })
|
|
615
578
|
] })
|
|
616
579
|
] }),
|
|
617
|
-
/* @__PURE__ */
|
|
580
|
+
/* @__PURE__ */ jsx4("div", { className: "flex shrink-0 items-center", children: /* @__PURE__ */ jsx4(
|
|
618
581
|
"button",
|
|
619
582
|
{
|
|
620
583
|
type: "button",
|
|
@@ -623,10 +586,10 @@ function TodayTopBar({
|
|
|
623
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",
|
|
624
587
|
"data-test": "today-refresh",
|
|
625
588
|
"aria-label": "Refresh today",
|
|
626
|
-
children: /* @__PURE__ */
|
|
589
|
+
children: /* @__PURE__ */ jsx4(
|
|
627
590
|
RefreshCw,
|
|
628
591
|
{
|
|
629
|
-
className:
|
|
592
|
+
className: cn2("h-4 w-4", refreshing && "animate-spin"),
|
|
630
593
|
"aria-hidden": true
|
|
631
594
|
}
|
|
632
595
|
)
|
|
@@ -666,8 +629,8 @@ function TodayHero({
|
|
|
666
629
|
brief,
|
|
667
630
|
briefMeta
|
|
668
631
|
}) {
|
|
669
|
-
return /* @__PURE__ */
|
|
670
|
-
/* @__PURE__ */
|
|
632
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mt-4 sm:mt-6", children: [
|
|
633
|
+
/* @__PURE__ */ jsx4(
|
|
671
634
|
"p",
|
|
672
635
|
{
|
|
673
636
|
className: "today-hero max-w-2xl font-display text-lg font-semibold tracking-tight text-ph-ink sm:text-xl sm:leading-snug",
|
|
@@ -675,9 +638,9 @@ function TodayHero({
|
|
|
675
638
|
},
|
|
676
639
|
typeof message === "string" ? message : "hero"
|
|
677
640
|
),
|
|
678
|
-
brief ? /* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
680
|
-
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
|
|
681
644
|
] }) : null
|
|
682
645
|
] });
|
|
683
646
|
}
|
|
@@ -693,20 +656,20 @@ function TodayPrimaryAction({
|
|
|
693
656
|
className,
|
|
694
657
|
dataTest = "today-primary-action"
|
|
695
658
|
}) {
|
|
696
|
-
const classes =
|
|
659
|
+
const classes = cn2(
|
|
697
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",
|
|
698
661
|
`today-primary-action--${accent}`,
|
|
699
662
|
active && "today-primary-action--active",
|
|
700
663
|
loading && "pointer-events-none opacity-70",
|
|
701
664
|
className
|
|
702
665
|
);
|
|
703
|
-
const body = /* @__PURE__ */
|
|
704
|
-
/* @__PURE__ */
|
|
705
|
-
/* @__PURE__ */
|
|
706
|
-
/* @__PURE__ */
|
|
707
|
-
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
|
|
708
671
|
] }),
|
|
709
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx4(
|
|
710
673
|
"span",
|
|
711
674
|
{
|
|
712
675
|
className: "today-primary-action__chevron shrink-0 text-base opacity-60 transition group-hover:translate-x-0.5 group-hover:opacity-100",
|
|
@@ -716,7 +679,7 @@ function TodayPrimaryAction({
|
|
|
716
679
|
)
|
|
717
680
|
] });
|
|
718
681
|
if (href && !onClick) {
|
|
719
|
-
return /* @__PURE__ */
|
|
682
|
+
return /* @__PURE__ */ jsx4(
|
|
720
683
|
"a",
|
|
721
684
|
{
|
|
722
685
|
href,
|
|
@@ -727,7 +690,7 @@ function TodayPrimaryAction({
|
|
|
727
690
|
}
|
|
728
691
|
);
|
|
729
692
|
}
|
|
730
|
-
return /* @__PURE__ */
|
|
693
|
+
return /* @__PURE__ */ jsx4(
|
|
731
694
|
"button",
|
|
732
695
|
{
|
|
733
696
|
type: "button",
|
|
@@ -743,33 +706,33 @@ function TodayPrimaryAction({
|
|
|
743
706
|
function TodayEmptyAction({
|
|
744
707
|
title,
|
|
745
708
|
description,
|
|
746
|
-
actionLabel,
|
|
709
|
+
actionLabel: actionLabel2,
|
|
747
710
|
href,
|
|
748
711
|
onClick,
|
|
749
712
|
dataTest
|
|
750
713
|
}) {
|
|
751
|
-
return /* @__PURE__ */
|
|
714
|
+
return /* @__PURE__ */ jsxs4(
|
|
752
715
|
"div",
|
|
753
716
|
{
|
|
754
717
|
className: "rounded-lg border border-dashed border-ph-border/80 bg-ph-muted/30 px-4 py-4 text-center",
|
|
755
718
|
"data-test": dataTest,
|
|
756
719
|
children: [
|
|
757
|
-
/* @__PURE__ */
|
|
758
|
-
description ? /* @__PURE__ */
|
|
759
|
-
|
|
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(
|
|
760
723
|
"a",
|
|
761
724
|
{
|
|
762
725
|
href,
|
|
763
726
|
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
764
|
-
children:
|
|
727
|
+
children: actionLabel2
|
|
765
728
|
}
|
|
766
|
-
) : /* @__PURE__ */
|
|
729
|
+
) : /* @__PURE__ */ jsx4(
|
|
767
730
|
"button",
|
|
768
731
|
{
|
|
769
732
|
type: "button",
|
|
770
733
|
onClick,
|
|
771
734
|
className: "mt-2.5 inline-flex text-sm font-semibold text-ph-brand hover:underline",
|
|
772
|
-
children:
|
|
735
|
+
children: actionLabel2
|
|
773
736
|
}
|
|
774
737
|
) : null
|
|
775
738
|
]
|
|
@@ -782,16 +745,16 @@ function TodayLayout({
|
|
|
782
745
|
aside,
|
|
783
746
|
className
|
|
784
747
|
}) {
|
|
785
|
-
return /* @__PURE__ */
|
|
748
|
+
return /* @__PURE__ */ jsxs4(
|
|
786
749
|
"div",
|
|
787
750
|
{
|
|
788
|
-
className:
|
|
751
|
+
className: cn2("mt-5 space-y-6 sm:mt-6", className),
|
|
789
752
|
"data-test": "today-layout",
|
|
790
753
|
children: [
|
|
791
|
-
primary ? /* @__PURE__ */
|
|
792
|
-
/* @__PURE__ */
|
|
793
|
-
/* @__PURE__ */
|
|
794
|
-
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
|
|
795
758
|
] })
|
|
796
759
|
]
|
|
797
760
|
}
|
|
@@ -805,22 +768,30 @@ function TodayAskAiCard({
|
|
|
805
768
|
onClick,
|
|
806
769
|
href
|
|
807
770
|
}) {
|
|
808
|
-
const classes =
|
|
771
|
+
const classes = cn2(
|
|
809
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",
|
|
810
773
|
className
|
|
811
774
|
);
|
|
812
|
-
const body = /* @__PURE__ */
|
|
813
|
-
/* @__PURE__ */
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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 })
|
|
818
789
|
] }),
|
|
819
|
-
/* @__PURE__ */
|
|
790
|
+
/* @__PURE__ */ jsx4("span", { className: "mt-1 block text-sm leading-relaxed text-ph-subtle", children: description })
|
|
820
791
|
] })
|
|
821
792
|
] });
|
|
822
793
|
if (onClick) {
|
|
823
|
-
return /* @__PURE__ */
|
|
794
|
+
return /* @__PURE__ */ jsx4(
|
|
824
795
|
"button",
|
|
825
796
|
{
|
|
826
797
|
type: "button",
|
|
@@ -832,9 +803,9 @@ function TodayAskAiCard({
|
|
|
832
803
|
);
|
|
833
804
|
}
|
|
834
805
|
if (href) {
|
|
835
|
-
return /* @__PURE__ */
|
|
806
|
+
return /* @__PURE__ */ jsx4("a", { href, className: classes, "data-test": "today-ask-ai", children: body });
|
|
836
807
|
}
|
|
837
|
-
return /* @__PURE__ */
|
|
808
|
+
return /* @__PURE__ */ jsx4("div", { className: classes, "data-test": "today-ask-ai", children: body });
|
|
838
809
|
}
|
|
839
810
|
function TodaySection({
|
|
840
811
|
icon: Icon,
|
|
@@ -845,22 +816,22 @@ function TodaySection({
|
|
|
845
816
|
testId,
|
|
846
817
|
children
|
|
847
818
|
}) {
|
|
848
|
-
return /* @__PURE__ */
|
|
849
|
-
/* @__PURE__ */
|
|
850
|
-
/* @__PURE__ */
|
|
851
|
-
/* @__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(
|
|
852
823
|
"span",
|
|
853
824
|
{
|
|
854
|
-
className:
|
|
825
|
+
className: cn2(
|
|
855
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]",
|
|
856
827
|
iconClassName != null ? iconClassName : "bg-ph-muted text-ph-ink"
|
|
857
828
|
),
|
|
858
|
-
children: /* @__PURE__ */
|
|
829
|
+
children: /* @__PURE__ */ jsx4(Icon, { className: "h-5 w-5", "aria-hidden": true })
|
|
859
830
|
}
|
|
860
831
|
),
|
|
861
|
-
/* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
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
|
|
864
835
|
] })
|
|
865
836
|
] }),
|
|
866
837
|
action
|
|
@@ -872,10 +843,10 @@ function TodayPanel({
|
|
|
872
843
|
children,
|
|
873
844
|
className
|
|
874
845
|
}) {
|
|
875
|
-
return /* @__PURE__ */
|
|
846
|
+
return /* @__PURE__ */ jsx4(
|
|
876
847
|
"div",
|
|
877
848
|
{
|
|
878
|
-
className:
|
|
849
|
+
className: cn2(
|
|
879
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",
|
|
880
851
|
className
|
|
881
852
|
),
|
|
@@ -887,41 +858,38 @@ function TodayEmptyState({
|
|
|
887
858
|
title,
|
|
888
859
|
description
|
|
889
860
|
}) {
|
|
890
|
-
return /* @__PURE__ */
|
|
891
|
-
/* @__PURE__ */
|
|
892
|
-
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
|
|
893
864
|
] });
|
|
894
865
|
}
|
|
895
866
|
|
|
896
867
|
// src/suite/components/app-switcher.tsx
|
|
897
868
|
import Image from "next/image";
|
|
898
869
|
import { useState } from "react";
|
|
899
|
-
import {
|
|
900
|
-
|
|
901
|
-
OpenNewWindow
|
|
902
|
-
} from "iconoir-react";
|
|
903
|
-
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";
|
|
904
872
|
function appSwitcherTriggerClass(open, collapsed = false) {
|
|
905
|
-
return
|
|
873
|
+
return cn2(
|
|
906
874
|
"group flex min-w-0 items-center gap-2 rounded-lg border px-2 py-1.5 text-left transition-all duration-200",
|
|
907
875
|
collapsed ? "h-11 w-11 justify-center px-0 py-0" : "w-full",
|
|
908
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"
|
|
909
877
|
);
|
|
910
878
|
}
|
|
911
879
|
function appSwitcherMarkClass() {
|
|
912
|
-
return "h-8 w-8 shrink-0 rounded-lg
|
|
880
|
+
return "h-8 w-8 shrink-0 rounded-lg";
|
|
913
881
|
}
|
|
914
882
|
function appSwitcherMenuItemClass() {
|
|
915
|
-
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";
|
|
916
884
|
}
|
|
917
885
|
function AppSwitcherMark({
|
|
918
886
|
children,
|
|
919
887
|
collapsed
|
|
920
888
|
}) {
|
|
921
|
-
return /* @__PURE__ */
|
|
889
|
+
return /* @__PURE__ */ jsx5(
|
|
922
890
|
"span",
|
|
923
891
|
{
|
|
924
|
-
className:
|
|
892
|
+
className: cn2(
|
|
925
893
|
"relative shrink-0",
|
|
926
894
|
collapsed && "group-hover:scale-[1.02]"
|
|
927
895
|
),
|
|
@@ -934,18 +902,18 @@ function AppSwitcherChevron({
|
|
|
934
902
|
collapsed = false
|
|
935
903
|
}) {
|
|
936
904
|
if (collapsed) {
|
|
937
|
-
return /* @__PURE__ */
|
|
905
|
+
return /* @__PURE__ */ jsx5(
|
|
938
906
|
"span",
|
|
939
907
|
{
|
|
940
|
-
className:
|
|
908
|
+
className: cn2(
|
|
941
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",
|
|
942
910
|
open && "border-ph-brand/40 bg-ph-brand/10"
|
|
943
911
|
),
|
|
944
912
|
"aria-hidden": true,
|
|
945
|
-
children: /* @__PURE__ */
|
|
913
|
+
children: /* @__PURE__ */ jsx5(
|
|
946
914
|
ChevronDown,
|
|
947
915
|
{
|
|
948
|
-
className:
|
|
916
|
+
className: cn2(
|
|
949
917
|
"h-2 w-2 text-ph-mutedtext transition-transform duration-200",
|
|
950
918
|
open && "rotate-180 text-ph-brand"
|
|
951
919
|
)
|
|
@@ -954,18 +922,18 @@ function AppSwitcherChevron({
|
|
|
954
922
|
}
|
|
955
923
|
);
|
|
956
924
|
}
|
|
957
|
-
return /* @__PURE__ */
|
|
925
|
+
return /* @__PURE__ */ jsx5(
|
|
958
926
|
"span",
|
|
959
927
|
{
|
|
960
|
-
className:
|
|
928
|
+
className: cn2(
|
|
961
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",
|
|
962
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"
|
|
963
931
|
),
|
|
964
932
|
"aria-hidden": true,
|
|
965
|
-
children: /* @__PURE__ */
|
|
933
|
+
children: /* @__PURE__ */ jsx5(
|
|
966
934
|
ChevronDown,
|
|
967
935
|
{
|
|
968
|
-
className:
|
|
936
|
+
className: cn2(
|
|
969
937
|
"h-3 w-3 transition-transform duration-200",
|
|
970
938
|
open && "rotate-180"
|
|
971
939
|
)
|
|
@@ -987,7 +955,7 @@ function AppSwitcher({
|
|
|
987
955
|
triggerDataTest
|
|
988
956
|
}) {
|
|
989
957
|
const [open, setOpen] = useState(false);
|
|
990
|
-
return /* @__PURE__ */
|
|
958
|
+
return /* @__PURE__ */ jsx5(
|
|
991
959
|
DropdownMenu2,
|
|
992
960
|
{
|
|
993
961
|
"aria-label": "Switch application",
|
|
@@ -998,26 +966,25 @@ function AppSwitcher({
|
|
|
998
966
|
align: "start",
|
|
999
967
|
open,
|
|
1000
968
|
onOpenChange: setOpen,
|
|
1001
|
-
trigger: /* @__PURE__ */
|
|
969
|
+
trigger: /* @__PURE__ */ jsxs5(
|
|
1002
970
|
"span",
|
|
1003
971
|
{
|
|
1004
972
|
className: appSwitcherTriggerClass(open, collapsed),
|
|
1005
973
|
"data-test": "app-switcher-trigger",
|
|
1006
|
-
"aria-expanded": open,
|
|
1007
974
|
children: [
|
|
1008
|
-
/* @__PURE__ */
|
|
975
|
+
/* @__PURE__ */ jsxs5(AppSwitcherMark, { collapsed, children: [
|
|
1009
976
|
mark,
|
|
1010
|
-
collapsed ? /* @__PURE__ */
|
|
977
|
+
collapsed ? /* @__PURE__ */ jsx5(AppSwitcherChevron, { open, collapsed: true }) : null
|
|
1011
978
|
] }),
|
|
1012
979
|
!collapsed ? title : null,
|
|
1013
|
-
!collapsed ? /* @__PURE__ */
|
|
980
|
+
!collapsed ? /* @__PURE__ */ jsx5(AppSwitcherChevron, { open }) : null
|
|
1014
981
|
]
|
|
1015
982
|
}
|
|
1016
983
|
),
|
|
1017
|
-
children: /* @__PURE__ */
|
|
1018
|
-
/* @__PURE__ */
|
|
1019
|
-
apps.filter((app) => app.slug !== currentApp).map((app) => /* @__PURE__ */
|
|
1020
|
-
/* @__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(
|
|
1021
988
|
DropdownItem2,
|
|
1022
989
|
{
|
|
1023
990
|
id: `switch-app-${app.slug}`,
|
|
@@ -1027,9 +994,9 @@ function AppSwitcher({
|
|
|
1027
994
|
setOpen(false);
|
|
1028
995
|
onSelect(app);
|
|
1029
996
|
},
|
|
1030
|
-
className:
|
|
1031
|
-
children: /* @__PURE__ */
|
|
1032
|
-
/* @__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(
|
|
1033
1000
|
Image,
|
|
1034
1001
|
{
|
|
1035
1002
|
src: app.icon,
|
|
@@ -1039,17 +1006,16 @@ function AppSwitcher({
|
|
|
1039
1006
|
className: "h-7 w-7 shrink-0 rounded-md object-contain"
|
|
1040
1007
|
}
|
|
1041
1008
|
),
|
|
1042
|
-
/* @__PURE__ */
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
/* @__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 })
|
|
1045
1012
|
] })
|
|
1046
1013
|
] })
|
|
1047
1014
|
}
|
|
1048
1015
|
),
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
|
|
1016
|
+
/* @__PURE__ */ jsx5(
|
|
1017
|
+
DropdownItem2,
|
|
1051
1018
|
{
|
|
1052
|
-
type: "button",
|
|
1053
1019
|
id: `switch-app-${app.slug}-new-tab`,
|
|
1054
1020
|
"data-test": `switch-app-${app.slug}-new-tab`,
|
|
1055
1021
|
"aria-label": `Open ${app.name} in a new tab`,
|
|
@@ -1058,8 +1024,9 @@ function AppSwitcher({
|
|
|
1058
1024
|
setOpen(false);
|
|
1059
1025
|
onSelect(app, { newTab: true });
|
|
1060
1026
|
},
|
|
1061
|
-
className: "absolute right-1.5 top-1/2 z-[1] flex h-8
|
|
1062
|
-
|
|
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" })
|
|
1063
1030
|
}
|
|
1064
1031
|
)
|
|
1065
1032
|
] }, app.slug))
|
|
@@ -1081,7 +1048,7 @@ var SUITE_APPS2 = [
|
|
|
1081
1048
|
description: "Organisation and billing",
|
|
1082
1049
|
icon: "/icon-shellstack.svg",
|
|
1083
1050
|
landing: "/home",
|
|
1084
|
-
baseUrlEnv: "
|
|
1051
|
+
baseUrlEnv: "NEXT_PUBLIC_PORTAL_URL",
|
|
1085
1052
|
baseUrlFallback: "http://localhost:3002"
|
|
1086
1053
|
},
|
|
1087
1054
|
{
|
|
@@ -1112,12 +1079,12 @@ var SUITE_APPS2 = [
|
|
|
1112
1079
|
baseUrlFallback: "http://localhost:3003"
|
|
1113
1080
|
},
|
|
1114
1081
|
{
|
|
1115
|
-
slug: "
|
|
1116
|
-
name: "
|
|
1082
|
+
slug: "shelly",
|
|
1083
|
+
name: "Shelly",
|
|
1117
1084
|
description: "AI teammates",
|
|
1118
|
-
icon: "/
|
|
1085
|
+
icon: "/shelly-icon.svg",
|
|
1119
1086
|
landing: "/today",
|
|
1120
|
-
baseUrlEnv: "
|
|
1087
|
+
baseUrlEnv: "NEXT_PUBLIC_SHELLY_URL",
|
|
1121
1088
|
baseUrlFallback: "http://localhost:3004"
|
|
1122
1089
|
}
|
|
1123
1090
|
];
|
|
@@ -1131,16 +1098,20 @@ var SOURCE_APP_SLUG = {
|
|
|
1131
1098
|
turtletime: "turtletime",
|
|
1132
1099
|
tides: "tides",
|
|
1133
1100
|
kraken: "kraken",
|
|
1134
|
-
|
|
1101
|
+
shelly: "shelly",
|
|
1135
1102
|
portal: "shellstack",
|
|
1136
1103
|
shellstack: "shellstack"
|
|
1137
1104
|
};
|
|
1105
|
+
function suiteAppSlugForNotificationSource(sourceApp) {
|
|
1106
|
+
var _a;
|
|
1107
|
+
return (_a = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a : null;
|
|
1108
|
+
}
|
|
1138
1109
|
function resolveSuiteNotificationHref(href, sourceApp) {
|
|
1139
1110
|
const value = (href || "").trim();
|
|
1140
1111
|
if (!value) return "";
|
|
1141
1112
|
if (/^(https?:|mailto:|\/\/)/i.test(value)) return value;
|
|
1142
1113
|
const path = value.startsWith("/") ? value : `/${value}`;
|
|
1143
|
-
const slug =
|
|
1114
|
+
const slug = suiteAppSlugForNotificationSource(sourceApp);
|
|
1144
1115
|
if (!slug) return path;
|
|
1145
1116
|
return `${suiteAppBaseUrl(slug)}${path}`;
|
|
1146
1117
|
}
|
|
@@ -1171,7 +1142,7 @@ function classifySuiteHref(href, bases, currentOrigin = "") {
|
|
|
1171
1142
|
}
|
|
1172
1143
|
|
|
1173
1144
|
// src/suite/components/suite-notification-bell.tsx
|
|
1174
|
-
import { jsx as
|
|
1145
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1175
1146
|
var POLL_MS = 6e4;
|
|
1176
1147
|
function timeAgo(iso) {
|
|
1177
1148
|
const then = new Date(iso).getTime();
|
|
@@ -1267,6 +1238,28 @@ function SuiteNotificationBell({
|
|
|
1267
1238
|
const target = resolveSuiteNotificationHref(n.href, n.source_app);
|
|
1268
1239
|
if (!target) return;
|
|
1269
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
|
+
}
|
|
1270
1263
|
window.location.assign(target);
|
|
1271
1264
|
return;
|
|
1272
1265
|
}
|
|
@@ -1289,7 +1282,7 @@ function SuiteNotificationBell({
|
|
|
1289
1282
|
} catch (e) {
|
|
1290
1283
|
}
|
|
1291
1284
|
}, [markAllRead]);
|
|
1292
|
-
return /* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsxs6(
|
|
1293
1286
|
DropdownMenu2,
|
|
1294
1287
|
{
|
|
1295
1288
|
"aria-label": unread > 0 ? `Notifications, ${unread} unread` : "Notifications",
|
|
@@ -1299,14 +1292,14 @@ function SuiteNotificationBell({
|
|
|
1299
1292
|
panelClassName: "w-80 overflow-hidden p-0",
|
|
1300
1293
|
open,
|
|
1301
1294
|
onOpenChange,
|
|
1302
|
-
trigger: /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
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
|
|
1305
1298
|
] }) }),
|
|
1306
1299
|
children: [
|
|
1307
|
-
/* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1309
|
-
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(
|
|
1310
1303
|
"button",
|
|
1311
1304
|
{
|
|
1312
1305
|
type: "button",
|
|
@@ -1318,27 +1311,26 @@ function SuiteNotificationBell({
|
|
|
1318
1311
|
}
|
|
1319
1312
|
) : null
|
|
1320
1313
|
] }),
|
|
1321
|
-
/* @__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(
|
|
1322
1315
|
"button",
|
|
1323
1316
|
{
|
|
1324
|
-
type: "button",
|
|
1325
1317
|
id: `${dataTest}-item-${n.id}`,
|
|
1326
1318
|
"data-test": `${dataTest}-item-${n.id}`,
|
|
1327
1319
|
onClick: () => void openItem(n),
|
|
1328
1320
|
className: "flex w-full flex-col gap-0.5 px-3 py-2 text-left transition hover:bg-ph-muted",
|
|
1329
1321
|
children: [
|
|
1330
|
-
/* @__PURE__ */
|
|
1331
|
-
!n.read_at ? /* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-2", children: [
|
|
1323
|
+
!n.read_at ? /* @__PURE__ */ jsx6(
|
|
1332
1324
|
"span",
|
|
1333
1325
|
{
|
|
1334
1326
|
className: "h-1.5 w-1.5 shrink-0 rounded-full bg-ph-brand",
|
|
1335
1327
|
"aria-hidden": true
|
|
1336
1328
|
}
|
|
1337
1329
|
) : null,
|
|
1338
|
-
/* @__PURE__ */
|
|
1330
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate text-sm font-medium text-ph-ink", children: n.title })
|
|
1339
1331
|
] }),
|
|
1340
|
-
n.body ? /* @__PURE__ */
|
|
1341
|
-
/* @__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: [
|
|
1342
1334
|
n.source_app,
|
|
1343
1335
|
" \xB7 ",
|
|
1344
1336
|
timeAgo(n.created_at)
|
|
@@ -1354,7 +1346,7 @@ function SuiteNotificationBell({
|
|
|
1354
1346
|
|
|
1355
1347
|
// src/suite/components/command-palette-host.tsx
|
|
1356
1348
|
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
1357
|
-
import { jsx as
|
|
1349
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1358
1350
|
function isEditableTarget() {
|
|
1359
1351
|
if (typeof document === "undefined") return false;
|
|
1360
1352
|
const el = document.activeElement;
|
|
@@ -1386,7 +1378,7 @@ function CommandPaletteHost({
|
|
|
1386
1378
|
return () => window.removeEventListener("keydown", onKey);
|
|
1387
1379
|
}, [open]);
|
|
1388
1380
|
if (!isAuthenticated) return null;
|
|
1389
|
-
return /* @__PURE__ */
|
|
1381
|
+
return /* @__PURE__ */ jsx7(
|
|
1390
1382
|
CommandPalette,
|
|
1391
1383
|
{
|
|
1392
1384
|
items,
|
|
@@ -1420,17 +1412,18 @@ function useIdleMount(timeoutMs = 1200) {
|
|
|
1420
1412
|
}
|
|
1421
1413
|
|
|
1422
1414
|
// src/suite/components/deferred-chrome.tsx
|
|
1423
|
-
import { Fragment as Fragment3, jsx as
|
|
1415
|
+
import { Fragment as Fragment3, jsx as jsx8 } from "react/jsx-runtime";
|
|
1424
1416
|
function DeferredChrome({ children }) {
|
|
1425
1417
|
const ready = useIdleMount();
|
|
1426
1418
|
if (!ready) return null;
|
|
1427
|
-
return /* @__PURE__ */
|
|
1419
|
+
return /* @__PURE__ */ jsx8(Fragment3, { children });
|
|
1428
1420
|
}
|
|
1429
1421
|
|
|
1430
1422
|
// src/suite/components/suite-mobile-drawer.tsx
|
|
1431
|
-
import
|
|
1423
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
1424
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
1432
1425
|
import { Xmark as X } from "iconoir-react";
|
|
1433
|
-
import { jsx as
|
|
1426
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1434
1427
|
function SuiteMobileDrawer({
|
|
1435
1428
|
open,
|
|
1436
1429
|
onClose,
|
|
@@ -1452,11 +1445,6 @@ function SuiteMobileDrawer({
|
|
|
1452
1445
|
}) {
|
|
1453
1446
|
const [rendered, setRendered] = useState5(open);
|
|
1454
1447
|
const [shown, setShown] = useState5(open);
|
|
1455
|
-
const panelRef = useRef(null);
|
|
1456
|
-
const onCloseRef = useRef(onClose);
|
|
1457
|
-
useEffect4(() => {
|
|
1458
|
-
onCloseRef.current = onClose;
|
|
1459
|
-
}, [onClose]);
|
|
1460
1448
|
useEffect4(() => {
|
|
1461
1449
|
if (open) {
|
|
1462
1450
|
queueMicrotask(() => setRendered(true));
|
|
@@ -1473,86 +1461,61 @@ function SuiteMobileDrawer({
|
|
|
1473
1461
|
const timeout = window.setTimeout(() => setRendered(false), durationMs);
|
|
1474
1462
|
return () => window.clearTimeout(timeout);
|
|
1475
1463
|
}, [open, durationMs]);
|
|
1476
|
-
useEffect4(() => {
|
|
1477
|
-
if (!open) return;
|
|
1478
|
-
const onKeyDown = (event) => {
|
|
1479
|
-
if (event.key === "Escape") onCloseRef.current();
|
|
1480
|
-
};
|
|
1481
|
-
window.addEventListener("keydown", onKeyDown);
|
|
1482
|
-
const previousOverflow = document.body.style.overflow;
|
|
1483
|
-
document.body.style.overflow = "hidden";
|
|
1484
|
-
const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1485
|
-
const frame = requestAnimationFrame(() => {
|
|
1486
|
-
var _a;
|
|
1487
|
-
return (_a = panelRef.current) == null ? void 0 : _a.focus();
|
|
1488
|
-
});
|
|
1489
|
-
return () => {
|
|
1490
|
-
window.removeEventListener("keydown", onKeyDown);
|
|
1491
|
-
document.body.style.overflow = previousOverflow;
|
|
1492
|
-
cancelAnimationFrame(frame);
|
|
1493
|
-
if (previouslyFocused == null ? void 0 : previouslyFocused.isConnected) previouslyFocused.focus();
|
|
1494
|
-
};
|
|
1495
|
-
}, [open]);
|
|
1496
1464
|
if (!rendered) return null;
|
|
1497
|
-
return /* @__PURE__ */
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
|
|
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,
|
|
1500
1468
|
{
|
|
1501
|
-
|
|
1469
|
+
forceMount: true,
|
|
1502
1470
|
id: backdropId,
|
|
1503
|
-
"data-test": backdropDataTest,
|
|
1504
|
-
|
|
1505
|
-
className:
|
|
1506
|
-
"
|
|
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",
|
|
1507
1475
|
shown ? "opacity-100" : "opacity-0"
|
|
1508
1476
|
),
|
|
1509
|
-
style: { transitionDuration: `${durationMs}ms` }
|
|
1510
|
-
onClick: onClose,
|
|
1511
|
-
"aria-label": backdropLabel
|
|
1477
|
+
style: { transitionDuration: `${durationMs}ms` }
|
|
1512
1478
|
}
|
|
1513
1479
|
),
|
|
1514
|
-
/* @__PURE__ */
|
|
1480
|
+
/* @__PURE__ */ jsx9(Dialog.Content, { forceMount: true, asChild: true, children: /* @__PURE__ */ jsxs7(
|
|
1515
1481
|
"aside",
|
|
1516
1482
|
{
|
|
1517
|
-
ref: panelRef,
|
|
1518
1483
|
role: "dialog",
|
|
1519
|
-
"aria-modal": "true",
|
|
1520
|
-
"aria-label": dialogLabel,
|
|
1521
|
-
tabIndex: -1,
|
|
1522
1484
|
"data-test": panelDataTest,
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
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",
|
|
1526
1489
|
shown ? "translate-x-0" : side === "right" ? "translate-x-full" : "-translate-x-full",
|
|
1527
1490
|
panelClassName
|
|
1528
1491
|
),
|
|
1529
1492
|
style: { transitionDuration: `${durationMs}ms` },
|
|
1530
1493
|
children: [
|
|
1531
|
-
|
|
1494
|
+
/* @__PURE__ */ jsx9(Dialog.Title, { className: "sr-only", children: dialogLabel }),
|
|
1495
|
+
showCloseButton ? /* @__PURE__ */ jsxs7(
|
|
1532
1496
|
"div",
|
|
1533
1497
|
{
|
|
1534
|
-
className:
|
|
1498
|
+
className: cn2(
|
|
1535
1499
|
"flex h-14 shrink-0 items-center border-b border-ph-border px-3",
|
|
1536
1500
|
title ? "justify-between" : "justify-end"
|
|
1537
1501
|
),
|
|
1538
1502
|
children: [
|
|
1539
|
-
title ? /* @__PURE__ */
|
|
1540
|
-
/* @__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(
|
|
1541
1505
|
"button",
|
|
1542
1506
|
{
|
|
1543
1507
|
type: "button",
|
|
1544
1508
|
id: closeButtonId,
|
|
1545
1509
|
"data-test": closeButtonDataTest,
|
|
1546
|
-
onClick: onClose,
|
|
1547
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",
|
|
1548
1511
|
"aria-label": closeLabel,
|
|
1549
|
-
children: /* @__PURE__ */
|
|
1512
|
+
children: /* @__PURE__ */ jsx9(X, { className: "h-4 w-4", "aria-hidden": true })
|
|
1550
1513
|
}
|
|
1551
|
-
)
|
|
1514
|
+
) })
|
|
1552
1515
|
]
|
|
1553
1516
|
}
|
|
1554
1517
|
) : null,
|
|
1555
|
-
/* @__PURE__ */
|
|
1518
|
+
/* @__PURE__ */ jsx9(
|
|
1556
1519
|
"div",
|
|
1557
1520
|
{
|
|
1558
1521
|
"data-test": "suite-mobile-drawer-body",
|
|
@@ -1562,13 +1525,13 @@ function SuiteMobileDrawer({
|
|
|
1562
1525
|
)
|
|
1563
1526
|
]
|
|
1564
1527
|
}
|
|
1565
|
-
)
|
|
1566
|
-
] });
|
|
1528
|
+
) })
|
|
1529
|
+
] }) });
|
|
1567
1530
|
}
|
|
1568
1531
|
|
|
1569
1532
|
// src/suite/components/suite-mobile-header.tsx
|
|
1570
1533
|
import { Menu } from "iconoir-react";
|
|
1571
|
-
import { jsx as
|
|
1534
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1572
1535
|
function SuiteMobileHeader({
|
|
1573
1536
|
onMenuClick,
|
|
1574
1537
|
menuIcon: MenuIcon = Menu,
|
|
@@ -1580,16 +1543,16 @@ function SuiteMobileHeader({
|
|
|
1580
1543
|
dataTest,
|
|
1581
1544
|
className
|
|
1582
1545
|
}) {
|
|
1583
|
-
return /* @__PURE__ */
|
|
1546
|
+
return /* @__PURE__ */ jsxs8(
|
|
1584
1547
|
"header",
|
|
1585
1548
|
{
|
|
1586
1549
|
"data-test": dataTest,
|
|
1587
|
-
className:
|
|
1550
|
+
className: cn2(
|
|
1588
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",
|
|
1589
1552
|
className
|
|
1590
1553
|
),
|
|
1591
1554
|
children: [
|
|
1592
|
-
onMenuClick ? /* @__PURE__ */
|
|
1555
|
+
onMenuClick ? /* @__PURE__ */ jsx10(
|
|
1593
1556
|
"button",
|
|
1594
1557
|
{
|
|
1595
1558
|
type: "button",
|
|
@@ -1598,20 +1561,20 @@ function SuiteMobileHeader({
|
|
|
1598
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",
|
|
1599
1562
|
onClick: onMenuClick,
|
|
1600
1563
|
"aria-label": menuLabel,
|
|
1601
|
-
children: /* @__PURE__ */
|
|
1564
|
+
children: /* @__PURE__ */ jsx10(MenuIcon, { className: "h-5 w-5", "aria-hidden": true })
|
|
1602
1565
|
}
|
|
1603
1566
|
) : null,
|
|
1604
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsx10(
|
|
1605
1568
|
"div",
|
|
1606
1569
|
{
|
|
1607
|
-
className:
|
|
1570
|
+
className: cn2(
|
|
1608
1571
|
"flex min-w-0 flex-1 items-center",
|
|
1609
1572
|
!onMenuClick && "pl-2"
|
|
1610
1573
|
),
|
|
1611
1574
|
children: title
|
|
1612
1575
|
}
|
|
1613
1576
|
),
|
|
1614
|
-
actions ? /* @__PURE__ */
|
|
1577
|
+
actions ? /* @__PURE__ */ jsx10("div", { className: "flex shrink-0 items-center gap-1", children: actions }) : null
|
|
1615
1578
|
]
|
|
1616
1579
|
}
|
|
1617
1580
|
);
|
|
@@ -1620,26 +1583,26 @@ function SuiteMobileHeader({
|
|
|
1620
1583
|
// src/suite/components/suite-layout.tsx
|
|
1621
1584
|
import {
|
|
1622
1585
|
useEffect as useEffect5,
|
|
1623
|
-
useRef
|
|
1586
|
+
useRef,
|
|
1624
1587
|
useState as useState6
|
|
1625
1588
|
} from "react";
|
|
1626
|
-
import { jsx as
|
|
1589
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1627
1590
|
function SuiteBreadcrumbs({ items, className }) {
|
|
1628
|
-
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) => {
|
|
1629
1592
|
const isLast = index === items.length - 1;
|
|
1630
|
-
return /* @__PURE__ */
|
|
1631
|
-
index > 0 ? /* @__PURE__ */
|
|
1632
|
-
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(
|
|
1633
1596
|
"a",
|
|
1634
1597
|
{
|
|
1635
1598
|
href: item.href,
|
|
1636
1599
|
className: "truncate transition hover:text-ph-ink",
|
|
1637
1600
|
children: item.label
|
|
1638
1601
|
}
|
|
1639
|
-
) : /* @__PURE__ */
|
|
1602
|
+
) : /* @__PURE__ */ jsx11(
|
|
1640
1603
|
"span",
|
|
1641
1604
|
{
|
|
1642
|
-
className:
|
|
1605
|
+
className: cn2(
|
|
1643
1606
|
"truncate",
|
|
1644
1607
|
isLast ? "font-medium text-ph-ink" : "text-ph-subtle"
|
|
1645
1608
|
),
|
|
@@ -1661,7 +1624,7 @@ function SuitePage({
|
|
|
1661
1624
|
role,
|
|
1662
1625
|
"aria-live": ariaLive
|
|
1663
1626
|
}) {
|
|
1664
|
-
return /* @__PURE__ */
|
|
1627
|
+
return /* @__PURE__ */ jsx11(
|
|
1665
1628
|
Component,
|
|
1666
1629
|
{
|
|
1667
1630
|
id,
|
|
@@ -1669,7 +1632,7 @@ function SuitePage({
|
|
|
1669
1632
|
"data-width": width,
|
|
1670
1633
|
role,
|
|
1671
1634
|
"aria-live": ariaLive,
|
|
1672
|
-
className:
|
|
1635
|
+
className: cn2(
|
|
1673
1636
|
"suite-page-stage relative flex w-full min-w-0 flex-col",
|
|
1674
1637
|
inset && "suite-page-inset",
|
|
1675
1638
|
className
|
|
@@ -1701,7 +1664,7 @@ function SuitePageHeader({
|
|
|
1701
1664
|
*/
|
|
1702
1665
|
sticky = true
|
|
1703
1666
|
}) {
|
|
1704
|
-
const headerRef =
|
|
1667
|
+
const headerRef = useRef(null);
|
|
1705
1668
|
const [stuck, setStuck] = useState6(false);
|
|
1706
1669
|
useEffect5(() => {
|
|
1707
1670
|
if (!sticky) return;
|
|
@@ -1729,33 +1692,33 @@ function SuitePageHeader({
|
|
|
1729
1692
|
sentinel.remove();
|
|
1730
1693
|
};
|
|
1731
1694
|
}, [sticky]);
|
|
1732
|
-
const resolvedIcon = todayIcon ? /* @__PURE__ */
|
|
1695
|
+
const resolvedIcon = todayIcon ? /* @__PURE__ */ jsx11(
|
|
1733
1696
|
TodayTimeIcon,
|
|
1734
1697
|
{
|
|
1735
|
-
className:
|
|
1698
|
+
className: cn2(
|
|
1736
1699
|
"h-6 w-6 text-amber-500",
|
|
1737
1700
|
todayIconClassName
|
|
1738
1701
|
)
|
|
1739
1702
|
}
|
|
1740
1703
|
) : icon;
|
|
1741
|
-
return /* @__PURE__ */
|
|
1704
|
+
return /* @__PURE__ */ jsxs9(
|
|
1742
1705
|
"header",
|
|
1743
1706
|
{
|
|
1744
1707
|
ref: headerRef,
|
|
1745
1708
|
"data-test": dataTest,
|
|
1746
1709
|
"data-stuck": sticky ? stuck ? "true" : "false" : void 0,
|
|
1747
|
-
className:
|
|
1710
|
+
className: cn2(
|
|
1748
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",
|
|
1749
1712
|
// No extra pt here — page inset sets the shared title baseline.
|
|
1750
1713
|
sticky && "suite-page-header-sticky",
|
|
1751
1714
|
className
|
|
1752
1715
|
),
|
|
1753
1716
|
children: [
|
|
1754
|
-
/* @__PURE__ */
|
|
1755
|
-
eyebrow ? /* @__PURE__ */
|
|
1756
|
-
breadcrumb ? /* @__PURE__ */
|
|
1757
|
-
/* @__PURE__ */
|
|
1758
|
-
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(
|
|
1759
1722
|
"div",
|
|
1760
1723
|
{
|
|
1761
1724
|
className: "hidden shrink-0 sm:flex sm:items-center [&_svg]:h-6 [&_svg]:w-6",
|
|
@@ -1763,24 +1726,24 @@ function SuitePageHeader({
|
|
|
1763
1726
|
children: resolvedIcon
|
|
1764
1727
|
}
|
|
1765
1728
|
) : null,
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
/* @__PURE__ */
|
|
1729
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
1730
|
+
/* @__PURE__ */ jsx11(
|
|
1768
1731
|
"h1",
|
|
1769
1732
|
{
|
|
1770
|
-
className:
|
|
1733
|
+
className: cn2(
|
|
1771
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",
|
|
1772
1735
|
titleClassName
|
|
1773
1736
|
),
|
|
1774
1737
|
children: title
|
|
1775
1738
|
}
|
|
1776
1739
|
),
|
|
1777
|
-
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
|
|
1778
1741
|
] })
|
|
1779
1742
|
] }),
|
|
1780
|
-
description ? /* @__PURE__ */
|
|
1743
|
+
description ? /* @__PURE__ */ jsx11(
|
|
1781
1744
|
"div",
|
|
1782
1745
|
{
|
|
1783
|
-
className:
|
|
1746
|
+
className: cn2(
|
|
1784
1747
|
"mt-1.5 max-w-2xl text-pretty text-sm leading-5 text-ph-subtle",
|
|
1785
1748
|
resolvedIcon && "sm:pl-9"
|
|
1786
1749
|
),
|
|
@@ -1788,7 +1751,7 @@ function SuitePageHeader({
|
|
|
1788
1751
|
}
|
|
1789
1752
|
) : null
|
|
1790
1753
|
] }),
|
|
1791
|
-
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
|
|
1792
1755
|
]
|
|
1793
1756
|
}
|
|
1794
1757
|
);
|
|
@@ -1799,13 +1762,13 @@ function SuiteToolbar({
|
|
|
1799
1762
|
label = "Page tools",
|
|
1800
1763
|
dataTest
|
|
1801
1764
|
}) {
|
|
1802
|
-
return /* @__PURE__ */
|
|
1765
|
+
return /* @__PURE__ */ jsx11(
|
|
1803
1766
|
"div",
|
|
1804
1767
|
{
|
|
1805
1768
|
role: "toolbar",
|
|
1806
1769
|
"aria-label": label,
|
|
1807
1770
|
"data-test": dataTest,
|
|
1808
|
-
className:
|
|
1771
|
+
className: cn2("flex min-w-0 flex-wrap items-center gap-2", className),
|
|
1809
1772
|
children
|
|
1810
1773
|
}
|
|
1811
1774
|
);
|
|
@@ -1816,12 +1779,12 @@ function SuiteTabList({
|
|
|
1816
1779
|
label,
|
|
1817
1780
|
dataTest
|
|
1818
1781
|
}) {
|
|
1819
|
-
return /* @__PURE__ */
|
|
1782
|
+
return /* @__PURE__ */ jsx11(
|
|
1820
1783
|
"nav",
|
|
1821
1784
|
{
|
|
1822
1785
|
"aria-label": label,
|
|
1823
1786
|
"data-test": dataTest,
|
|
1824
|
-
className:
|
|
1787
|
+
className: cn2(
|
|
1825
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]",
|
|
1826
1789
|
className
|
|
1827
1790
|
),
|
|
@@ -1835,26 +1798,26 @@ function SuiteSectionHeader({
|
|
|
1835
1798
|
action,
|
|
1836
1799
|
className
|
|
1837
1800
|
}) {
|
|
1838
|
-
return /* @__PURE__ */
|
|
1801
|
+
return /* @__PURE__ */ jsxs9(
|
|
1839
1802
|
"div",
|
|
1840
1803
|
{
|
|
1841
|
-
className:
|
|
1804
|
+
className: cn2(
|
|
1842
1805
|
"flex min-w-0 flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
|
|
1843
1806
|
className
|
|
1844
1807
|
),
|
|
1845
1808
|
children: [
|
|
1846
|
-
/* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1848
|
-
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
|
|
1849
1812
|
] }),
|
|
1850
|
-
action ? /* @__PURE__ */
|
|
1813
|
+
action ? /* @__PURE__ */ jsx11("div", { className: "flex min-h-[44px] shrink-0 items-center", children: action }) : null
|
|
1851
1814
|
]
|
|
1852
1815
|
}
|
|
1853
1816
|
);
|
|
1854
1817
|
}
|
|
1855
1818
|
|
|
1856
1819
|
// src/suite/components/suite-settings-layout.tsx
|
|
1857
|
-
import { jsx as
|
|
1820
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1858
1821
|
function SuiteSettingsLayout({
|
|
1859
1822
|
children,
|
|
1860
1823
|
sidebar,
|
|
@@ -1868,13 +1831,13 @@ function SuiteSettingsLayout({
|
|
|
1868
1831
|
className,
|
|
1869
1832
|
contentClassName
|
|
1870
1833
|
}) {
|
|
1871
|
-
return /* @__PURE__ */
|
|
1834
|
+
return /* @__PURE__ */ jsxs10(
|
|
1872
1835
|
SuitePage,
|
|
1873
1836
|
{
|
|
1874
1837
|
dataTest,
|
|
1875
|
-
className:
|
|
1838
|
+
className: cn2("flex h-full flex-col overflow-hidden", className),
|
|
1876
1839
|
children: [
|
|
1877
|
-
header != null ? header : /* @__PURE__ */
|
|
1840
|
+
header != null ? header : /* @__PURE__ */ jsx12(
|
|
1878
1841
|
SuitePageHeader,
|
|
1879
1842
|
{
|
|
1880
1843
|
sticky: true,
|
|
@@ -1883,10 +1846,10 @@ function SuiteSettingsLayout({
|
|
|
1883
1846
|
description
|
|
1884
1847
|
}
|
|
1885
1848
|
),
|
|
1886
|
-
loading != null ? loading : /* @__PURE__ */
|
|
1887
|
-
mobileNav ? /* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1889
|
-
/* @__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(
|
|
1890
1853
|
"aside",
|
|
1891
1854
|
{
|
|
1892
1855
|
"aria-label": "Settings",
|
|
@@ -1894,10 +1857,10 @@ function SuiteSettingsLayout({
|
|
|
1894
1857
|
children: sidebar
|
|
1895
1858
|
}
|
|
1896
1859
|
),
|
|
1897
|
-
/* @__PURE__ */
|
|
1860
|
+
/* @__PURE__ */ jsx12(
|
|
1898
1861
|
"div",
|
|
1899
1862
|
{
|
|
1900
|
-
className:
|
|
1863
|
+
className: cn2(
|
|
1901
1864
|
"min-h-0 min-w-0 flex-1 overflow-y-auto overscroll-contain pb-6",
|
|
1902
1865
|
contentClassName
|
|
1903
1866
|
),
|
|
@@ -1915,24 +1878,25 @@ function SuiteSettingsLayout({
|
|
|
1915
1878
|
import Image2 from "next/image";
|
|
1916
1879
|
import { useRouter as useRouter2 } from "next/navigation";
|
|
1917
1880
|
import { LogOut, Settings } from "iconoir-react";
|
|
1918
|
-
import { jsx as
|
|
1881
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1919
1882
|
function computeInitials(name, email) {
|
|
1920
1883
|
const source = (name || email || "?").trim();
|
|
1921
1884
|
return source.split(/[\s@]+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join("").toUpperCase();
|
|
1922
1885
|
}
|
|
1923
1886
|
var AVATAR_TOKENS = [
|
|
1924
|
-
"bg-ph-brand",
|
|
1925
|
-
"bg-ph-violet",
|
|
1926
|
-
"bg-ph-info",
|
|
1927
|
-
"bg-ph-success",
|
|
1928
|
-
"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)]"]
|
|
1929
1892
|
];
|
|
1930
1893
|
function avatarColorClass(seed) {
|
|
1931
1894
|
let hash = 0;
|
|
1932
1895
|
for (let i = 0; i < seed.length; i += 1) {
|
|
1933
1896
|
hash = seed.charCodeAt(i) + ((hash << 5) - hash);
|
|
1934
1897
|
}
|
|
1935
|
-
|
|
1898
|
+
const [bg, ink] = AVATAR_TOKENS[Math.abs(hash) % AVATAR_TOKENS.length];
|
|
1899
|
+
return `${bg} ${ink}`;
|
|
1936
1900
|
}
|
|
1937
1901
|
function SuiteUserMenu({
|
|
1938
1902
|
name,
|
|
@@ -1950,7 +1914,7 @@ function SuiteUserMenu({
|
|
|
1950
1914
|
const router = useRouter2();
|
|
1951
1915
|
const initials = fallbackInitials != null ? fallbackInitials : computeInitials(name, email);
|
|
1952
1916
|
const fallbackColor = avatarColorClass(email || name || "?");
|
|
1953
|
-
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(
|
|
1954
1918
|
Image2,
|
|
1955
1919
|
{
|
|
1956
1920
|
src: image,
|
|
@@ -1960,17 +1924,17 @@ function SuiteUserMenu({
|
|
|
1960
1924
|
className: "h-full w-full object-cover",
|
|
1961
1925
|
unoptimized: true
|
|
1962
1926
|
}
|
|
1963
|
-
) : /* @__PURE__ */
|
|
1927
|
+
) : /* @__PURE__ */ jsx13(
|
|
1964
1928
|
"span",
|
|
1965
1929
|
{
|
|
1966
|
-
className:
|
|
1967
|
-
"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",
|
|
1968
1932
|
fallbackColor
|
|
1969
1933
|
),
|
|
1970
1934
|
children: initials
|
|
1971
1935
|
}
|
|
1972
1936
|
) });
|
|
1973
|
-
const accountMenu = /* @__PURE__ */
|
|
1937
|
+
const accountMenu = /* @__PURE__ */ jsxs11(
|
|
1974
1938
|
DropdownMenu,
|
|
1975
1939
|
{
|
|
1976
1940
|
trigger: avatar,
|
|
@@ -1982,30 +1946,30 @@ function SuiteUserMenu({
|
|
|
1982
1946
|
sideOffset: 6,
|
|
1983
1947
|
collisionPadding: 16,
|
|
1984
1948
|
modal: false,
|
|
1985
|
-
className:
|
|
1949
|
+
className: cn2(
|
|
1986
1950
|
"[&_.ph-dropdown-trigger]:rounded-full",
|
|
1987
1951
|
showSignOutAction ? void 0 : className
|
|
1988
1952
|
),
|
|
1989
1953
|
"data-test": dataTest,
|
|
1990
1954
|
children: [
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
1993
|
-
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
|
|
1994
1958
|
] }),
|
|
1995
|
-
/* @__PURE__ */
|
|
1996
|
-
/* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsx13("div", { className: "my-1 border-t border-ph-border" }),
|
|
1960
|
+
/* @__PURE__ */ jsxs11(
|
|
1997
1961
|
DropdownItem,
|
|
1998
1962
|
{
|
|
1999
1963
|
"data-test": `${dataTest}-settings`,
|
|
2000
1964
|
onClick: () => router.push(settingsHref),
|
|
2001
1965
|
children: [
|
|
2002
|
-
/* @__PURE__ */
|
|
1966
|
+
/* @__PURE__ */ jsx13(Settings, { className: "h-4 w-4 text-ph-mutedtext", "aria-hidden": true }),
|
|
2003
1967
|
"Profile settings"
|
|
2004
1968
|
]
|
|
2005
1969
|
}
|
|
2006
1970
|
),
|
|
2007
|
-
/* @__PURE__ */
|
|
2008
|
-
/* @__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 }),
|
|
2009
1973
|
"Sign out"
|
|
2010
1974
|
] })
|
|
2011
1975
|
]
|
|
@@ -2014,16 +1978,16 @@ function SuiteUserMenu({
|
|
|
2014
1978
|
if (!showSignOutAction) {
|
|
2015
1979
|
return accountMenu;
|
|
2016
1980
|
}
|
|
2017
|
-
return /* @__PURE__ */
|
|
1981
|
+
return /* @__PURE__ */ jsxs11(
|
|
2018
1982
|
"div",
|
|
2019
1983
|
{
|
|
2020
|
-
className:
|
|
1984
|
+
className: cn2(
|
|
2021
1985
|
"flex w-full min-w-0 flex-1 items-center justify-between gap-2",
|
|
2022
1986
|
className
|
|
2023
1987
|
),
|
|
2024
1988
|
children: [
|
|
2025
|
-
/* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
1989
|
+
/* @__PURE__ */ jsx13("div", { className: "shrink-0", children: accountMenu }),
|
|
1990
|
+
/* @__PURE__ */ jsx13(
|
|
2027
1991
|
"button",
|
|
2028
1992
|
{
|
|
2029
1993
|
type: "button",
|
|
@@ -2032,7 +1996,7 @@ function SuiteUserMenu({
|
|
|
2032
1996
|
"aria-label": "Sign out",
|
|
2033
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",
|
|
2034
1998
|
onClick: onSignOut,
|
|
2035
|
-
children: /* @__PURE__ */
|
|
1999
|
+
children: /* @__PURE__ */ jsx13(LogOut, { className: "h-4 w-4", "aria-hidden": true })
|
|
2036
2000
|
}
|
|
2037
2001
|
)
|
|
2038
2002
|
]
|
|
@@ -2042,7 +2006,7 @@ function SuiteUserMenu({
|
|
|
2042
2006
|
|
|
2043
2007
|
// src/suite/components/suite-bottom-nav.tsx
|
|
2044
2008
|
import Link from "next/link";
|
|
2045
|
-
import { Fragment as Fragment4, jsx as
|
|
2009
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2046
2010
|
function SuiteBottomNav({
|
|
2047
2011
|
items,
|
|
2048
2012
|
ariaLabel = "Primary navigation",
|
|
@@ -2055,8 +2019,8 @@ function SuiteBottomNav({
|
|
|
2055
2019
|
);
|
|
2056
2020
|
}
|
|
2057
2021
|
const activeIndex = items.findIndex((item) => item.active);
|
|
2058
|
-
return /* @__PURE__ */
|
|
2059
|
-
/* @__PURE__ */
|
|
2022
|
+
return /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
2023
|
+
/* @__PURE__ */ jsx14(
|
|
2060
2024
|
"div",
|
|
2061
2025
|
{
|
|
2062
2026
|
"aria-hidden": true,
|
|
@@ -2064,12 +2028,12 @@ function SuiteBottomNav({
|
|
|
2064
2028
|
style: { height: "calc(60px + env(safe-area-inset-bottom))" }
|
|
2065
2029
|
}
|
|
2066
2030
|
),
|
|
2067
|
-
/* @__PURE__ */
|
|
2031
|
+
/* @__PURE__ */ jsxs12(
|
|
2068
2032
|
"nav",
|
|
2069
2033
|
{
|
|
2070
2034
|
"aria-label": ariaLabel,
|
|
2071
2035
|
"data-test": dataTest,
|
|
2072
|
-
className:
|
|
2036
|
+
className: cn2(
|
|
2073
2037
|
"suite-bottom-nav no-print z-40 grid auto-cols-fr grid-flow-col lg:hidden",
|
|
2074
2038
|
className
|
|
2075
2039
|
),
|
|
@@ -2079,31 +2043,31 @@ function SuiteBottomNav({
|
|
|
2079
2043
|
"--suite-nav-active": activeIndex >= 0 ? activeIndex : 0
|
|
2080
2044
|
},
|
|
2081
2045
|
children: [
|
|
2082
|
-
activeIndex >= 0 ? /* @__PURE__ */
|
|
2046
|
+
activeIndex >= 0 ? /* @__PURE__ */ jsx14("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
|
|
2083
2047
|
items.map((item) => {
|
|
2084
2048
|
var _a;
|
|
2085
2049
|
const Icon = item.icon;
|
|
2086
2050
|
const active = Boolean(item.active);
|
|
2087
|
-
return /* @__PURE__ */
|
|
2051
|
+
return /* @__PURE__ */ jsxs12(
|
|
2088
2052
|
Link,
|
|
2089
2053
|
{
|
|
2090
2054
|
href: item.href,
|
|
2091
2055
|
id: item.id,
|
|
2092
2056
|
"data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
2093
2057
|
"aria-current": active ? "page" : void 0,
|
|
2094
|
-
className:
|
|
2058
|
+
className: cn2(
|
|
2095
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",
|
|
2096
2060
|
active && "font-semibold text-ph-brand"
|
|
2097
2061
|
),
|
|
2098
2062
|
children: [
|
|
2099
|
-
/* @__PURE__ */
|
|
2063
|
+
/* @__PURE__ */ jsx14(
|
|
2100
2064
|
"span",
|
|
2101
2065
|
{
|
|
2102
|
-
className:
|
|
2066
|
+
className: cn2(
|
|
2103
2067
|
"suite-bottom-nav__icon relative z-10 inline-flex items-center justify-center",
|
|
2104
2068
|
active && "suite-bottom-nav__icon--active"
|
|
2105
2069
|
),
|
|
2106
|
-
children: /* @__PURE__ */
|
|
2070
|
+
children: /* @__PURE__ */ jsx14(
|
|
2107
2071
|
Icon,
|
|
2108
2072
|
{
|
|
2109
2073
|
className: "h-6 w-6",
|
|
@@ -2113,7 +2077,7 @@ function SuiteBottomNav({
|
|
|
2113
2077
|
)
|
|
2114
2078
|
}
|
|
2115
2079
|
),
|
|
2116
|
-
/* @__PURE__ */
|
|
2080
|
+
/* @__PURE__ */ jsx14("span", { className: "relative z-10 max-w-full truncate", children: item.label })
|
|
2117
2081
|
]
|
|
2118
2082
|
},
|
|
2119
2083
|
item.href
|
|
@@ -2127,7 +2091,7 @@ function SuiteBottomNav({
|
|
|
2127
2091
|
|
|
2128
2092
|
// src/suite/components/today-calibrating.tsx
|
|
2129
2093
|
import { Refresh as RefreshCw2, SunLight as Sun } from "iconoir-react";
|
|
2130
|
-
import { jsx as
|
|
2094
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2131
2095
|
function TodayCalibrating({
|
|
2132
2096
|
onRetry,
|
|
2133
2097
|
retrying = false,
|
|
@@ -2137,27 +2101,27 @@ function TodayCalibrating({
|
|
|
2137
2101
|
retrySpinnerClassName = "text-ph-brand"
|
|
2138
2102
|
}) {
|
|
2139
2103
|
void _variant;
|
|
2140
|
-
return /* @__PURE__ */
|
|
2104
|
+
return /* @__PURE__ */ jsxs13(
|
|
2141
2105
|
"div",
|
|
2142
2106
|
{
|
|
2143
|
-
className:
|
|
2107
|
+
className: cn2(
|
|
2144
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",
|
|
2145
2109
|
className
|
|
2146
2110
|
),
|
|
2147
2111
|
"data-test": "today-calibrating",
|
|
2148
2112
|
children: [
|
|
2149
|
-
/* @__PURE__ */
|
|
2113
|
+
/* @__PURE__ */ jsx15(
|
|
2150
2114
|
"div",
|
|
2151
2115
|
{
|
|
2152
2116
|
className: "pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_35%,rgba(251,191,36,0.1),transparent_55%)]",
|
|
2153
2117
|
"aria-hidden": true
|
|
2154
2118
|
}
|
|
2155
2119
|
),
|
|
2156
|
-
/* @__PURE__ */
|
|
2157
|
-
/* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
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(
|
|
2161
2125
|
"button",
|
|
2162
2126
|
{
|
|
2163
2127
|
type: "button",
|
|
@@ -2165,7 +2129,7 @@ function TodayCalibrating({
|
|
|
2165
2129
|
disabled: retrying,
|
|
2166
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",
|
|
2167
2131
|
children: [
|
|
2168
|
-
retrying ? /* @__PURE__ */
|
|
2132
|
+
retrying ? /* @__PURE__ */ jsx15(Spinner, { size: "sm", className: retrySpinnerClassName }) : /* @__PURE__ */ jsx15(RefreshCw2, { className: "h-4 w-4", "aria-hidden": true }),
|
|
2169
2133
|
"Try again"
|
|
2170
2134
|
]
|
|
2171
2135
|
}
|
|
@@ -2183,7 +2147,7 @@ import {
|
|
|
2183
2147
|
useEffect as useEffect6,
|
|
2184
2148
|
useId,
|
|
2185
2149
|
useLayoutEffect,
|
|
2186
|
-
useRef as
|
|
2150
|
+
useRef as useRef2,
|
|
2187
2151
|
useState as useState7
|
|
2188
2152
|
} from "react";
|
|
2189
2153
|
import {
|
|
@@ -2194,8 +2158,8 @@ import {
|
|
|
2194
2158
|
Square,
|
|
2195
2159
|
WarningTriangle
|
|
2196
2160
|
} from "iconoir-react";
|
|
2197
|
-
import { Fragment as Fragment5, jsx as
|
|
2198
|
-
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"));
|
|
2199
2163
|
var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
|
|
2200
2164
|
var SUITE_ASK_AI_OPEN_KEY = "shellstack:shelly-open";
|
|
2201
2165
|
var SUITE_ASK_AI_OPEN_QUERY = "shelly";
|
|
@@ -2277,7 +2241,8 @@ function SuiteAiPanel({
|
|
|
2277
2241
|
suiteAppBases,
|
|
2278
2242
|
onSwitchApp,
|
|
2279
2243
|
onSameAppNavigate,
|
|
2280
|
-
resolveAction
|
|
2244
|
+
resolveAction,
|
|
2245
|
+
isWaitingForReply = false
|
|
2281
2246
|
}) {
|
|
2282
2247
|
const inputId = useId();
|
|
2283
2248
|
const [uncontrolledOpen, setUncontrolledOpen] = useState7(false);
|
|
@@ -2297,10 +2262,11 @@ function SuiteAiPanel({
|
|
|
2297
2262
|
const [hydrating, setHydrating] = useState7(false);
|
|
2298
2263
|
const [error, setError] = useState7("");
|
|
2299
2264
|
const [atBottom, setAtBottom] = useState7(true);
|
|
2300
|
-
const scrollerRef =
|
|
2301
|
-
const textareaRef =
|
|
2302
|
-
const abortRef =
|
|
2303
|
-
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;
|
|
2304
2270
|
useEffect6(() => {
|
|
2305
2271
|
function onOpen(event) {
|
|
2306
2272
|
var _a;
|
|
@@ -2328,7 +2294,7 @@ function SuiteAiPanel({
|
|
|
2328
2294
|
setAtBottom(distance < 64);
|
|
2329
2295
|
}, []);
|
|
2330
2296
|
const hydrate = useCallback2(async () => {
|
|
2331
|
-
var _a;
|
|
2297
|
+
var _a, _b, _c;
|
|
2332
2298
|
setHydrating(true);
|
|
2333
2299
|
setError("");
|
|
2334
2300
|
try {
|
|
@@ -2336,6 +2302,11 @@ function SuiteAiPanel({
|
|
|
2336
2302
|
setMessages((_a = data.messages) != null ? _a : []);
|
|
2337
2303
|
if (!data.configured) {
|
|
2338
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
|
+
}
|
|
2339
2310
|
}
|
|
2340
2311
|
} catch (err) {
|
|
2341
2312
|
setError(
|
|
@@ -2358,7 +2329,7 @@ function SuiteAiPanel({
|
|
|
2358
2329
|
}, [open, hydrate]);
|
|
2359
2330
|
useEffect6(() => {
|
|
2360
2331
|
if (open && atBottom) scrollToBottom();
|
|
2361
|
-
}, [messages,
|
|
2332
|
+
}, [messages, waiting, open, atBottom, scrollToBottom]);
|
|
2362
2333
|
useEffect6(() => {
|
|
2363
2334
|
var _a;
|
|
2364
2335
|
if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
|
|
@@ -2372,7 +2343,7 @@ function SuiteAiPanel({
|
|
|
2372
2343
|
async function ask(text) {
|
|
2373
2344
|
var _a;
|
|
2374
2345
|
const trimmed = text.trim();
|
|
2375
|
-
if (!trimmed ||
|
|
2346
|
+
if (!trimmed || waiting) return;
|
|
2376
2347
|
const controller = new AbortController();
|
|
2377
2348
|
abortRef.current = controller;
|
|
2378
2349
|
setLoading(true);
|
|
@@ -2488,32 +2459,32 @@ function SuiteAiPanel({
|
|
|
2488
2459
|
}
|
|
2489
2460
|
if (!open) return null;
|
|
2490
2461
|
const Icon = BrandIcon != null ? BrandIcon : Sparks;
|
|
2491
|
-
return /* @__PURE__ */
|
|
2462
|
+
return /* @__PURE__ */ jsxs14(
|
|
2492
2463
|
"aside",
|
|
2493
2464
|
{
|
|
2494
2465
|
className: "flex h-full min-h-0 flex-col bg-ph-canvas",
|
|
2495
2466
|
"data-test": "suite-ask-ai-panel",
|
|
2496
2467
|
"aria-label": title,
|
|
2497
2468
|
children: [
|
|
2498
|
-
/* @__PURE__ */
|
|
2499
|
-
/* @__PURE__ */
|
|
2500
|
-
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(
|
|
2501
2472
|
"button",
|
|
2502
2473
|
{
|
|
2503
2474
|
type: "button",
|
|
2504
2475
|
onClick: () => void handleClear(),
|
|
2505
|
-
disabled:
|
|
2476
|
+
disabled: waiting,
|
|
2506
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",
|
|
2507
2478
|
"data-test": "ask-ai-clear",
|
|
2508
2479
|
children: [
|
|
2509
|
-
/* @__PURE__ */
|
|
2480
|
+
/* @__PURE__ */ jsx16(Erase, { className: "h-3.5 w-3.5" }),
|
|
2510
2481
|
"Clear"
|
|
2511
2482
|
]
|
|
2512
2483
|
}
|
|
2513
2484
|
) : null
|
|
2514
2485
|
] }),
|
|
2515
|
-
/* @__PURE__ */
|
|
2516
|
-
/* @__PURE__ */
|
|
2486
|
+
/* @__PURE__ */ jsxs14("div", { className: "relative min-h-0 flex-1", children: [
|
|
2487
|
+
/* @__PURE__ */ jsxs14(
|
|
2517
2488
|
"div",
|
|
2518
2489
|
{
|
|
2519
2490
|
ref: scrollerRef,
|
|
@@ -2524,25 +2495,25 @@ function SuiteAiPanel({
|
|
|
2524
2495
|
"aria-label": "Conversation",
|
|
2525
2496
|
className: "suite-scroll-lock h-full space-y-5 overflow-y-auto px-2 py-3",
|
|
2526
2497
|
children: [
|
|
2527
|
-
hydrating && messages.length === 0 ? /* @__PURE__ */
|
|
2528
|
-
/* @__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" }),
|
|
2529
2500
|
"Loading your chat\u2026"
|
|
2530
2501
|
] }) : null,
|
|
2531
|
-
!hydrating && messages.length === 0 && !error ? /* @__PURE__ */
|
|
2532
|
-
/* @__PURE__ */
|
|
2533
|
-
/* @__PURE__ */
|
|
2534
|
-
/* @__PURE__ */
|
|
2535
|
-
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(
|
|
2536
2507
|
"button",
|
|
2537
2508
|
{
|
|
2538
2509
|
type: "button",
|
|
2539
2510
|
onClick: () => void ask(preset.prompt),
|
|
2540
|
-
disabled:
|
|
2511
|
+
disabled: waiting || hydrating,
|
|
2541
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",
|
|
2542
2513
|
children: [
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__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" })
|
|
2546
2517
|
]
|
|
2547
2518
|
},
|
|
2548
2519
|
preset.label
|
|
@@ -2552,48 +2523,61 @@ function SuiteAiPanel({
|
|
|
2552
2523
|
var _a;
|
|
2553
2524
|
const isUser = message.role === "user";
|
|
2554
2525
|
if (isUser) {
|
|
2555
|
-
return /* @__PURE__ */
|
|
2526
|
+
return /* @__PURE__ */ jsx16(
|
|
2556
2527
|
"div",
|
|
2557
2528
|
{
|
|
2558
2529
|
className: "flex justify-end",
|
|
2559
2530
|
"data-test": "ask-ai-user",
|
|
2560
|
-
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 })
|
|
2561
2532
|
},
|
|
2562
2533
|
`user-${index}`
|
|
2563
2534
|
);
|
|
2564
2535
|
}
|
|
2565
|
-
return /* @__PURE__ */
|
|
2536
|
+
return /* @__PURE__ */ jsxs14(
|
|
2566
2537
|
"div",
|
|
2567
2538
|
{
|
|
2568
2539
|
className: "flex items-end gap-2",
|
|
2569
2540
|
"data-test": "ask-ai-assistant",
|
|
2570
2541
|
children: [
|
|
2571
|
-
/* @__PURE__ */
|
|
2542
|
+
/* @__PURE__ */ jsx16(
|
|
2572
2543
|
"span",
|
|
2573
2544
|
{
|
|
2574
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",
|
|
2575
2546
|
"aria-hidden": true,
|
|
2576
|
-
children: /* @__PURE__ */
|
|
2547
|
+
children: /* @__PURE__ */ jsx16(Icon, { className: "h-3.5 w-3.5" })
|
|
2577
2548
|
}
|
|
2578
2549
|
),
|
|
2579
|
-
/* @__PURE__ */
|
|
2580
|
-
/* @__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(
|
|
2581
2552
|
Suspense,
|
|
2582
2553
|
{
|
|
2583
|
-
fallback: /* @__PURE__ */
|
|
2584
|
-
|
|
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 })
|
|
2585
2569
|
}
|
|
2586
2570
|
) }),
|
|
2587
|
-
((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */
|
|
2571
|
+
((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */ jsxs14(
|
|
2588
2572
|
"div",
|
|
2589
2573
|
{
|
|
2590
2574
|
"data-test": "ask-ai-action",
|
|
2591
2575
|
"data-status": action.status,
|
|
2592
2576
|
className: "rounded-xl border border-ph-border bg-ph-surface px-3 py-2 text-sm text-ph-ink",
|
|
2593
2577
|
children: [
|
|
2594
|
-
/* @__PURE__ */
|
|
2595
|
-
action.status === "proposed" ? /* @__PURE__ */
|
|
2596
|
-
/* @__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(
|
|
2597
2581
|
"button",
|
|
2598
2582
|
{
|
|
2599
2583
|
type: "button",
|
|
@@ -2604,7 +2588,7 @@ function SuiteAiPanel({
|
|
|
2604
2588
|
children: resolvingId === action.id ? "Working\u2026" : "Confirm"
|
|
2605
2589
|
}
|
|
2606
2590
|
),
|
|
2607
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ jsx16(
|
|
2608
2592
|
"button",
|
|
2609
2593
|
{
|
|
2610
2594
|
type: "button",
|
|
@@ -2616,11 +2600,11 @@ function SuiteAiPanel({
|
|
|
2616
2600
|
}
|
|
2617
2601
|
)
|
|
2618
2602
|
] }) : null,
|
|
2619
|
-
action.status === "applied" ? /* @__PURE__ */
|
|
2603
|
+
action.status === "applied" ? /* @__PURE__ */ jsxs14("p", { className: "mt-1 text-xs text-ph-subtle", children: [
|
|
2620
2604
|
"Done",
|
|
2621
|
-
action.href ? /* @__PURE__ */
|
|
2605
|
+
action.href ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
2622
2606
|
" \xB7 ",
|
|
2623
|
-
/* @__PURE__ */
|
|
2607
|
+
/* @__PURE__ */ jsx16(
|
|
2624
2608
|
"a",
|
|
2625
2609
|
{
|
|
2626
2610
|
href: action.href,
|
|
@@ -2630,8 +2614,8 @@ function SuiteAiPanel({
|
|
|
2630
2614
|
)
|
|
2631
2615
|
] }) : null
|
|
2632
2616
|
] }) : null,
|
|
2633
|
-
action.status === "cancelled" ? /* @__PURE__ */
|
|
2634
|
-
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
|
|
2635
2619
|
]
|
|
2636
2620
|
},
|
|
2637
2621
|
action.id
|
|
@@ -2642,31 +2626,31 @@ function SuiteAiPanel({
|
|
|
2642
2626
|
`assistant-${index}`
|
|
2643
2627
|
);
|
|
2644
2628
|
}),
|
|
2645
|
-
|
|
2646
|
-
/* @__PURE__ */
|
|
2647
|
-
/* @__PURE__ */
|
|
2648
|
-
/* @__PURE__ */
|
|
2649
|
-
/* @__PURE__ */
|
|
2650
|
-
/* @__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]" })
|
|
2651
2635
|
] })
|
|
2652
2636
|
] }) : null,
|
|
2653
|
-
|
|
2654
|
-
error ? /* @__PURE__ */
|
|
2637
|
+
waiting ? /* @__PURE__ */ jsx16("span", { className: "sr-only", "aria-live": "polite", children: "Assistant is responding\u2026" }) : null,
|
|
2638
|
+
error ? /* @__PURE__ */ jsxs14(
|
|
2655
2639
|
"div",
|
|
2656
2640
|
{
|
|
2657
2641
|
role: "alert",
|
|
2658
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",
|
|
2659
2643
|
children: [
|
|
2660
|
-
/* @__PURE__ */
|
|
2661
|
-
/* @__PURE__ */
|
|
2662
|
-
/* @__PURE__ */
|
|
2663
|
-
/* @__PURE__ */
|
|
2664
|
-
/* @__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(
|
|
2665
2649
|
"button",
|
|
2666
2650
|
{
|
|
2667
2651
|
type: "button",
|
|
2668
2652
|
onClick: retry,
|
|
2669
|
-
disabled:
|
|
2653
|
+
disabled: waiting,
|
|
2670
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",
|
|
2671
2655
|
children: "Try again"
|
|
2672
2656
|
}
|
|
@@ -2678,20 +2662,20 @@ function SuiteAiPanel({
|
|
|
2678
2662
|
]
|
|
2679
2663
|
}
|
|
2680
2664
|
),
|
|
2681
|
-
!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(
|
|
2682
2666
|
"button",
|
|
2683
2667
|
{
|
|
2684
2668
|
type: "button",
|
|
2685
2669
|
onClick: () => scrollToBottom("smooth"),
|
|
2686
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",
|
|
2687
2671
|
"aria-label": "Scroll to latest",
|
|
2688
|
-
children: /* @__PURE__ */
|
|
2672
|
+
children: /* @__PURE__ */ jsx16(ArrowDown, { className: "h-4 w-4" })
|
|
2689
2673
|
}
|
|
2690
2674
|
) }) }) : null
|
|
2691
2675
|
] }),
|
|
2692
|
-
/* @__PURE__ */
|
|
2693
|
-
/* @__PURE__ */
|
|
2694
|
-
/* @__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(
|
|
2695
2679
|
"textarea",
|
|
2696
2680
|
{
|
|
2697
2681
|
id: inputId,
|
|
@@ -2710,7 +2694,7 @@ function SuiteAiPanel({
|
|
|
2710
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"
|
|
2711
2695
|
}
|
|
2712
2696
|
),
|
|
2713
|
-
loading ? /* @__PURE__ */
|
|
2697
|
+
loading ? /* @__PURE__ */ jsx16(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ jsx16(
|
|
2714
2698
|
"button",
|
|
2715
2699
|
{
|
|
2716
2700
|
type: "button",
|
|
@@ -2718,9 +2702,18 @@ function SuiteAiPanel({
|
|
|
2718
2702
|
"data-test": "ask-ai-stop",
|
|
2719
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",
|
|
2720
2704
|
"aria-label": "Stop generating",
|
|
2721
|
-
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" })
|
|
2722
2715
|
}
|
|
2723
|
-
)
|
|
2716
|
+
) : /* @__PURE__ */ jsx16(Tooltip, { content: "Send message", children: /* @__PURE__ */ jsx16(
|
|
2724
2717
|
"button",
|
|
2725
2718
|
{
|
|
2726
2719
|
type: "button",
|
|
@@ -2729,7 +2722,7 @@ function SuiteAiPanel({
|
|
|
2729
2722
|
"data-test": "ask-ai-send",
|
|
2730
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",
|
|
2731
2724
|
"aria-label": "Send message",
|
|
2732
|
-
children: /* @__PURE__ */
|
|
2725
|
+
children: /* @__PURE__ */ jsx16(ArrowUp, { className: "h-4 w-4" })
|
|
2733
2726
|
}
|
|
2734
2727
|
) })
|
|
2735
2728
|
] }) })
|
|
@@ -2741,7 +2734,7 @@ function SuiteAiPanel({
|
|
|
2741
2734
|
// src/suite/components/workspace-switcher.tsx
|
|
2742
2735
|
import { useState as useState8 } from "react";
|
|
2743
2736
|
import { Building, Check, NavArrowDown } from "iconoir-react";
|
|
2744
|
-
import { Fragment as Fragment6, jsx as
|
|
2737
|
+
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2745
2738
|
function SuiteWorkspaceSwitcher({
|
|
2746
2739
|
workspaces = [],
|
|
2747
2740
|
groups,
|
|
@@ -2759,7 +2752,7 @@ function SuiteWorkspaceSwitcher({
|
|
|
2759
2752
|
var _a;
|
|
2760
2753
|
const [open, setOpen] = useState8(false);
|
|
2761
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 }] : [];
|
|
2762
|
-
return /* @__PURE__ */
|
|
2755
|
+
return /* @__PURE__ */ jsx17(
|
|
2763
2756
|
DropdownMenu2,
|
|
2764
2757
|
{
|
|
2765
2758
|
"aria-label": "Switch workspace",
|
|
@@ -2770,24 +2763,23 @@ function SuiteWorkspaceSwitcher({
|
|
|
2770
2763
|
align: "start",
|
|
2771
2764
|
open,
|
|
2772
2765
|
onOpenChange: setOpen,
|
|
2773
|
-
trigger: /* @__PURE__ */
|
|
2766
|
+
trigger: /* @__PURE__ */ jsxs15(
|
|
2774
2767
|
"span",
|
|
2775
2768
|
{
|
|
2776
|
-
className:
|
|
2769
|
+
className: cn2(
|
|
2777
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",
|
|
2778
2771
|
collapsed ? "h-10 w-10 justify-center p-0" : "w-full px-3 py-2",
|
|
2779
2772
|
open && "border-ph-brand/40"
|
|
2780
2773
|
),
|
|
2781
2774
|
"data-test": "workspace-switcher-trigger",
|
|
2782
|
-
"aria-expanded": open,
|
|
2783
2775
|
children: [
|
|
2784
|
-
/* @__PURE__ */
|
|
2785
|
-
!collapsed ? /* @__PURE__ */
|
|
2786
|
-
/* @__PURE__ */
|
|
2787
|
-
/* @__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(
|
|
2788
2780
|
NavArrowDown,
|
|
2789
2781
|
{
|
|
2790
|
-
className:
|
|
2782
|
+
className: cn2(
|
|
2791
2783
|
"h-3.5 w-3.5 shrink-0 text-ph-mutedtext transition-transform",
|
|
2792
2784
|
open && "rotate-180"
|
|
2793
2785
|
),
|
|
@@ -2798,21 +2790,20 @@ function SuiteWorkspaceSwitcher({
|
|
|
2798
2790
|
]
|
|
2799
2791
|
}
|
|
2800
2792
|
),
|
|
2801
|
-
children: /* @__PURE__ */
|
|
2793
|
+
children: /* @__PURE__ */ jsxs15(
|
|
2802
2794
|
"div",
|
|
2803
2795
|
{
|
|
2804
2796
|
id: "workspace-switcher-menu",
|
|
2805
2797
|
className: "p-1",
|
|
2806
2798
|
"data-test": "workspace-switcher-menu",
|
|
2807
2799
|
children: [
|
|
2808
|
-
sections.length === 0 ? /* @__PURE__ */
|
|
2809
|
-
/* @__PURE__ */
|
|
2810
|
-
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(
|
|
2811
2803
|
DropdownItem2,
|
|
2812
2804
|
{
|
|
2813
2805
|
id: `workspace-option-${workspace.id}`,
|
|
2814
|
-
|
|
2815
|
-
"aria-selected": workspace.id === currentId,
|
|
2806
|
+
"aria-current": workspace.id === currentId ? "true" : void 0,
|
|
2816
2807
|
"data-test": "workspace-option",
|
|
2817
2808
|
"data-workspace-id": workspace.id,
|
|
2818
2809
|
onMouseDown: (event) => event.preventDefault(),
|
|
@@ -2821,12 +2812,12 @@ function SuiteWorkspaceSwitcher({
|
|
|
2821
2812
|
onSelect(workspace);
|
|
2822
2813
|
},
|
|
2823
2814
|
className: appSwitcherMenuItemClass(),
|
|
2824
|
-
children: /* @__PURE__ */
|
|
2825
|
-
/* @__PURE__ */
|
|
2826
|
-
/* @__PURE__ */
|
|
2827
|
-
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
|
|
2828
2819
|
] }),
|
|
2829
|
-
workspace.id === currentId ? /* @__PURE__ */
|
|
2820
|
+
workspace.id === currentId ? /* @__PURE__ */ jsx17(
|
|
2830
2821
|
Check,
|
|
2831
2822
|
{
|
|
2832
2823
|
className: "h-4 w-4 shrink-0 text-ph-brand",
|
|
@@ -2838,7 +2829,7 @@ function SuiteWorkspaceSwitcher({
|
|
|
2838
2829
|
workspace.id
|
|
2839
2830
|
))
|
|
2840
2831
|
] }, section.id)),
|
|
2841
|
-
footer ? /* @__PURE__ */
|
|
2832
|
+
footer ? /* @__PURE__ */ jsx17("div", { className: "mt-1 border-t border-ph-border pt-1", children: footer }) : null
|
|
2842
2833
|
]
|
|
2843
2834
|
}
|
|
2844
2835
|
)
|
|
@@ -2846,6 +2837,63 @@ function SuiteWorkspaceSwitcher({
|
|
|
2846
2837
|
);
|
|
2847
2838
|
}
|
|
2848
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
|
+
|
|
2849
2897
|
// src/suite/lib/use-sidebar-width.ts
|
|
2850
2898
|
import {
|
|
2851
2899
|
useCallback as useCallback3,
|
|
@@ -2863,8 +2911,7 @@ var LEGACY_SIDEBAR_WIDTH_KEYS = [
|
|
|
2863
2911
|
"tides-sidebar-width",
|
|
2864
2912
|
"tt-sidebar-width",
|
|
2865
2913
|
"kraken-sidebar-width",
|
|
2866
|
-
"shellstack-sidebar-width"
|
|
2867
|
-
"nakama-sidebar-width"
|
|
2914
|
+
"shellstack-sidebar-width"
|
|
2868
2915
|
];
|
|
2869
2916
|
function isSuiteSidebarKey(storageKey) {
|
|
2870
2917
|
return storageKey === SUITE_SIDEBAR_WIDTH_KEY || LEGACY_SIDEBAR_WIDTH_KEYS.includes(
|
|
@@ -2872,6 +2919,7 @@ function isSuiteSidebarKey(storageKey) {
|
|
|
2872
2919
|
);
|
|
2873
2920
|
}
|
|
2874
2921
|
function sidebarColumnWidth(width, collapsed, _chatOpen = false) {
|
|
2922
|
+
void _chatOpen;
|
|
2875
2923
|
if (collapsed) return SIDEBAR_RAIL_WIDTH;
|
|
2876
2924
|
return width;
|
|
2877
2925
|
}
|
|
@@ -2888,50 +2936,6 @@ function parseWidth(raw) {
|
|
|
2888
2936
|
const parsed = Number.parseInt(raw, 10);
|
|
2889
2937
|
return Number.isNaN(parsed) ? null : parsed;
|
|
2890
2938
|
}
|
|
2891
|
-
function suiteCookieDomainAttr() {
|
|
2892
|
-
var _a;
|
|
2893
|
-
const host = window.location.hostname;
|
|
2894
|
-
if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
|
|
2895
|
-
return "";
|
|
2896
|
-
}
|
|
2897
|
-
if (host.endsWith(".localhost")) {
|
|
2898
|
-
return "; Domain=.localhost";
|
|
2899
|
-
}
|
|
2900
|
-
const known = /* @__PURE__ */ new Set([
|
|
2901
|
-
"tides",
|
|
2902
|
-
"kraken",
|
|
2903
|
-
"turtletime",
|
|
2904
|
-
"time",
|
|
2905
|
-
"nakama",
|
|
2906
|
-
"app",
|
|
2907
|
-
"shellstack",
|
|
2908
|
-
"portal"
|
|
2909
|
-
]);
|
|
2910
|
-
const parts = host.split(".");
|
|
2911
|
-
if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
|
|
2912
|
-
return `; Domain=.${parts.slice(1).join(".")}`;
|
|
2913
|
-
}
|
|
2914
|
-
if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
|
|
2915
|
-
return "";
|
|
2916
|
-
}
|
|
2917
|
-
function readCookie(name) {
|
|
2918
|
-
const prefix = `${name}=`;
|
|
2919
|
-
for (const part of document.cookie.split(";")) {
|
|
2920
|
-
const trimmed = part.trim();
|
|
2921
|
-
if (trimmed.startsWith(prefix)) {
|
|
2922
|
-
return decodeURIComponent(trimmed.slice(prefix.length));
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
return null;
|
|
2926
|
-
}
|
|
2927
|
-
function writeCookie(name, value) {
|
|
2928
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2929
|
-
document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
2930
|
-
}
|
|
2931
|
-
function clearCookie(name) {
|
|
2932
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2933
|
-
document.cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
|
|
2934
|
-
}
|
|
2935
2939
|
function readSidebarWidth(storageKey) {
|
|
2936
2940
|
try {
|
|
2937
2941
|
if (isSuiteSidebarKey(storageKey)) {
|
|
@@ -3087,7 +3091,7 @@ function SuiteSkeleton({
|
|
|
3087
3091
|
return /* @__PURE__ */ jsx20(
|
|
3088
3092
|
"div",
|
|
3089
3093
|
{
|
|
3090
|
-
className:
|
|
3094
|
+
className: cn2("space-y-2", circle ? "flex flex-col items-center" : ""),
|
|
3091
3095
|
"aria-hidden": true,
|
|
3092
3096
|
children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx20(
|
|
3093
3097
|
"div",
|
|
@@ -3097,7 +3101,7 @@ function SuiteSkeleton({
|
|
|
3097
3101
|
children: /* @__PURE__ */ jsx20(
|
|
3098
3102
|
"div",
|
|
3099
3103
|
{
|
|
3100
|
-
className:
|
|
3104
|
+
className: cn2(
|
|
3101
3105
|
"ph-skeleton",
|
|
3102
3106
|
circle ? "h-10 w-10 rounded-full" : "h-3",
|
|
3103
3107
|
className
|
|
@@ -3121,7 +3125,7 @@ function SuiteSkeletonCard({
|
|
|
3121
3125
|
return /* @__PURE__ */ jsxs17(
|
|
3122
3126
|
"div",
|
|
3123
3127
|
{
|
|
3124
|
-
className:
|
|
3128
|
+
className: cn2(
|
|
3125
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",
|
|
3126
3130
|
className
|
|
3127
3131
|
),
|
|
@@ -3164,7 +3168,7 @@ function SuiteSkeletonList({
|
|
|
3164
3168
|
className,
|
|
3165
3169
|
items = 4
|
|
3166
3170
|
}) {
|
|
3167
|
-
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(
|
|
3168
3172
|
"div",
|
|
3169
3173
|
{
|
|
3170
3174
|
className: "animate-[skeleton-stagger_0.6s_ease-out_both]",
|
|
@@ -3191,7 +3195,7 @@ function SuiteEmptyState({
|
|
|
3191
3195
|
return /* @__PURE__ */ jsxs17(
|
|
3192
3196
|
"div",
|
|
3193
3197
|
{
|
|
3194
|
-
className:
|
|
3198
|
+
className: cn2(
|
|
3195
3199
|
"relative overflow-hidden rounded-2xl border border-ph-border bg-ph-surface text-center",
|
|
3196
3200
|
size === "sm" ? "px-5 py-8" : "px-6 py-12 sm:px-10 sm:py-16",
|
|
3197
3201
|
className
|
|
@@ -3204,9 +3208,9 @@ function SuiteEmptyState({
|
|
|
3204
3208
|
/* @__PURE__ */ jsxs17("div", { className: "relative", children: [
|
|
3205
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,
|
|
3206
3210
|
/* @__PURE__ */ jsx20(
|
|
3207
|
-
"
|
|
3211
|
+
"h2",
|
|
3208
3212
|
{
|
|
3209
|
-
className:
|
|
3213
|
+
className: cn2(
|
|
3210
3214
|
"font-semibold text-ph-ink",
|
|
3211
3215
|
size === "sm" ? "text-base" : "text-lg"
|
|
3212
3216
|
),
|
|
@@ -3237,14 +3241,14 @@ function SuiteSettingsMobileNav({
|
|
|
3237
3241
|
{
|
|
3238
3242
|
"data-test": dataTest,
|
|
3239
3243
|
"aria-label": ariaLabel,
|
|
3240
|
-
className:
|
|
3244
|
+
className: cn2("suite-settings-mobile-nav lg:hidden", className),
|
|
3241
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) => {
|
|
3242
3246
|
const Icon = item.icon;
|
|
3243
3247
|
const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
|
|
3244
3248
|
const iconNode = isValidElement(item.icon) ? item.icon : /* @__PURE__ */ jsx21(
|
|
3245
3249
|
Icon,
|
|
3246
3250
|
{
|
|
3247
|
-
className:
|
|
3251
|
+
className: cn2(
|
|
3248
3252
|
"h-4 w-4 shrink-0 transition",
|
|
3249
3253
|
active ? "text-ph-surface" : "text-ph-mutedtext"
|
|
3250
3254
|
),
|
|
@@ -3259,7 +3263,7 @@ function SuiteSettingsMobileNav({
|
|
|
3259
3263
|
"data-test": item.testId,
|
|
3260
3264
|
onClick: () => onSelect(item.href),
|
|
3261
3265
|
"aria-current": active ? "page" : void 0,
|
|
3262
|
-
className:
|
|
3266
|
+
className: cn2(
|
|
3263
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",
|
|
3264
3268
|
"min-h-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
|
|
3265
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"
|
|
@@ -3344,7 +3348,7 @@ function SuiteSidebar({
|
|
|
3344
3348
|
"aria-pressed": askAiOpen,
|
|
3345
3349
|
"aria-label": askAiOpen ? "Back to navigation" : "Shelly AI",
|
|
3346
3350
|
onClick: toggleAskAi,
|
|
3347
|
-
className:
|
|
3351
|
+
className: cn2(
|
|
3348
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",
|
|
3349
3353
|
askAiOpen ? "bg-ph-brand/10 text-ph-brand" : "text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink"
|
|
3350
3354
|
),
|
|
@@ -3356,7 +3360,7 @@ function SuiteSidebar({
|
|
|
3356
3360
|
"div",
|
|
3357
3361
|
{
|
|
3358
3362
|
"data-suite-chat-open": "",
|
|
3359
|
-
className:
|
|
3363
|
+
className: cn2(
|
|
3360
3364
|
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
3361
3365
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3362
3366
|
className
|
|
@@ -3365,12 +3369,12 @@ function SuiteSidebar({
|
|
|
3365
3369
|
/* @__PURE__ */ jsxs19(
|
|
3366
3370
|
"div",
|
|
3367
3371
|
{
|
|
3368
|
-
className:
|
|
3372
|
+
className: cn2(
|
|
3369
3373
|
"flex h-14 shrink-0 items-center gap-1 border-b border-ph-border px-2",
|
|
3370
3374
|
surface ? "bg-ph-surface" : "bg-ph-canvas"
|
|
3371
3375
|
),
|
|
3372
3376
|
children: [
|
|
3373
|
-
/* @__PURE__ */ jsx22(
|
|
3377
|
+
/* @__PURE__ */ jsx22(
|
|
3374
3378
|
"button",
|
|
3375
3379
|
{
|
|
3376
3380
|
type: "button",
|
|
@@ -3380,7 +3384,7 @@ function SuiteSidebar({
|
|
|
3380
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",
|
|
3381
3385
|
children: /* @__PURE__ */ jsx22(NavArrowLeft, { className: "h-4 w-4", "aria-hidden": true })
|
|
3382
3386
|
}
|
|
3383
|
-
)
|
|
3387
|
+
),
|
|
3384
3388
|
/* @__PURE__ */ jsx22("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-ph-ink", children: "Shelly AI" })
|
|
3385
3389
|
]
|
|
3386
3390
|
}
|
|
@@ -3393,7 +3397,7 @@ function SuiteSidebar({
|
|
|
3393
3397
|
return /* @__PURE__ */ jsxs19(
|
|
3394
3398
|
"div",
|
|
3395
3399
|
{
|
|
3396
|
-
className:
|
|
3400
|
+
className: cn2(
|
|
3397
3401
|
"flex h-full w-full min-w-0 flex-col text-ph-ink",
|
|
3398
3402
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3399
3403
|
className
|
|
@@ -3402,13 +3406,13 @@ function SuiteSidebar({
|
|
|
3402
3406
|
appSwitcher || notificationBell ? /* @__PURE__ */ jsxs19(
|
|
3403
3407
|
"div",
|
|
3404
3408
|
{
|
|
3405
|
-
className:
|
|
3409
|
+
className: cn2(
|
|
3406
3410
|
"flex shrink-0 border-b border-ph-border",
|
|
3407
3411
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3408
3412
|
collapsed ? "flex-col items-center gap-1 px-1 py-2" : "h-14 items-center justify-between gap-2 px-3"
|
|
3409
3413
|
),
|
|
3410
3414
|
children: [
|
|
3411
|
-
/* @__PURE__ */ jsx22("div", { className:
|
|
3415
|
+
/* @__PURE__ */ jsx22("div", { className: cn2("min-w-0", collapsed ? "shrink-0" : "flex-1"), children: renderNode(appSwitcher, collapsed) }),
|
|
3412
3416
|
collapsed ? null : /* @__PURE__ */ jsx22("div", { className: "shrink-0", children: renderNode(notificationBell, collapsed) })
|
|
3413
3417
|
]
|
|
3414
3418
|
}
|
|
@@ -3416,14 +3420,23 @@ function SuiteSidebar({
|
|
|
3416
3420
|
/* @__PURE__ */ jsxs19(
|
|
3417
3421
|
"div",
|
|
3418
3422
|
{
|
|
3419
|
-
className:
|
|
3423
|
+
className: cn2(
|
|
3420
3424
|
"flex min-h-0 flex-1 flex-col",
|
|
3421
3425
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3422
3426
|
chatOpen ? "min-h-0" : "overflow-y-auto",
|
|
3423
|
-
collapsed ? "px-1.5 py-2" : "p-
|
|
3427
|
+
collapsed ? "px-1.5 py-2" : "p-3"
|
|
3424
3428
|
),
|
|
3425
3429
|
children: [
|
|
3426
|
-
/* @__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,
|
|
3427
3440
|
chatOpen ? /* @__PURE__ */ jsxs19("div", { className: "flex min-h-0 flex-1 flex-col", children: [
|
|
3428
3441
|
/* @__PURE__ */ jsxs19("div", { className: "mb-2 flex shrink-0 items-center gap-1", children: [
|
|
3429
3442
|
/* @__PURE__ */ jsxs19(
|
|
@@ -3443,7 +3456,7 @@ function SuiteSidebar({
|
|
|
3443
3456
|
] }),
|
|
3444
3457
|
/* @__PURE__ */ jsx22("div", { className: "min-h-0 flex-1", children: askAi })
|
|
3445
3458
|
] }) : /* @__PURE__ */ jsxs19(Fragment7, { children: [
|
|
3446
|
-
/* @__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) => {
|
|
3447
3460
|
var _a;
|
|
3448
3461
|
const Icon = item.icon;
|
|
3449
3462
|
const active = Boolean(item.active);
|
|
@@ -3455,7 +3468,7 @@ function SuiteSidebar({
|
|
|
3455
3468
|
"data-test": (_a = item.dataTest) != null ? _a : "nav-link",
|
|
3456
3469
|
"aria-current": active ? "page" : void 0,
|
|
3457
3470
|
onClick: item.onClick,
|
|
3458
|
-
className:
|
|
3471
|
+
className: cn2(
|
|
3459
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",
|
|
3460
3473
|
active ? "bg-ph-muted" : "text-ph-subtle hover:bg-ph-muted hover:text-ph-ink",
|
|
3461
3474
|
collapsed ? "mx-auto size-11 shrink-0 justify-center gap-0 px-0 py-0" : "w-full px-2.5 py-2"
|
|
@@ -3464,7 +3477,7 @@ function SuiteSidebar({
|
|
|
3464
3477
|
/* @__PURE__ */ jsx22(
|
|
3465
3478
|
"span",
|
|
3466
3479
|
{
|
|
3467
|
-
className:
|
|
3480
|
+
className: cn2(
|
|
3468
3481
|
"relative flex h-4 w-4 shrink-0 items-center justify-center",
|
|
3469
3482
|
item.iconClassName
|
|
3470
3483
|
),
|
|
@@ -3481,7 +3494,7 @@ function SuiteSidebar({
|
|
|
3481
3494
|
/* @__PURE__ */ jsx22(
|
|
3482
3495
|
"span",
|
|
3483
3496
|
{
|
|
3484
|
-
className:
|
|
3497
|
+
className: cn2(
|
|
3485
3498
|
"relative truncate",
|
|
3486
3499
|
active ? "text-ph-ink" : "text-ph-subtle group-hover:text-ph-ink",
|
|
3487
3500
|
collapsed && "sr-only"
|
|
@@ -3511,7 +3524,7 @@ function SuiteSidebar({
|
|
|
3511
3524
|
/* @__PURE__ */ jsx22(
|
|
3512
3525
|
"div",
|
|
3513
3526
|
{
|
|
3514
|
-
className:
|
|
3527
|
+
className: cn2(
|
|
3515
3528
|
"shrink-0 border-t border-ph-border",
|
|
3516
3529
|
surface ? "bg-ph-surface" : "bg-ph-canvas",
|
|
3517
3530
|
collapsed ? "p-1.5" : "p-3"
|
|
@@ -3519,20 +3532,14 @@ function SuiteSidebar({
|
|
|
3519
3532
|
children: /* @__PURE__ */ jsxs19(
|
|
3520
3533
|
"div",
|
|
3521
3534
|
{
|
|
3522
|
-
className:
|
|
3535
|
+
className: cn2(
|
|
3523
3536
|
"flex items-center gap-2",
|
|
3524
3537
|
collapsed ? "flex-col items-center justify-center [&>div]:w-auto" : "w-full min-w-0"
|
|
3525
3538
|
),
|
|
3526
3539
|
children: [
|
|
3527
3540
|
renderNode(userMenu, collapsed),
|
|
3528
|
-
showAskAi ? /* @__PURE__ */ jsx22(
|
|
3529
|
-
|
|
3530
|
-
{
|
|
3531
|
-
className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"),
|
|
3532
|
-
children: /* @__PURE__ */ jsx22(Tooltip, { content: "Shelly AI", side: collapsed ? "right" : "top", children: askAiButton })
|
|
3533
|
-
}
|
|
3534
|
-
) : footerExtras ? /* @__PURE__ */ jsx22("div", { className: cn("shrink-0", collapsed ? "mt-2" : "ml-auto"), children: renderNode(footerExtras, collapsed) }) : null,
|
|
3535
|
-
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
|
|
3536
3543
|
]
|
|
3537
3544
|
}
|
|
3538
3545
|
)
|
|
@@ -3562,7 +3569,7 @@ function SuiteAppLayout({
|
|
|
3562
3569
|
"div",
|
|
3563
3570
|
{
|
|
3564
3571
|
"data-test": "app-shell",
|
|
3565
|
-
className:
|
|
3572
|
+
className: cn2(
|
|
3566
3573
|
"suite-app-layout flex h-dvh overflow-hidden",
|
|
3567
3574
|
className
|
|
3568
3575
|
),
|
|
@@ -3570,6 +3577,7 @@ function SuiteAppLayout({
|
|
|
3570
3577
|
/* @__PURE__ */ jsxs20(
|
|
3571
3578
|
"aside",
|
|
3572
3579
|
{
|
|
3580
|
+
"aria-label": "Sidebar",
|
|
3573
3581
|
className: "relative hidden shrink-0 flex-col overflow-visible border-r border-ph-border ease-out lg:flex",
|
|
3574
3582
|
style: { width: `${sidebarWidth}px` },
|
|
3575
3583
|
"data-collapsed": collapsed ? "true" : "false",
|
|
@@ -3581,6 +3589,10 @@ function SuiteAppLayout({
|
|
|
3581
3589
|
role: "separator",
|
|
3582
3590
|
"aria-orientation": "vertical",
|
|
3583
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`,
|
|
3584
3596
|
"data-test": "sidebar-resize-handle",
|
|
3585
3597
|
tabIndex: onResizeBy ? 0 : void 0,
|
|
3586
3598
|
onPointerDown: onStartResize,
|
|
@@ -3597,7 +3609,7 @@ function SuiteAppLayout({
|
|
|
3597
3609
|
onResizeBy == null ? void 0 : onResizeBy(16);
|
|
3598
3610
|
}
|
|
3599
3611
|
},
|
|
3600
|
-
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)]"
|
|
3601
3613
|
}
|
|
3602
3614
|
) : null
|
|
3603
3615
|
]
|
|
@@ -3609,10 +3621,10 @@ function SuiteAppLayout({
|
|
|
3609
3621
|
"main",
|
|
3610
3622
|
{
|
|
3611
3623
|
id: "main-content",
|
|
3612
|
-
tabIndex:
|
|
3624
|
+
tabIndex: 0,
|
|
3613
3625
|
"data-lock-scroll": lockMainScroll ? "true" : void 0,
|
|
3614
|
-
className:
|
|
3615
|
-
"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",
|
|
3616
3628
|
"suite-app-layout__main",
|
|
3617
3629
|
lockMainScroll ? "overflow-hidden" : "overflow-y-auto"
|
|
3618
3630
|
),
|
|
@@ -3625,6 +3637,1973 @@ function SuiteAppLayout({
|
|
|
3625
3637
|
}
|
|
3626
3638
|
);
|
|
3627
3639
|
}
|
|
3640
|
+
|
|
3641
|
+
// src/suite/components/suite-integration-picker.tsx
|
|
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";
|
|
3657
|
+
var DESCRIPTION_LIMIT = 90;
|
|
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]
|
|
3782
|
+
);
|
|
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) => {
|
|
3788
|
+
var _a;
|
|
3789
|
+
return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a = item.categories) != null ? _a : []).includes(activeCategory));
|
|
3790
|
+
});
|
|
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
|
+
)
|
|
4318
|
+
] }),
|
|
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
|
+
] });
|
|
5606
|
+
}
|
|
3628
5607
|
export {
|
|
3629
5608
|
APP_ACCENTS,
|
|
3630
5609
|
APP_GLYPHS,
|
|
@@ -3651,6 +5630,7 @@ export {
|
|
|
3651
5630
|
SUITE_SIDEBAR_WIDTH_COOKIE,
|
|
3652
5631
|
SUITE_SIDEBAR_WIDTH_KEY,
|
|
3653
5632
|
SUITE_SPRINGS,
|
|
5633
|
+
SUITE_THEME_COOKIE,
|
|
3654
5634
|
SourceAppGlyph,
|
|
3655
5635
|
SuiteAiPanel,
|
|
3656
5636
|
SuiteAppIcon,
|
|
@@ -3658,8 +5638,11 @@ export {
|
|
|
3658
5638
|
SuiteAppStrip,
|
|
3659
5639
|
SuiteBottomNav,
|
|
3660
5640
|
SuiteBreadcrumbs,
|
|
5641
|
+
SuiteClientsProjectsDirectory,
|
|
3661
5642
|
SuiteEmptyState,
|
|
3662
5643
|
SuiteIcon,
|
|
5644
|
+
SuiteIntegrationPicker,
|
|
5645
|
+
SuiteIntegrationRules,
|
|
3663
5646
|
SuiteMobileDrawer,
|
|
3664
5647
|
SuiteMobileHeader,
|
|
3665
5648
|
SuiteMotionProvider,
|
|
@@ -3695,7 +5678,7 @@ export {
|
|
|
3695
5678
|
appSwitcherMenuItemClass,
|
|
3696
5679
|
appSwitcherTriggerClass,
|
|
3697
5680
|
classifySuiteHref,
|
|
3698
|
-
cn,
|
|
5681
|
+
cn2 as cn,
|
|
3699
5682
|
consumePendingAskAiPrompt,
|
|
3700
5683
|
consumeSuiteAskAiOpenFromLocation,
|
|
3701
5684
|
getTodayGreeting,
|
|
@@ -3712,6 +5695,7 @@ export {
|
|
|
3712
5695
|
sourceToSuiteApp,
|
|
3713
5696
|
suiteAppBaseUrl,
|
|
3714
5697
|
suiteAppLabel,
|
|
5698
|
+
suiteThemeBootScript,
|
|
3715
5699
|
useIdleMount,
|
|
3716
5700
|
useSidebarWidth,
|
|
3717
5701
|
useSuiteTheme
|