@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.mjs CHANGED
@@ -465,13 +465,13 @@ function SuiteAppStrip({
465
465
  ),
466
466
  "aria-label": "ShellStack suite apps",
467
467
  children: SUITE_APPS.map((app) => {
468
- var _a;
468
+ var _a2;
469
469
  return /* @__PURE__ */ jsxs4(
470
470
  "div",
471
471
  {
472
472
  className: "flex items-center gap-2 rounded-full border border-ph-border bg-ph-surface px-2.5 py-1.5 shadow-sm",
473
473
  children: [
474
- (_a = icons == null ? void 0 : icons[app]) != null ? _a : /* @__PURE__ */ jsx4(SuiteAppIcon, { app, size: "sm" }),
474
+ (_a2 = icons == null ? void 0 : icons[app]) != null ? _a2 : /* @__PURE__ */ jsx4(SuiteAppIcon, { app, size: "sm" }),
475
475
  /* @__PURE__ */ jsx4("span", { className: "text-xs font-medium text-ph-subtle", children: APP_META[app].name })
476
476
  ]
477
477
  },
@@ -590,13 +590,13 @@ function TodayTopBar({
590
590
  ] });
591
591
  }
592
592
  function getTodayGreeting(user, stats) {
593
- var _a, _b, _c, _d, _e;
593
+ var _a2, _b, _c, _d, _e;
594
594
  const hour = (/* @__PURE__ */ new Date()).getHours();
595
595
  let period = "morning";
596
596
  if (hour >= 12 && hour < 17) period = "afternoon";
597
597
  else if (hour >= 17 && hour < 21) period = "evening";
598
598
  else if (hour >= 21 || hour < 5) period = "night";
599
- 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;
599
+ 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;
600
600
  let greeting = `Good ${period}`;
601
601
  if (name) greeting += `, ${name}`;
602
602
  const taskCount = (_c = stats == null ? void 0 : stats.taskCount) != null ? _c : 0;
@@ -1095,8 +1095,8 @@ var SOURCE_APP_SLUG = {
1095
1095
  shellstack: "shellstack"
1096
1096
  };
1097
1097
  function suiteAppSlugForNotificationSource(sourceApp) {
1098
- var _a;
1099
- return (_a = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a : null;
1098
+ var _a2;
1099
+ return (_a2 = SOURCE_APP_SLUG[(sourceApp || "").toLowerCase()]) != null ? _a2 : null;
1100
1100
  }
1101
1101
  function resolveSuiteNotificationHref(href, sourceApp) {
1102
1102
  const value = (href || "").trim();
@@ -1184,14 +1184,14 @@ function SuiteNotificationBell({
1184
1184
  useEffect(() => {
1185
1185
  if (cacheKey) {
1186
1186
  queueMicrotask(() => {
1187
- var _a;
1187
+ var _a2;
1188
1188
  try {
1189
1189
  const raw = sessionStorage.getItem(cacheKey);
1190
1190
  if (raw) {
1191
1191
  const cached = JSON.parse(raw);
1192
1192
  if (Array.isArray(cached.notifications)) {
1193
1193
  setItems(cached.notifications);
1194
- setUnread((_a = cached.unread_count) != null ? _a : 0);
1194
+ setUnread((_a2 = cached.unread_count) != null ? _a2 : 0);
1195
1195
  }
1196
1196
  }
1197
1197
  } catch (e) {
@@ -1262,9 +1262,9 @@ function SuiteNotificationBell({
1262
1262
  const markAll = useCallback(async () => {
1263
1263
  setItems(
1264
1264
  (prev) => prev.map((i) => {
1265
- var _a;
1265
+ var _a2;
1266
1266
  return __spreadProps(__spreadValues({}, i), {
1267
- read_at: (_a = i.read_at) != null ? _a : (/* @__PURE__ */ new Date()).toISOString()
1267
+ read_at: (_a2 = i.read_at) != null ? _a2 : (/* @__PURE__ */ new Date()).toISOString()
1268
1268
  });
1269
1269
  })
1270
1270
  );
@@ -2047,7 +2047,7 @@ function SuiteBottomNav({
2047
2047
  children: [
2048
2048
  activeIndex >= 0 ? /* @__PURE__ */ jsx14("span", { "aria-hidden": true, className: "suite-bottom-nav__indicator" }) : null,
2049
2049
  items.map((item) => {
2050
- var _a;
2050
+ var _a2;
2051
2051
  const Icon = item.icon;
2052
2052
  const active = Boolean(item.active);
2053
2053
  return /* @__PURE__ */ jsxs12(
@@ -2055,7 +2055,7 @@ function SuiteBottomNav({
2055
2055
  {
2056
2056
  href: item.href,
2057
2057
  id: item.id,
2058
- "data-test": (_a = item.dataTest) != null ? _a : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
2058
+ "data-test": (_a2 = item.dataTest) != null ? _a2 : `suite-nav-${item.label.toLowerCase().replace(/\s+/g, "-")}`,
2059
2059
  "aria-current": active ? "page" : void 0,
2060
2060
  className: cn2(
2061
2061
  "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",
@@ -2154,7 +2154,7 @@ import {
2154
2154
 
2155
2155
  // src/suite/lib/cookies.ts
2156
2156
  function suiteCookieDomainAttr() {
2157
- var _a;
2157
+ var _a2;
2158
2158
  const host = window.location.hostname;
2159
2159
  if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
2160
2160
  return "";
@@ -2173,7 +2173,7 @@ function suiteCookieDomainAttr() {
2173
2173
  "portal"
2174
2174
  ]);
2175
2175
  const parts = host.split(".");
2176
- if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
2176
+ if (parts.length >= 3 && known.has((_a2 = parts[0]) != null ? _a2 : "")) {
2177
2177
  return `; Domain=.${parts.slice(1).join(".")}`;
2178
2178
  }
2179
2179
  if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
@@ -2441,8 +2441,8 @@ function consumeSuiteAskAiOpenFromLocation() {
2441
2441
  }
2442
2442
  var pendingAskAiPrompt = null;
2443
2443
  function openSuiteAskAi(detail) {
2444
- var _a;
2445
- pendingAskAiPrompt = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || null;
2444
+ var _a2;
2445
+ pendingAskAiPrompt = ((_a2 = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a2.trim()) || null;
2446
2446
  if (typeof window === "undefined") return;
2447
2447
  window.dispatchEvent(
2448
2448
  new CustomEvent(SUITE_OPEN_ASK_AI_EVENT, {
@@ -2514,9 +2514,9 @@ function SuiteAiPanel({
2514
2514
  const waiting = loading || isWaitingForReply;
2515
2515
  useEffect7(() => {
2516
2516
  function onOpen(event) {
2517
- var _a;
2517
+ var _a2;
2518
2518
  const detail = event.detail;
2519
- const queued = ((_a = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a.trim()) || consumePendingAskAiPrompt();
2519
+ const queued = ((_a2 = detail == null ? void 0 : detail.prompt) == null ? void 0 : _a2.trim()) || consumePendingAskAiPrompt();
2520
2520
  setOpen(true);
2521
2521
  if (queued) {
2522
2522
  pendingPromptRef.current = queued;
@@ -2539,12 +2539,12 @@ function SuiteAiPanel({
2539
2539
  setAtBottom(distance < 64);
2540
2540
  }, []);
2541
2541
  const hydrate = useCallback3(async () => {
2542
- var _a, _b, _c;
2542
+ var _a2, _b, _c;
2543
2543
  setHydrating(true);
2544
2544
  setError("");
2545
2545
  try {
2546
2546
  const data = await fetchChat();
2547
- setMessages((_a = data.messages) != null ? _a : []);
2547
+ setMessages((_a2 = data.messages) != null ? _a2 : []);
2548
2548
  if (!data.configured) {
2549
2549
  setError("ShellStack AI is not configured for this workspace yet.");
2550
2550
  } else {
@@ -2562,9 +2562,9 @@ function SuiteAiPanel({
2562
2562
  }
2563
2563
  }, [fetchChat]);
2564
2564
  useEffect7(() => {
2565
- var _a;
2565
+ var _a2;
2566
2566
  if (!open) return;
2567
- const queued = (_a = pendingPromptRef.current) != null ? _a : consumePendingAskAiPrompt();
2567
+ const queued = (_a2 = pendingPromptRef.current) != null ? _a2 : consumePendingAskAiPrompt();
2568
2568
  pendingPromptRef.current = queued;
2569
2569
  void hydrate().then(() => {
2570
2570
  const pending = pendingPromptRef.current;
@@ -2576,8 +2576,8 @@ function SuiteAiPanel({
2576
2576
  if (open && atBottom) scrollToBottom();
2577
2577
  }, [messages, waiting, open, atBottom, scrollToBottom]);
2578
2578
  useEffect7(() => {
2579
- var _a;
2580
- if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
2579
+ var _a2;
2580
+ if (open && !hydrating) (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
2581
2581
  }, [open, hydrating]);
2582
2582
  useEffect7(() => {
2583
2583
  if (!open) return;
@@ -2591,7 +2591,7 @@ function SuiteAiPanel({
2591
2591
  el.style.height = `${Math.min(el.scrollHeight, 176)}px`;
2592
2592
  }, [prompt, open]);
2593
2593
  async function ask(text) {
2594
- var _a;
2594
+ var _a2;
2595
2595
  const trimmed = text.trim();
2596
2596
  if (!trimmed || waiting) return;
2597
2597
  const controller = new AbortController();
@@ -2607,20 +2607,20 @@ function SuiteAiPanel({
2607
2607
  signal: controller.signal
2608
2608
  });
2609
2609
  if (controller.signal.aborted) return;
2610
- const nextMessages = (_a = result.messages) != null ? _a : [];
2610
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
2611
2611
  setMessages(nextMessages);
2612
2612
  notifySuiteMutated(
2613
2613
  nextMessages.flatMap((message) => {
2614
- var _a2;
2615
- return (_a2 = message.actions) != null ? _a2 : [];
2614
+ var _a3;
2615
+ return (_a3 = message.actions) != null ? _a3 : [];
2616
2616
  })
2617
2617
  );
2618
2618
  } catch (err) {
2619
2619
  if (controller.signal.aborted) return;
2620
2620
  setMessages(
2621
2621
  (prev) => {
2622
- var _a2, _b;
2623
- 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;
2622
+ var _a3, _b;
2623
+ 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;
2624
2624
  }
2625
2625
  );
2626
2626
  setPrompt(trimmed);
@@ -2633,8 +2633,8 @@ function SuiteAiPanel({
2633
2633
  }
2634
2634
  }
2635
2635
  function stop() {
2636
- var _a;
2637
- (_a = abortRef.current) == null ? void 0 : _a.abort();
2636
+ var _a2;
2637
+ (_a2 = abortRef.current) == null ? void 0 : _a2.abort();
2638
2638
  abortRef.current = null;
2639
2639
  setLoading(false);
2640
2640
  if (!cancelMessage) return;
@@ -2644,14 +2644,14 @@ function SuiteAiPanel({
2644
2644
  });
2645
2645
  }
2646
2646
  function retry() {
2647
- var _a;
2648
- const lastUser = (_a = [...messages].reverse().find((message) => message.role === "user")) == null ? void 0 : _a.content;
2647
+ var _a2;
2648
+ const lastUser = (_a2 = [...messages].reverse().find((message) => message.role === "user")) == null ? void 0 : _a2.content;
2649
2649
  setError("");
2650
2650
  if (lastUser) void ask(lastUser);
2651
2651
  else void hydrate();
2652
2652
  }
2653
2653
  async function saveEdit(index) {
2654
- var _a;
2654
+ var _a2;
2655
2655
  const trimmed = editDraft.trim();
2656
2656
  if (!trimmed || waiting) return;
2657
2657
  setEditingIndex(null);
@@ -2669,12 +2669,12 @@ function SuiteAiPanel({
2669
2669
  signal: controller.signal
2670
2670
  }) : await sendMessage({ prompt: trimmed, signal: controller.signal });
2671
2671
  if (controller.signal.aborted) return;
2672
- const nextMessages = (_a = result.messages) != null ? _a : [];
2672
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
2673
2673
  setMessages(nextMessages);
2674
2674
  notifySuiteMutated(
2675
2675
  nextMessages.flatMap((message) => {
2676
- var _a2;
2677
- return (_a2 = message.actions) != null ? _a2 : [];
2676
+ var _a3;
2677
+ return (_a3 = message.actions) != null ? _a3 : [];
2678
2678
  })
2679
2679
  );
2680
2680
  } catch (err) {
@@ -2712,18 +2712,18 @@ function SuiteAiPanel({
2712
2712
  }
2713
2713
  }
2714
2714
  async function handleResolve(actionId, decision) {
2715
- var _a;
2715
+ var _a2;
2716
2716
  if (!resolveAction || resolvingId) return;
2717
2717
  setResolvingId(actionId);
2718
2718
  setError("");
2719
2719
  try {
2720
2720
  const result = await resolveAction(actionId, decision);
2721
- const nextMessages = (_a = result.messages) != null ? _a : [];
2721
+ const nextMessages = (_a2 = result.messages) != null ? _a2 : [];
2722
2722
  setMessages(nextMessages);
2723
2723
  notifySuiteMutated(
2724
2724
  nextMessages.flatMap((message) => {
2725
- var _a2;
2726
- return (_a2 = message.actions) != null ? _a2 : [];
2725
+ var _a3;
2726
+ return (_a3 = message.actions) != null ? _a3 : [];
2727
2727
  })
2728
2728
  );
2729
2729
  } catch (err) {
@@ -2735,12 +2735,12 @@ function SuiteAiPanel({
2735
2735
  }
2736
2736
  }
2737
2737
  function onConversationClick(event) {
2738
- var _a;
2738
+ var _a2;
2739
2739
  if (event.defaultPrevented) return;
2740
2740
  if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
2741
2741
  return;
2742
2742
  }
2743
- const anchor = (_a = event.target) == null ? void 0 : _a.closest("a");
2743
+ const anchor = (_a2 = event.target) == null ? void 0 : _a2.closest("a");
2744
2744
  if (!anchor || !suiteAppBases) return;
2745
2745
  const href = anchor.href;
2746
2746
  if (!href) return;
@@ -2828,7 +2828,7 @@ function SuiteAiPanel({
2828
2828
  )) }) : null
2829
2829
  ] }) : null,
2830
2830
  messages.map((message, index) => {
2831
- var _a;
2831
+ var _a2;
2832
2832
  const isUser = message.role === "user";
2833
2833
  if (isUser) {
2834
2834
  if (editingIndex === index) {
@@ -2961,7 +2961,7 @@ function SuiteAiPanel({
2961
2961
  )
2962
2962
  }
2963
2963
  ) }),
2964
- ((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */ jsxs14(
2964
+ ((_a2 = message.actions) != null ? _a2 : []).map((action) => /* @__PURE__ */ jsxs14(
2965
2965
  "div",
2966
2966
  {
2967
2967
  "data-test": "ask-ai-action",
@@ -3087,7 +3087,7 @@ function SuiteAiPanel({
3087
3087
  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"
3088
3088
  }
3089
3089
  ),
3090
- loading ? /* @__PURE__ */ jsx17(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ jsx17(
3090
+ waiting ? /* @__PURE__ */ jsx17(Tooltip, { content: "Stop generating", children: /* @__PURE__ */ jsx17(
3091
3091
  "button",
3092
3092
  {
3093
3093
  type: "button",
@@ -3097,16 +3097,7 @@ function SuiteAiPanel({
3097
3097
  "aria-label": "Stop generating",
3098
3098
  children: /* @__PURE__ */ jsx17(Square, { className: "h-3.5 w-3.5 fill-current" })
3099
3099
  }
3100
- ) }) : isWaitingForReply ? /* @__PURE__ */ jsx17(
3101
- "span",
3102
- {
3103
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-ph-muted text-ph-subtle",
3104
- "data-test": "ask-ai-waiting",
3105
- role: "status",
3106
- "aria-label": "Shelly is responding",
3107
- children: /* @__PURE__ */ jsx17(Spinner, { className: "h-4 w-4 animate-spin" })
3108
- }
3109
- ) : /* @__PURE__ */ jsx17(Tooltip, { content: "Send message", children: /* @__PURE__ */ jsx17(
3100
+ ) }) : /* @__PURE__ */ jsx17(Tooltip, { content: "Send message", children: /* @__PURE__ */ jsx17(
3110
3101
  "button",
3111
3102
  {
3112
3103
  type: "button",
@@ -3142,9 +3133,9 @@ function SuiteWorkspaceSwitcher({
3142
3133
  triggerDataTest,
3143
3134
  footer
3144
3135
  }) {
3145
- var _a;
3136
+ var _a2;
3146
3137
  const [open, setOpen] = useState9(false);
3147
- 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 }] : [];
3138
+ 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 }] : [];
3148
3139
  return /* @__PURE__ */ jsx18(
3149
3140
  DropdownMenu2,
3150
3141
  {
@@ -3850,7 +3841,7 @@ function SuiteSidebar({
3850
3841
  /* @__PURE__ */ jsx23("div", { className: "min-h-0 flex-1", children: askAi })
3851
3842
  ] }) : /* @__PURE__ */ jsxs19(Fragment7, { children: [
3852
3843
  /* @__PURE__ */ jsx23("nav", { "aria-label": "Pages", className: "shrink-0 space-y-1", children: /* @__PURE__ */ jsx23("div", { className: "space-y-1", children: navItems.map((item) => {
3853
- var _a;
3844
+ var _a2;
3854
3845
  const Icon = item.icon;
3855
3846
  const active = Boolean(item.active);
3856
3847
  const link = /* @__PURE__ */ jsxs19(
@@ -3858,7 +3849,7 @@ function SuiteSidebar({
3858
3849
  {
3859
3850
  href: item.href,
3860
3851
  id: item.id,
3861
- "data-test": (_a = item.dataTest) != null ? _a : "nav-link",
3852
+ "data-test": (_a2 = item.dataTest) != null ? _a2 : "nav-link",
3862
3853
  "aria-current": active ? "page" : void 0,
3863
3854
  onClick: item.onClick,
3864
3855
  className: cn2(
@@ -4076,15 +4067,15 @@ var AUTH_SCHEME_LABELS = {
4076
4067
  OAUTH2: "OAuth 2.0"
4077
4068
  };
4078
4069
  function authSchemeLabel(scheme) {
4079
- var _a;
4070
+ var _a2;
4080
4071
  const normalised = scheme.trim().toUpperCase();
4081
- return (_a = AUTH_SCHEME_LABELS[normalised]) != null ? _a : normalised.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
4072
+ return (_a2 = AUTH_SCHEME_LABELS[normalised]) != null ? _a2 : normalised.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
4082
4073
  }
4083
4074
  function authSchemesFor(item) {
4084
- var _a;
4075
+ var _a2;
4085
4076
  return Array.from(
4086
4077
  new Set(
4087
- ((_a = item.authSchemes) != null ? _a : []).map((scheme) => scheme.trim().toUpperCase()).filter(Boolean)
4078
+ ((_a2 = item.authSchemes) != null ? _a2 : []).map((scheme) => scheme.trim().toUpperCase()).filter(Boolean)
4088
4079
  )
4089
4080
  );
4090
4081
  }
@@ -4107,10 +4098,10 @@ var CATEGORY_APP_AFFINITY = {
4107
4098
  };
4108
4099
  var DEFAULT_APP_AFFINITY = ["tides", "kraken"];
4109
4100
  function suiteAppsForIntegration(categories) {
4110
- var _a;
4101
+ var _a2;
4111
4102
  const apps = /* @__PURE__ */ new Set();
4112
4103
  for (const category of categories != null ? categories : []) {
4113
- for (const app of (_a = CATEGORY_APP_AFFINITY[category.trim().toLowerCase()]) != null ? _a : []) {
4104
+ for (const app of (_a2 = CATEGORY_APP_AFFINITY[category.trim().toLowerCase()]) != null ? _a2 : []) {
4114
4105
  apps.add(app);
4115
4106
  }
4116
4107
  }
@@ -4167,8 +4158,8 @@ function SuiteIntegrationPicker({
4167
4158
  const itemCategories = useMemo2(
4168
4159
  () => Array.from(
4169
4160
  new Set(items.flatMap((item) => {
4170
- var _a;
4171
- return (_a = item.categories) != null ? _a : [];
4161
+ var _a2;
4162
+ return (_a2 = item.categories) != null ? _a2 : [];
4172
4163
  }))
4173
4164
  ).sort(),
4174
4165
  [items]
@@ -4178,8 +4169,8 @@ function SuiteIntegrationPicker({
4178
4169
  const activeCategory = controlledCategory != null ? controlledCategory : category;
4179
4170
  const categoryLabel = (value) => value.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
4180
4171
  const filtered = onSearchChange || onCategoryChange ? items : items.filter((item) => {
4181
- var _a;
4182
- return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a = item.categories) != null ? _a : []).includes(activeCategory));
4172
+ var _a2;
4173
+ return item.label.toLowerCase().includes(activeSearch.trim().toLowerCase()) && (activeCategory === "all" || ((_a2 = item.categories) != null ? _a2 : []).includes(activeCategory));
4183
4174
  });
4184
4175
  const visibleCategories = categories.filter(
4185
4176
  (value) => categoryLabel(value).toLowerCase().includes(categoryQuery.trim().toLowerCase())
@@ -4204,7 +4195,7 @@ function SuiteIntegrationPicker({
4204
4195
  closeCategoryMenu(true);
4205
4196
  }
4206
4197
  function moveCategoryFocus(event, value) {
4207
- var _a;
4198
+ var _a2;
4208
4199
  const index = categoryValues.indexOf(value);
4209
4200
  let nextIndex = null;
4210
4201
  if (event.key === "ArrowDown") nextIndex = (index + 1) % categoryValues.length;
@@ -4214,16 +4205,16 @@ function SuiteIntegrationPicker({
4214
4205
  else if (event.key === "End") nextIndex = categoryValues.length - 1;
4215
4206
  if (nextIndex === null) return;
4216
4207
  event.preventDefault();
4217
- (_a = categoryOptionRefs.current[categoryValues[nextIndex]]) == null ? void 0 : _a.focus();
4208
+ (_a2 = categoryOptionRefs.current[categoryValues[nextIndex]]) == null ? void 0 : _a2.focus();
4218
4209
  }
4219
4210
  function handleCategoryTriggerKeyDown(event) {
4220
- var _a;
4211
+ var _a2;
4221
4212
  if (event.key === "ArrowDown") {
4222
4213
  event.preventDefault();
4223
4214
  openCategoryMenu(activeCategory === "all" ? "all" : activeCategory);
4224
4215
  } else if (event.key === "ArrowUp") {
4225
4216
  event.preventDefault();
4226
- openCategoryMenu((_a = categoryValues.at(-1)) != null ? _a : "all");
4217
+ openCategoryMenu((_a2 = categoryValues.at(-1)) != null ? _a2 : "all");
4227
4218
  } else if (event.key === "Enter" || event.key === " ") {
4228
4219
  event.preventDefault();
4229
4220
  openCategoryMenu("search");
@@ -4241,7 +4232,7 @@ function SuiteIntegrationPicker({
4241
4232
  resetAuthForm();
4242
4233
  }
4243
4234
  async function prepareConnection(item, scheme) {
4244
- var _a;
4235
+ var _a2;
4245
4236
  setMethodItem(null);
4246
4237
  setAuthError(null);
4247
4238
  setConnectionError(null);
@@ -4263,7 +4254,7 @@ function SuiteIntegrationPicker({
4263
4254
  try {
4264
4255
  const details = await onFetchAuthFields(item, scheme);
4265
4256
  if (requestId !== authRequestRef.current) return;
4266
- const resolvedScheme = (_a = details.auth_scheme) != null ? _a : scheme;
4257
+ const resolvedScheme = (_a2 = details.auth_scheme) != null ? _a2 : scheme;
4267
4258
  if (details.managed) {
4268
4259
  setAuthItem(null);
4269
4260
  await onConnect(item, { auth_scheme: resolvedScheme });
@@ -4348,8 +4339,8 @@ function SuiteIntegrationPicker({
4348
4339
  useEffect9(() => {
4349
4340
  if (!categoryMenuOpen) return;
4350
4341
  const handlePointerDown = (event) => {
4351
- var _a;
4352
- if (!((_a = categoryMenuRef.current) == null ? void 0 : _a.contains(event.target))) {
4342
+ var _a2;
4343
+ if (!((_a2 = categoryMenuRef.current) == null ? void 0 : _a2.contains(event.target))) {
4353
4344
  closeCategoryMenu();
4354
4345
  }
4355
4346
  };
@@ -4364,11 +4355,11 @@ function SuiteIntegrationPicker({
4364
4355
  };
4365
4356
  }, [categoryMenuOpen]);
4366
4357
  useEffect9(() => {
4367
- var _a, _b, _c;
4358
+ var _a2, _b, _c;
4368
4359
  const target = pendingCategoryFocus.current;
4369
4360
  if (!target) return;
4370
4361
  pendingCategoryFocus.current = null;
4371
- if (target === "trigger") (_a = categoryTriggerRef.current) == null ? void 0 : _a.focus();
4362
+ if (target === "trigger") (_a2 = categoryTriggerRef.current) == null ? void 0 : _a2.focus();
4372
4363
  else if (target === "search") (_b = categorySearchRef.current) == null ? void 0 : _b.focus();
4373
4364
  else (_c = categoryOptionRefs.current[target]) == null ? void 0 : _c.focus();
4374
4365
  }, [activeCategory, categoryMenuOpen, categoryQuery, visibleCategories]);
@@ -4481,10 +4472,10 @@ function SuiteIntegrationPicker({
4481
4472
  placeholder: "Search categories...",
4482
4473
  "aria-label": "Search categories",
4483
4474
  onKeyDown: (event) => {
4484
- var _a;
4475
+ var _a2;
4485
4476
  if (event.key === "ArrowDown") {
4486
4477
  event.preventDefault();
4487
- (_a = categoryOptionRefs.current[categoryValues[0]]) == null ? void 0 : _a.focus();
4478
+ (_a2 = categoryOptionRefs.current[categoryValues[0]]) == null ? void 0 : _a2.focus();
4488
4479
  } else if (event.key === "Escape") {
4489
4480
  event.preventDefault();
4490
4481
  closeCategoryMenu(true);
@@ -4547,7 +4538,7 @@ function SuiteIntegrationPicker({
4547
4538
  }
4548
4539
  ) : /* @__PURE__ */ jsxs21("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: [
4549
4540
  filtered.map((item) => {
4550
- var _a, _b;
4541
+ var _a2, _b;
4551
4542
  const isExpanded = expanded === item.id;
4552
4543
  const longDescription = item.description.length > DESCRIPTION_LIMIT;
4553
4544
  const text = isExpanded || !longDescription ? item.description : `${item.description.slice(0, DESCRIPTION_LIMIT).trimEnd()}...`;
@@ -4564,7 +4555,7 @@ function SuiteIntegrationPicker({
4564
4555
  onClick: () => longDescription && setExpanded(isExpanded ? null : item.id),
4565
4556
  "aria-expanded": isExpanded,
4566
4557
  children: /* @__PURE__ */ jsxs21("span", { className: "flex items-start gap-3", children: [
4567
- /* @__PURE__ */ jsx25("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__ */ jsx25(Plug, { className: "h-5 w-5", "aria-hidden": true }) }),
4558
+ /* @__PURE__ */ jsx25("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__ */ jsx25(Plug, { className: "h-5 w-5", "aria-hidden": true }) }),
4568
4559
  /* @__PURE__ */ jsxs21("span", { className: "min-w-0", children: [
4569
4560
  /* @__PURE__ */ jsx25("span", { className: "block truncate font-medium text-ph-ink", children: item.label }),
4570
4561
  /* @__PURE__ */ jsx25("span", { className: "mt-1 block text-xs text-ph-subtle", children: text }),
@@ -4772,12 +4763,12 @@ function SuiteIntegrationPicker({
4772
4763
  }
4773
4764
  ) : null,
4774
4765
  authItem.fields.map((field) => {
4775
- var _a, _b;
4766
+ var _a2, _b;
4776
4767
  return /* @__PURE__ */ jsx25(
4777
4768
  Input,
4778
4769
  {
4779
4770
  label: field.label,
4780
- type: (_a = field.type) != null ? _a : "password",
4771
+ type: (_a2 = field.type) != null ? _a2 : "password",
4781
4772
  required: true,
4782
4773
  value: (_b = authValues[field.name]) != null ? _b : "",
4783
4774
  onChange: (event) => setAuthValues((current) => __spreadProps(__spreadValues({}, current), {
@@ -4820,8 +4811,8 @@ var ACTION_LABELS = {
4820
4811
  create_suite_notification: "Send a suite notification"
4821
4812
  };
4822
4813
  function actionLabel(actionType) {
4823
- var _a;
4824
- return (_a = ACTION_LABELS[actionType]) != null ? _a : actionType;
4814
+ var _a2;
4815
+ return (_a2 = ACTION_LABELS[actionType]) != null ? _a2 : actionType;
4825
4816
  }
4826
4817
  function formatDateTime(value) {
4827
4818
  if (!value) return "\u2014";
@@ -5210,225 +5201,583 @@ function SuiteIntegrationRules({
5210
5201
 
5211
5202
  // src/suite/components/suite-clients-projects-directory.tsx
5212
5203
  import {
5213
- useEffect as useEffect10,
5214
- useMemo as useMemo3,
5215
- useRef as useRef5,
5216
- useState as useState13
5204
+ useEffect as useEffect11,
5205
+ useMemo as useMemo4,
5206
+ useRef as useRef6,
5207
+ useState as useState14
5217
5208
  } from "react";
5218
5209
  import {
5219
5210
  ArrowLeft,
5220
- MediaImagePlus as ImagePlus,
5221
5211
  MoreHoriz as MoreHorizontal,
5222
5212
  Plus as Plus2,
5223
- Search as Search2,
5213
+ Prohibition,
5214
+ Search as Search3,
5224
5215
  Trash
5225
5216
  } from "iconoir-react";
5226
- import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
5227
- var DEFAULT_ICON = "castle-emblem";
5228
- var DEFAULT_COLOR = "#6366f1";
5229
- var DIRECTORY_ICON_OPTIONS = [
5230
- ["arena", "Arena"],
5231
- ["bridge", "Bridge"],
5232
- ["capitol", "Capitol"],
5233
- ["castle-emblem", "Castle"],
5234
- ["castle-flag", "Castle flag"],
5235
- ["lighthouse", "Lighthouse"],
5236
- ["tower", "Tower"],
5237
- ["wooden-sign", "Sign"],
5238
- ["anvil", "Anvil"],
5239
- ["book", "Book"],
5240
- ["chessboard", "Chessboard"],
5241
- ["cog", "Settings"],
5242
- ["hammer", "Build"],
5243
- ["light-bulb", "Idea"],
5244
- ["microphone", "Communication"],
5245
- ["quill-ink", "Writing"],
5246
- ["scroll-unfurled", "Notes"],
5247
- ["hourglass", "Planning"],
5248
- ["wrench", "Tools"],
5249
- ["archer", "Archer"],
5250
- ["archery-target", "Target"],
5251
- ["axe", "Axe"],
5252
- ["campfire", "Campfire"],
5253
- ["compass", "Compass"],
5254
- ["crossed-swords", "Battle"],
5255
- ["knight-helmet", "Knight"],
5256
- ["mountains", "Mountains"],
5257
- ["shield", "Shield"],
5258
- ["ship-emblem", "Voyage"],
5259
- ["sword", "Sword"],
5260
- ["trophy", "Trophy"],
5261
- ["apple", "Apple"],
5262
- ["butterfly", "Butterfly"],
5263
- ["clover", "Clover"],
5264
- ["dragon", "Dragon"],
5265
- ["fire", "Fire"],
5266
- ["flower", "Flower"],
5267
- ["flowers", "Flowers"],
5268
- ["grass", "Grass"],
5269
- ["leaf", "Leaf"],
5270
- ["pine-tree", "Pine tree"],
5271
- ["sun", "Sun"],
5272
- ["water-drop", "Water"],
5273
- ["aura", "Aura"],
5274
- ["crystal-ball", "Crystal ball"],
5275
- ["diamond", "Diamond"],
5276
- ["explosion", "Explosion"],
5277
- ["fire-symbol", "Fire symbol"],
5278
- ["gem", "Gem"],
5279
- ["lightning-trio", "Lightning"],
5280
- ["potion", "Potion"],
5281
- ["rune-stone", "Rune stone"],
5282
- ["skull", "Skull"],
5283
- ["tentacle", "Tentacle"],
5284
- ["wolf-head", "Wolf"],
5285
- ["anchor", "Anchor"],
5286
- ["beer", "Beer"],
5287
- ["carrot", "Carrot"],
5288
- ["cat", "Cat"],
5289
- ["crown", "Crown"],
5290
- ["gold-bar", "Gold bar"],
5291
- ["helmet", "Helmet"],
5292
- ["key", "Key"],
5293
- ["three-keys", "Keys"]
5294
- ];
5295
- function isDirectoryIcon(value) {
5296
- return DIRECTORY_ICON_OPTIONS.some(([name]) => name === value);
5217
+
5218
+ // src/suite/lib/palette-api.ts
5219
+ var _a;
5220
+ var PALETTE_URL = ((_a = process.env.NEXT_PUBLIC_PALETTE_URL) != null ? _a : "http://localhost:8010").replace(/\/$/, "");
5221
+ function toQuery(params) {
5222
+ const query = new URLSearchParams();
5223
+ for (const [key, value] of Object.entries(params != null ? params : {})) {
5224
+ if (value !== void 0 && value !== null && value !== "") {
5225
+ query.set(key, String(value));
5226
+ }
5227
+ }
5228
+ return query.toString();
5297
5229
  }
5298
- function DirectoryIconPicker({
5299
- value,
5300
- preview,
5301
- onFileChange,
5302
- onClear,
5303
- onChange
5230
+ async function paletteGet(path, params) {
5231
+ const suffix = toQuery(params);
5232
+ const response = await fetch(
5233
+ `${PALETTE_URL}${path}${suffix ? `?${suffix}` : ""}`,
5234
+ { headers: { Accept: "application/json" } }
5235
+ );
5236
+ if (!response.ok) {
5237
+ throw new Error(`Palette request failed (${response.status}).`);
5238
+ }
5239
+ return await response.json();
5240
+ }
5241
+ var cache = /* @__PURE__ */ new Map();
5242
+ async function paletteGetCached(path, params, ttlMs) {
5243
+ const key = `${path}?${toQuery(params)}`;
5244
+ const now = Date.now();
5245
+ const hit = cache.get(key);
5246
+ if (hit && hit.expires > now) return hit.value;
5247
+ const value = await paletteGet(path, params);
5248
+ cache.set(key, { expires: now + ttlMs, value });
5249
+ return value;
5250
+ }
5251
+ function fetchPaletteLibrary(options) {
5252
+ return paletteGetCached("/library", options, 5 * 6e4);
5253
+ }
5254
+ function fetchPaletteCollection(slug, options) {
5255
+ return paletteGetCached(
5256
+ `/collections/${slug}`,
5257
+ options,
5258
+ 2 * 6e4
5259
+ );
5260
+ }
5261
+ function findPaletteIcons(options) {
5262
+ return paletteGet("/find", options);
5263
+ }
5264
+ function paletteIconSrc(imageUrl, color) {
5265
+ if (!imageUrl || !color) return imageUrl;
5266
+ if (!imageUrl.includes("/svgrepo/")) return imageUrl;
5267
+ return `${PALETTE_URL}/render?src=${encodeURIComponent(imageUrl)}&color=${encodeURIComponent(color)}`;
5268
+ }
5269
+
5270
+ // src/suite/components/suite-entity-icon.tsx
5271
+ import { jsx as jsx27 } from "react/jsx-runtime";
5272
+ function SuiteEntityIcon({
5273
+ imageUrl,
5274
+ label,
5275
+ color,
5276
+ className,
5277
+ roundedClass = "rounded-md",
5278
+ style,
5279
+ tinted = false
5304
5280
  }) {
5305
- const iconRefs = useRef5({});
5306
- function moveSelection(event, index) {
5307
- var _a;
5308
- let nextIndex = null;
5309
- if (event.key === "ArrowRight" || event.key === "ArrowDown") {
5310
- nextIndex = (index + 1) % DIRECTORY_ICON_OPTIONS.length;
5311
- } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
5312
- nextIndex = (index - 1 + DIRECTORY_ICON_OPTIONS.length) % DIRECTORY_ICON_OPTIONS.length;
5313
- } else if (event.key === "Home") {
5314
- nextIndex = 0;
5315
- } else if (event.key === "End") {
5316
- nextIndex = DIRECTORY_ICON_OPTIONS.length - 1;
5317
- }
5318
- if (nextIndex === null) return;
5319
- event.preventDefault();
5320
- const [nextIcon] = DIRECTORY_ICON_OPTIONS[nextIndex];
5321
- onChange(nextIcon);
5322
- (_a = iconRefs.current[nextIcon]) == null ? void 0 : _a.focus();
5281
+ const hasColor = typeof color === "string" && /^#[0-9a-fA-F]{3,8}$/.test(color);
5282
+ const tint = hasColor ? color : null;
5283
+ const neutralBackground = "var(--ph-muted, rgba(127,127,127,0.08))";
5284
+ if (imageUrl) {
5285
+ const src = tinted && tint ? paletteIconSrc(imageUrl, tint) : imageUrl;
5286
+ return /* @__PURE__ */ jsx27(
5287
+ "span",
5288
+ {
5289
+ className: cn(
5290
+ "inline-flex shrink-0 items-center justify-center overflow-hidden leading-none",
5291
+ roundedClass,
5292
+ className
5293
+ ),
5294
+ style: __spreadValues({
5295
+ backgroundColor: tint ? `${tint}18` : neutralBackground
5296
+ }, style),
5297
+ children: /* @__PURE__ */ jsx27("img", { src: src != null ? src : void 0, alt: "", className: "h-full w-full object-cover" })
5298
+ }
5299
+ );
5323
5300
  }
5324
- return /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
5325
- /* @__PURE__ */ jsx27("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Icon" }),
5326
- /* @__PURE__ */ jsx27(
5327
- "div",
5301
+ const initial = label == null ? void 0 : label.trim().charAt(0).toUpperCase();
5302
+ return /* @__PURE__ */ jsx27(
5303
+ "span",
5304
+ {
5305
+ className: cn(
5306
+ "inline-flex shrink-0 items-center justify-center font-semibold leading-none",
5307
+ roundedClass,
5308
+ className
5309
+ ),
5310
+ style: __spreadValues({
5311
+ color: tint != null ? tint : "var(--ph-mutedtext)",
5312
+ backgroundColor: tint ? `${tint}18` : neutralBackground
5313
+ }, style),
5314
+ "aria-hidden": "true",
5315
+ children: initial ? /* @__PURE__ */ jsx27("span", { className: "text-[0.7em]", children: initial }) : /* @__PURE__ */ jsx27("span", { className: "block h-1.5 w-1.5 rounded-full bg-current opacity-40" })
5316
+ }
5317
+ );
5318
+ }
5319
+
5320
+ // src/suite/components/suite-palette-library.tsx
5321
+ import {
5322
+ useCallback as useCallback6,
5323
+ useEffect as useEffect10,
5324
+ useMemo as useMemo3,
5325
+ useRef as useRef5,
5326
+ useState as useState13
5327
+ } from "react";
5328
+ import { Filter as Filter2, FilterList, NavArrowDown as NavArrowDown3, Search as Search2 } from "iconoir-react";
5329
+ import { Fragment as Fragment9, jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
5330
+ var PAGE_SIZE = 60;
5331
+ var DISCOVER_LIMIT = 120;
5332
+ var ICON_TYPES = [
5333
+ { value: "all", label: "All types" },
5334
+ { value: "line", label: "Line" },
5335
+ { value: "solid", label: "Solid" },
5336
+ { value: "duotone", label: "Duotone" },
5337
+ { value: "color", label: "Colour" },
5338
+ { value: "mixed", label: "Mixed" }
5339
+ ];
5340
+ function FilterSelect({
5341
+ icon: Icon,
5342
+ label,
5343
+ value,
5344
+ onChange,
5345
+ children
5346
+ }) {
5347
+ return /* @__PURE__ */ jsxs23("div", { className: "relative", children: [
5348
+ /* @__PURE__ */ jsx28(
5349
+ Icon,
5328
5350
  {
5329
- role: "radiogroup",
5330
- "aria-label": "Icon",
5331
- className: "grid grid-cols-6 gap-1.5 rounded-lg border border-ph-border p-1.5 sm:grid-cols-8",
5332
- children: DIRECTORY_ICON_OPTIONS.map(([name, label], index) => {
5333
- const selected = value === name;
5334
- return /* @__PURE__ */ jsx27(
5335
- "button",
5351
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
5352
+ "aria-hidden": true
5353
+ }
5354
+ ),
5355
+ /* @__PURE__ */ jsx28(
5356
+ "select",
5357
+ {
5358
+ "aria-label": label,
5359
+ value,
5360
+ onChange: (event) => onChange(event.target.value),
5361
+ 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",
5362
+ children
5363
+ }
5364
+ ),
5365
+ /* @__PURE__ */ jsx28(
5366
+ NavArrowDown3,
5367
+ {
5368
+ className: "pointer-events-none absolute right-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-ph-mutedtext",
5369
+ "aria-hidden": true
5370
+ }
5371
+ )
5372
+ ] });
5373
+ }
5374
+ function SuitePaletteLibrary({
5375
+ onPick
5376
+ }) {
5377
+ var _a2, _b;
5378
+ const [collections, setCollections] = useState13([]);
5379
+ const [typeFilter, setTypeFilter] = useState13("all");
5380
+ const [collectionFilter, setCollectionFilter] = useState13("");
5381
+ const [libraryOpen, setLibraryOpen] = useState13(false);
5382
+ const [libraryQuery, setLibraryQuery] = useState13("");
5383
+ const libraryRef = useRef5(null);
5384
+ const [icons, setIcons] = useState13([]);
5385
+ const [total, setTotal] = useState13(0);
5386
+ const [page, setPage] = useState13(1);
5387
+ const [query, setQuery] = useState13("");
5388
+ const [loading, setLoading] = useState13(true);
5389
+ const [loadingMore, setLoadingMore] = useState13(false);
5390
+ const [error, setError] = useState13(null);
5391
+ const requestId = useRef5(0);
5392
+ const libraryOptions = useMemo3(() => {
5393
+ const list = collections.filter(
5394
+ (item) => typeFilter === "all" || item.style === typeFilter
5395
+ );
5396
+ return [...list].sort(
5397
+ (a, b) => Number(b.featured) - Number(a.featured) || a.name.localeCompare(b.name)
5398
+ );
5399
+ }, [collections, typeFilter]);
5400
+ const discoverIcons = useMemo3(() => {
5401
+ const seen = /* @__PURE__ */ new Set();
5402
+ const out = [];
5403
+ for (const collection of libraryOptions) {
5404
+ for (const url of collection.preview) {
5405
+ if (seen.has(url)) continue;
5406
+ seen.add(url);
5407
+ out.push({ id: url, name: collection.name, tags: [], url });
5408
+ if (out.length >= DISCOVER_LIMIT) return out;
5409
+ }
5410
+ }
5411
+ return out;
5412
+ }, [libraryOptions]);
5413
+ const loadCollection = useCallback6(async (slug, nextPage = 1) => {
5414
+ const id = ++requestId.current;
5415
+ if (nextPage === 1) {
5416
+ setLoading(true);
5417
+ setIcons([]);
5418
+ } else {
5419
+ setLoadingMore(true);
5420
+ }
5421
+ setError(null);
5422
+ try {
5423
+ const detail = await fetchPaletteCollection(slug, {
5424
+ page: nextPage,
5425
+ size: PAGE_SIZE
5426
+ });
5427
+ if (id !== requestId.current) return;
5428
+ setTotal(detail.count);
5429
+ setPage(nextPage);
5430
+ setIcons(
5431
+ (current) => nextPage === 1 ? detail.icons : [...current, ...detail.icons]
5432
+ );
5433
+ } catch (err) {
5434
+ if (id === requestId.current) {
5435
+ setError(err instanceof Error ? err.message : "Could not load icons.");
5436
+ }
5437
+ } finally {
5438
+ if (id === requestId.current) {
5439
+ setLoading(false);
5440
+ setLoadingMore(false);
5441
+ }
5442
+ }
5443
+ }, []);
5444
+ useEffect10(() => {
5445
+ let cancelled = false;
5446
+ fetchPaletteLibrary().then((library) => {
5447
+ if (cancelled) return;
5448
+ setCollections(library.collections);
5449
+ }).catch((err) => {
5450
+ if (cancelled) return;
5451
+ setError(err instanceof Error ? err.message : "Could not load the library.");
5452
+ setLoading(false);
5453
+ });
5454
+ return () => {
5455
+ cancelled = true;
5456
+ };
5457
+ }, []);
5458
+ useEffect10(() => {
5459
+ if (!collections.length) return;
5460
+ if (collectionFilter && !libraryOptions.some((c) => c.slug === collectionFilter)) {
5461
+ setCollectionFilter("");
5462
+ }
5463
+ }, [libraryOptions, collectionFilter, collections.length]);
5464
+ useEffect10(() => {
5465
+ if (query.trim()) return;
5466
+ if (collectionFilter) {
5467
+ void loadCollection(collectionFilter, 1);
5468
+ return;
5469
+ }
5470
+ requestId.current += 1;
5471
+ setLoading(false);
5472
+ setPage(1);
5473
+ setIcons(discoverIcons);
5474
+ setTotal(discoverIcons.length);
5475
+ }, [collectionFilter, query, loadCollection, discoverIcons]);
5476
+ useEffect10(() => {
5477
+ const term = query.trim();
5478
+ if (!term) return;
5479
+ const id = ++requestId.current;
5480
+ setLoading(true);
5481
+ setError(null);
5482
+ const handle = setTimeout(async () => {
5483
+ try {
5484
+ const results = await findPaletteIcons({
5485
+ q: term,
5486
+ collection: collectionFilter || void 0,
5487
+ style: typeFilter === "all" ? void 0 : typeFilter,
5488
+ limit: 120
5489
+ });
5490
+ if (id !== requestId.current) return;
5491
+ setTotal(results.total);
5492
+ setPage(1);
5493
+ setIcons(
5494
+ results.results.map((hit) => ({
5495
+ id: `${hit.collection}/${hit.id}`,
5496
+ name: hit.name,
5497
+ tags: hit.tags,
5498
+ url: hit.url
5499
+ }))
5500
+ );
5501
+ } catch (err) {
5502
+ if (id === requestId.current) {
5503
+ setError(err instanceof Error ? err.message : "Search failed.");
5504
+ }
5505
+ } finally {
5506
+ if (id === requestId.current) setLoading(false);
5507
+ }
5508
+ }, 250);
5509
+ return () => clearTimeout(handle);
5510
+ }, [query, collectionFilter, typeFilter]);
5511
+ const searching = Boolean(query.trim());
5512
+ const activeLibrary = (_a2 = collections.find((c) => c.slug === collectionFilter)) != null ? _a2 : null;
5513
+ const filteredLibraries = useMemo3(() => {
5514
+ const term = libraryQuery.trim().toLowerCase();
5515
+ if (!term) return libraryOptions;
5516
+ return libraryOptions.filter((c) => c.name.toLowerCase().includes(term));
5517
+ }, [libraryOptions, libraryQuery]);
5518
+ useEffect10(() => {
5519
+ if (!libraryOpen) return;
5520
+ const onPointerDown = (event) => {
5521
+ var _a3;
5522
+ if (!((_a3 = libraryRef.current) == null ? void 0 : _a3.contains(event.target))) setLibraryOpen(false);
5523
+ };
5524
+ document.addEventListener("pointerdown", onPointerDown);
5525
+ return () => document.removeEventListener("pointerdown", onPointerDown);
5526
+ }, [libraryOpen]);
5527
+ return /* @__PURE__ */ jsxs23("div", { className: "space-y-3", "data-test": "palette-icon-library", children: [
5528
+ /* @__PURE__ */ jsxs23("div", { ref: libraryRef, className: "space-y-2", children: [
5529
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2 sm:flex-row", children: [
5530
+ /* @__PURE__ */ jsxs23("div", { className: "relative flex-1", children: [
5531
+ /* @__PURE__ */ jsx28(
5532
+ Search2,
5336
5533
  {
5337
- type: "button",
5338
- role: "radio",
5339
- "aria-label": label,
5340
- "aria-checked": selected,
5341
- tabIndex: selected ? 0 : -1,
5342
- title: label,
5343
- onClick: () => onChange(name),
5344
- onKeyDown: (event) => moveSelection(event, index),
5345
- ref: (element) => {
5346
- iconRefs.current[name] = element;
5347
- },
5348
- className: cn(
5349
- "flex h-9 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink",
5350
- selected && "bg-ph-muted text-ph-ink ring-2 ring-ph-brand ring-inset"
5351
- ),
5352
- children: /* @__PURE__ */ jsx27(
5353
- "i",
5534
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
5535
+ "aria-hidden": true
5536
+ }
5537
+ ),
5538
+ /* @__PURE__ */ jsx28(
5539
+ "input",
5540
+ {
5541
+ type: "search",
5542
+ value: query,
5543
+ onChange: (event) => setQuery(event.target.value),
5544
+ placeholder: "Search icons \u2014 handshake, rocket, briefcase\u2026",
5545
+ "aria-label": "Search icons",
5546
+ 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"
5547
+ }
5548
+ )
5549
+ ] }),
5550
+ /* @__PURE__ */ jsxs23(
5551
+ "button",
5552
+ {
5553
+ type: "button",
5554
+ "aria-haspopup": "listbox",
5555
+ "aria-expanded": libraryOpen,
5556
+ onClick: () => setLibraryOpen((open) => !open),
5557
+ 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",
5558
+ children: [
5559
+ /* @__PURE__ */ jsx28(FilterList, { className: "h-4 w-4 shrink-0 text-ph-mutedtext", "aria-hidden": true }),
5560
+ /* @__PURE__ */ jsx28("span", { className: "max-w-[10rem] truncate", children: (_b = activeLibrary == null ? void 0 : activeLibrary.name) != null ? _b : "All libraries" }),
5561
+ /* @__PURE__ */ jsx28(
5562
+ NavArrowDown3,
5354
5563
  {
5355
- className: cn("ra", `ra-${name}`, "text-base leading-none"),
5564
+ className: cn(
5565
+ "h-3.5 w-3.5 shrink-0 text-ph-mutedtext transition-transform",
5566
+ libraryOpen && "rotate-180"
5567
+ ),
5356
5568
  "aria-hidden": true
5357
5569
  }
5358
5570
  )
5359
- },
5360
- name
5361
- );
5362
- })
5363
- }
5364
- ),
5365
- /* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-ph-border bg-ph-muted p-2", children: [
5366
- /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 text-sm font-medium text-ph-ink", children: [
5367
- /* @__PURE__ */ jsx27(ImagePlus, { className: "h-4 w-4", "aria-hidden": true }),
5368
- " Custom image"
5369
- ] }),
5370
- /* @__PURE__ */ jsx27("p", { className: "mt-1 text-xs text-ph-mutedtext", children: "PNG, JPG, GIF, WebP, or SVG \u2014 max 512 KB." }),
5371
- /* @__PURE__ */ jsx27(
5372
- FileUpload,
5373
- {
5374
- accept: "image/png,image/jpeg,image/gif,image/webp,image/svg+xml,.svg",
5375
- onChange: (event) => {
5376
- var _a, _b;
5377
- return onFileChange((_b = (_a = event.target.files) == null ? void 0 : _a[0]) != null ? _b : null);
5571
+ ]
5378
5572
  }
5379
- }
5380
- ),
5381
- preview ? /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex items-center gap-2", children: [
5382
- /* @__PURE__ */ jsx27(
5383
- "img",
5573
+ ),
5574
+ /* @__PURE__ */ jsx28(
5575
+ FilterSelect,
5384
5576
  {
5385
- src: preview,
5386
- alt: "",
5387
- className: "h-8 w-8 rounded object-cover"
5577
+ icon: Filter2,
5578
+ label: "Filter by icon type",
5579
+ value: typeFilter,
5580
+ onChange: setTypeFilter,
5581
+ children: ICON_TYPES.map((type) => /* @__PURE__ */ jsx28("option", { value: type.value, children: type.label }, type.value))
5388
5582
  }
5389
- ),
5583
+ )
5584
+ ] }),
5585
+ libraryOpen ? /* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-ph-border bg-ph-surface p-2", children: [
5586
+ /* @__PURE__ */ jsxs23("div", { className: "relative mb-2", children: [
5587
+ /* @__PURE__ */ jsx28(
5588
+ Search2,
5589
+ {
5590
+ className: "pointer-events-none absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
5591
+ "aria-hidden": true
5592
+ }
5593
+ ),
5594
+ /* @__PURE__ */ jsx28(
5595
+ "input",
5596
+ {
5597
+ type: "search",
5598
+ autoFocus: true,
5599
+ value: libraryQuery,
5600
+ onChange: (event) => setLibraryQuery(event.target.value),
5601
+ placeholder: "Search libraries\u2026",
5602
+ "aria-label": "Search libraries",
5603
+ 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"
5604
+ }
5605
+ )
5606
+ ] }),
5390
5607
  /* @__PURE__ */ jsxs23(
5391
- "button",
5608
+ "ul",
5392
5609
  {
5393
- type: "button",
5394
- className: "text-xs text-ph-mutedtext hover:text-ph-ink",
5395
- onClick: onClear,
5610
+ role: "listbox",
5611
+ "aria-label": "Libraries",
5612
+ className: "max-h-56 overflow-y-auto",
5396
5613
  children: [
5397
- /* @__PURE__ */ jsx27(Trash, { className: "mr-1 inline h-3.5 w-3.5", "aria-hidden": true }),
5398
- " Remove custom image"
5614
+ /* @__PURE__ */ jsx28("li", { children: /* @__PURE__ */ jsx28(
5615
+ "button",
5616
+ {
5617
+ type: "button",
5618
+ role: "option",
5619
+ "aria-selected": !collectionFilter,
5620
+ onClick: () => {
5621
+ setCollectionFilter("");
5622
+ setLibraryOpen(false);
5623
+ },
5624
+ className: cn(
5625
+ "flex w-full items-center rounded-md px-2 py-1.5 text-left text-sm",
5626
+ !collectionFilter ? "bg-ph-muted text-ph-ink" : "text-ph-ink hover:bg-ph-muted"
5627
+ ),
5628
+ children: "All libraries"
5629
+ }
5630
+ ) }),
5631
+ filteredLibraries.map((collection) => /* @__PURE__ */ jsx28("li", { children: /* @__PURE__ */ jsxs23(
5632
+ "button",
5633
+ {
5634
+ type: "button",
5635
+ role: "option",
5636
+ "aria-selected": collectionFilter === collection.slug,
5637
+ onClick: () => {
5638
+ setCollectionFilter(collection.slug);
5639
+ setLibraryOpen(false);
5640
+ },
5641
+ className: cn(
5642
+ "flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-left text-sm",
5643
+ collectionFilter === collection.slug ? "bg-ph-muted text-ph-ink" : "text-ph-ink hover:bg-ph-muted"
5644
+ ),
5645
+ children: [
5646
+ /* @__PURE__ */ jsx28("span", { className: "truncate", children: collection.name }),
5647
+ /* @__PURE__ */ jsx28("span", { className: "shrink-0 text-xs text-ph-mutedtext", children: collection.count })
5648
+ ]
5649
+ }
5650
+ ) }, collection.slug)),
5651
+ filteredLibraries.length === 0 ? /* @__PURE__ */ jsx28("li", { className: "px-2 py-4 text-center text-sm text-ph-mutedtext", children: "No libraries match." }) : null
5399
5652
  ]
5400
5653
  }
5401
5654
  )
5402
5655
  ] }) : null
5656
+ ] }),
5657
+ error ? /* @__PURE__ */ jsx28("p", { className: "text-sm text-ph-danger", children: error }) : loading ? /* @__PURE__ */ jsx28("p", { className: "py-8 text-center text-sm text-ph-mutedtext", children: "Loading icons\u2026" }) : icons.length === 0 ? /* @__PURE__ */ jsx28("p", { className: "py-8 text-center text-sm text-ph-mutedtext", children: "No icons matched. Try another word or filter." }) : /* @__PURE__ */ jsxs23(Fragment9, { children: [
5658
+ /* @__PURE__ */ jsx28("div", { className: "max-h-[320px] overflow-y-auto rounded-lg border border-ph-border p-2", children: /* @__PURE__ */ jsx28("div", { className: "grid grid-cols-6 gap-1.5 sm:grid-cols-8", children: icons.map((icon) => /* @__PURE__ */ jsx28(
5659
+ "button",
5660
+ {
5661
+ type: "button",
5662
+ onClick: () => onPick({ url: icon.url, name: icon.name }),
5663
+ title: icon.name,
5664
+ "aria-label": `Use ${icon.name}`,
5665
+ className: "flex h-10 items-center justify-center rounded-md border border-transparent p-1.5 hover:border-ph-brand hover:bg-ph-muted",
5666
+ children: /* @__PURE__ */ jsx28(
5667
+ "img",
5668
+ {
5669
+ src: icon.url,
5670
+ alt: "",
5671
+ loading: "lazy",
5672
+ decoding: "async",
5673
+ className: "h-6 w-6"
5674
+ }
5675
+ )
5676
+ },
5677
+ icon.id
5678
+ )) }) }),
5679
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between text-xs text-ph-mutedtext", children: [
5680
+ /* @__PURE__ */ jsxs23("span", { children: [
5681
+ icons.length,
5682
+ " of ",
5683
+ total,
5684
+ searching ? " matching" : activeLibrary ? ` in ${activeLibrary.name}` : " across all libraries"
5685
+ ] }),
5686
+ !searching && activeLibrary && icons.length < total ? /* @__PURE__ */ jsx28(
5687
+ "button",
5688
+ {
5689
+ type: "button",
5690
+ disabled: loadingMore,
5691
+ onClick: () => void loadCollection(activeLibrary.slug, page + 1),
5692
+ className: cn(
5693
+ "font-medium text-ph-brand hover:underline",
5694
+ loadingMore && "opacity-50"
5695
+ ),
5696
+ children: loadingMore ? "Loading\u2026" : "Load more"
5697
+ }
5698
+ ) : null
5699
+ ] })
5403
5700
  ] })
5404
5701
  ] });
5405
5702
  }
5406
- function DirectoryIcon({
5407
- item
5703
+
5704
+ // src/suite/components/suite-clients-projects-directory.tsx
5705
+ import { Fragment as Fragment10, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
5706
+ var DEFAULT_ICON = "";
5707
+ var DEFAULT_COLOR = "#6366f1";
5708
+ function DirectoryIconPicker({
5709
+ preview,
5710
+ label,
5711
+ color,
5712
+ onFileChange,
5713
+ onClear,
5714
+ onBrowse
5408
5715
  }) {
5409
- const icon = item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON;
5410
- return /* @__PURE__ */ jsx27(
5411
- "span",
5412
- {
5413
- className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-white",
5414
- style: { backgroundColor: item.color || "var(--ph-brand)" },
5415
- children: item.icon_image ? (
5416
- // eslint-disable-next-line @next/next/no-img-element
5417
- /* @__PURE__ */ jsx27(
5418
- "img",
5716
+ return /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
5717
+ /* @__PURE__ */ jsx29("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Icon" }),
5718
+ /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-ph-border bg-ph-muted p-3", children: [
5719
+ /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-3", children: [
5720
+ /* @__PURE__ */ jsx29(
5721
+ SuiteEntityIcon,
5419
5722
  {
5420
- src: item.icon_image,
5421
- alt: "",
5422
- className: "h-full w-full rounded-lg object-cover"
5723
+ imageUrl: preview,
5724
+ label,
5725
+ color,
5726
+ tinted: true,
5727
+ className: "h-9 w-9 text-base"
5423
5728
  }
5424
- )
5425
- ) : /* @__PURE__ */ jsx27(
5426
- "i",
5729
+ ),
5730
+ /* @__PURE__ */ jsxs24("div", { className: "min-w-0 flex-1", children: [
5731
+ /* @__PURE__ */ jsx29("p", { className: "text-sm font-medium text-ph-ink", children: preview ? "Custom image" : "No icon yet" }),
5732
+ /* @__PURE__ */ jsx29("p", { className: "text-xs text-ph-mutedtext", children: preview ? "Shown on cards and lists." : "Browse the library or upload your own." })
5733
+ ] }),
5734
+ onBrowse ? /* @__PURE__ */ jsx29(
5735
+ "button",
5736
+ {
5737
+ type: "button",
5738
+ onClick: onBrowse,
5739
+ 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",
5740
+ children: "Browse library"
5741
+ }
5742
+ ) : null
5743
+ ] }),
5744
+ /* @__PURE__ */ jsx29("div", { className: "mt-3", children: /* @__PURE__ */ jsx29(
5745
+ FileUpload,
5427
5746
  {
5428
- className: cn("ra", `ra-${icon}`, "text-base leading-none"),
5429
- "aria-hidden": true
5747
+ accept: "image/png,image/jpeg,image/gif,image/webp,image/svg+xml,.svg",
5748
+ onChange: (event) => {
5749
+ var _a2, _b;
5750
+ return onFileChange((_b = (_a2 = event.target.files) == null ? void 0 : _a2[0]) != null ? _b : null);
5751
+ }
5430
5752
  }
5431
- )
5753
+ ) }),
5754
+ preview ? /* @__PURE__ */ jsxs24(
5755
+ "button",
5756
+ {
5757
+ type: "button",
5758
+ 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",
5759
+ onClick: onClear,
5760
+ children: [
5761
+ /* @__PURE__ */ jsx29(Trash, { className: "h-3.5 w-3.5", "aria-hidden": true }),
5762
+ " Remove image"
5763
+ ]
5764
+ }
5765
+ ) : null
5766
+ ] })
5767
+ ] });
5768
+ }
5769
+ function DirectoryIcon({
5770
+ item
5771
+ }) {
5772
+ return /* @__PURE__ */ jsx29(
5773
+ SuiteEntityIcon,
5774
+ {
5775
+ imageUrl: item.icon_image,
5776
+ label: item.name,
5777
+ color: item.color,
5778
+ tinted: true,
5779
+ className: "h-8 w-8 text-sm",
5780
+ roundedClass: "rounded-lg"
5432
5781
  }
5433
5782
  );
5434
5783
  }
@@ -5444,51 +5793,53 @@ function SuiteClientsProjectsDirectory({
5444
5793
  onCreateProject,
5445
5794
  onUpdateProject,
5446
5795
  onDeleteProject,
5796
+ renderIconLibrary,
5447
5797
  dataTest = "suite-clients-projects-directory"
5448
5798
  }) {
5449
- var _a;
5450
- const [query, setQuery] = useState13("");
5451
- const [selectedClientId, setSelectedClientId] = useState13(null);
5452
- const [mobileDetail, setMobileDetail] = useState13(false);
5453
- const [editing, setEditing] = useState13(null);
5454
- const [draft, setDraft] = useState13({
5799
+ var _a2;
5800
+ const [query, setQuery] = useState14("");
5801
+ const [selectedClientId, setSelectedClientId] = useState14(null);
5802
+ const [mobileDetail, setMobileDetail] = useState14(false);
5803
+ const [editing, setEditing] = useState14(null);
5804
+ const [draft, setDraft] = useState14({
5455
5805
  name: "",
5456
5806
  icon: DEFAULT_ICON,
5457
5807
  color: DEFAULT_COLOR
5458
5808
  });
5459
- const [draftClientId, setDraftClientId] = useState13(null);
5460
- const [preview, setPreview] = useState13(null);
5461
- const [draftArchived, setDraftArchived] = useState13(false);
5462
- const [confirming, setConfirming] = useState13(null);
5463
- const [saving, setSaving] = useState13(false);
5464
- const [mutationError, setMutationError] = useState13(null);
5465
- const clientButtonRefs = useRef5({});
5466
- const backToClientsRef = useRef5(null);
5467
- const mobileFocusTarget = useRef5(null);
5468
- useEffect10(() => {
5469
- var _a2, _b;
5809
+ const [draftClientId, setDraftClientId] = useState14(null);
5810
+ const [preview, setPreview] = useState14(null);
5811
+ const [libraryOpen, setLibraryOpen] = useState14(false);
5812
+ const [draftArchived, setDraftArchived] = useState14(false);
5813
+ const [confirming, setConfirming] = useState14(null);
5814
+ const [saving, setSaving] = useState14(false);
5815
+ const [mutationError, setMutationError] = useState14(null);
5816
+ const clientButtonRefs = useRef6({});
5817
+ const backToClientsRef = useRef6(null);
5818
+ const mobileFocusTarget = useRef6(null);
5819
+ useEffect11(() => {
5820
+ var _a3, _b;
5470
5821
  if (selectedClientId && clients.some((client) => client.id === selectedClientId))
5471
5822
  return;
5472
- setSelectedClientId((_b = (_a2 = clients[0]) == null ? void 0 : _a2.id) != null ? _b : null);
5823
+ setSelectedClientId((_b = (_a3 = clients[0]) == null ? void 0 : _a3.id) != null ? _b : null);
5473
5824
  }, [clients, selectedClientId]);
5474
- useEffect10(() => {
5475
- var _a2, _b;
5825
+ useEffect11(() => {
5826
+ var _a3, _b;
5476
5827
  const target = mobileFocusTarget.current;
5477
5828
  if (!target) return;
5478
5829
  mobileFocusTarget.current = null;
5479
- if (target === "detail") (_a2 = backToClientsRef.current) == null ? void 0 : _a2.focus();
5830
+ if (target === "detail") (_a3 = backToClientsRef.current) == null ? void 0 : _a3.focus();
5480
5831
  else if (selectedClientId)
5481
5832
  (_b = clientButtonRefs.current[selectedClientId]) == null ? void 0 : _b.focus();
5482
5833
  }, [mobileDetail, selectedClientId]);
5483
- const filteredClients = useMemo3(() => {
5834
+ const filteredClients = useMemo4(() => {
5484
5835
  const value = query.trim().toLowerCase();
5485
5836
  return [...clients].sort((a, b) => a.name.localeCompare(b.name)).filter((client) => !value || client.name.toLowerCase().includes(value));
5486
5837
  }, [clients, query]);
5487
- const selectedClient = (_a = clients.find((client) => client.id === selectedClientId)) != null ? _a : null;
5838
+ const selectedClient = (_a2 = clients.find((client) => client.id === selectedClientId)) != null ? _a2 : null;
5488
5839
  const selectedProjects = projects.filter((project) => project.clientId === selectedClientId).sort((a, b) => a.name.localeCompare(b.name));
5489
5840
  function isMobileDirectoryView() {
5490
- var _a2, _b;
5491
- return (_b = (_a2 = window.matchMedia) == null ? void 0 : _a2.call(window, "(max-width: 1023px)").matches) != null ? _b : false;
5841
+ var _a3, _b;
5842
+ return (_b = (_a3 = window.matchMedia) == null ? void 0 : _a3.call(window, "(max-width: 1023px)").matches) != null ? _b : false;
5492
5843
  }
5493
5844
  function selectClient(client) {
5494
5845
  setSelectedClientId(client.id);
@@ -5496,7 +5847,7 @@ function SuiteClientsProjectsDirectory({
5496
5847
  if (isMobileDirectoryView()) mobileFocusTarget.current = "detail";
5497
5848
  }
5498
5849
  function moveClientSelection(event, index) {
5499
- var _a2;
5850
+ var _a3;
5500
5851
  let nextIndex = null;
5501
5852
  if (event.key === "ArrowDown") {
5502
5853
  nextIndex = (index + 1) % filteredClients.length;
@@ -5511,7 +5862,7 @@ function SuiteClientsProjectsDirectory({
5511
5862
  event.preventDefault();
5512
5863
  const client = filteredClients[nextIndex];
5513
5864
  selectClient(client);
5514
- if (!isMobileDirectoryView()) (_a2 = clientButtonRefs.current[client.id]) == null ? void 0 : _a2.focus();
5865
+ if (!isMobileDirectoryView()) (_a3 = clientButtonRefs.current[client.id]) == null ? void 0 : _a3.focus();
5515
5866
  }
5516
5867
  function openNew(kind) {
5517
5868
  setMutationError(null);
@@ -5520,6 +5871,7 @@ function SuiteClientsProjectsDirectory({
5520
5871
  icon: DEFAULT_ICON,
5521
5872
  color: DEFAULT_COLOR,
5522
5873
  iconImageFile: null,
5874
+ iconImageUrl: null,
5523
5875
  clearIconImage: false
5524
5876
  });
5525
5877
  setPreview(null);
@@ -5528,13 +5880,14 @@ function SuiteClientsProjectsDirectory({
5528
5880
  setEditing({ kind: kind === "client" ? "new-client" : "new-project" });
5529
5881
  }
5530
5882
  function openEdit(item, kind) {
5531
- var _a2;
5883
+ var _a3, _b;
5532
5884
  setMutationError(null);
5533
5885
  setDraft({
5534
5886
  name: item.name,
5535
- icon: item.icon && isDirectoryIcon(item.icon) ? item.icon : DEFAULT_ICON,
5887
+ icon: (_a3 = item.icon) != null ? _a3 : DEFAULT_ICON,
5536
5888
  color: item.color || DEFAULT_COLOR,
5537
5889
  iconImageFile: null,
5890
+ iconImageUrl: null,
5538
5891
  clearIconImage: false
5539
5892
  });
5540
5893
  setPreview(item.icon_image || null);
@@ -5542,7 +5895,7 @@ function SuiteClientsProjectsDirectory({
5542
5895
  kind === "project" && Boolean(item.isArchived)
5543
5896
  );
5544
5897
  setDraftClientId(
5545
- kind === "project" ? (_a2 = item.clientId) != null ? _a2 : null : null
5898
+ kind === "project" ? (_b = item.clientId) != null ? _b : null : null
5546
5899
  );
5547
5900
  setEditing({ kind, item });
5548
5901
  }
@@ -5556,6 +5909,7 @@ function SuiteClientsProjectsDirectory({
5556
5909
  if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
5557
5910
  setDraft((current) => __spreadProps(__spreadValues({}, current), {
5558
5911
  iconImageFile: file,
5912
+ iconImageUrl: null,
5559
5913
  clearIconImage: false
5560
5914
  }));
5561
5915
  setPreview(URL.createObjectURL(file));
@@ -5565,9 +5919,21 @@ function SuiteClientsProjectsDirectory({
5565
5919
  setPreview(null);
5566
5920
  setDraft((current) => __spreadProps(__spreadValues({}, current), {
5567
5921
  iconImageFile: null,
5922
+ iconImageUrl: null,
5568
5923
  clearIconImage: true
5569
5924
  }));
5570
5925
  }
5926
+ function pickFromLibrary(icon) {
5927
+ if (preview == null ? void 0 : preview.startsWith("blob:")) URL.revokeObjectURL(preview);
5928
+ setMutationError(null);
5929
+ setPreview(icon.url);
5930
+ setDraft((current) => __spreadProps(__spreadValues({}, current), {
5931
+ iconImageFile: null,
5932
+ iconImageUrl: icon.url,
5933
+ clearIconImage: false
5934
+ }));
5935
+ setLibraryOpen(false);
5936
+ }
5571
5937
  function closeEditor() {
5572
5938
  if (!saving) setEditing(null);
5573
5939
  }
@@ -5603,14 +5969,14 @@ function SuiteClientsProjectsDirectory({
5603
5969
  setConfirming({ item, kind });
5604
5970
  }
5605
5971
  async function toggleArchive(project) {
5606
- var _a2;
5972
+ var _a3, _b;
5607
5973
  if (!onUpdateProject) return;
5608
5974
  try {
5609
5975
  await onUpdateProject(project, {
5610
5976
  name: project.name,
5611
- icon: project.icon && isDirectoryIcon(project.icon) ? project.icon : DEFAULT_ICON,
5977
+ icon: (_a3 = project.icon) != null ? _a3 : DEFAULT_ICON,
5612
5978
  color: project.color || DEFAULT_COLOR,
5613
- clientId: (_a2 = project.clientId) != null ? _a2 : null,
5979
+ clientId: (_b = project.clientId) != null ? _b : null,
5614
5980
  isArchived: !project.isArchived
5615
5981
  });
5616
5982
  } catch (err) {
@@ -5633,10 +5999,10 @@ function SuiteClientsProjectsDirectory({
5633
5999
  );
5634
6000
  }
5635
6001
  }
5636
- return /* @__PURE__ */ jsxs23("div", { "data-test": dataTest, className: "space-y-3", children: [
5637
- error || mutationError ? /* @__PURE__ */ jsx27(Alert, { status: "danger", live: "assertive", children: error || mutationError }) : null,
5638
- loading ? /* @__PURE__ */ jsx27("p", { className: "text-sm text-ph-mutedtext", children: "Loading directory..." }) : /* @__PURE__ */ jsxs23("div", { className: "overflow-hidden rounded-xl border border-ph-border bg-ph-surface lg:grid lg:min-h-[22rem] lg:grid-cols-[minmax(14rem,18rem)_1fr]", children: [
5639
- /* @__PURE__ */ jsxs23(
6002
+ return /* @__PURE__ */ jsxs24("div", { "data-test": dataTest, className: "space-y-3", children: [
6003
+ error || mutationError ? /* @__PURE__ */ jsx29(Alert, { status: "danger", live: "assertive", children: error || mutationError }) : null,
6004
+ loading ? /* @__PURE__ */ jsx29("p", { className: "text-sm text-ph-mutedtext", children: "Loading directory..." }) : /* @__PURE__ */ jsxs24("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: [
6005
+ /* @__PURE__ */ jsxs24(
5640
6006
  "section",
5641
6007
  {
5642
6008
  className: cn(
@@ -5644,16 +6010,16 @@ function SuiteClientsProjectsDirectory({
5644
6010
  mobileDetail ? "hidden lg:block" : "block"
5645
6011
  ),
5646
6012
  children: [
5647
- /* @__PURE__ */ jsxs23("div", { className: "flex h-14 items-center gap-2 border-b border-ph-border px-3", children: [
5648
- /* @__PURE__ */ jsxs23("div", { className: "relative min-w-0 flex-1", children: [
5649
- /* @__PURE__ */ jsx27(
5650
- Search2,
6013
+ /* @__PURE__ */ jsxs24("div", { className: "flex h-14 items-center gap-2 border-b border-ph-border px-3", children: [
6014
+ /* @__PURE__ */ jsxs24("div", { className: "relative min-w-0 flex-1", children: [
6015
+ /* @__PURE__ */ jsx29(
6016
+ Search3,
5651
6017
  {
5652
6018
  className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ph-mutedtext",
5653
6019
  "aria-hidden": true
5654
6020
  }
5655
6021
  ),
5656
- /* @__PURE__ */ jsx27(
6022
+ /* @__PURE__ */ jsx29(
5657
6023
  Input,
5658
6024
  {
5659
6025
  hideLabel: true,
@@ -5665,18 +6031,18 @@ function SuiteClientsProjectsDirectory({
5665
6031
  }
5666
6032
  )
5667
6033
  ] }),
5668
- canEdit && onCreateClient ? /* @__PURE__ */ jsx27(
6034
+ canEdit && onCreateClient ? /* @__PURE__ */ jsx29(
5669
6035
  Button,
5670
6036
  {
5671
6037
  size: "sm",
5672
6038
  variant: "primary",
5673
- icon: /* @__PURE__ */ jsx27(Plus2, { className: "h-4 w-4" }),
6039
+ icon: /* @__PURE__ */ jsx29(Plus2, { className: "h-4 w-4" }),
5674
6040
  onClick: () => openNew("client"),
5675
6041
  children: "New client"
5676
6042
  }
5677
6043
  ) : null
5678
6044
  ] }),
5679
- /* @__PURE__ */ jsx27(
6045
+ /* @__PURE__ */ jsx29(
5680
6046
  "ul",
5681
6047
  {
5682
6048
  role: "listbox",
@@ -5687,7 +6053,7 @@ function SuiteClientsProjectsDirectory({
5687
6053
  const count = projects.filter(
5688
6054
  (project) => project.clientId === client.id
5689
6055
  ).length;
5690
- return /* @__PURE__ */ jsx27("li", { role: "none", children: /* @__PURE__ */ jsxs23(
6056
+ return /* @__PURE__ */ jsx29("li", { role: "none", children: /* @__PURE__ */ jsxs24(
5691
6057
  "button",
5692
6058
  {
5693
6059
  type: "button",
@@ -5704,10 +6070,10 @@ function SuiteClientsProjectsDirectory({
5704
6070
  selected ? "bg-ph-muted" : "hover:bg-ph-canvas"
5705
6071
  ),
5706
6072
  children: [
5707
- /* @__PURE__ */ jsx27(DirectoryIcon, { item: client }),
5708
- /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex-1", children: [
5709
- /* @__PURE__ */ jsx27("span", { className: "block truncate text-sm font-medium text-ph-ink", children: client.name }),
5710
- /* @__PURE__ */ jsxs23("span", { className: "text-xs text-ph-mutedtext", children: [
6073
+ /* @__PURE__ */ jsx29(DirectoryIcon, { item: client }),
6074
+ /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex-1", children: [
6075
+ /* @__PURE__ */ jsx29("span", { className: "block truncate text-sm font-medium text-ph-ink", children: client.name }),
6076
+ /* @__PURE__ */ jsxs24("span", { className: "text-xs text-ph-mutedtext", children: [
5711
6077
  count,
5712
6078
  " project",
5713
6079
  count === 1 ? "" : "s"
@@ -5716,13 +6082,13 @@ function SuiteClientsProjectsDirectory({
5716
6082
  ]
5717
6083
  }
5718
6084
  ) }, client.id);
5719
- }) : /* @__PURE__ */ jsx27("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: clients.length ? "No matches." : "Add a client to get started." })
6085
+ }) : /* @__PURE__ */ jsx29("li", { className: "px-3 py-8 text-center text-sm text-ph-mutedtext", children: clients.length ? "No matches." : "Add a client to get started." })
5720
6086
  }
5721
6087
  )
5722
6088
  ]
5723
6089
  }
5724
6090
  ),
5725
- /* @__PURE__ */ jsxs23(
6091
+ /* @__PURE__ */ jsxs24(
5726
6092
  "section",
5727
6093
  {
5728
6094
  className: cn(
@@ -5730,8 +6096,8 @@ function SuiteClientsProjectsDirectory({
5730
6096
  mobileDetail ? "flex" : "hidden lg:flex"
5731
6097
  ),
5732
6098
  children: [
5733
- /* @__PURE__ */ jsx27("div", { className: "flex min-h-14 items-center gap-2 border-b border-ph-border px-3 py-2", children: selectedClient ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
5734
- /* @__PURE__ */ jsx27(
6099
+ /* @__PURE__ */ jsx29("div", { className: "flex min-h-14 items-center gap-2 border-b border-ph-border px-3 py-2", children: selectedClient ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
6100
+ /* @__PURE__ */ jsx29(
5735
6101
  "button",
5736
6102
  {
5737
6103
  type: "button",
@@ -5742,36 +6108,36 @@ function SuiteClientsProjectsDirectory({
5742
6108
  setMobileDetail(false);
5743
6109
  },
5744
6110
  "aria-label": "Back to clients",
5745
- children: /* @__PURE__ */ jsx27(ArrowLeft, { className: "h-4 w-4" })
6111
+ children: /* @__PURE__ */ jsx29(ArrowLeft, { className: "h-4 w-4" })
5746
6112
  }
5747
6113
  ),
5748
- /* @__PURE__ */ jsx27(DirectoryIcon, { item: selectedClient }),
5749
- /* @__PURE__ */ jsxs23("div", { className: "min-w-0 flex-1", children: [
5750
- /* @__PURE__ */ jsx27("h3", { className: "truncate text-sm font-semibold text-ph-ink", children: selectedClient.name }),
5751
- /* @__PURE__ */ jsxs23("p", { className: "text-xs text-ph-mutedtext", children: [
6114
+ /* @__PURE__ */ jsx29(DirectoryIcon, { item: selectedClient }),
6115
+ /* @__PURE__ */ jsxs24("div", { className: "min-w-0 flex-1", children: [
6116
+ /* @__PURE__ */ jsx29("h3", { className: "truncate text-sm font-semibold text-ph-ink", children: selectedClient.name }),
6117
+ /* @__PURE__ */ jsxs24("p", { className: "text-xs text-ph-mutedtext", children: [
5752
6118
  selectedProjects.length,
5753
6119
  " project",
5754
6120
  selectedProjects.length === 1 ? "" : "s"
5755
6121
  ] })
5756
6122
  ] }),
5757
- canEdit && (onUpdateClient || onDeleteClient) ? /* @__PURE__ */ jsx27("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx27(
6123
+ canEdit && (onUpdateClient || onDeleteClient) ? /* @__PURE__ */ jsx29("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx29(
5758
6124
  DropdownMenu,
5759
6125
  {
5760
6126
  "aria-label": `Actions for ${selectedClient.name}`,
5761
6127
  align: "end",
5762
- trigger: /* @__PURE__ */ jsxs23("span", { className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink", children: [
5763
- /* @__PURE__ */ jsx27(MoreHorizontal, { className: "h-4 w-4", "aria-hidden": true }),
5764
- /* @__PURE__ */ jsx27("span", { className: "sr-only", children: "Client actions" })
6128
+ trigger: /* @__PURE__ */ jsxs24("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: [
6129
+ /* @__PURE__ */ jsx29(MoreHorizontal, { className: "h-4 w-4", "aria-hidden": true }),
6130
+ /* @__PURE__ */ jsx29("span", { className: "sr-only", children: "Client actions" })
5765
6131
  ] }),
5766
- children: /* @__PURE__ */ jsxs23("div", { className: "p-1", children: [
5767
- onUpdateClient ? /* @__PURE__ */ jsx27(
6132
+ children: /* @__PURE__ */ jsxs24("div", { className: "p-1", children: [
6133
+ onUpdateClient ? /* @__PURE__ */ jsx29(
5768
6134
  DropdownItem,
5769
6135
  {
5770
6136
  onClick: () => openEdit(selectedClient, "client"),
5771
6137
  children: "Edit client"
5772
6138
  }
5773
6139
  ) : null,
5774
- onDeleteClient ? /* @__PURE__ */ jsx27(
6140
+ onDeleteClient ? /* @__PURE__ */ jsx29(
5775
6141
  DropdownItem,
5776
6142
  {
5777
6143
  className: "text-red-600",
@@ -5782,32 +6148,32 @@ function SuiteClientsProjectsDirectory({
5782
6148
  ] })
5783
6149
  }
5784
6150
  ) }) : null
5785
- ] }) : /* @__PURE__ */ jsx27("p", { className: "text-sm text-ph-mutedtext", children: "Select a client" }) }),
5786
- canEdit && onCreateProject ? /* @__PURE__ */ jsx27("div", { className: "border-b border-ph-border p-3", children: /* @__PURE__ */ jsx27(
6151
+ ] }) : /* @__PURE__ */ jsx29("p", { className: "text-sm text-ph-mutedtext", children: "Select a client" }) }),
6152
+ canEdit && onCreateProject ? /* @__PURE__ */ jsx29("div", { className: "border-b border-ph-border p-3", children: /* @__PURE__ */ jsx29(
5787
6153
  Button,
5788
6154
  {
5789
6155
  variant: "primary",
5790
- icon: /* @__PURE__ */ jsx27(Plus2, { className: "h-4 w-4" }),
6156
+ icon: /* @__PURE__ */ jsx29(Plus2, { className: "h-4 w-4" }),
5791
6157
  onClick: () => openNew("project"),
5792
6158
  children: "Add project"
5793
6159
  }
5794
6160
  ) }) : null,
5795
- /* @__PURE__ */ jsx27("ul", { className: "flex-1 p-2", children: selectedClient && selectedProjects.length ? selectedProjects.map((project) => /* @__PURE__ */ jsx27("li", { children: /* @__PURE__ */ jsxs23(
6161
+ /* @__PURE__ */ jsx29("ul", { className: "flex-1 p-2", children: selectedClient && selectedProjects.length ? selectedProjects.map((project) => /* @__PURE__ */ jsx29("li", { children: /* @__PURE__ */ jsxs24(
5796
6162
  "div",
5797
6163
  {
5798
6164
  className: "flex items-center gap-3 rounded-lg px-2 py-1 hover:bg-ph-canvas",
5799
6165
  onClick: () => openEdit(project, "project"),
5800
6166
  children: [
5801
- /* @__PURE__ */ jsxs23(
6167
+ /* @__PURE__ */ jsxs24(
5802
6168
  "button",
5803
6169
  {
5804
6170
  type: "button",
5805
6171
  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",
5806
6172
  onClick: () => openEdit(project, "project"),
5807
6173
  children: [
5808
- /* @__PURE__ */ jsx27(DirectoryIcon, { item: project }),
5809
- /* @__PURE__ */ jsxs23("span", { className: "min-w-0 flex-1", children: [
5810
- /* @__PURE__ */ jsx27(
6174
+ /* @__PURE__ */ jsx29(DirectoryIcon, { item: project }),
6175
+ /* @__PURE__ */ jsxs24("span", { className: "min-w-0 flex-1", children: [
6176
+ /* @__PURE__ */ jsx29(
5811
6177
  "span",
5812
6178
  {
5813
6179
  className: cn(
@@ -5817,36 +6183,36 @@ function SuiteClientsProjectsDirectory({
5817
6183
  children: project.name
5818
6184
  }
5819
6185
  ),
5820
- /* @__PURE__ */ jsx27("span", { className: "text-xs text-ph-mutedtext", children: project.isArchived ? "Archived" : "Active" })
6186
+ /* @__PURE__ */ jsx29("span", { className: "text-xs text-ph-mutedtext", children: project.isArchived ? "Archived" : "Active" })
5821
6187
  ] })
5822
6188
  ]
5823
6189
  }
5824
6190
  ),
5825
- canEdit && (onUpdateProject || onDeleteProject) ? /* @__PURE__ */ jsx27("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx27(
6191
+ canEdit && (onUpdateProject || onDeleteProject) ? /* @__PURE__ */ jsx29("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx29(
5826
6192
  DropdownMenu,
5827
6193
  {
5828
6194
  "aria-label": `Actions for ${project.name}`,
5829
6195
  align: "end",
5830
- trigger: /* @__PURE__ */ jsxs23("span", { className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-ph-mutedtext hover:bg-ph-muted hover:text-ph-ink", children: [
5831
- /* @__PURE__ */ jsx27(
6196
+ trigger: /* @__PURE__ */ jsxs24("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: [
6197
+ /* @__PURE__ */ jsx29(
5832
6198
  MoreHorizontal,
5833
6199
  {
5834
6200
  className: "h-4 w-4",
5835
6201
  "aria-hidden": true
5836
6202
  }
5837
6203
  ),
5838
- /* @__PURE__ */ jsx27("span", { className: "sr-only", children: "Project actions" })
6204
+ /* @__PURE__ */ jsx29("span", { className: "sr-only", children: "Project actions" })
5839
6205
  ] }),
5840
- children: /* @__PURE__ */ jsxs23("div", { className: "p-1", children: [
5841
- onUpdateProject ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
5842
- /* @__PURE__ */ jsx27(
6206
+ children: /* @__PURE__ */ jsxs24("div", { className: "p-1", children: [
6207
+ onUpdateProject ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
6208
+ /* @__PURE__ */ jsx29(
5843
6209
  DropdownItem,
5844
6210
  {
5845
6211
  onClick: () => openEdit(project, "project"),
5846
6212
  children: "Edit project"
5847
6213
  }
5848
6214
  ),
5849
- /* @__PURE__ */ jsx27(
6215
+ /* @__PURE__ */ jsx29(
5850
6216
  DropdownItem,
5851
6217
  {
5852
6218
  onClick: () => void toggleArchive(project),
@@ -5854,7 +6220,7 @@ function SuiteClientsProjectsDirectory({
5854
6220
  }
5855
6221
  )
5856
6222
  ] }) : null,
5857
- onDeleteProject ? /* @__PURE__ */ jsx27(
6223
+ onDeleteProject ? /* @__PURE__ */ jsx29(
5858
6224
  DropdownItem,
5859
6225
  {
5860
6226
  className: "text-red-600",
@@ -5867,20 +6233,20 @@ function SuiteClientsProjectsDirectory({
5867
6233
  ) }) : null
5868
6234
  ]
5869
6235
  }
5870
- ) }, project.id)) : /* @__PURE__ */ jsx27("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." }) })
6236
+ ) }, project.id)) : /* @__PURE__ */ jsx29("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." }) })
5871
6237
  ]
5872
6238
  }
5873
6239
  )
5874
6240
  ] }),
5875
- /* @__PURE__ */ jsx27(
6241
+ /* @__PURE__ */ jsx29(
5876
6242
  Modal,
5877
6243
  {
5878
6244
  open: editing !== null,
5879
6245
  onClose: closeEditor,
5880
6246
  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",
5881
- footer: /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
5882
- /* @__PURE__ */ jsx27(Button, { variant: "tertiary", onClick: closeEditor, disabled: saving, children: "Cancel" }),
5883
- /* @__PURE__ */ jsx27(
6247
+ footer: /* @__PURE__ */ jsxs24("div", { className: "flex justify-end gap-2", children: [
6248
+ /* @__PURE__ */ jsx29(Button, { variant: "tertiary", onClick: closeEditor, disabled: saving, children: "Cancel" }),
6249
+ /* @__PURE__ */ jsx29(
5884
6250
  Button,
5885
6251
  {
5886
6252
  variant: "primary",
@@ -5890,8 +6256,8 @@ function SuiteClientsProjectsDirectory({
5890
6256
  }
5891
6257
  )
5892
6258
  ] }),
5893
- children: /* @__PURE__ */ jsxs23("div", { className: "space-y-3", children: [
5894
- /* @__PURE__ */ jsx27(
6259
+ children: /* @__PURE__ */ jsxs24("div", { className: "space-y-3", children: [
6260
+ /* @__PURE__ */ jsx29(
5895
6261
  Input,
5896
6262
  {
5897
6263
  label: "Name",
@@ -5900,22 +6266,35 @@ function SuiteClientsProjectsDirectory({
5900
6266
  onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { name: event.target.value }))
5901
6267
  }
5902
6268
  ),
5903
- /* @__PURE__ */ jsx27(
6269
+ /* @__PURE__ */ jsx29(
5904
6270
  DirectoryIconPicker,
5905
6271
  {
5906
- value: isDirectoryIcon(draft.icon) ? draft.icon : DEFAULT_ICON,
5907
6272
  preview,
6273
+ label: draft.name,
6274
+ color: draft.color,
5908
6275
  onFileChange: chooseImage,
5909
6276
  onClear: clearImage,
5910
- onChange: (icon) => {
5911
- if (preview) clearImage();
5912
- setDraft((current) => __spreadProps(__spreadValues({}, current), { icon }));
5913
- }
6277
+ onBrowse: () => setLibraryOpen(true)
5914
6278
  }
5915
6279
  ),
5916
- /* @__PURE__ */ jsxs23("div", { children: [
5917
- /* @__PURE__ */ jsx27("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Colour" }),
5918
- /* @__PURE__ */ jsxs23("div", { className: "flex flex-wrap gap-2", children: [
6280
+ /* @__PURE__ */ jsxs24("div", { children: [
6281
+ /* @__PURE__ */ jsx29("span", { className: "mb-1.5 block text-sm font-medium text-ph-ink", children: "Colour" }),
6282
+ /* @__PURE__ */ jsxs24("div", { className: "flex flex-wrap items-center gap-2", children: [
6283
+ /* @__PURE__ */ jsx29(
6284
+ "button",
6285
+ {
6286
+ type: "button",
6287
+ "aria-label": "No colour",
6288
+ "aria-pressed": !draft.color,
6289
+ title: "No colour",
6290
+ onClick: () => setDraft(__spreadProps(__spreadValues({}, draft), { color: "" })),
6291
+ className: cn(
6292
+ "flex h-8 w-8 items-center justify-center rounded-full border border-ph-border bg-ph-surface text-ph-mutedtext ring-offset-2",
6293
+ !draft.color && "ring-2 ring-ph-brand"
6294
+ ),
6295
+ children: /* @__PURE__ */ jsx29(Prohibition, { className: "h-4 w-4", "aria-hidden": true })
6296
+ }
6297
+ ),
5919
6298
  [
5920
6299
  "#6366f1",
5921
6300
  "#0ea5e9",
@@ -5924,7 +6303,7 @@ function SuiteClientsProjectsDirectory({
5924
6303
  "#ef4444",
5925
6304
  "#a855f7",
5926
6305
  "#64748b"
5927
- ].map((color) => /* @__PURE__ */ jsx27(
6306
+ ].map((color) => /* @__PURE__ */ jsx29(
5928
6307
  "button",
5929
6308
  {
5930
6309
  type: "button",
@@ -5939,33 +6318,70 @@ function SuiteClientsProjectsDirectory({
5939
6318
  },
5940
6319
  color
5941
6320
  )),
5942
- /* @__PURE__ */ jsx27(
5943
- Input,
6321
+ /* @__PURE__ */ jsxs24(
6322
+ "label",
5944
6323
  {
5945
- hideLabel: true,
5946
- label: "Custom colour",
5947
- type: "color",
5948
- value: draft.color,
5949
- onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { color: event.target.value })),
5950
- className: "h-8 w-8 p-0"
6324
+ className: cn(
6325
+ "relative inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-full ring-1 ring-ph-border ring-offset-2",
6326
+ ![
6327
+ "#6366f1",
6328
+ "#0ea5e9",
6329
+ "#10b981",
6330
+ "#f59e0b",
6331
+ "#ef4444",
6332
+ "#a855f7",
6333
+ "#64748b"
6334
+ ].includes(draft.color) && "ring-2 ring-ph-brand"
6335
+ ),
6336
+ style: {
6337
+ background: "conic-gradient(from 0deg, #ef4444, #f59e0b, #eab308, #22c55e, #06b6d4, #3b82f6, #8b5cf6, #ec4899, #ef4444)"
6338
+ },
6339
+ title: "Custom colour",
6340
+ children: [
6341
+ /* @__PURE__ */ jsx29("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-ph-surface", children: [
6342
+ "#6366f1",
6343
+ "#0ea5e9",
6344
+ "#10b981",
6345
+ "#f59e0b",
6346
+ "#ef4444",
6347
+ "#a855f7",
6348
+ "#64748b"
6349
+ ].includes(draft.color) ? /* @__PURE__ */ jsx29(Plus2, { className: "h-3 w-3 text-ph-ink", "aria-hidden": true }) : /* @__PURE__ */ jsx29(
6350
+ "span",
6351
+ {
6352
+ className: "h-2.5 w-2.5 rounded-full",
6353
+ style: { backgroundColor: draft.color }
6354
+ }
6355
+ ) }),
6356
+ /* @__PURE__ */ jsx29(
6357
+ "input",
6358
+ {
6359
+ type: "color",
6360
+ "aria-label": "Custom colour",
6361
+ value: draft.color,
6362
+ onChange: (event) => setDraft(__spreadProps(__spreadValues({}, draft), { color: event.target.value })),
6363
+ className: "sr-only"
6364
+ }
6365
+ )
6366
+ ]
5951
6367
  }
5952
6368
  )
5953
6369
  ] })
5954
6370
  ] }),
5955
- (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs23(
6371
+ (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs24(
5956
6372
  Select,
5957
6373
  {
5958
6374
  label: "Client",
5959
6375
  value: draftClientId != null ? draftClientId : "",
5960
6376
  onChange: (event) => setDraftClientId(event.target.value || null),
5961
6377
  children: [
5962
- /* @__PURE__ */ jsx27("option", { value: "", children: "No client" }),
5963
- clients.map((client) => /* @__PURE__ */ jsx27("option", { value: client.id, children: client.name }, client.id))
6378
+ /* @__PURE__ */ jsx29("option", { value: "", children: "No client" }),
6379
+ clients.map((client) => /* @__PURE__ */ jsx29("option", { value: client.id, children: client.name }, client.id))
5964
6380
  ]
5965
6381
  }
5966
6382
  ) : null,
5967
- (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs23("label", { className: "flex items-center gap-2 text-sm text-ph-ink", children: [
5968
- /* @__PURE__ */ jsx27(
6383
+ (editing == null ? void 0 : editing.kind.includes("project")) ? /* @__PURE__ */ jsxs24("label", { className: "flex items-center gap-2 text-sm text-ph-ink", children: [
6384
+ /* @__PURE__ */ jsx29(
5969
6385
  "input",
5970
6386
  {
5971
6387
  type: "checkbox",
@@ -5978,17 +6394,26 @@ function SuiteClientsProjectsDirectory({
5978
6394
  ] })
5979
6395
  }
5980
6396
  ),
5981
- /* @__PURE__ */ jsx27(
6397
+ libraryOpen ? /* @__PURE__ */ jsx29(
6398
+ Modal,
6399
+ {
6400
+ open: true,
6401
+ onClose: () => setLibraryOpen(false),
6402
+ title: "Icon library",
6403
+ children: renderIconLibrary ? renderIconLibrary({ onPick: pickFromLibrary }) : /* @__PURE__ */ jsx29(SuitePaletteLibrary, { onPick: pickFromLibrary })
6404
+ }
6405
+ ) : null,
6406
+ /* @__PURE__ */ jsx29(
5982
6407
  Modal,
5983
6408
  {
5984
6409
  open: confirming !== null,
5985
6410
  onClose: () => setConfirming(null),
5986
6411
  title: "Confirm deletion",
5987
- footer: /* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
5988
- /* @__PURE__ */ jsx27(Button, { variant: "tertiary", onClick: () => setConfirming(null), children: "Cancel" }),
5989
- /* @__PURE__ */ jsx27(Button, { variant: "primary", onClick: () => void confirmRemove(), children: "Delete" })
6412
+ footer: /* @__PURE__ */ jsxs24("div", { className: "flex justify-end gap-2", children: [
6413
+ /* @__PURE__ */ jsx29(Button, { variant: "tertiary", onClick: () => setConfirming(null), children: "Cancel" }),
6414
+ /* @__PURE__ */ jsx29(Button, { variant: "primary", onClick: () => void confirmRemove(), children: "Delete" })
5990
6415
  ] }),
5991
- children: /* @__PURE__ */ jsxs23("p", { className: "text-sm text-ph-ink", children: [
6416
+ children: /* @__PURE__ */ jsxs24("p", { className: "text-sm text-ph-ink", children: [
5992
6417
  "Delete ",
5993
6418
  confirming == null ? void 0 : confirming.item.name,
5994
6419
  "? This cannot be undone."
@@ -6033,6 +6458,7 @@ export {
6033
6458
  SuiteBreadcrumbs,
6034
6459
  SuiteClientsProjectsDirectory,
6035
6460
  SuiteEmptyState,
6461
+ SuiteEntityIcon,
6036
6462
  SuiteIcon,
6037
6463
  SuiteIntegrationPicker,
6038
6464
  SuiteIntegrationRules,
@@ -6042,6 +6468,7 @@ export {
6042
6468
  SuiteNotificationBell,
6043
6469
  SuitePage,
6044
6470
  SuitePageHeader,
6471
+ SuitePaletteLibrary,
6045
6472
  SuiteSectionHeader,
6046
6473
  SuiteSettingsLayout,
6047
6474
  SuiteSettingsMobileNav,
@@ -6074,6 +6501,9 @@ export {
6074
6501
  cn2 as cn,
6075
6502
  consumePendingAskAiPrompt,
6076
6503
  consumeSuiteAskAiOpenFromLocation,
6504
+ fetchPaletteCollection,
6505
+ fetchPaletteLibrary,
6506
+ findPaletteIcons,
6077
6507
  getTodayGreeting,
6078
6508
  m,
6079
6509
  openSuiteAskAi,