@xenide-io/the-old-ui-theme 0.9.9 → 0.9.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/suite.js CHANGED
@@ -168,6 +168,7 @@ __export(suite_exports, {
168
168
  SuiteBreadcrumbs: () => SuiteBreadcrumbs,
169
169
  SuiteClientsProjectsDirectory: () => SuiteClientsProjectsDirectory,
170
170
  SuiteEmptyState: () => SuiteEmptyState,
171
+ SuiteEntityIcon: () => SuiteEntityIcon,
171
172
  SuiteIcon: () => SuiteIcon,
172
173
  SuiteIntegrationPicker: () => SuiteIntegrationPicker,
173
174
  SuiteIntegrationRules: () => SuiteIntegrationRules,
@@ -177,6 +178,7 @@ __export(suite_exports, {
177
178
  SuiteNotificationBell: () => SuiteNotificationBell,
178
179
  SuitePage: () => SuitePage,
179
180
  SuitePageHeader: () => SuitePageHeader,
181
+ SuitePaletteLibrary: () => SuitePaletteLibrary,
180
182
  SuiteSectionHeader: () => SuiteSectionHeader,
181
183
  SuiteSettingsLayout: () => SuiteSettingsLayout,
182
184
  SuiteSettingsMobileNav: () => SuiteSettingsMobileNav,
@@ -209,6 +211,9 @@ __export(suite_exports, {
209
211
  cn: () => cn,
210
212
  consumePendingAskAiPrompt: () => consumePendingAskAiPrompt,
211
213
  consumeSuiteAskAiOpenFromLocation: () => consumeSuiteAskAiOpenFromLocation,
214
+ fetchPaletteCollection: () => fetchPaletteCollection,
215
+ fetchPaletteLibrary: () => fetchPaletteLibrary,
216
+ findPaletteIcons: () => findPaletteIcons,
212
217
  getTodayGreeting: () => getTodayGreeting,
213
218
  m: () => import_react15.m,
214
219
  openSuiteAskAi: () => openSuiteAskAi,
@@ -672,13 +677,13 @@ function SuiteAppStrip({
672
677
  ),
673
678
  "aria-label": "ShellStack suite apps",
674
679
  children: SUITE_APPS.map((app) => {
675
- var _a;
680
+ var _a2;
676
681
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
677
682
  "div",
678
683
  {
679
684
  className: "flex items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-2.5 py-1.5 shadow-sm",
680
685
  children: [
681
- (_a = icons == null ? void 0 : icons[app]) != null ? _a : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SuiteAppIcon, { app, size: "sm" }),
686
+ (_a2 = icons == null ? void 0 : icons[app]) != null ? _a2 : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SuiteAppIcon, { app, size: "sm" }),
682
687
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-xs font-medium text-ph-subtle", children: APP_META[app].name })
683
688
  ]
684
689
  },
@@ -797,13 +802,13 @@ function TodayTopBar({
797
802
  ] });
798
803
  }
799
804
  function getTodayGreeting(user, stats) {
800
- var _a, _b, _c, _d, _e;
805
+ var _a2, _b, _c, _d, _e;
801
806
  const hour = (/* @__PURE__ */ new Date()).getHours();
802
807
  let period = "morning";
803
808
  if (hour >= 12 && hour < 17) period = "afternoon";
804
809
  else if (hour >= 17 && hour < 21) period = "evening";
805
810
  else if (hour >= 21 || hour < 5) period = "night";
806
- const name = (user == null ? void 0 : user.first_name) || ((_a = user == null ? void 0 : user.name) == null ? void 0 : _a.split(" ")[0]) || ((_b = user == null ? void 0 : user.email) == null ? void 0 : _b.split("@")[0]) || null;
811
+ const name = (user == null ? void 0 : user.first_name) || ((_a2 = user == null ? void 0 : user.name) == null ? void 0 : _a2.split(" ")[0]) || ((_b = user == null ? void 0 : user.email) == null ? void 0 : _b.split("@")[0]) || null;
807
812
  let greeting = `Good ${period}`;
808
813
  if (name) greeting += `, ${name}`;
809
814
  const taskCount = (_c = stats == null ? void 0 : stats.taskCount) != null ? _c : 0;
@@ -1302,8 +1307,8 @@ var SOURCE_APP_SLUG = {
1302
1307
  shellstack: "shellstack"
1303
1308
  };
1304
1309
  function suiteAppSlugForNotificationSource(sourceApp) {
1305
- var _a;
1306
- return (_a = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a : null;
1310
+ var _a2;
1311
+ return (_a2 = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a2 : null;
1307
1312
  }
1308
1313
  function resolveSuiteNotificationHref(href, sourceApp) {
1309
1314
  const value = (href || "").trim();
@@ -1391,14 +1396,14 @@ function SuiteNotificationBell({
1391
1396
  (0, import_react2.useEffect)(() => {
1392
1397
  if (cacheKey) {
1393
1398
  queueMicrotask(() => {
1394
- var _a;
1399
+ var _a2;
1395
1400
  try {
1396
1401
  const raw = sessionStorage.getItem(cacheKey);
1397
1402
  if (raw) {
1398
1403
  const cached = JSON.parse(raw);
1399
1404
  if (Array.isArray(cached.notifications)) {
1400
1405
  setItems(cached.notifications);
1401
- setUnread((_a = cached.unread_count) != null ? _a : 0);
1406
+ setUnread((_a2 = cached.unread_count) != null ? _a2 : 0);
1402
1407
  }
1403
1408
  }
1404
1409
  } catch (e) {
@@ -1469,9 +1474,9 @@ function SuiteNotificationBell({
1469
1474
  const markAll = (0, import_react2.useCallback)(async () => {
1470
1475
  setItems(
1471
1476
  (prev) => prev.map((i) => {
1472
- var _a;
1477
+ var _a2;
1473
1478
  return __spreadProps(__spreadValues({}, i), {
1474
- read_at: (_a = i.read_at) != null ? _a : (/* @__PURE__ */ new Date()).toISOString()
1479
+ read_at: (_a2 = i.read_at) != null ? _a2 : (/* @__PURE__ */ new Date()).toISOString()
1475
1480
  });
1476
1481
  })
1477
1482
  );
@@ -2087,8 +2092,8 @@ function cn2(...parts) {
2087
2092
 
2088
2093
  // src/components/icons/IconBase.tsx
2089
2094
  var import_jsx_runtime13 = require("react/jsx-runtime");
2090
- var IconBase = (0, import_react7.forwardRef)(function IconBase2(_a, ref) {
2091
- var _b = _a, {
2095
+ var IconBase = (0, import_react7.forwardRef)(function IconBase2(_a2, ref) {
2096
+ var _b = _a2, {
2092
2097
  className,
2093
2098
  size,
2094
2099
  children,
@@ -2503,8 +2508,8 @@ var IconActivity = createIconBasePath(
2503
2508
  var IconFlask = createIconBasePath(
2504
2509
  "M19.8 18.4L14 10.67V6.5l1.35-1.35c.39-.39.39-1.02 0-1.41L14.65 2.7a.9959.9959 0 0 0-1.41 0L9.35 6.54c-.39.39-.39 1.02 0 1.41L10.7 9.3v4.17L4.2 18.4C3.53 19.07 4.04 20.25 5 20.25h14c.96 0 1.47-1.18.8-1.85zM6.91 18.25l5.09-5.09 5.09 5.09H6.91z"
2505
2510
  );
2506
- var IconSpinner = (0, import_react9.forwardRef)(function IconSpinner2(_a, ref) {
2507
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
2511
+ var IconSpinner = (0, import_react9.forwardRef)(function IconSpinner2(_a2, ref) {
2512
+ var _b = _a2, { className } = _b, props = __objRest(_b, ["className"]);
2508
2513
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IconSync, __spreadValues({ ref, className: cn2("ph-icon-spin", className) }, props));
2509
2514
  });
2510
2515
  IconSpinner.displayName = "IconSpinner";
@@ -2603,8 +2608,8 @@ for (const [name, Icon] of Object.entries(CANONICAL_ICONS)) {
2603
2608
  namedIcon.displayName = `Icon${name[0].toUpperCase()}${name.slice(1)}`;
2604
2609
  }
2605
2610
  }
2606
- var IconByName = (0, import_react9.forwardRef)(function IconByName2(_a, ref) {
2607
- var _b = _a, { name } = _b, props = __objRest(_b, ["name"]);
2611
+ var IconByName = (0, import_react9.forwardRef)(function IconByName2(_a2, ref) {
2612
+ var _b = _a2, { name } = _b, props = __objRest(_b, ["name"]);
2608
2613
  const Icon = PH_ICONS[name];
2609
2614
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, __spreadValues({ ref }, props));
2610
2615
  });
@@ -2658,8 +2663,8 @@ function DropdownContent({
2658
2663
  }
2659
2664
  ) });
2660
2665
  }
2661
- function DropdownMenu(_a) {
2662
- var _b = _a, {
2666
+ function DropdownMenu(_a2) {
2667
+ var _b = _a2, {
2663
2668
  trigger,
2664
2669
  triggerId,
2665
2670
  triggerDataTest,
@@ -2734,8 +2739,8 @@ function DropdownMenu(_a) {
2734
2739
  }
2735
2740
  ) }));
2736
2741
  }
2737
- function DropdownItem(_a) {
2738
- var _b = _a, {
2742
+ function DropdownItem(_a2) {
2743
+ var _b = _a2, {
2739
2744
  className,
2740
2745
  children,
2741
2746
  disabled
@@ -2934,7 +2939,7 @@ function SuiteBottomNav({
2934
2939
  children: [
2935
2940
  activeIndex >= 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
2936
2941
  items.map((item) => {
2937
- var _a;
2942
+ var _a2;
2938
2943
  const Icon = item.icon;
2939
2944
  const active = Boolean(item.active);
2940
2945
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
@@ -2942,7 +2947,7 @@ function SuiteBottomNav({
2942
2947
  {
2943
2948
  href: item.href,
2944
2949
  id: item.id,
2945
- "data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
2950
+ "data-test": (_a2 = item.dataTest) != null ? _a2 : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
2946
2951
  "aria-current": active ? "page" : void 0,
2947
2952
  className: cn(
2948
2953
  "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",
@@ -3033,7 +3038,7 @@ var import_react10 = require("react");
3033
3038
 
3034
3039
  // src/suite/lib/cookies.ts
3035
3040
  function suiteCookieDomainAttr() {
3036
- var _a;
3041
+ var _a2;
3037
3042
  const host = window.location.hostname;
3038
3043
  if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
3039
3044
  return "";
@@ -3052,7 +3057,7 @@ function suiteCookieDomainAttr() {
3052
3057
  "portal"
3053
3058
  ]);
3054
3059
  const parts = host.split(".");
3055
- if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
3060
+ if (parts.length >= 3 && known.has((_a2 = parts[0]) != null ? _a2 : "")) {
3056
3061
  return `; Domain=.${parts.slice(1).join(".")}`;
3057
3062
  }
3058
3063
  if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
@@ -3261,10 +3266,10 @@ function useSuiteTheme() {
3261
3266
 
3262
3267
  // src/suite/lib/theme-boot.ts
3263
3268
  function suiteThemeBootScript(options) {
3264
- var _a, _b, _c, _d;
3269
+ var _a2, _b, _c, _d;
3265
3270
  const light = JSON.stringify(options.lightThemeId);
3266
3271
  const dark = JSON.stringify(options.darkThemeId);
3267
- const storageKey = JSON.stringify((_a = options.storageKey) != null ? _a : null);
3272
+ const storageKey = JSON.stringify((_a2 = options.storageKey) != null ? _a2 : null);
3268
3273
  const metaLight = JSON.stringify((_b = options.themeColorLight) != null ? _b : null);
3269
3274
  const metaDark = JSON.stringify((_c = options.themeColorDark) != null ? _c : null);
3270
3275
  const fallback = JSON.stringify((_d = options.fallback) != null ? _d : "light");
@@ -3461,8 +3466,8 @@ function consumeSuiteAskAiOpenFromLocation() {
3461
3466
  }
3462
3467
  var pendingAskAiPrompt = null;
3463
3468
  function openSuiteAskAi(detail) {
3464
- var _a;
3465
- pendingAskAiPrompt = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || null;
3469
+ var _a2;
3470
+ pendingAskAiPrompt = ((_a2 = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a2.trim()) || null;
3466
3471
  if (typeof window === "undefined") return;
3467
3472
  window.dispatchEvent(
3468
3473
  new CustomEvent(SUITE_OPEN_ASK_AI_EVENT, {
@@ -3534,9 +3539,9 @@ function SuiteAiPanel({
3534
3539
  const waiting = loading || isWaitingForReply;
3535
3540
  (0, import_react12.useEffect)(() => {
3536
3541
  function onOpen(event) {
3537
- var _a;
3542
+ var _a2;
3538
3543
  const detail = event.detail;
3539
- const queued = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || consumePendingAskAiPrompt();
3544
+ const queued = ((_a2 = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a2.trim()) || consumePendingAskAiPrompt();
3540
3545
  setOpen(true);
3541
3546
  if (queued) {
3542
3547
  pendingPromptRef.current = queued;
@@ -3559,12 +3564,12 @@ function SuiteAiPanel({
3559
3564
  setAtBottom(distance < 64);
3560
3565
  }, []);
3561
3566
  const hydrate = (0, import_react12.useCallback)(async () => {
3562
- var _a, _b, _c;
3567
+ var _a2, _b, _c;
3563
3568
  setHydrating(true);
3564
3569
  setError("");
3565
3570
  try {
3566
3571
  const data = await fetchChat();
3567
- setMessages((_a = data.messages) != null ? _a : []);
3572
+ setMessages((_a2 = data.messages) != null ? _a2 : []);
3568
3573
  if (!data.configured) {
3569
3574
  setError("ShellStack AI is not configured for this workspace yet.");
3570
3575
  } else {
@@ -3582,9 +3587,9 @@ function SuiteAiPanel({
3582
3587
  }
3583
3588
  }, [fetchChat]);
3584
3589
  (0, import_react12.useEffect)(() => {
3585
- var _a;
3590
+ var _a2;
3586
3591
  if (!open) return;
3587
- const queued = (_a = pendingPromptRef.current) != null ? _a : consumePendingAskAiPrompt();
3592
+ const queued = (_a2 = pendingPromptRef.current) != null ? _a2 : consumePendingAskAiPrompt();
3588
3593
  pendingPromptRef.current = queued;
3589
3594
  void hydrate().then(() => {
3590
3595
  const pending = pendingPromptRef.current;
@@ -3596,8 +3601,8 @@ function SuiteAiPanel({
3596
3601
  if (open && atBottom) scrollToBottom();
3597
3602
  }, [messages, waiting, open, atBottom, scrollToBottom]);
3598
3603
  (0, import_react12.useEffect)(() => {
3599
- var _a;
3600
- if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
3604
+ var _a2;
3605
+ if (open && !hydrating) (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
3601
3606
  }, [open, hydrating]);
3602
3607
  (0, import_react12.useEffect)(() => {
3603
3608
  if (!open) return;
@@ -3611,7 +3616,7 @@ function SuiteAiPanel({
3611
3616
  el.style.height = `${Math.min(el.scrollHeight, 176)}px`;
3612
3617
  }, [prompt, open]);
3613
3618
  async function ask(text) {
3614
- var _a;
3619
+ var _a2;
3615
3620
  const trimmed = text.trim();
3616
3621
  if (!trimmed || waiting) return;
3617
3622
  const controller = new AbortController();
@@ -3627,20 +3632,20 @@ function SuiteAiPanel({
3627
3632
  signal: controller.signal
3628
3633
  });
3629
3634
  if (controller.signal.aborted) return;
3630
- const nextMessages = (_a = result.messages) != null ? _a : [];
3635
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
3631
3636
  setMessages(nextMessages);
3632
3637
  notifySuiteMutated(
3633
3638
  nextMessages.flatMap((message) => {
3634
- var _a2;
3635
- return (_a2 = message.actions) != null ? _a2 : [];
3639
+ var _a3;
3640
+ return (_a3 = message.actions) != null ? _a3 : [];
3636
3641
  })
3637
3642
  );
3638
3643
  } catch (err) {
3639
3644
  if (controller.signal.aborted) return;
3640
3645
  setMessages(
3641
3646
  (prev) => {
3642
- var _a2, _b;
3643
- return ((_a2 = prev[prev.length - 1]) == null ? void 0 : _a2.role) === "user" && ((_b = prev[prev.length - 1]) == null ? void 0 : _b.content) === trimmed ? prev.slice(0, -1) : prev;
3647
+ var _a3, _b;
3648
+ return ((_a3 = prev[prev.length - 1]) == null ? void 0 : _a3.role) === "user" && ((_b = prev[prev.length - 1]) == null ? void 0 : _b.content) === trimmed ? prev.slice(0, -1) : prev;
3644
3649
  }
3645
3650
  );
3646
3651
  setPrompt(trimmed);
@@ -3653,8 +3658,8 @@ function SuiteAiPanel({
3653
3658
  }
3654
3659
  }
3655
3660
  function stop() {
3656
- var _a;
3657
- (_a = abortRef.current) == null ? void 0 : _a.abort();
3661
+ var _a2;
3662
+ (_a2 = abortRef.current) == null ? void 0 : _a2.abort();
3658
3663
  abortRef.current = null;
3659
3664
  setLoading(false);
3660
3665
  if (!cancelMessage) return;
@@ -3664,14 +3669,14 @@ function SuiteAiPanel({
3664
3669
  });
3665
3670
  }
3666
3671
  function retry() {
3667
- var _a;
3668
- const lastUser = (_a = [...messages].reverse().find((message) => message.role === "user")) == null ? void 0 : _a.content;
3672
+ var _a2;
3673
+ const lastUser = (_a2 = [...messages].reverse().find((message) => message.role === "user")) == null ? void 0 : _a2.content;
3669
3674
  setError("");
3670
3675
  if (lastUser) void ask(lastUser);
3671
3676
  else void hydrate();
3672
3677
  }
3673
3678
  async function saveEdit(index) {
3674
- var _a;
3679
+ var _a2;
3675
3680
  const trimmed = editDraft.trim();
3676
3681
  if (!trimmed || waiting) return;
3677
3682
  setEditingIndex(null);
@@ -3689,12 +3694,12 @@ function SuiteAiPanel({
3689
3694
  signal: controller.signal
3690
3695
  }) : await sendMessage({ prompt: trimmed, signal: controller.signal });
3691
3696
  if (controller.signal.aborted) return;
3692
- const nextMessages = (_a = result.messages) != null ? _a : [];
3697
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
3693
3698
  setMessages(nextMessages);
3694
3699
  notifySuiteMutated(
3695
3700
  nextMessages.flatMap((message) => {
3696
- var _a2;
3697
- return (_a2 = message.actions) != null ? _a2 : [];
3701
+ var _a3;
3702
+ return (_a3 = message.actions) != null ? _a3 : [];
3698
3703
  })
3699
3704
  );
3700
3705
  } catch (err) {
@@ -3732,18 +3737,18 @@ function SuiteAiPanel({
3732
3737
  }
3733
3738
  }
3734
3739
  async function handleResolve(actionId, decision) {
3735
- var _a;
3740
+ var _a2;
3736
3741
  if (!resolveAction || resolvingId) return;
3737
3742
  setResolvingId(actionId);
3738
3743
  setError("");
3739
3744
  try {
3740
3745
  const result = await resolveAction(actionId, decision);
3741
- const nextMessages = (_a = result.messages) != null ? _a : [];
3746
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
3742
3747
  setMessages(nextMessages);
3743
3748
  notifySuiteMutated(
3744
3749
  nextMessages.flatMap((message) => {
3745
- var _a2;
3746
- return (_a2 = message.actions) != null ? _a2 : [];
3750
+ var _a3;
3751
+ return (_a3 = message.actions) != null ? _a3 : [];
3747
3752
  })
3748
3753
  );
3749
3754
  } catch (err) {
@@ -3755,12 +3760,12 @@ function SuiteAiPanel({
3755
3760
  }
3756
3761
  }
3757
3762
  function onConversationClick(event) {
3758
- var _a;
3763
+ var _a2;
3759
3764
  if (event.defaultPrevented) return;
3760
3765
  if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
3761
3766
  return;
3762
3767
  }
3763
- const anchor = (_a = event.target) == null ? void 0 : _a.closest("a");
3768
+ const anchor = (_a2 = event.target) == null ? void 0 : _a2.closest("a");
3764
3769
  if (!anchor || !suiteAppBases) return;
3765
3770
  const href = anchor.href;
3766
3771
  if (!href) return;
@@ -3848,7 +3853,7 @@ function SuiteAiPanel({
3848
3853
  )) }) : null
3849
3854
  ] }) : null,
3850
3855
  messages.map((message, index) => {
3851
- var _a;
3856
+ var _a2;
3852
3857
  const isUser = message.role === "user";
3853
3858
  if (isUser) {
3854
3859
  if (editingIndex === index) {
@@ -3981,7 +3986,7 @@ function SuiteAiPanel({
3981
3986
  )
3982
3987
  }
3983
3988
  ) }),
3984
- ((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3989
+ ((_a2 = message.actions) != null ? _a2 : []).map((action) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3985
3990
  "div",
3986
3991
  {
3987
3992
  "data-test": "ask-ai-action",
@@ -4107,7 +4112,7 @@ function SuiteAiPanel({
4107
4112
  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"
4108
4113
  }
4109
4114
  ),
4110
- loading ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4115
+ waiting ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4111
4116
  "button",
4112
4117
  {
4113
4118
  type: "button",
@@ -4117,16 +4122,7 @@ function SuiteAiPanel({
4117
4122
  "aria-label": "Stop generating",
4118
4123
  children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_iconoir_react8.Square, { className: "h-3.5 w-3.5 fill-current" })
4119
4124
  }
4120
- ) }) : isWaitingForReply ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4121
- "span",
4122
- {
4123
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-ph-muted text-ph-subtle",
4124
- "data-test": "ask-ai-waiting",
4125
- role: "status",
4126
- "aria-label": "Shelly is responding",
4127
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Spinner, { className: "h-4 w-4 animate-spin" })
4128
- }
4129
- ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: "Send message", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4125
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Tooltip, { content: "Send message", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4130
4126
  "button",
4131
4127
  {
4132
4128
  type: "button",
@@ -4162,9 +4158,9 @@ function SuiteWorkspaceSwitcher({
4162
4158
  triggerDataTest,
4163
4159
  footer
4164
4160
  }) {
4165
- var _a;
4161
+ var _a2;
4166
4162
  const [open, setOpen] = (0, import_react13.useState)(false);
4167
- 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 }] : [];
4163
+ const sections = (_a2 = groups == null ? void 0 : groups.filter((group) => group.workspaces.length > 0)) != null ? _a2 : workspaces.length > 0 ? [{ id: "workspaces", label: "Switch workspace", workspaces }] : [];
4168
4164
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4169
4165
  DropdownMenu2,
4170
4166
  {
@@ -4866,7 +4862,7 @@ function SuiteSidebar({
4866
4862
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "min-h-0 flex-1", children: askAi })
4867
4863
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
4868
4864
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("nav", { "aria-label": "Pages", className: "shrink-0 space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "space-y-1", children: navItems.map((item) => {
4869
- var _a;
4865
+ var _a2;
4870
4866
  const Icon = item.icon;
4871
4867
  const active = Boolean(item.active);
4872
4868
  const link = /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
@@ -4874,7 +4870,7 @@ function SuiteSidebar({
4874
4870
  {
4875
4871
  href: item.href,
4876
4872
  id: item.id,
4877
- "data-test": (_a = item.dataTest) != null ? _a : "nav-link",
4873
+ "data-test": (_a2 = item.dataTest) != null ? _a2 : "nav-link",
4878
4874
  "aria-current": active ? "page" : void 0,
4879
4875
  onClick: item.onClick,
4880
4876
  className: cn(
@@ -5080,8 +5076,8 @@ var shapeClass = {
5080
5076
  square: "ph-btn-square",
5081
5077
  wide: "ph-btn-wide"
5082
5078
  };
5083
- var Button = (0, import_react18.forwardRef)(function Button2(_a, ref) {
5084
- var _b = _a, {
5079
+ var Button = (0, import_react18.forwardRef)(function Button2(_a2, ref) {
5080
+ var _b = _a2, {
5085
5081
  variant = "secondary",
5086
5082
  size = "md",
5087
5083
  shape = "default",
@@ -5158,8 +5154,8 @@ var statusClassMap = {
5158
5154
  warning: "ph-alert-warning",
5159
5155
  danger: "ph-alert-danger"
5160
5156
  };
5161
- var Alert = (0, import_react19.forwardRef)(function Alert2(_a, ref) {
5162
- var _b = _a, {
5157
+ var Alert = (0, import_react19.forwardRef)(function Alert2(_a2, ref) {
5158
+ var _b = _a2, {
5163
5159
  status = "info",
5164
5160
  title,
5165
5161
  description,
@@ -5231,8 +5227,8 @@ var sizeMap = {
5231
5227
  sm: "text-[10px] px-1.5 py-0.5",
5232
5228
  md: ""
5233
5229
  };
5234
- var Badge = (0, import_react20.forwardRef)(function Badge2(_a, ref) {
5235
- var _b = _a, {
5230
+ var Badge = (0, import_react20.forwardRef)(function Badge2(_a2, ref) {
5231
+ var _b = _a2, {
5236
5232
  variant = "neutral",
5237
5233
  size = "md",
5238
5234
  children,
@@ -5269,8 +5265,8 @@ var variantMap2 = {
5269
5265
  elevated: "ph-card-elevated",
5270
5266
  highlighted: "ph-card-highlighted"
5271
5267
  };
5272
- var Card = (0, import_react21.forwardRef)(function Card2(_a, ref) {
5273
- var _b = _a, {
5268
+ var Card = (0, import_react21.forwardRef)(function Card2(_a2, ref) {
5269
+ var _b = _a2, {
5274
5270
  children,
5275
5271
  title,
5276
5272
  description,
@@ -5362,8 +5358,8 @@ var import_iconoir_react11 = require("iconoir-react");
5362
5358
  // src/components/ui/FormField.tsx
5363
5359
  var import_react22 = require("react");
5364
5360
  var import_jsx_runtime36 = require("react/jsx-runtime");
5365
- function FormField(_a) {
5366
- var _b = _a, {
5361
+ function FormField(_a2) {
5362
+ var _b = _a2, {
5367
5363
  controlId,
5368
5364
  label,
5369
5365
  hideLabel = false,
@@ -5423,8 +5419,8 @@ function joinIds(...ids) {
5423
5419
  const value = ids.filter(Boolean).join(" ");
5424
5420
  return value || void 0;
5425
5421
  }
5426
- var Input = (0, import_react23.forwardRef)(function Input2(_a, ref) {
5427
- var _b = _a, {
5422
+ var Input = (0, import_react23.forwardRef)(function Input2(_a2, ref) {
5423
+ var _b = _a2, {
5428
5424
  id: idProp,
5429
5425
  label,
5430
5426
  hideLabel = false,
@@ -5506,8 +5502,8 @@ var Input = (0, import_react23.forwardRef)(function Input2(_a, ref) {
5506
5502
  );
5507
5503
  });
5508
5504
  Input.displayName = "Input";
5509
- var Select = (0, import_react23.forwardRef)(function Select2(_a, ref) {
5510
- var _b = _a, {
5505
+ var Select = (0, import_react23.forwardRef)(function Select2(_a2, ref) {
5506
+ var _b = _a2, {
5511
5507
  id: idProp,
5512
5508
  label,
5513
5509
  hideLabel = false,
@@ -5557,8 +5553,8 @@ var Select = (0, import_react23.forwardRef)(function Select2(_a, ref) {
5557
5553
  ) });
5558
5554
  });
5559
5555
  Select.displayName = "Select";
5560
- var Textarea = (0, import_react23.forwardRef)(function Textarea2(_a, ref) {
5561
- var _b = _a, {
5556
+ var Textarea = (0, import_react23.forwardRef)(function Textarea2(_a2, ref) {
5557
+ var _b = _a2, {
5562
5558
  id: idProp,
5563
5559
  label,
5564
5560
  hideLabel = false,
@@ -5604,8 +5600,8 @@ var Textarea = (0, import_react23.forwardRef)(function Textarea2(_a, ref) {
5604
5600
  ) });
5605
5601
  });
5606
5602
  Textarea.displayName = "Textarea";
5607
- var Checkbox = (0, import_react23.forwardRef)(function Checkbox2(_a, ref) {
5608
- var _b = _a, {
5603
+ var Checkbox = (0, import_react23.forwardRef)(function Checkbox2(_a2, ref) {
5604
+ var _b = _a2, {
5609
5605
  id: idProp,
5610
5606
  label,
5611
5607
  error,
@@ -5659,8 +5655,8 @@ var Checkbox = (0, import_react23.forwardRef)(function Checkbox2(_a, ref) {
5659
5655
  ] });
5660
5656
  });
5661
5657
  Checkbox.displayName = "Checkbox";
5662
- var Radio = (0, import_react23.forwardRef)(function Radio2(_a, ref) {
5663
- var _b = _a, {
5658
+ var Radio = (0, import_react23.forwardRef)(function Radio2(_a2, ref) {
5659
+ var _b = _a2, {
5664
5660
  id: idProp,
5665
5661
  label,
5666
5662
  className,
@@ -5690,8 +5686,8 @@ var Radio = (0, import_react23.forwardRef)(function Radio2(_a, ref) {
5690
5686
  ] });
5691
5687
  });
5692
5688
  Radio.displayName = "Radio";
5693
- var Toggle = (0, import_react23.forwardRef)(function Toggle2(_a, ref) {
5694
- var _b = _a, {
5689
+ var Toggle = (0, import_react23.forwardRef)(function Toggle2(_a2, ref) {
5690
+ var _b = _a2, {
5695
5691
  id: idProp,
5696
5692
  label,
5697
5693
  className,
@@ -5722,8 +5718,8 @@ var Toggle = (0, import_react23.forwardRef)(function Toggle2(_a, ref) {
5722
5718
  ] });
5723
5719
  });
5724
5720
  Toggle.displayName = "Toggle";
5725
- var Range = (0, import_react23.forwardRef)(function Range2(_a, ref) {
5726
- var _b = _a, {
5721
+ var Range = (0, import_react23.forwardRef)(function Range2(_a2, ref) {
5722
+ var _b = _a2, {
5727
5723
  id: idProp,
5728
5724
  label,
5729
5725
  minLabel,
@@ -5753,8 +5749,8 @@ var Range = (0, import_react23.forwardRef)(function Range2(_a, ref) {
5753
5749
  ] });
5754
5750
  });
5755
5751
  Range.displayName = "Range";
5756
- var FileUpload = (0, import_react23.forwardRef)(function FileUpload2(_a, ref) {
5757
- var _b = _a, {
5752
+ var FileUpload = (0, import_react23.forwardRef)(function FileUpload2(_a2, ref) {
5753
+ var _b = _a2, {
5758
5754
  id: idProp,
5759
5755
  label,
5760
5756
  prompt = "Drop file or browse",
@@ -5842,9 +5838,9 @@ function Modal({
5842
5838
  restoreFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
5843
5839
  },
5844
5840
  onCloseAutoFocus: (event) => {
5845
- var _a;
5841
+ var _a2;
5846
5842
  event.preventDefault();
5847
- (_a = restoreFocusRef.current) == null ? void 0 : _a.focus();
5843
+ (_a2 = restoreFocusRef.current) == null ? void 0 : _a2.focus();
5848
5844
  },
5849
5845
  onEscapeKeyDown: (event) => {
5850
5846
  if (!canDismiss || !closeOnEscape) event.preventDefault();
@@ -5913,15 +5909,15 @@ var AUTH_SCHEME_LABELS = {
5913
5909
  OAUTH2: "OAuth 2.0"
5914
5910
  };
5915
5911
  function authSchemeLabel(scheme) {
5916
- var _a;
5912
+ var _a2;
5917
5913
  const normalised = scheme.trim().toUpperCase();
5918
- return (_a = AUTH_SCHEME_LABELS[normalised]) != null ? _a : normalised.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
5914
+ return (_a2 = AUTH_SCHEME_LABELS[normalised]) != null ? _a2 : normalised.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
5919
5915
  }
5920
5916
  function authSchemesFor(item) {
5921
- var _a;
5917
+ var _a2;
5922
5918
  return Array.from(
5923
5919
  new Set(
5924
- ((_a = item.authSchemes) != null ? _a : []).map((scheme) => scheme.trim().toUpperCase()).filter(Boolean)
5920
+ ((_a2 = item.authSchemes) != null ? _a2 : []).map((scheme) => scheme.trim().toUpperCase()).filter(Boolean)
5925
5921
  )
5926
5922
  );
5927
5923
  }
@@ -5944,10 +5940,10 @@ var CATEGORY_APP_AFFINITY = {
5944
5940
  };
5945
5941
  var DEFAULT_APP_AFFINITY = ["tides", "kraken"];
5946
5942
  function suiteAppsForIntegration(categories) {
5947
- var _a;
5943
+ var _a2;
5948
5944
  const apps = /* @__PURE__ */ new Set();
5949
5945
  for (const category of categories != null ? categories : []) {
5950
- for (const app of (_a = CATEGORY_APP_AFFINITY[category.trim().toLowerCase()]) != null ? _a : []) {
5946
+ for (const app of (_a2 = CATEGORY_APP_AFFINITY[category.trim().toLowerCase()]) != null ? _a2 : []) {
5951
5947
  apps.add(app);
5952
5948
  }
5953
5949
  }
@@ -6004,8 +6000,8 @@ function SuiteIntegrationPicker({
6004
6000
  const itemCategories = (0, import_react25.useMemo)(
6005
6001
  () => Array.from(
6006
6002
  new Set(items.flatMap((item) => {
6007
- var _a;
6008
- return (_a = item.categories) != null ? _a : [];
6003
+ var _a2;
6004
+ return (_a2 = item.categories) != null ? _a2 : [];
6009
6005
  }))
6010
6006
  ).sort(),
6011
6007
  [items]
@@ -6015,8 +6011,8 @@ function SuiteIntegrationPicker({
6015
6011
  const activeCategory = controlledCategory != null ? controlledCategory : category;
6016
6012
  const categoryLabel = (value) => value.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
6017
6013
  const filtered = onSearchChange || onCategoryChange ? items : items.filter((item) => {
6018
- var _a;
6019
- return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a = item.categories) != null ? _a : []).includes(activeCategory));
6014
+ var _a2;
6015
+ return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a2 = item.categories) != null ? _a2 : []).includes(activeCategory));
6020
6016
  });
6021
6017
  const visibleCategories = categories.filter(
6022
6018
  (value) => categoryLabel(value).toLowerCase().includes(categoryQuery.trim().toLowerCase())
@@ -6041,7 +6037,7 @@ function SuiteIntegrationPicker({
6041
6037
  closeCategoryMenu(true);
6042
6038
  }
6043
6039
  function moveCategoryFocus(event, value) {
6044
- var _a;
6040
+ var _a2;
6045
6041
  const index = categoryValues.indexOf(value);
6046
6042
  let nextIndex = null;
6047
6043
  if (event.key === "ArrowDown") nextIndex = (index + 1) % categoryValues.length;
@@ -6051,16 +6047,16 @@ function SuiteIntegrationPicker({
6051
6047
  else if (event.key === "End") nextIndex = categoryValues.length - 1;
6052
6048
  if (nextIndex === null) return;
6053
6049
  event.preventDefault();
6054
- (_a = categoryOptionRefs.current[categoryValues[nextIndex]]) == null ? void 0 : _a.focus();
6050
+ (_a2 = categoryOptionRefs.current[categoryValues[nextIndex]]) == null ? void 0 : _a2.focus();
6055
6051
  }
6056
6052
  function handleCategoryTriggerKeyDown(event) {
6057
- var _a;
6053
+ var _a2;
6058
6054
  if (event.key === "ArrowDown") {
6059
6055
  event.preventDefault();
6060
6056
  openCategoryMenu(activeCategory === "all" ? "all" : activeCategory);
6061
6057
  } else if (event.key === "ArrowUp") {
6062
6058
  event.preventDefault();
6063
- openCategoryMenu((_a = categoryValues.at(-1)) != null ? _a : "all");
6059
+ openCategoryMenu((_a2 = categoryValues.at(-1)) != null ? _a2 : "all");
6064
6060
  } else if (event.key === "Enter" || event.key === " ") {
6065
6061
  event.preventDefault();
6066
6062
  openCategoryMenu("search");
@@ -6078,7 +6074,7 @@ function SuiteIntegrationPicker({
6078
6074
  resetAuthForm();
6079
6075
  }
6080
6076
  async function prepareConnection(item, scheme) {
6081
- var _a;
6077
+ var _a2;
6082
6078
  setMethodItem(null);
6083
6079
  setAuthError(null);
6084
6080
  setConnectionError(null);
@@ -6100,7 +6096,7 @@ function SuiteIntegrationPicker({
6100
6096
  try {
6101
6097
  const details = await onFetchAuthFields(item, scheme);
6102
6098
  if (requestId !== authRequestRef.current) return;
6103
- const resolvedScheme = (_a = details.auth_scheme) != null ? _a : scheme;
6099
+ const resolvedScheme = (_a2 = details.auth_scheme) != null ? _a2 : scheme;
6104
6100
  if (details.managed) {
6105
6101
  setAuthItem(null);
6106
6102
  await onConnect(item, { auth_scheme: resolvedScheme });
@@ -6185,8 +6181,8 @@ function SuiteIntegrationPicker({
6185
6181
  (0, import_react25.useEffect)(() => {
6186
6182
  if (!categoryMenuOpen) return;
6187
6183
  const handlePointerDown = (event) => {
6188
- var _a;
6189
- if (!((_a = categoryMenuRef.current) == null ? void 0 : _a.contains(event.target))) {
6184
+ var _a2;
6185
+ if (!((_a2 = categoryMenuRef.current) == null ? void 0 : _a2.contains(event.target))) {
6190
6186
  closeCategoryMenu();
6191
6187
  }
6192
6188
  };
@@ -6201,11 +6197,11 @@ function SuiteIntegrationPicker({
6201
6197
  };
6202
6198
  }, [categoryMenuOpen]);
6203
6199
  (0, import_react25.useEffect)(() => {
6204
- var _a, _b, _c;
6200
+ var _a2, _b, _c;
6205
6201
  const target = pendingCategoryFocus.current;
6206
6202
  if (!target) return;
6207
6203
  pendingCategoryFocus.current = null;
6208
- if (target === "trigger") (_a = categoryTriggerRef.current) == null ? void 0 : _a.focus();
6204
+ if (target === "trigger") (_a2 = categoryTriggerRef.current) == null ? void 0 : _a2.focus();
6209
6205
  else if (target === "search") (_b = categorySearchRef.current) == null ? void 0 : _b.focus();
6210
6206
  else (_c = categoryOptionRefs.current[target]) == null ? void 0 : _c.focus();
6211
6207
  }, [activeCategory, categoryMenuOpen, categoryQuery, visibleCategories]);
@@ -6318,10 +6314,10 @@ function SuiteIntegrationPicker({
6318
6314
  placeholder: "Search categories...",
6319
6315
  "aria-label": "Search categories",
6320
6316
  onKeyDown: (event) => {
6321
- var _a;
6317
+ var _a2;
6322
6318
  if (event.key === "ArrowDown") {
6323
6319
  event.preventDefault();
6324
- (_a = categoryOptionRefs.current[categoryValues[0]]) == null ? void 0 : _a.focus();
6320
+ (_a2 = categoryOptionRefs.current[categoryValues[0]]) == null ? void 0 : _a2.focus();
6325
6321
  } else if (event.key === "Escape") {
6326
6322
  event.preventDefault();
6327
6323
  closeCategoryMenu(true);
@@ -6384,7 +6380,7 @@ function SuiteIntegrationPicker({
6384
6380
  }
6385
6381
  ) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: [
6386
6382
  filtered.map((item) => {
6387
- var _a, _b;
6383
+ var _a2, _b;
6388
6384
  const isExpanded = expanded === item.id;
6389
6385
  const longDescription = item.description.length > DESCRIPTION_LIMIT;
6390
6386
  const text = isExpanded || !longDescription ? item.description : `${item.description.slice(0, DESCRIPTION_LIMIT).trimEnd()}...`;
@@ -6401,7 +6397,7 @@ function SuiteIntegrationPicker({
6401
6397
  onClick: () => longDescription && setExpanded(isExpanded ? null : item.id),
6402
6398
  "aria-expanded": isExpanded,
6403
6399
  children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "flex items-start gap-3", children: [
6404
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("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__ */ (0, import_jsx_runtime39.jsx)(import_iconoir_react12.EvPlug, { className: "h-5 w-5", "aria-hidden": true }) }),
6400
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-ph-muted text-ph-ink", children: (_a2 = item.icon) != null ? _a2 : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_iconoir_react12.EvPlug, { className: "h-5 w-5", "aria-hidden": true }) }),
6405
6401
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "min-w-0", children: [
6406
6402
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "block truncate font-medium text-ph-ink", children: item.label }),
6407
6403
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "mt-1 block text-xs text-ph-subtle", children: text }),
@@ -6609,12 +6605,12 @@ function SuiteIntegrationPicker({
6609
6605
  }
6610
6606
  ) : null,
6611
6607
  authItem.fields.map((field) => {
6612
- var _a, _b;
6608
+ var _a2, _b;
6613
6609
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
6614
6610
  Input,
6615
6611
  {
6616
6612
  label: field.label,
6617
- type: (_a = field.type) != null ? _a : "password",
6613
+ type: (_a2 = field.type) != null ? _a2 : "password",
6618
6614
  required: true,
6619
6615
  value: (_b = authValues[field.name]) != null ? _b : "",
6620
6616
  onChange: (event) => setAuthValues((current) => __spreadProps(__spreadValues({}, current), {
@@ -6657,8 +6653,8 @@ var ACTION_LABELS = {
6657
6653
  create_suite_notification: "Send a suite notification"
6658
6654
  };
6659
6655
  function actionLabel(actionType) {
6660
- var _a;
6661
- return (_a = ACTION_LABELS[actionType]) != null ? _a : actionType;
6656
+ var _a2;
6657
+ return (_a2 = ACTION_LABELS[actionType]) != null ? _a2 : actionType;
6662
6658
  }
6663
6659
  function formatDateTime(value) {
6664
6660
  if (!value) return "\u2014";
@@ -7046,214 +7042,566 @@ function SuiteIntegrationRules({
7046
7042
  }
7047
7043
 
7048
7044
  // src/suite/components/suite-clients-projects-directory.tsx
7045
+ var import_react28 = require("react");
7046
+ var import_iconoir_react15 = require("iconoir-react");
7047
+
7048
+ // src/suite/lib/palette-api.ts
7049
+ var _a;
7050
+ var PALETTE_URL = ((_a = process.env.NEXT_PUBLIC_PALETTE_URL) != null ? _a : "http://localhost:8010").replace(/\/$/, "");
7051
+ function toQuery(params) {
7052
+ const query = new URLSearchParams();
7053
+ for (const [key, value] of Object.entries(params != null ? params : {})) {
7054
+ if (value !== void 0 && value !== null && value !== "") {
7055
+ query.set(key, String(value));
7056
+ }
7057
+ }
7058
+ return query.toString();
7059
+ }
7060
+ async function paletteGet(path, params) {
7061
+ const suffix = toQuery(params);
7062
+ const response = await fetch(
7063
+ `${PALETTE_URL}${path}${suffix ? `?${suffix}` : ""}`,
7064
+ { headers: { Accept: "application/json" } }
7065
+ );
7066
+ if (!response.ok) {
7067
+ throw new Error(`Palette request failed (${response.status}).`);
7068
+ }
7069
+ return await response.json();
7070
+ }
7071
+ var cache = /* @__PURE__ */ new Map();
7072
+ async function paletteGetCached(path, params, ttlMs) {
7073
+ const key = `${path}?${toQuery(params)}`;
7074
+ const now = Date.now();
7075
+ const hit = cache.get(key);
7076
+ if (hit && hit.expires > now) return hit.value;
7077
+ const value = await paletteGet(path, params);
7078
+ cache.set(key, { expires: now + ttlMs, value });
7079
+ return value;
7080
+ }
7081
+ function fetchPaletteLibrary(options) {
7082
+ return paletteGetCached("/library", options, 5 * 6e4);
7083
+ }
7084
+ function fetchPaletteCollection(slug, options) {
7085
+ return paletteGetCached(
7086
+ `/collections/${slug}`,
7087
+ options,
7088
+ 2 * 6e4
7089
+ );
7090
+ }
7091
+ function findPaletteIcons(options) {
7092
+ return paletteGet("/find", options);
7093
+ }
7094
+ function paletteIconSrc(imageUrl, color) {
7095
+ if (!imageUrl || !color) return imageUrl;
7096
+ if (!imageUrl.includes("/svgrepo/")) return imageUrl;
7097
+ return `${PALETTE_URL}/render?src=${encodeURIComponent(imageUrl)}&color=${encodeURIComponent(color)}`;
7098
+ }
7099
+
7100
+ // src/suite/components/suite-entity-icon.tsx
7101
+ var import_jsx_runtime41 = require("react/jsx-runtime");
7102
+ function SuiteEntityIcon({
7103
+ imageUrl,
7104
+ label,
7105
+ color,
7106
+ className,
7107
+ roundedClass = "rounded-md",
7108
+ style,
7109
+ tinted = false
7110
+ }) {
7111
+ const hasColor = typeof color === "string" && /^#[0-9a-fA-F]{3,8}$/.test(color);
7112
+ const tint = hasColor ? color : null;
7113
+ const neutralBackground = "var(--ph-muted, rgba(127,127,127,0.08))";
7114
+ if (imageUrl) {
7115
+ const src = tinted && tint ? paletteIconSrc(imageUrl, tint) : imageUrl;
7116
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7117
+ "span",
7118
+ {
7119
+ className: cn2(
7120
+ "inline-flex shrink-0 items-center justify-center overflow-hidden leading-none",
7121
+ roundedClass,
7122
+ className
7123
+ ),
7124
+ style: __spreadValues({
7125
+ backgroundColor: tint ? `${tint}18` : neutralBackground
7126
+ }, style),
7127
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("img", { src: src != null ? src : void 0, alt: "", className: "h-full w-full object-cover" })
7128
+ }
7129
+ );
7130
+ }
7131
+ const initial = label == null ? void 0 : label.trim().charAt(0).toUpperCase();
7132
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7133
+ "span",
7134
+ {
7135
+ className: cn2(
7136
+ "inline-flex shrink-0 items-center justify-center font-semibold leading-none",
7137
+ roundedClass,
7138
+ className
7139
+ ),
7140
+ style: __spreadValues({
7141
+ color: tint != null ? tint : "var(--ph-mutedtext)",
7142
+ backgroundColor: tint ? `${tint}18` : neutralBackground
7143
+ }, style),
7144
+ "aria-hidden": "true",
7145
+ children: initial ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-[0.7em]", children: initial }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "block h-1.5 w-1.5 rounded-full bg-current opacity-40" })
7146
+ }
7147
+ );
7148
+ }
7149
+
7150
+ // src/suite/components/suite-palette-library.tsx
7049
7151
  var import_react27 = require("react");
7050
7152
  var import_iconoir_react14 = require("iconoir-react");
7051
- var import_jsx_runtime41 = require("react/jsx-runtime");
7052
- var DEFAULT_ICON = "castle-emblem";
7053
- var DEFAULT_COLOR = "#6366f1";
7054
- var DIRECTORY_ICON_OPTIONS = [
7055
- ["arena", "Arena"],
7056
- ["bridge", "Bridge"],
7057
- ["capitol", "Capitol"],
7058
- ["castle-emblem", "Castle"],
7059
- ["castle-flag", "Castle flag"],
7060
- ["lighthouse", "Lighthouse"],
7061
- ["tower", "Tower"],
7062
- ["wooden-sign", "Sign"],
7063
- ["anvil", "Anvil"],
7064
- ["book", "Book"],
7065
- ["chessboard", "Chessboard"],
7066
- ["cog", "Settings"],
7067
- ["hammer", "Build"],
7068
- ["light-bulb", "Idea"],
7069
- ["microphone", "Communication"],
7070
- ["quill-ink", "Writing"],
7071
- ["scroll-unfurled", "Notes"],
7072
- ["hourglass", "Planning"],
7073
- ["wrench", "Tools"],
7074
- ["archer", "Archer"],
7075
- ["archery-target", "Target"],
7076
- ["axe", "Axe"],
7077
- ["campfire", "Campfire"],
7078
- ["compass", "Compass"],
7079
- ["crossed-swords", "Battle"],
7080
- ["knight-helmet", "Knight"],
7081
- ["mountains", "Mountains"],
7082
- ["shield", "Shield"],
7083
- ["ship-emblem", "Voyage"],
7084
- ["sword", "Sword"],
7085
- ["trophy", "Trophy"],
7086
- ["apple", "Apple"],
7087
- ["butterfly", "Butterfly"],
7088
- ["clover", "Clover"],
7089
- ["dragon", "Dragon"],
7090
- ["fire", "Fire"],
7091
- ["flower", "Flower"],
7092
- ["flowers", "Flowers"],
7093
- ["grass", "Grass"],
7094
- ["leaf", "Leaf"],
7095
- ["pine-tree", "Pine tree"],
7096
- ["sun", "Sun"],
7097
- ["water-drop", "Water"],
7098
- ["aura", "Aura"],
7099
- ["crystal-ball", "Crystal ball"],
7100
- ["diamond", "Diamond"],
7101
- ["explosion", "Explosion"],
7102
- ["fire-symbol", "Fire symbol"],
7103
- ["gem", "Gem"],
7104
- ["lightning-trio", "Lightning"],
7105
- ["potion", "Potion"],
7106
- ["rune-stone", "Rune stone"],
7107
- ["skull", "Skull"],
7108
- ["tentacle", "Tentacle"],
7109
- ["wolf-head", "Wolf"],
7110
- ["anchor", "Anchor"],
7111
- ["beer", "Beer"],
7112
- ["carrot", "Carrot"],
7113
- ["cat", "Cat"],
7114
- ["crown", "Crown"],
7115
- ["gold-bar", "Gold bar"],
7116
- ["helmet", "Helmet"],
7117
- ["key", "Key"],
7118
- ["three-keys", "Keys"]
7153
+ var import_jsx_runtime42 = require("react/jsx-runtime");
7154
+ var PAGE_SIZE = 60;
7155
+ var DISCOVER_LIMIT = 120;
7156
+ var ICON_TYPES = [
7157
+ { value: "all", label: "All types" },
7158
+ { value: "line", label: "Line" },
7159
+ { value: "solid", label: "Solid" },
7160
+ { value: "duotone", label: "Duotone" },
7161
+ { value: "color", label: "Colour" },
7162
+ { value: "mixed", label: "Mixed" }
7119
7163
  ];
7120
- function isDirectoryIcon(value) {
7121
- return DIRECTORY_ICON_OPTIONS.some(([name]) => name === value);
7122
- }
7123
- function DirectoryIconPicker({
7164
+ function FilterSelect({
7165
+ icon: Icon,
7166
+ label,
7124
7167
  value,
7125
- preview,
7126
- onFileChange,
7127
- onClear,
7128
- onChange
7168
+ onChange,
7169
+ children
7129
7170
  }) {
7130
- const iconRefs = (0, import_react27.useRef)({});
7131
- function moveSelection(event, index) {
7132
- var _a;
7133
- let nextIndex = null;
7134
- if (event.key === "ArrowRight" || event.key === "ArrowDown") {
7135
- nextIndex = (index + 1) % DIRECTORY_ICON_OPTIONS.length;
7136
- } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
7137
- nextIndex = (index - 1 + DIRECTORY_ICON_OPTIONS.length) % DIRECTORY_ICON_OPTIONS.length;
7138
- } else if (event.key === "Home") {
7139
- nextIndex = 0;
7140
- } else if (event.key === "End") {
7141
- nextIndex = DIRECTORY_ICON_OPTIONS.length - 1;
7142
- }
7143
- if (nextIndex === null) return;
7144
- event.preventDefault();
7145
- const [nextIcon] = DIRECTORY_ICON_OPTIONS[nextIndex];
7146
- onChange(nextIcon);
7147
- (_a = iconRefs.current[nextIcon]) == null ? void 0 : _a.focus();
7148
- }
7149
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "space-y-2", children: [
7150
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Icon" }),
7151
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7152
- "div",
7171
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "relative", children: [
7172
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7173
+ Icon,
7153
7174
  {
7154
- role: "radiogroup",
7155
- "aria-label": "Icon",
7156
- className: "grid grid-cols-6 gap-1.5 rounded-lg border border-ph-border p-1.5 sm:grid-cols-8",
7157
- children: DIRECTORY_ICON_OPTIONS.map(([name, label], index) => {
7158
- const selected = value === name;
7159
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7160
- "button",
7175
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
7176
+ "aria-hidden": true
7177
+ }
7178
+ ),
7179
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7180
+ "select",
7181
+ {
7182
+ "aria-label": label,
7183
+ value,
7184
+ onChange: (event) => onChange(event.target.value),
7185
+ className: "h-full w-full appearance-none rounded-lg border border-ph-border bg-ph-surface py-2 pl-8 pr-7 text-sm text-ph-ink focus:border-ph-brand focus:outline-none",
7186
+ children
7187
+ }
7188
+ ),
7189
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7190
+ import_iconoir_react14.NavArrowDown,
7191
+ {
7192
+ className: "pointer-events-none absolute right-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-ph-mutedtext",
7193
+ "aria-hidden": true
7194
+ }
7195
+ )
7196
+ ] });
7197
+ }
7198
+ function SuitePaletteLibrary({
7199
+ onPick
7200
+ }) {
7201
+ var _a2, _b;
7202
+ const [collections, setCollections] = (0, import_react27.useState)([]);
7203
+ const [typeFilter, setTypeFilter] = (0, import_react27.useState)("all");
7204
+ const [collectionFilter, setCollectionFilter] = (0, import_react27.useState)("");
7205
+ const [libraryOpen, setLibraryOpen] = (0, import_react27.useState)(false);
7206
+ const [libraryQuery, setLibraryQuery] = (0, import_react27.useState)("");
7207
+ const libraryRef = (0, import_react27.useRef)(null);
7208
+ const [icons, setIcons] = (0, import_react27.useState)([]);
7209
+ const [total, setTotal] = (0, import_react27.useState)(0);
7210
+ const [page, setPage] = (0, import_react27.useState)(1);
7211
+ const [query, setQuery] = (0, import_react27.useState)("");
7212
+ const [loading, setLoading] = (0, import_react27.useState)(true);
7213
+ const [loadingMore, setLoadingMore] = (0, import_react27.useState)(false);
7214
+ const [error, setError] = (0, import_react27.useState)(null);
7215
+ const requestId = (0, import_react27.useRef)(0);
7216
+ const libraryOptions = (0, import_react27.useMemo)(() => {
7217
+ const list = collections.filter(
7218
+ (item) => typeFilter === "all" || item.style === typeFilter
7219
+ );
7220
+ return [...list].sort(
7221
+ (a, b) => Number(b.featured) - Number(a.featured) || a.name.localeCompare(b.name)
7222
+ );
7223
+ }, [collections, typeFilter]);
7224
+ const discoverIcons = (0, import_react27.useMemo)(() => {
7225
+ const seen = /* @__PURE__ */ new Set();
7226
+ const out = [];
7227
+ for (const collection of libraryOptions) {
7228
+ for (const url of collection.preview) {
7229
+ if (seen.has(url)) continue;
7230
+ seen.add(url);
7231
+ out.push({ id: url, name: collection.name, tags: [], url });
7232
+ if (out.length >= DISCOVER_LIMIT) return out;
7233
+ }
7234
+ }
7235
+ return out;
7236
+ }, [libraryOptions]);
7237
+ const loadCollection = (0, import_react27.useCallback)(async (slug, nextPage = 1) => {
7238
+ const id = ++requestId.current;
7239
+ if (nextPage === 1) {
7240
+ setLoading(true);
7241
+ setIcons([]);
7242
+ } else {
7243
+ setLoadingMore(true);
7244
+ }
7245
+ setError(null);
7246
+ try {
7247
+ const detail = await fetchPaletteCollection(slug, {
7248
+ page: nextPage,
7249
+ size: PAGE_SIZE
7250
+ });
7251
+ if (id !== requestId.current) return;
7252
+ setTotal(detail.count);
7253
+ setPage(nextPage);
7254
+ setIcons(
7255
+ (current) => nextPage === 1 ? detail.icons : [...current, ...detail.icons]
7256
+ );
7257
+ } catch (err) {
7258
+ if (id === requestId.current) {
7259
+ setError(err instanceof Error ? err.message : "Could not load icons.");
7260
+ }
7261
+ } finally {
7262
+ if (id === requestId.current) {
7263
+ setLoading(false);
7264
+ setLoadingMore(false);
7265
+ }
7266
+ }
7267
+ }, []);
7268
+ (0, import_react27.useEffect)(() => {
7269
+ let cancelled = false;
7270
+ fetchPaletteLibrary().then((library) => {
7271
+ if (cancelled) return;
7272
+ setCollections(library.collections);
7273
+ }).catch((err) => {
7274
+ if (cancelled) return;
7275
+ setError(err instanceof Error ? err.message : "Could not load the library.");
7276
+ setLoading(false);
7277
+ });
7278
+ return () => {
7279
+ cancelled = true;
7280
+ };
7281
+ }, []);
7282
+ (0, import_react27.useEffect)(() => {
7283
+ if (!collections.length) return;
7284
+ if (collectionFilter && !libraryOptions.some((c) => c.slug === collectionFilter)) {
7285
+ setCollectionFilter("");
7286
+ }
7287
+ }, [libraryOptions, collectionFilter, collections.length]);
7288
+ (0, import_react27.useEffect)(() => {
7289
+ if (query.trim()) return;
7290
+ if (collectionFilter) {
7291
+ void loadCollection(collectionFilter, 1);
7292
+ return;
7293
+ }
7294
+ requestId.current += 1;
7295
+ setLoading(false);
7296
+ setPage(1);
7297
+ setIcons(discoverIcons);
7298
+ setTotal(discoverIcons.length);
7299
+ }, [collectionFilter, query, loadCollection, discoverIcons]);
7300
+ (0, import_react27.useEffect)(() => {
7301
+ const term = query.trim();
7302
+ if (!term) return;
7303
+ const id = ++requestId.current;
7304
+ setLoading(true);
7305
+ setError(null);
7306
+ const handle = setTimeout(async () => {
7307
+ try {
7308
+ const results = await findPaletteIcons({
7309
+ q: term,
7310
+ collection: collectionFilter || void 0,
7311
+ style: typeFilter === "all" ? void 0 : typeFilter,
7312
+ limit: 120
7313
+ });
7314
+ if (id !== requestId.current) return;
7315
+ setTotal(results.total);
7316
+ setPage(1);
7317
+ setIcons(
7318
+ results.results.map((hit) => ({
7319
+ id: `${hit.collection}/${hit.id}`,
7320
+ name: hit.name,
7321
+ tags: hit.tags,
7322
+ url: hit.url
7323
+ }))
7324
+ );
7325
+ } catch (err) {
7326
+ if (id === requestId.current) {
7327
+ setError(err instanceof Error ? err.message : "Search failed.");
7328
+ }
7329
+ } finally {
7330
+ if (id === requestId.current) setLoading(false);
7331
+ }
7332
+ }, 250);
7333
+ return () => clearTimeout(handle);
7334
+ }, [query, collectionFilter, typeFilter]);
7335
+ const searching = Boolean(query.trim());
7336
+ const activeLibrary = (_a2 = collections.find((c) => c.slug === collectionFilter)) != null ? _a2 : null;
7337
+ const filteredLibraries = (0, import_react27.useMemo)(() => {
7338
+ const term = libraryQuery.trim().toLowerCase();
7339
+ if (!term) return libraryOptions;
7340
+ return libraryOptions.filter((c) => c.name.toLowerCase().includes(term));
7341
+ }, [libraryOptions, libraryQuery]);
7342
+ (0, import_react27.useEffect)(() => {
7343
+ if (!libraryOpen) return;
7344
+ const onPointerDown = (event) => {
7345
+ var _a3;
7346
+ if (!((_a3 = libraryRef.current) == null ? void 0 : _a3.contains(event.target))) setLibraryOpen(false);
7347
+ };
7348
+ document.addEventListener("pointerdown", onPointerDown);
7349
+ return () => document.removeEventListener("pointerdown", onPointerDown);
7350
+ }, [libraryOpen]);
7351
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-3", "data-test": "palette-icon-library", children: [
7352
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { ref: libraryRef, className: "space-y-2", children: [
7353
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
7354
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "relative flex-1", children: [
7355
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7356
+ import_iconoir_react14.Search,
7161
7357
  {
7162
- type: "button",
7163
- role: "radio",
7164
- "aria-label": label,
7165
- "aria-checked": selected,
7166
- tabIndex: selected ? 0 : -1,
7167
- title: label,
7168
- onClick: () => onChange(name),
7169
- onKeyDown: (event) => moveSelection(event, index),
7170
- ref: (element) => {
7171
- iconRefs.current[name] = element;
7172
- },
7173
- className: cn2(
7174
- "flex h-9 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink",
7175
- selected && "bg-ph-muted text-ph-ink ring-2 ring-ph-brand ring-inset"
7176
- ),
7177
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7178
- "i",
7358
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
7359
+ "aria-hidden": true
7360
+ }
7361
+ ),
7362
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7363
+ "input",
7364
+ {
7365
+ type: "search",
7366
+ value: query,
7367
+ onChange: (event) => setQuery(event.target.value),
7368
+ placeholder: "Search icons \u2014 handshake, rocket, briefcase\u2026",
7369
+ "aria-label": "Search icons",
7370
+ className: "w-full rounded-lg border border-ph-border bg-ph-surface py-2 pl-8 pr-3 text-sm text-ph-ink placeholder:text-ph-mutedtext focus:border-ph-brand focus:outline-none"
7371
+ }
7372
+ )
7373
+ ] }),
7374
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
7375
+ "button",
7376
+ {
7377
+ type: "button",
7378
+ "aria-haspopup": "listbox",
7379
+ "aria-expanded": libraryOpen,
7380
+ onClick: () => setLibraryOpen((open) => !open),
7381
+ className: "flex items-center gap-2 rounded-lg border border-ph-border bg-ph-surface px-2.5 py-2 text-sm text-ph-ink hover:border-ph-brand focus:outline-none focus-visible:ring-2 focus-visible:ring-ph-brand",
7382
+ children: [
7383
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_iconoir_react14.FilterList, { className: "h-4 w-4 shrink-0 text-ph-mutedtext", "aria-hidden": true }),
7384
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "max-w-[10rem] truncate", children: (_b = activeLibrary == null ? void 0 : activeLibrary.name) != null ? _b : "All libraries" }),
7385
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7386
+ import_iconoir_react14.NavArrowDown,
7179
7387
  {
7180
- className: cn2("ra", `ra-${name}`, "text-base leading-none"),
7388
+ className: cn2(
7389
+ "h-3.5 w-3.5 shrink-0 text-ph-mutedtext transition-transform",
7390
+ libraryOpen && "rotate-180"
7391
+ ),
7181
7392
  "aria-hidden": true
7182
7393
  }
7183
7394
  )
7184
- },
7185
- name
7186
- );
7187
- })
7188
- }
7189
- ),
7190
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "rounded-lg border border-ph-border bg-ph-muted p-2", children: [
7191
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-2 text-sm font-medium text-ph-ink", children: [
7192
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.MediaImagePlus, { className: "h-4 w-4", "aria-hidden": true }),
7193
- " Custom image"
7194
- ] }),
7195
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "mt-1 text-xs text-ph-mutedtext", children: "PNG, JPG, GIF, WebP, or SVG \u2014 max 512 KB." }),
7196
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7197
- FileUpload,
7198
- {
7199
- accept: "image/png,image/jpeg,image/gif,image/webp,image/svg+xml,.svg",
7200
- onChange: (event) => {
7201
- var _a, _b;
7202
- return onFileChange((_b = (_a = event.target.files) == null ? void 0 : _a[0]) != null ? _b : null);
7395
+ ]
7203
7396
  }
7204
- }
7205
- ),
7206
- preview ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "mt-2 flex items-center gap-2", children: [
7207
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7208
- "img",
7397
+ ),
7398
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7399
+ FilterSelect,
7209
7400
  {
7210
- src: preview,
7211
- alt: "",
7212
- className: "h-8 w-8 rounded object-cover"
7401
+ icon: import_iconoir_react14.Filter,
7402
+ label: "Filter by icon type",
7403
+ value: typeFilter,
7404
+ onChange: setTypeFilter,
7405
+ children: ICON_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: type.value, children: type.label }, type.value))
7213
7406
  }
7214
- ),
7215
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7216
- "button",
7407
+ )
7408
+ ] }),
7409
+ libraryOpen ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "rounded-lg border border-ph-border bg-ph-surface p-2", children: [
7410
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "relative mb-2", children: [
7411
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7412
+ import_iconoir_react14.Search,
7413
+ {
7414
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
7415
+ "aria-hidden": true
7416
+ }
7417
+ ),
7418
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7419
+ "input",
7420
+ {
7421
+ type: "search",
7422
+ autoFocus: true,
7423
+ value: libraryQuery,
7424
+ onChange: (event) => setLibraryQuery(event.target.value),
7425
+ placeholder: "Search libraries\u2026",
7426
+ "aria-label": "Search libraries",
7427
+ className: "w-full rounded-md border border-ph-border bg-ph-muted py-1.5 pl-8 pr-3 text-sm text-ph-ink placeholder:text-ph-mutedtext focus:border-ph-brand focus:outline-none"
7428
+ }
7429
+ )
7430
+ ] }),
7431
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
7432
+ "ul",
7217
7433
  {
7218
- type: "button",
7219
- className: "text-xs text-ph-mutedtext hover:text-ph-ink",
7220
- onClick: onClear,
7434
+ role: "listbox",
7435
+ "aria-label": "Libraries",
7436
+ className: "max-h-56 overflow-y-auto",
7221
7437
  children: [
7222
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.Trash, { className: "mr-1 inline h-3.5 w-3.5", "aria-hidden": true }),
7223
- " Remove custom image"
7438
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7439
+ "button",
7440
+ {
7441
+ type: "button",
7442
+ role: "option",
7443
+ "aria-selected": !collectionFilter,
7444
+ onClick: () => {
7445
+ setCollectionFilter("");
7446
+ setLibraryOpen(false);
7447
+ },
7448
+ className: cn2(
7449
+ "flex w-full items-center rounded-md px-2 py-1.5 text-left text-sm",
7450
+ !collectionFilter ? "bg-ph-muted text-ph-ink" : "text-ph-ink hover:bg-ph-muted"
7451
+ ),
7452
+ children: "All libraries"
7453
+ }
7454
+ ) }),
7455
+ filteredLibraries.map((collection) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
7456
+ "button",
7457
+ {
7458
+ type: "button",
7459
+ role: "option",
7460
+ "aria-selected": collectionFilter === collection.slug,
7461
+ onClick: () => {
7462
+ setCollectionFilter(collection.slug);
7463
+ setLibraryOpen(false);
7464
+ },
7465
+ className: cn2(
7466
+ "flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-left text-sm",
7467
+ collectionFilter === collection.slug ? "bg-ph-muted text-ph-ink" : "text-ph-ink hover:bg-ph-muted"
7468
+ ),
7469
+ children: [
7470
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "truncate", children: collection.name }),
7471
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "shrink-0 text-xs text-ph-mutedtext", children: collection.count })
7472
+ ]
7473
+ }
7474
+ ) }, collection.slug)),
7475
+ filteredLibraries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { className: "px-2 py-4 text-center text-sm text-ph-mutedtext", children: "No libraries match." }) : null
7224
7476
  ]
7225
7477
  }
7226
7478
  )
7227
7479
  ] }) : null
7480
+ ] }),
7481
+ error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm text-ph-danger", children: error }) : loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "py-8 text-center text-sm text-ph-mutedtext", children: "Loading icons\u2026" }) : icons.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "py-8 text-center text-sm text-ph-mutedtext", children: "No icons matched. Try another word or filter." }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
7482
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "max-h-[320px] overflow-y-auto rounded-lg border border-ph-border p-2", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "grid grid-cols-6 gap-1.5 sm:grid-cols-8", children: icons.map((icon) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7483
+ "button",
7484
+ {
7485
+ type: "button",
7486
+ onClick: () => onPick({ url: icon.url, name: icon.name }),
7487
+ title: icon.name,
7488
+ "aria-label": `Use ${icon.name}`,
7489
+ className: "flex h-10 items-center justify-center rounded-md border border-transparent p-1.5 hover:border-ph-brand hover:bg-ph-muted",
7490
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7491
+ "img",
7492
+ {
7493
+ src: icon.url,
7494
+ alt: "",
7495
+ loading: "lazy",
7496
+ decoding: "async",
7497
+ className: "h-6 w-6"
7498
+ }
7499
+ )
7500
+ },
7501
+ icon.id
7502
+ )) }) }),
7503
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between text-xs text-ph-mutedtext", children: [
7504
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { children: [
7505
+ icons.length,
7506
+ " of ",
7507
+ total,
7508
+ searching ? " matching" : activeLibrary ? ` in ${activeLibrary.name}` : " across all libraries"
7509
+ ] }),
7510
+ !searching && activeLibrary && icons.length < total ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7511
+ "button",
7512
+ {
7513
+ type: "button",
7514
+ disabled: loadingMore,
7515
+ onClick: () => void loadCollection(activeLibrary.slug, page + 1),
7516
+ className: cn2(
7517
+ "font-medium text-ph-brand hover:underline",
7518
+ loadingMore && "opacity-50"
7519
+ ),
7520
+ children: loadingMore ? "Loading\u2026" : "Load more"
7521
+ }
7522
+ ) : null
7523
+ ] })
7228
7524
  ] })
7229
7525
  ] });
7230
7526
  }
7231
- function DirectoryIcon({
7232
- item
7527
+
7528
+ // src/suite/components/suite-clients-projects-directory.tsx
7529
+ var import_jsx_runtime43 = require("react/jsx-runtime");
7530
+ var DEFAULT_ICON = "";
7531
+ var DEFAULT_COLOR = "#6366f1";
7532
+ function DirectoryIconPicker({
7533
+ preview,
7534
+ label,
7535
+ color,
7536
+ onFileChange,
7537
+ onClear,
7538
+ onBrowse
7233
7539
  }) {
7234
- const icon = item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON;
7235
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7236
- "span",
7237
- {
7238
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-white",
7239
- style: { backgroundColor: item.color || "var(--ph-brand)" },
7240
- children: item.icon_image ? (
7241
- // eslint-disable-next-line @next/next/no-img-element
7242
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7243
- "img",
7540
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "space-y-2", children: [
7541
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Icon" }),
7542
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "rounded-lg border border-ph-border bg-ph-muted p-3", children: [
7543
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-3", children: [
7544
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7545
+ SuiteEntityIcon,
7244
7546
  {
7245
- src: item.icon_image,
7246
- alt: "",
7247
- className: "h-full w-full rounded-lg object-cover"
7547
+ imageUrl: preview,
7548
+ label,
7549
+ color,
7550
+ tinted: true,
7551
+ className: "h-9 w-9 text-base"
7248
7552
  }
7249
- )
7250
- ) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7251
- "i",
7553
+ ),
7554
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "min-w-0 flex-1", children: [
7555
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm font-medium text-ph-ink", children: preview ? "Custom image" : "No icon yet" }),
7556
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-xs text-ph-mutedtext", children: preview ? "Shown on cards and lists." : "Browse the library or upload your own." })
7557
+ ] }),
7558
+ onBrowse ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7559
+ "button",
7560
+ {
7561
+ type: "button",
7562
+ onClick: onBrowse,
7563
+ className: "rounded-md border border-ph-border px-3 py-1.5 text-xs font-medium text-ph-ink hover:border-ph-brand hover:bg-ph-surface",
7564
+ children: "Browse library"
7565
+ }
7566
+ ) : null
7567
+ ] }),
7568
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7569
+ FileUpload,
7570
+ {
7571
+ accept: "image/png,image/jpeg,image/gif,image/webp,image/svg+xml,.svg",
7572
+ onChange: (event) => {
7573
+ var _a2, _b;
7574
+ return onFileChange((_b = (_a2 = event.target.files) == null ? void 0 : _a2[0]) != null ? _b : null);
7575
+ }
7576
+ }
7577
+ ) }),
7578
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7579
+ "button",
7252
7580
  {
7253
- className: cn2("ra", `ra-${icon}`, "text-base leading-none"),
7254
- "aria-hidden": true
7581
+ type: "button",
7582
+ className: "mt-2 inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-ph-mutedtext hover:bg-ph-surface hover:text-ph-ink",
7583
+ onClick: onClear,
7584
+ children: [
7585
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.Trash, { className: "h-3.5 w-3.5", "aria-hidden": true }),
7586
+ " Remove image"
7587
+ ]
7255
7588
  }
7256
- )
7589
+ ) : null
7590
+ ] })
7591
+ ] });
7592
+ }
7593
+ function DirectoryIcon({
7594
+ item
7595
+ }) {
7596
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7597
+ SuiteEntityIcon,
7598
+ {
7599
+ imageUrl: item.icon_image,
7600
+ label: item.name,
7601
+ color: item.color,
7602
+ tinted: true,
7603
+ className: "h-8 w-8 text-sm",
7604
+ roundedClass: "rounded-lg"
7257
7605
  }
7258
7606
  );
7259
7607
  }
@@ -7269,51 +7617,53 @@ function SuiteClientsProjectsDirectory({
7269
7617
  onCreateProject,
7270
7618
  onUpdateProject,
7271
7619
  onDeleteProject,
7620
+ renderIconLibrary,
7272
7621
  dataTest = "suite-clients-projects-directory"
7273
7622
  }) {
7274
- var _a;
7275
- const [query, setQuery] = (0, import_react27.useState)("");
7276
- const [selectedClientId, setSelectedClientId] = (0, import_react27.useState)(null);
7277
- const [mobileDetail, setMobileDetail] = (0, import_react27.useState)(false);
7278
- const [editing, setEditing] = (0, import_react27.useState)(null);
7279
- const [draft, setDraft] = (0, import_react27.useState)({
7623
+ var _a2;
7624
+ const [query, setQuery] = (0, import_react28.useState)("");
7625
+ const [selectedClientId, setSelectedClientId] = (0, import_react28.useState)(null);
7626
+ const [mobileDetail, setMobileDetail] = (0, import_react28.useState)(false);
7627
+ const [editing, setEditing] = (0, import_react28.useState)(null);
7628
+ const [draft, setDraft] = (0, import_react28.useState)({
7280
7629
  name: "",
7281
7630
  icon: DEFAULT_ICON,
7282
7631
  color: DEFAULT_COLOR
7283
7632
  });
7284
- const [draftClientId, setDraftClientId] = (0, import_react27.useState)(null);
7285
- const [preview, setPreview] = (0, import_react27.useState)(null);
7286
- const [draftArchived, setDraftArchived] = (0, import_react27.useState)(false);
7287
- const [confirming, setConfirming] = (0, import_react27.useState)(null);
7288
- const [saving, setSaving] = (0, import_react27.useState)(false);
7289
- const [mutationError, setMutationError] = (0, import_react27.useState)(null);
7290
- const clientButtonRefs = (0, import_react27.useRef)({});
7291
- const backToClientsRef = (0, import_react27.useRef)(null);
7292
- const mobileFocusTarget = (0, import_react27.useRef)(null);
7293
- (0, import_react27.useEffect)(() => {
7294
- var _a2, _b;
7633
+ const [draftClientId, setDraftClientId] = (0, import_react28.useState)(null);
7634
+ const [preview, setPreview] = (0, import_react28.useState)(null);
7635
+ const [libraryOpen, setLibraryOpen] = (0, import_react28.useState)(false);
7636
+ const [draftArchived, setDraftArchived] = (0, import_react28.useState)(false);
7637
+ const [confirming, setConfirming] = (0, import_react28.useState)(null);
7638
+ const [saving, setSaving] = (0, import_react28.useState)(false);
7639
+ const [mutationError, setMutationError] = (0, import_react28.useState)(null);
7640
+ const clientButtonRefs = (0, import_react28.useRef)({});
7641
+ const backToClientsRef = (0, import_react28.useRef)(null);
7642
+ const mobileFocusTarget = (0, import_react28.useRef)(null);
7643
+ (0, import_react28.useEffect)(() => {
7644
+ var _a3, _b;
7295
7645
  if (selectedClientId && clients.some((client) => client.id === selectedClientId))
7296
7646
  return;
7297
- setSelectedClientId((_b = (_a2 = clients[0]) == null ? void 0 : _a2.id) != null ? _b : null);
7647
+ setSelectedClientId((_b = (_a3 = clients[0]) == null ? void 0 : _a3.id) != null ? _b : null);
7298
7648
  }, [clients, selectedClientId]);
7299
- (0, import_react27.useEffect)(() => {
7300
- var _a2, _b;
7649
+ (0, import_react28.useEffect)(() => {
7650
+ var _a3, _b;
7301
7651
  const target = mobileFocusTarget.current;
7302
7652
  if (!target) return;
7303
7653
  mobileFocusTarget.current = null;
7304
- if (target === "detail") (_a2 = backToClientsRef.current) == null ? void 0 : _a2.focus();
7654
+ if (target === "detail") (_a3 = backToClientsRef.current) == null ? void 0 : _a3.focus();
7305
7655
  else if (selectedClientId)
7306
7656
  (_b = clientButtonRefs.current[selectedClientId]) == null ? void 0 : _b.focus();
7307
7657
  }, [mobileDetail, selectedClientId]);
7308
- const filteredClients = (0, import_react27.useMemo)(() => {
7658
+ const filteredClients = (0, import_react28.useMemo)(() => {
7309
7659
  const value = query.trim().toLowerCase();
7310
7660
  return [...clients].sort((a, b) => a.name.localeCompare(b.name)).filter((client) => !value || client.name.toLowerCase().includes(value));
7311
7661
  }, [clients, query]);
7312
- const selectedClient = (_a = clients.find((client) => client.id === selectedClientId)) != null ? _a : null;
7662
+ const selectedClient = (_a2 = clients.find((client) => client.id === selectedClientId)) != null ? _a2 : null;
7313
7663
  const selectedProjects = projects.filter((project) => project.clientId === selectedClientId).sort((a, b) => a.name.localeCompare(b.name));
7314
7664
  function isMobileDirectoryView() {
7315
- var _a2, _b;
7316
- return (_b = (_a2 = window.matchMedia) == null ? void 0 : _a2.call(window, "(max-width: 1023px)").matches) != null ? _b : false;
7665
+ var _a3, _b;
7666
+ return (_b = (_a3 = window.matchMedia) == null ? void 0 : _a3.call(window, "(max-width: 1023px)").matches) != null ? _b : false;
7317
7667
  }
7318
7668
  function selectClient(client) {
7319
7669
  setSelectedClientId(client.id);
@@ -7321,7 +7671,7 @@ function SuiteClientsProjectsDirectory({
7321
7671
  if (isMobileDirectoryView()) mobileFocusTarget.current = "detail";
7322
7672
  }
7323
7673
  function moveClientSelection(event, index) {
7324
- var _a2;
7674
+ var _a3;
7325
7675
  let nextIndex = null;
7326
7676
  if (event.key === "ArrowDown") {
7327
7677
  nextIndex = (index + 1) % filteredClients.length;
@@ -7336,7 +7686,7 @@ function SuiteClientsProjectsDirectory({
7336
7686
  event.preventDefault();
7337
7687
  const client = filteredClients[nextIndex];
7338
7688
  selectClient(client);
7339
- if (!isMobileDirectoryView()) (_a2 = clientButtonRefs.current[client.id]) == null ? void 0 : _a2.focus();
7689
+ if (!isMobileDirectoryView()) (_a3 = clientButtonRefs.current[client.id]) == null ? void 0 : _a3.focus();
7340
7690
  }
7341
7691
  function openNew(kind) {
7342
7692
  setMutationError(null);
@@ -7345,6 +7695,7 @@ function SuiteClientsProjectsDirectory({
7345
7695
  icon: DEFAULT_ICON,
7346
7696
  color: DEFAULT_COLOR,
7347
7697
  iconImageFile: null,
7698
+ iconImageUrl: null,
7348
7699
  clearIconImage: false
7349
7700
  });
7350
7701
  setPreview(null);
@@ -7353,13 +7704,14 @@ function SuiteClientsProjectsDirectory({
7353
7704
  setEditing({ kind: kind === "client" ? "new-client" : "new-project" });
7354
7705
  }
7355
7706
  function openEdit(item, kind) {
7356
- var _a2;
7707
+ var _a3, _b;
7357
7708
  setMutationError(null);
7358
7709
  setDraft({
7359
7710
  name: item.name,
7360
- icon: item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON,
7711
+ icon: (_a3 = item.icon) != null ? _a3 : DEFAULT_ICON,
7361
7712
  color: item.color || DEFAULT_COLOR,
7362
7713
  iconImageFile: null,
7714
+ iconImageUrl: null,
7363
7715
  clearIconImage: false
7364
7716
  });
7365
7717
  setPreview(item.icon_image || null);
@@ -7367,7 +7719,7 @@ function SuiteClientsProjectsDirectory({
7367
7719
  kind === "project" && Boolean(item.isArchived)
7368
7720
  );
7369
7721
  setDraftClientId(
7370
- kind === "project" ? (_a2 = item.clientId) != null ? _a2 : null : null
7722
+ kind === "project" ? (_b = item.clientId) != null ? _b : null : null
7371
7723
  );
7372
7724
  setEditing({ kind, item });
7373
7725
  }
@@ -7381,6 +7733,7 @@ function SuiteClientsProjectsDirectory({
7381
7733
  if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
7382
7734
  setDraft((current) => __spreadProps(__spreadValues({}, current), {
7383
7735
  iconImageFile: file,
7736
+ iconImageUrl: null,
7384
7737
  clearIconImage: false
7385
7738
  }));
7386
7739
  setPreview(URL.createObjectURL(file));
@@ -7390,9 +7743,21 @@ function SuiteClientsProjectsDirectory({
7390
7743
  setPreview(null);
7391
7744
  setDraft((current) => __spreadProps(__spreadValues({}, current), {
7392
7745
  iconImageFile: null,
7746
+ iconImageUrl: null,
7393
7747
  clearIconImage: true
7394
7748
  }));
7395
7749
  }
7750
+ function pickFromLibrary(icon) {
7751
+ if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
7752
+ setMutationError(null);
7753
+ setPreview(icon.url);
7754
+ setDraft((current) => __spreadProps(__spreadValues({}, current), {
7755
+ iconImageFile: null,
7756
+ iconImageUrl: icon.url,
7757
+ clearIconImage: false
7758
+ }));
7759
+ setLibraryOpen(false);
7760
+ }
7396
7761
  function closeEditor() {
7397
7762
  if (!saving) setEditing(null);
7398
7763
  }
@@ -7428,14 +7793,14 @@ function SuiteClientsProjectsDirectory({
7428
7793
  setConfirming({ item, kind });
7429
7794
  }
7430
7795
  async function toggleArchive(project) {
7431
- var _a2;
7796
+ var _a3, _b;
7432
7797
  if (!onUpdateProject) return;
7433
7798
  try {
7434
7799
  await onUpdateProject(project, {
7435
7800
  name: project.name,
7436
- icon: project.icon && isDirectoryIcon(project.icon) ? project.icon : DEFAULT_ICON,
7801
+ icon: (_a3 = project.icon) != null ? _a3 : DEFAULT_ICON,
7437
7802
  color: project.color || DEFAULT_COLOR,
7438
- clientId: (_a2 = project.clientId) != null ? _a2 : null,
7803
+ clientId: (_b = project.clientId) != null ? _b : null,
7439
7804
  isArchived: !project.isArchived
7440
7805
  });
7441
7806
  } catch (err) {
@@ -7458,10 +7823,10 @@ function SuiteClientsProjectsDirectory({
7458
7823
  );
7459
7824
  }
7460
7825
  }
7461
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { "data-test": dataTest, className: "space-y-3", children: [
7462
- error || mutationError ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Alert, { status: "danger", live: "assertive", children: error || mutationError }) : null,
7463
- loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-ph-mutedtext", children: "Loading directory..." }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("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: [
7464
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7826
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { "data-test": dataTest, className: "space-y-3", children: [
7827
+ error || mutationError ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Alert, { status: "danger", live: "assertive", children: error || mutationError }) : null,
7828
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm text-ph-mutedtext", children: "Loading directory..." }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("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: [
7829
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7465
7830
  "section",
7466
7831
  {
7467
7832
  className: cn2(
@@ -7469,16 +7834,16 @@ function SuiteClientsProjectsDirectory({
7469
7834
  mobileDetail ? "hidden lg:block" : "block"
7470
7835
  ),
7471
7836
  children: [
7472
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex h-14 items-center gap-2 border-b border-ph-border px-3", children: [
7473
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
7474
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7475
- import_iconoir_react14.Search,
7837
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex h-14 items-center gap-2 border-b border-ph-border px-3", children: [
7838
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
7839
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7840
+ import_iconoir_react15.Search,
7476
7841
  {
7477
7842
  className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
7478
7843
  "aria-hidden": true
7479
7844
  }
7480
7845
  ),
7481
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7846
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7482
7847
  Input,
7483
7848
  {
7484
7849
  hideLabel: true,
@@ -7490,18 +7855,18 @@ function SuiteClientsProjectsDirectory({
7490
7855
  }
7491
7856
  )
7492
7857
  ] }),
7493
- canEdit && onCreateClient ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7858
+ canEdit && onCreateClient ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7494
7859
  Button,
7495
7860
  {
7496
7861
  size: "sm",
7497
7862
  variant: "primary",
7498
- icon: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.Plus, { className: "h-4 w-4" }),
7863
+ icon: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.Plus, { className: "h-4 w-4" }),
7499
7864
  onClick: () => openNew("client"),
7500
7865
  children: "New client"
7501
7866
  }
7502
7867
  ) : null
7503
7868
  ] }),
7504
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7869
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7505
7870
  "ul",
7506
7871
  {
7507
7872
  role: "listbox",
@@ -7512,7 +7877,7 @@ function SuiteClientsProjectsDirectory({
7512
7877
  const count = projects.filter(
7513
7878
  (project) => project.clientId === client.id
7514
7879
  ).length;
7515
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7880
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7516
7881
  "button",
7517
7882
  {
7518
7883
  type: "button",
@@ -7529,10 +7894,10 @@ function SuiteClientsProjectsDirectory({
7529
7894
  selected ? "bg-ph-muted" : "hover:bg-ph-canvas"
7530
7895
  ),
7531
7896
  children: [
7532
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(DirectoryIcon, { item: client }),
7533
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "min-w-0 flex-1", children: [
7534
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "block truncate text-sm font-medium text-ph-ink", children: client.name }),
7535
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "text-xs text-ph-mutedtext", children: [
7897
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(DirectoryIcon, { item: client }),
7898
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "min-w-0 flex-1", children: [
7899
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "block truncate text-sm font-medium text-ph-ink", children: client.name }),
7900
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-xs text-ph-mutedtext", children: [
7536
7901
  count,
7537
7902
  " project",
7538
7903
  count === 1 ? "" : "s"
@@ -7541,13 +7906,13 @@ function SuiteClientsProjectsDirectory({
7541
7906
  ]
7542
7907
  }
7543
7908
  ) }, client.id);
7544
- }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: clients.length ? "No matches." : "Add a client to get started." })
7909
+ }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: clients.length ? "No matches." : "Add a client to get started." })
7545
7910
  }
7546
7911
  )
7547
7912
  ]
7548
7913
  }
7549
7914
  ),
7550
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7915
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7551
7916
  "section",
7552
7917
  {
7553
7918
  className: cn2(
@@ -7555,8 +7920,8 @@ function SuiteClientsProjectsDirectory({
7555
7920
  mobileDetail ? "flex" : "hidden lg:flex"
7556
7921
  ),
7557
7922
  children: [
7558
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex min-h-14 items-center gap-2 border-b border-ph-border px-3 py-2", children: selectedClient ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
7559
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7923
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex min-h-14 items-center gap-2 border-b border-ph-border px-3 py-2", children: selectedClient ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
7924
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7560
7925
  "button",
7561
7926
  {
7562
7927
  type: "button",
@@ -7567,36 +7932,36 @@ function SuiteClientsProjectsDirectory({
7567
7932
  setMobileDetail(false);
7568
7933
  },
7569
7934
  "aria-label": "Back to clients",
7570
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.ArrowLeft, { className: "h-4 w-4" })
7935
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.ArrowLeft, { className: "h-4 w-4" })
7571
7936
  }
7572
7937
  ),
7573
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(DirectoryIcon, { item: selectedClient }),
7574
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "min-w-0 flex-1", children: [
7575
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h3", { className: "truncate text-sm font-semibold text-ph-ink", children: selectedClient.name }),
7576
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("p", { className: "text-xs text-ph-mutedtext", children: [
7938
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(DirectoryIcon, { item: selectedClient }),
7939
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "min-w-0 flex-1", children: [
7940
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h3", { className: "truncate text-sm font-semibold text-ph-ink", children: selectedClient.name }),
7941
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "text-xs text-ph-mutedtext", children: [
7577
7942
  selectedProjects.length,
7578
7943
  " project",
7579
7944
  selectedProjects.length === 1 ? "" : "s"
7580
7945
  ] })
7581
7946
  ] }),
7582
- canEdit && (onUpdateClient || onDeleteClient) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7947
+ canEdit && (onUpdateClient || onDeleteClient) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7583
7948
  DropdownMenu,
7584
7949
  {
7585
7950
  "aria-label": `Actions for ${selectedClient.name}`,
7586
7951
  align: "end",
7587
- trigger: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("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: [
7588
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.MoreHoriz, { className: "h-4 w-4", "aria-hidden": true }),
7589
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "sr-only", children: "Client actions" })
7952
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("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: [
7953
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.MoreHoriz, { className: "h-4 w-4", "aria-hidden": true }),
7954
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "sr-only", children: "Client actions" })
7590
7955
  ] }),
7591
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "p-1", children: [
7592
- onUpdateClient ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7956
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "p-1", children: [
7957
+ onUpdateClient ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7593
7958
  DropdownItem,
7594
7959
  {
7595
7960
  onClick: () => openEdit(selectedClient, "client"),
7596
7961
  children: "Edit client"
7597
7962
  }
7598
7963
  ) : null,
7599
- onDeleteClient ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7964
+ onDeleteClient ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7600
7965
  DropdownItem,
7601
7966
  {
7602
7967
  className: "text-red-600",
@@ -7607,32 +7972,32 @@ function SuiteClientsProjectsDirectory({
7607
7972
  ] })
7608
7973
  }
7609
7974
  ) }) : null
7610
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-ph-mutedtext", children: "Select a client" }) }),
7611
- canEdit && onCreateProject ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "border-b border-ph-border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7975
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm text-ph-mutedtext", children: "Select a client" }) }),
7976
+ canEdit && onCreateProject ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "border-b border-ph-border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7612
7977
  Button,
7613
7978
  {
7614
7979
  variant: "primary",
7615
- icon: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_iconoir_react14.Plus, { className: "h-4 w-4" }),
7980
+ icon: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.Plus, { className: "h-4 w-4" }),
7616
7981
  onClick: () => openNew("project"),
7617
7982
  children: "Add project"
7618
7983
  }
7619
7984
  ) }) : null,
7620
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { className: "flex-1 p-2", children: selectedClient && selectedProjects.length ? selectedProjects.map((project) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7985
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "flex-1 p-2", children: selectedClient && selectedProjects.length ? selectedProjects.map((project) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7621
7986
  "div",
7622
7987
  {
7623
7988
  className: "flex items-center gap-3 rounded-lg px-2 py-1 hover:bg-ph-canvas",
7624
7989
  onClick: () => openEdit(project, "project"),
7625
7990
  children: [
7626
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
7991
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7627
7992
  "button",
7628
7993
  {
7629
7994
  type: "button",
7630
7995
  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",
7631
7996
  onClick: () => openEdit(project, "project"),
7632
7997
  children: [
7633
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(DirectoryIcon, { item: project }),
7634
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "min-w-0 flex-1", children: [
7635
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7998
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(DirectoryIcon, { item: project }),
7999
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "min-w-0 flex-1", children: [
8000
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7636
8001
  "span",
7637
8002
  {
7638
8003
  className: cn2(
@@ -7642,36 +8007,36 @@ function SuiteClientsProjectsDirectory({
7642
8007
  children: project.name
7643
8008
  }
7644
8009
  ),
7645
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-xs text-ph-mutedtext", children: project.isArchived ? "Archived" : "Active" })
8010
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-ph-mutedtext", children: project.isArchived ? "Archived" : "Active" })
7646
8011
  ] })
7647
8012
  ]
7648
8013
  }
7649
8014
  ),
7650
- canEdit && (onUpdateProject || onDeleteProject) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8015
+ canEdit && (onUpdateProject || onDeleteProject) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7651
8016
  DropdownMenu,
7652
8017
  {
7653
8018
  "aria-label": `Actions for ${project.name}`,
7654
8019
  align: "end",
7655
- trigger: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("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: [
7656
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7657
- import_iconoir_react14.MoreHoriz,
8020
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("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: [
8021
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8022
+ import_iconoir_react15.MoreHoriz,
7658
8023
  {
7659
8024
  className: "h-4 w-4",
7660
8025
  "aria-hidden": true
7661
8026
  }
7662
8027
  ),
7663
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "sr-only", children: "Project actions" })
8028
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "sr-only", children: "Project actions" })
7664
8029
  ] }),
7665
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "p-1", children: [
7666
- onUpdateProject ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
7667
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8030
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "p-1", children: [
8031
+ onUpdateProject ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
8032
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7668
8033
  DropdownItem,
7669
8034
  {
7670
8035
  onClick: () => openEdit(project, "project"),
7671
8036
  children: "Edit project"
7672
8037
  }
7673
8038
  ),
7674
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8039
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7675
8040
  DropdownItem,
7676
8041
  {
7677
8042
  onClick: () => void toggleArchive(project),
@@ -7679,7 +8044,7 @@ function SuiteClientsProjectsDirectory({
7679
8044
  }
7680
8045
  )
7681
8046
  ] }) : null,
7682
- onDeleteProject ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8047
+ onDeleteProject ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7683
8048
  DropdownItem,
7684
8049
  {
7685
8050
  className: "text-red-600",
@@ -7692,20 +8057,20 @@ function SuiteClientsProjectsDirectory({
7692
8057
  ) }) : null
7693
8058
  ]
7694
8059
  }
7695
- ) }, project.id)) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("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." }) })
8060
+ ) }, project.id)) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("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." }) })
7696
8061
  ]
7697
8062
  }
7698
8063
  )
7699
8064
  ] }),
7700
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8065
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7701
8066
  Modal,
7702
8067
  {
7703
8068
  open: editing !== null,
7704
8069
  onClose: closeEditor,
7705
8070
  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",
7706
- footer: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex justify-end gap-2", children: [
7707
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Button, { variant: "tertiary", onClick: closeEditor, disabled: saving, children: "Cancel" }),
7708
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8071
+ footer: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex justify-end gap-2", children: [
8072
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { variant: "tertiary", onClick: closeEditor, disabled: saving, children: "Cancel" }),
8073
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7709
8074
  Button,
7710
8075
  {
7711
8076
  variant: "primary",
@@ -7715,8 +8080,8 @@ function SuiteClientsProjectsDirectory({
7715
8080
  }
7716
8081
  )
7717
8082
  ] }),
7718
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "space-y-3", children: [
7719
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8083
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "space-y-3", children: [
8084
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7720
8085
  Input,
7721
8086
  {
7722
8087
  label: "Name",
@@ -7725,22 +8090,35 @@ function SuiteClientsProjectsDirectory({
7725
8090
  onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { name: event.target.value }))
7726
8091
  }
7727
8092
  ),
7728
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8093
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7729
8094
  DirectoryIconPicker,
7730
8095
  {
7731
- value: isDirectoryIcon(draft.icon) ? draft.icon : DEFAULT_ICON,
7732
8096
  preview,
8097
+ label: draft.name,
8098
+ color: draft.color,
7733
8099
  onFileChange: chooseImage,
7734
8100
  onClear: clearImage,
7735
- onChange: (icon) => {
7736
- if (preview) clearImage();
7737
- setDraft((current) => __spreadProps(__spreadValues({}, current), { icon }));
7738
- }
8101
+ onBrowse: () => setLibraryOpen(true)
7739
8102
  }
7740
8103
  ),
7741
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
7742
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Colour" }),
7743
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-wrap gap-2", children: [
8104
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { children: [
8105
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Colour" }),
8106
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
8107
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8108
+ "button",
8109
+ {
8110
+ type: "button",
8111
+ "aria-label": "No colour",
8112
+ "aria-pressed": !draft.color,
8113
+ title: "No colour",
8114
+ onClick: () => setDraft(__spreadProps(__spreadValues({}, draft), { color: "" })),
8115
+ className: cn2(
8116
+ "flex h-8 w-8 items-center justify-center rounded-full border border-ph-border bg-ph-surface text-ph-mutedtext ring-offset-2",
8117
+ !draft.color && "ring-2 ring-ph-brand"
8118
+ ),
8119
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.Prohibition, { className: "h-4 w-4", "aria-hidden": true })
8120
+ }
8121
+ ),
7744
8122
  [
7745
8123
  "#6366f1",
7746
8124
  "#0ea5e9",
@@ -7749,7 +8127,7 @@ function SuiteClientsProjectsDirectory({
7749
8127
  "#ef4444",
7750
8128
  "#a855f7",
7751
8129
  "#64748b"
7752
- ].map((color) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8130
+ ].map((color) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7753
8131
  "button",
7754
8132
  {
7755
8133
  type: "button",
@@ -7764,33 +8142,70 @@ function SuiteClientsProjectsDirectory({
7764
8142
  },
7765
8143
  color
7766
8144
  )),
7767
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7768
- Input,
8145
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8146
+ "label",
7769
8147
  {
7770
- hideLabel: true,
7771
- label: "Custom colour",
7772
- type: "color",
7773
- value: draft.color,
7774
- onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { color: event.target.value })),
7775
- className: "h-8 w-8 p-0"
8148
+ className: cn2(
8149
+ "relative inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-full ring-1 ring-ph-border ring-offset-2",
8150
+ ![
8151
+ "#6366f1",
8152
+ "#0ea5e9",
8153
+ "#10b981",
8154
+ "#f59e0b",
8155
+ "#ef4444",
8156
+ "#a855f7",
8157
+ "#64748b"
8158
+ ].includes(draft.color) && "ring-2 ring-ph-brand"
8159
+ ),
8160
+ style: {
8161
+ background: "conic-gradient(from 0deg, #ef4444, #f59e0b, #eab308, #22c55e, #06b6d4, #3b82f6, #8b5cf6, #ec4899, #ef4444)"
8162
+ },
8163
+ title: "Custom colour",
8164
+ children: [
8165
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-ph-surface", children: [
8166
+ "#6366f1",
8167
+ "#0ea5e9",
8168
+ "#10b981",
8169
+ "#f59e0b",
8170
+ "#ef4444",
8171
+ "#a855f7",
8172
+ "#64748b"
8173
+ ].includes(draft.color) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_iconoir_react15.Plus, { className: "h-3 w-3 text-ph-ink", "aria-hidden": true }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8174
+ "span",
8175
+ {
8176
+ className: "h-2.5 w-2.5 rounded-full",
8177
+ style: { backgroundColor: draft.color }
8178
+ }
8179
+ ) }),
8180
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8181
+ "input",
8182
+ {
8183
+ type: "color",
8184
+ "aria-label": "Custom colour",
8185
+ value: draft.color,
8186
+ onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { color: event.target.value })),
8187
+ className: "sr-only"
8188
+ }
8189
+ )
8190
+ ]
7776
8191
  }
7777
8192
  )
7778
8193
  ] })
7779
8194
  ] }),
7780
- (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8195
+ (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
7781
8196
  Select,
7782
8197
  {
7783
8198
  label: "Client",
7784
8199
  value: draftClientId != null ? draftClientId : "",
7785
8200
  onChange: (event) => setDraftClientId(event.target.value || null),
7786
8201
  children: [
7787
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "", children: "No client" }),
7788
- clients.map((client) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: client.id, children: client.name }, client.id))
8202
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "No client" }),
8203
+ clients.map((client) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: client.id, children: client.name }, client.id))
7789
8204
  ]
7790
8205
  }
7791
8206
  ) : null,
7792
- (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "flex items-center gap-2 text-sm text-ph-ink", children: [
7793
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8207
+ (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: "flex items-center gap-2 text-sm text-ph-ink", children: [
8208
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7794
8209
  "input",
7795
8210
  {
7796
8211
  type: "checkbox",
@@ -7803,17 +8218,26 @@ function SuiteClientsProjectsDirectory({
7803
8218
  ] })
7804
8219
  }
7805
8220
  ),
7806
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8221
+ libraryOpen ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8222
+ Modal,
8223
+ {
8224
+ open: true,
8225
+ onClose: () => setLibraryOpen(false),
8226
+ title: "Icon library",
8227
+ children: renderIconLibrary ? renderIconLibrary({ onPick: pickFromLibrary }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SuitePaletteLibrary, { onPick: pickFromLibrary })
8228
+ }
8229
+ ) : null,
8230
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
7807
8231
  Modal,
7808
8232
  {
7809
8233
  open: confirming !== null,
7810
8234
  onClose: () => setConfirming(null),
7811
8235
  title: "Confirm deletion",
7812
- footer: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex justify-end gap-2", children: [
7813
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Button, { variant: "tertiary", onClick: () => setConfirming(null), children: "Cancel" }),
7814
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Button, { variant: "primary", onClick: () => void confirmRemove(), children: "Delete" })
8236
+ footer: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex justify-end gap-2", children: [
8237
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { variant: "tertiary", onClick: () => setConfirming(null), children: "Cancel" }),
8238
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Button, { variant: "primary", onClick: () => void confirmRemove(), children: "Delete" })
7815
8239
  ] }),
7816
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("p", { className: "text-sm text-ph-ink", children: [
8240
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("p", { className: "text-sm text-ph-ink", children: [
7817
8241
  "Delete ",
7818
8242
  confirming == null ? void 0 : confirming.item.name,
7819
8243
  "? This cannot be undone."
@@ -7859,6 +8283,7 @@ function SuiteClientsProjectsDirectory({
7859
8283
  SuiteBreadcrumbs,
7860
8284
  SuiteClientsProjectsDirectory,
7861
8285
  SuiteEmptyState,
8286
+ SuiteEntityIcon,
7862
8287
  SuiteIcon,
7863
8288
  SuiteIntegrationPicker,
7864
8289
  SuiteIntegrationRules,
@@ -7868,6 +8293,7 @@ function SuiteClientsProjectsDirectory({
7868
8293
  SuiteNotificationBell,
7869
8294
  SuitePage,
7870
8295
  SuitePageHeader,
8296
+ SuitePaletteLibrary,
7871
8297
  SuiteSectionHeader,
7872
8298
  SuiteSettingsLayout,
7873
8299
  SuiteSettingsMobileNav,
@@ -7900,6 +8326,9 @@ function SuiteClientsProjectsDirectory({
7900
8326
  cn,
7901
8327
  consumePendingAskAiPrompt,
7902
8328
  consumeSuiteAskAiOpenFromLocation,
8329
+ fetchPaletteCollection,
8330
+ fetchPaletteLibrary,
8331
+ findPaletteIcons,
7903
8332
  getTodayGreeting,
7904
8333
  m,
7905
8334
  openSuiteAskAi,