@xenide-io/the-old-ui-theme 0.9.0 → 0.9.2

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
@@ -59,324 +59,31 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
59
59
  ));
60
60
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
61
61
 
62
- // src/suite/lib/cookies.ts
63
- function suiteCookieDomainAttr() {
64
- var _a;
65
- const host = window.location.hostname;
66
- if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
67
- return "";
68
- }
69
- if (host.endsWith(".localhost")) {
70
- return "; Domain=.localhost";
71
- }
72
- const known = /* @__PURE__ */ new Set([
73
- "tides",
74
- "kraken",
75
- "turtletime",
76
- "time",
77
- "shelly",
78
- "app",
79
- "shellstack",
80
- "portal"
81
- ]);
82
- const parts = host.split(".");
83
- if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
84
- return `; Domain=.${parts.slice(1).join(".")}`;
85
- }
86
- if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
87
- return "";
88
- }
89
- function readCookie(name) {
90
- const prefix = `${name}=`;
91
- for (const part of document.cookie.split(";")) {
92
- const trimmed = part.trim();
93
- if (trimmed.startsWith(prefix)) {
94
- return decodeURIComponent(trimmed.slice(prefix.length));
95
- }
96
- }
97
- return null;
98
- }
99
- function writeCookie(name, value) {
100
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
101
- document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
102
- }
103
- function clearCookie(name) {
104
- const secure = window.location.protocol === "https:" ? "; Secure" : "";
105
- document.cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
106
- }
107
- var init_cookies = __esm({
108
- "src/suite/lib/cookies.ts"() {
109
- "use strict";
110
- }
111
- });
112
-
113
- // src/suite/lib/theme-cookie.ts
114
- var SUITE_THEME_COOKIE, SUITE_THEME_CHANNEL;
115
- var init_theme_cookie = __esm({
116
- "src/suite/lib/theme-cookie.ts"() {
117
- "use strict";
118
- SUITE_THEME_COOKIE = "xenide-suite-theme";
119
- SUITE_THEME_CHANNEL = "xenide-suite-theme";
120
- }
62
+ // src/suite/components/ai-message-markdown.tsx
63
+ var ai_message_markdown_exports = {};
64
+ __export(ai_message_markdown_exports, {
65
+ default: () => SuiteAiMarkdownMessage
121
66
  });
122
-
123
- // src/suite/components/theme-provider.tsx
124
- function broadcastTheme(theme) {
125
- if (typeof BroadcastChannel === "undefined") return;
126
- try {
127
- suiteThemeChannel != null ? suiteThemeChannel : suiteThemeChannel = new BroadcastChannel(SUITE_THEME_CHANNEL);
128
- suiteThemeChannel.postMessage(theme);
129
- } catch (e) {
130
- }
131
- }
132
- function readSharedTheme() {
133
- if (typeof window === "undefined") return null;
134
- try {
135
- const value = readCookie(SUITE_THEME_COOKIE);
136
- return value === "light" || value === "dark" || value === "system" ? value : null;
137
- } catch (e) {
138
- return null;
139
- }
140
- }
141
- function writeSharedTheme(theme) {
142
- try {
143
- writeCookie(SUITE_THEME_COOKIE, theme);
144
- } catch (e) {
145
- }
146
- }
147
- function systemTheme(fallback) {
148
- if (typeof window === "undefined") return fallback;
149
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
150
- }
151
- function resolveTheme(theme, fallback) {
152
- return theme === "system" ? systemTheme(fallback) : theme;
153
- }
154
- function applyTheme(theme, config) {
155
- const resolved = resolveTheme(theme, config.fallbackTheme);
156
- if (typeof document === "undefined") return resolved;
157
- document.documentElement.setAttribute(
158
- "data-theme",
159
- resolved === "dark" ? config.darkThemeId : config.lightThemeId
160
- );
161
- document.documentElement.classList.toggle("dark", resolved === "dark");
162
- if (config.themeColorLight && config.themeColorDark) {
163
- const meta = document.getElementById(
164
- "theme-color-meta"
165
- );
166
- if (meta) {
167
- meta.content = resolved === "light" ? config.themeColorLight : config.themeColorDark;
168
- }
169
- }
170
- return resolved;
171
- }
172
- function readStoredTheme(storageKey) {
173
- if (typeof window === "undefined") return "system";
174
- const shared = readSharedTheme();
175
- if (shared) return shared;
176
- try {
177
- const stored = localStorage.getItem(storageKey);
178
- if (stored === "light" || stored === "dark" || stored === "system")
179
- return stored;
180
- } catch (e) {
181
- }
182
- return "system";
183
- }
184
- function SuiteThemeProvider({
185
- config,
186
- children
187
- }) {
188
- const [state, setState] = (0, import_react10.useState)(() => {
189
- const theme = readStoredTheme(config.storageKey);
190
- if (typeof document === "undefined") {
191
- return { theme, resolvedTheme: config.fallbackTheme };
192
- }
193
- const domTheme = document.documentElement.getAttribute("data-theme");
194
- const resolvedTheme = domTheme === config.darkThemeId ? "dark" : domTheme === config.lightThemeId ? "light" : resolveTheme(theme, config.fallbackTheme);
195
- return { theme, resolvedTheme };
196
- });
197
- const themeRef = (0, import_react10.useRef)(state.theme);
198
- themeRef.current = state.theme;
199
- (0, import_react10.useEffect)(() => {
200
- applyTheme(state.theme, config);
201
- }, [state.theme, config]);
202
- (0, import_react10.useEffect)(() => {
203
- if (readSharedTheme() == null) writeSharedTheme(state.theme);
204
- }, []);
205
- (0, import_react10.useEffect)(() => {
206
- if (state.theme !== "system") return;
207
- const media = window.matchMedia("(prefers-color-scheme: dark)");
208
- const update = () => {
209
- const resolved = applyTheme("system", config);
210
- setState((current) => __spreadProps(__spreadValues({}, current), { resolvedTheme: resolved }));
211
- };
212
- media.addEventListener("change", update);
213
- return () => media.removeEventListener("change", update);
214
- }, [state.theme, config]);
215
- (0, import_react10.useEffect)(() => {
216
- let channel = null;
217
- try {
218
- channel = new BroadcastChannel(SUITE_THEME_CHANNEL);
219
- } catch (e) {
220
- channel = null;
221
- }
222
- const adopt = (next) => {
223
- if (next !== "light" && next !== "dark" && next !== "system") return;
224
- if (next === themeRef.current) return;
225
- const resolved = applyTheme(next, config);
226
- try {
227
- localStorage.setItem(config.storageKey, next);
228
- } catch (e) {
229
- }
230
- setState({ theme: next, resolvedTheme: resolved });
231
- };
232
- const readShared = () => adopt(readSharedTheme());
233
- const onChannel = (event) => adopt(event.data);
234
- const onStorage = (event) => {
235
- if (event.key === config.storageKey) adopt(event.newValue);
236
- };
237
- let poll = null;
238
- const startPolling = () => {
239
- if (poll == null) poll = setInterval(readShared, 2e3);
240
- };
241
- const stopPolling = () => {
242
- if (poll != null) {
243
- clearInterval(poll);
244
- poll = null;
245
- }
246
- };
247
- const onVisibility = () => {
248
- if (document.visibilityState === "visible") {
249
- readShared();
250
- startPolling();
251
- } else {
252
- stopPolling();
253
- }
254
- };
255
- channel == null ? void 0 : channel.addEventListener("message", onChannel);
256
- window.addEventListener("storage", onStorage);
257
- window.addEventListener("focus", readShared);
258
- document.addEventListener("visibilitychange", onVisibility);
259
- if (document.visibilityState === "visible") startPolling();
260
- return () => {
261
- channel == null ? void 0 : channel.removeEventListener("message", onChannel);
262
- channel == null ? void 0 : channel.close();
263
- window.removeEventListener("storage", onStorage);
264
- window.removeEventListener("focus", readShared);
265
- document.removeEventListener("visibilitychange", onVisibility);
266
- stopPolling();
267
- };
268
- }, [config]);
269
- const setTheme = (0, import_react10.useCallback)(
270
- (next) => {
271
- const resolved = applyTheme(next, config);
272
- setState({ theme: next, resolvedTheme: resolved });
273
- try {
274
- localStorage.setItem(config.storageKey, next);
275
- } catch (e) {
276
- }
277
- writeSharedTheme(next);
278
- broadcastTheme(next);
279
- },
280
- [config]
281
- );
282
- const toggleTheme = (0, import_react10.useCallback)(() => {
283
- const next = resolveTheme(themeRef.current, config.fallbackTheme) === "dark" ? "light" : "dark";
284
- setTheme(next);
285
- }, [config, setTheme]);
286
- const value = (0, import_react10.useMemo)(
287
- () => ({ theme: state.theme, resolvedTheme: state.resolvedTheme, setTheme, toggleTheme }),
288
- [state.theme, state.resolvedTheme, setTheme, toggleTheme]
289
- );
290
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SuiteThemeContext.Provider, { value, children });
291
- }
292
- function useSuiteTheme() {
293
- const ctx = (0, import_react10.useContext)(SuiteThemeContext);
294
- if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
295
- return ctx;
296
- }
297
- var import_react10, import_jsx_runtime21, SuiteThemeContext, suiteThemeChannel;
298
- var init_theme_provider = __esm({
299
- "src/suite/components/theme-provider.tsx"() {
300
- "use strict";
301
- "use client";
302
- import_react10 = require("react");
303
- init_cookies();
304
- init_theme_cookie();
305
- import_jsx_runtime21 = require("react/jsx-runtime");
306
- SuiteThemeContext = (0, import_react10.createContext)(null);
307
- suiteThemeChannel = null;
308
- }
309
- });
310
-
311
- // src/suite/components/ai-message-blocknote.tsx
312
- var ai_message_blocknote_exports = {};
313
- __export(ai_message_blocknote_exports, {
314
- default: () => SuiteAiBlockNoteMessage
315
- });
316
- function SuiteAiBlockNoteMessage({
67
+ function SuiteAiMarkdownMessage({
317
68
  markdown
318
69
  }) {
319
- const { resolvedTheme } = useSuiteTheme();
320
- const editor = (0, import_react13.useCreateBlockNote)({ schema: assistantSchema });
321
- useIsomorphicLayoutEffect(() => {
322
- try {
323
- const blocks = editor.tryParseMarkdownToBlocks(markdown);
324
- editor.replaceBlocks(
325
- editor.document,
326
- blocks.length > 0 ? blocks : [{ type: "paragraph", content: markdown }]
327
- );
328
- } catch (e) {
329
- editor.replaceBlocks(editor.document, [
330
- { type: "paragraph", content: markdown }
331
- ]);
332
- }
333
- }, [editor, markdown]);
334
- (0, import_react12.useEffect)(() => {
335
- const el = editor.domElement;
336
- el == null ? void 0 : el.setAttribute("aria-label", "Assistant message");
337
- }, [editor]);
338
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
339
- import_react13.BlockNoteViewRaw,
70
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "suite-ai-markdown", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
71
+ import_react_markdown.default,
340
72
  {
341
- editor,
342
- editable: false,
343
- theme: resolvedTheme,
344
- className: "suite-ai-blocknote",
345
- formattingToolbar: false,
346
- sideMenu: false,
347
- slashMenu: false,
348
- linkToolbar: false,
349
- filePanel: false,
350
- tableHandles: false,
351
- comments: false
73
+ remarkPlugins: [import_remark_gfm.default],
74
+ components: { img: () => null },
75
+ children: markdown
352
76
  }
353
- );
77
+ ) });
354
78
  }
355
- var import_react12, import_core, import_react13, import_style, import_jsx_runtime23, useIsomorphicLayoutEffect, assistantSchema;
356
- var init_ai_message_blocknote = __esm({
357
- "src/suite/components/ai-message-blocknote.tsx"() {
79
+ var import_react_markdown, import_remark_gfm, import_jsx_runtime23;
80
+ var init_ai_message_markdown = __esm({
81
+ "src/suite/components/ai-message-markdown.tsx"() {
358
82
  "use strict";
359
83
  "use client";
360
- import_react12 = require("react");
361
- import_core = require("@blocknote/core");
362
- import_react13 = require("@blocknote/react");
363
- import_style = require("@blocknote/react/style.css");
364
- init_theme_provider();
84
+ import_react_markdown = __toESM(require("react-markdown"));
85
+ import_remark_gfm = __toESM(require("remark-gfm"));
365
86
  import_jsx_runtime23 = require("react/jsx-runtime");
366
- useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react12.useLayoutEffect : import_react12.useEffect;
367
- assistantSchema = import_core.BlockNoteSchema.create({
368
- blockSpecs: {
369
- paragraph: import_core.defaultBlockSpecs.paragraph,
370
- heading: import_core.defaultBlockSpecs.heading,
371
- bulletListItem: import_core.defaultBlockSpecs.bulletListItem,
372
- numberedListItem: import_core.defaultBlockSpecs.numberedListItem,
373
- checkListItem: import_core.defaultBlockSpecs.checkListItem,
374
- codeBlock: import_core.defaultBlockSpecs.codeBlock,
375
- quote: import_core.defaultBlockSpecs.quote,
376
- table: import_core.defaultBlockSpecs.table,
377
- divider: import_core.defaultBlockSpecs.divider
378
- }
379
- });
380
87
  }
381
88
  });
382
89
 
@@ -460,7 +167,7 @@ __export(suite_exports, {
460
167
  consumePendingAskAiPrompt: () => consumePendingAskAiPrompt,
461
168
  consumeSuiteAskAiOpenFromLocation: () => consumeSuiteAskAiOpenFromLocation,
462
169
  getTodayGreeting: () => getTodayGreeting,
463
- m: () => import_react17.m,
170
+ m: () => import_react15.m,
464
171
  openSuiteAskAi: () => openSuiteAskAi,
465
172
  pathWithSuiteAskAiOpen: () => pathWithSuiteAskAiOpen,
466
173
  persistSidebarWidth: () => persistSidebarWidth,
@@ -3268,11 +2975,238 @@ function TodayCalibrating({
3268
2975
  );
3269
2976
  }
3270
2977
 
3271
- // src/suite/index.ts
3272
- init_theme_provider();
2978
+ // src/suite/components/theme-provider.tsx
2979
+ var import_react10 = require("react");
2980
+
2981
+ // src/suite/lib/cookies.ts
2982
+ function suiteCookieDomainAttr() {
2983
+ var _a;
2984
+ const host = window.location.hostname;
2985
+ if (host === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) {
2986
+ return "";
2987
+ }
2988
+ if (host.endsWith(".localhost")) {
2989
+ return "; Domain=.localhost";
2990
+ }
2991
+ const known = /* @__PURE__ */ new Set([
2992
+ "tides",
2993
+ "kraken",
2994
+ "turtletime",
2995
+ "time",
2996
+ "shelly",
2997
+ "app",
2998
+ "shellstack",
2999
+ "portal"
3000
+ ]);
3001
+ const parts = host.split(".");
3002
+ if (parts.length >= 3 && known.has((_a = parts[0]) != null ? _a : "")) {
3003
+ return `; Domain=.${parts.slice(1).join(".")}`;
3004
+ }
3005
+ if (parts.length >= 2) return `; Domain=.${parts.slice(1).join(".")}`;
3006
+ return "";
3007
+ }
3008
+ function readCookie(name) {
3009
+ const prefix = `${name}=`;
3010
+ for (const part of document.cookie.split(";")) {
3011
+ const trimmed = part.trim();
3012
+ if (trimmed.startsWith(prefix)) {
3013
+ return decodeURIComponent(trimmed.slice(prefix.length));
3014
+ }
3015
+ }
3016
+ return null;
3017
+ }
3018
+ function writeCookie(name, value) {
3019
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
3020
+ document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=31536000; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
3021
+ }
3022
+ function clearCookie(name) {
3023
+ const secure = window.location.protocol === "https:" ? "; Secure" : "";
3024
+ document.cookie = `${name}=; Path=/; Max-Age=0; SameSite=Lax${suiteCookieDomainAttr()}${secure}`;
3025
+ }
3026
+
3027
+ // src/suite/lib/theme-cookie.ts
3028
+ var SUITE_THEME_COOKIE = "xenide-suite-theme";
3029
+ var SUITE_THEME_CHANNEL = "xenide-suite-theme";
3030
+
3031
+ // src/suite/components/theme-provider.tsx
3032
+ var import_jsx_runtime21 = require("react/jsx-runtime");
3033
+ var SuiteThemeContext = (0, import_react10.createContext)(null);
3034
+ var suiteThemeChannel = null;
3035
+ function broadcastTheme(theme) {
3036
+ if (typeof BroadcastChannel === "undefined") return;
3037
+ try {
3038
+ suiteThemeChannel != null ? suiteThemeChannel : suiteThemeChannel = new BroadcastChannel(SUITE_THEME_CHANNEL);
3039
+ suiteThemeChannel.postMessage(theme);
3040
+ } catch (e) {
3041
+ }
3042
+ }
3043
+ function readSharedTheme() {
3044
+ if (typeof window === "undefined") return null;
3045
+ try {
3046
+ const value = readCookie(SUITE_THEME_COOKIE);
3047
+ return value === "light" || value === "dark" || value === "system" ? value : null;
3048
+ } catch (e) {
3049
+ return null;
3050
+ }
3051
+ }
3052
+ function writeSharedTheme(theme) {
3053
+ try {
3054
+ writeCookie(SUITE_THEME_COOKIE, theme);
3055
+ } catch (e) {
3056
+ }
3057
+ }
3058
+ function systemTheme(fallback) {
3059
+ if (typeof window === "undefined") return fallback;
3060
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
3061
+ }
3062
+ function resolveTheme(theme, fallback) {
3063
+ return theme === "system" ? systemTheme(fallback) : theme;
3064
+ }
3065
+ function applyTheme(theme, config) {
3066
+ const resolved = resolveTheme(theme, config.fallbackTheme);
3067
+ if (typeof document === "undefined") return resolved;
3068
+ document.documentElement.setAttribute(
3069
+ "data-theme",
3070
+ resolved === "dark" ? config.darkThemeId : config.lightThemeId
3071
+ );
3072
+ document.documentElement.classList.toggle("dark", resolved === "dark");
3073
+ if (config.themeColorLight && config.themeColorDark) {
3074
+ const meta = document.getElementById(
3075
+ "theme-color-meta"
3076
+ );
3077
+ if (meta) {
3078
+ meta.content = resolved === "light" ? config.themeColorLight : config.themeColorDark;
3079
+ }
3080
+ }
3081
+ return resolved;
3082
+ }
3083
+ function readStoredTheme(storageKey) {
3084
+ if (typeof window === "undefined") return "system";
3085
+ const shared = readSharedTheme();
3086
+ if (shared) return shared;
3087
+ try {
3088
+ const stored = localStorage.getItem(storageKey);
3089
+ if (stored === "light" || stored === "dark" || stored === "system")
3090
+ return stored;
3091
+ } catch (e) {
3092
+ }
3093
+ return "system";
3094
+ }
3095
+ function SuiteThemeProvider({
3096
+ config,
3097
+ children
3098
+ }) {
3099
+ const [state, setState] = (0, import_react10.useState)(() => {
3100
+ const theme = readStoredTheme(config.storageKey);
3101
+ if (typeof document === "undefined") {
3102
+ return { theme, resolvedTheme: config.fallbackTheme };
3103
+ }
3104
+ const domTheme = document.documentElement.getAttribute("data-theme");
3105
+ const resolvedTheme = domTheme === config.darkThemeId ? "dark" : domTheme === config.lightThemeId ? "light" : resolveTheme(theme, config.fallbackTheme);
3106
+ return { theme, resolvedTheme };
3107
+ });
3108
+ const themeRef = (0, import_react10.useRef)(state.theme);
3109
+ themeRef.current = state.theme;
3110
+ (0, import_react10.useEffect)(() => {
3111
+ applyTheme(state.theme, config);
3112
+ }, [state.theme, config]);
3113
+ (0, import_react10.useEffect)(() => {
3114
+ if (readSharedTheme() == null) writeSharedTheme(state.theme);
3115
+ }, []);
3116
+ (0, import_react10.useEffect)(() => {
3117
+ if (state.theme !== "system") return;
3118
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
3119
+ const update = () => {
3120
+ const resolved = applyTheme("system", config);
3121
+ setState((current) => __spreadProps(__spreadValues({}, current), { resolvedTheme: resolved }));
3122
+ };
3123
+ media.addEventListener("change", update);
3124
+ return () => media.removeEventListener("change", update);
3125
+ }, [state.theme, config]);
3126
+ (0, import_react10.useEffect)(() => {
3127
+ let channel = null;
3128
+ try {
3129
+ channel = new BroadcastChannel(SUITE_THEME_CHANNEL);
3130
+ } catch (e) {
3131
+ channel = null;
3132
+ }
3133
+ const adopt = (next) => {
3134
+ if (next !== "light" && next !== "dark" && next !== "system") return;
3135
+ if (next === themeRef.current) return;
3136
+ const resolved = applyTheme(next, config);
3137
+ try {
3138
+ localStorage.setItem(config.storageKey, next);
3139
+ } catch (e) {
3140
+ }
3141
+ setState({ theme: next, resolvedTheme: resolved });
3142
+ };
3143
+ const readShared = () => adopt(readSharedTheme());
3144
+ const onChannel = (event) => adopt(event.data);
3145
+ const onStorage = (event) => {
3146
+ if (event.key === config.storageKey) adopt(event.newValue);
3147
+ };
3148
+ let poll = null;
3149
+ const startPolling = () => {
3150
+ if (poll == null) poll = setInterval(readShared, 2e3);
3151
+ };
3152
+ const stopPolling = () => {
3153
+ if (poll != null) {
3154
+ clearInterval(poll);
3155
+ poll = null;
3156
+ }
3157
+ };
3158
+ const onVisibility = () => {
3159
+ if (document.visibilityState === "visible") {
3160
+ readShared();
3161
+ startPolling();
3162
+ } else {
3163
+ stopPolling();
3164
+ }
3165
+ };
3166
+ channel == null ? void 0 : channel.addEventListener("message", onChannel);
3167
+ window.addEventListener("storage", onStorage);
3168
+ window.addEventListener("focus", readShared);
3169
+ document.addEventListener("visibilitychange", onVisibility);
3170
+ if (document.visibilityState === "visible") startPolling();
3171
+ return () => {
3172
+ channel == null ? void 0 : channel.removeEventListener("message", onChannel);
3173
+ channel == null ? void 0 : channel.close();
3174
+ window.removeEventListener("storage", onStorage);
3175
+ window.removeEventListener("focus", readShared);
3176
+ document.removeEventListener("visibilitychange", onVisibility);
3177
+ stopPolling();
3178
+ };
3179
+ }, [config]);
3180
+ const setTheme = (0, import_react10.useCallback)(
3181
+ (next) => {
3182
+ const resolved = applyTheme(next, config);
3183
+ setState({ theme: next, resolvedTheme: resolved });
3184
+ try {
3185
+ localStorage.setItem(config.storageKey, next);
3186
+ } catch (e) {
3187
+ }
3188
+ writeSharedTheme(next);
3189
+ broadcastTheme(next);
3190
+ },
3191
+ [config]
3192
+ );
3193
+ const toggleTheme = (0, import_react10.useCallback)(() => {
3194
+ const next = resolveTheme(themeRef.current, config.fallbackTheme) === "dark" ? "light" : "dark";
3195
+ setTheme(next);
3196
+ }, [config, setTheme]);
3197
+ const value = (0, import_react10.useMemo)(
3198
+ () => ({ theme: state.theme, resolvedTheme: state.resolvedTheme, setTheme, toggleTheme }),
3199
+ [state.theme, state.resolvedTheme, setTheme, toggleTheme]
3200
+ );
3201
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SuiteThemeContext.Provider, { value, children });
3202
+ }
3203
+ function useSuiteTheme() {
3204
+ const ctx = (0, import_react10.useContext)(SuiteThemeContext);
3205
+ if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
3206
+ return ctx;
3207
+ }
3273
3208
 
3274
3209
  // src/suite/lib/theme-boot.ts
3275
- init_theme_cookie();
3276
3210
  function suiteThemeBootScript(options) {
3277
3211
  var _a, _b, _c, _d;
3278
3212
  const light = JSON.stringify(options.lightThemeId);
@@ -3285,7 +3219,7 @@ function suiteThemeBootScript(options) {
3285
3219
  }
3286
3220
 
3287
3221
  // src/suite/components/ai-panel.tsx
3288
- var import_react14 = require("react");
3222
+ var import_react12 = require("react");
3289
3223
  var import_iconoir_react8 = require("iconoir-react");
3290
3224
 
3291
3225
  // src/components/ui/Tooltip.tsx
@@ -3432,7 +3366,7 @@ function Tooltip({
3432
3366
 
3433
3367
  // src/suite/components/ai-panel.tsx
3434
3368
  var import_jsx_runtime24 = require("react/jsx-runtime");
3435
- var SuiteAiBlockNoteMessage2 = (0, import_react14.lazy)(() => Promise.resolve().then(() => (init_ai_message_blocknote(), ai_message_blocknote_exports)));
3369
+ var SuiteAiMarkdownMessage2 = (0, import_react12.lazy)(() => Promise.resolve().then(() => (init_ai_message_markdown(), ai_message_markdown_exports)));
3436
3370
  var SUITE_OPEN_ASK_AI_EVENT = "shellstack:open-ask-ai";
3437
3371
  var SUITE_ASK_AI_OPEN_KEY = "shellstack:shelly-open";
3438
3372
  var SUITE_ASK_AI_OPEN_QUERY = "shelly";
@@ -3517,11 +3451,11 @@ function SuiteAiPanel({
3517
3451
  resolveAction,
3518
3452
  isWaitingForReply = false
3519
3453
  }) {
3520
- const inputId = (0, import_react14.useId)();
3521
- const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react14.useState)(false);
3522
- const [resolvingId, setResolvingId] = (0, import_react14.useState)("");
3454
+ const inputId = (0, import_react12.useId)();
3455
+ const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react12.useState)(false);
3456
+ const [resolvingId, setResolvingId] = (0, import_react12.useState)("");
3523
3457
  const open = openProp != null ? openProp : uncontrolledOpen;
3524
- const setOpen = (0, import_react14.useCallback)(
3458
+ const setOpen = (0, import_react12.useCallback)(
3525
3459
  (next) => {
3526
3460
  persistSuiteAskAiOpen(next);
3527
3461
  if (openProp === void 0) setUncontrolledOpen(next);
@@ -3529,18 +3463,18 @@ function SuiteAiPanel({
3529
3463
  },
3530
3464
  [onOpenChange, openProp]
3531
3465
  );
3532
- const [prompt, setPrompt] = (0, import_react14.useState)("");
3533
- const [messages, setMessages] = (0, import_react14.useState)([]);
3534
- const [loading, setLoading] = (0, import_react14.useState)(false);
3535
- const [hydrating, setHydrating] = (0, import_react14.useState)(false);
3536
- const [error, setError] = (0, import_react14.useState)("");
3537
- const [atBottom, setAtBottom] = (0, import_react14.useState)(true);
3538
- const scrollerRef = (0, import_react14.useRef)(null);
3539
- const textareaRef = (0, import_react14.useRef)(null);
3540
- const abortRef = (0, import_react14.useRef)(null);
3541
- const pendingPromptRef = (0, import_react14.useRef)(null);
3466
+ const [prompt, setPrompt] = (0, import_react12.useState)("");
3467
+ const [messages, setMessages] = (0, import_react12.useState)([]);
3468
+ const [loading, setLoading] = (0, import_react12.useState)(false);
3469
+ const [hydrating, setHydrating] = (0, import_react12.useState)(false);
3470
+ const [error, setError] = (0, import_react12.useState)("");
3471
+ const [atBottom, setAtBottom] = (0, import_react12.useState)(true);
3472
+ const scrollerRef = (0, import_react12.useRef)(null);
3473
+ const textareaRef = (0, import_react12.useRef)(null);
3474
+ const abortRef = (0, import_react12.useRef)(null);
3475
+ const pendingPromptRef = (0, import_react12.useRef)(null);
3542
3476
  const waiting = loading || isWaitingForReply;
3543
- (0, import_react14.useEffect)(() => {
3477
+ (0, import_react12.useEffect)(() => {
3544
3478
  function onOpen(event) {
3545
3479
  var _a;
3546
3480
  const detail = event.detail;
@@ -3554,19 +3488,19 @@ function SuiteAiPanel({
3554
3488
  window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
3555
3489
  return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
3556
3490
  }, [setOpen]);
3557
- const scrollToBottom = (0, import_react14.useCallback)((behavior = "auto") => {
3491
+ const scrollToBottom = (0, import_react12.useCallback)((behavior = "auto") => {
3558
3492
  const el = scrollerRef.current;
3559
3493
  if (!el) return;
3560
3494
  el.scrollTo({ top: el.scrollHeight, behavior });
3561
3495
  setAtBottom(true);
3562
3496
  }, []);
3563
- const handleScroll = (0, import_react14.useCallback)(() => {
3497
+ const handleScroll = (0, import_react12.useCallback)(() => {
3564
3498
  const el = scrollerRef.current;
3565
3499
  if (!el) return;
3566
3500
  const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
3567
3501
  setAtBottom(distance < 64);
3568
3502
  }, []);
3569
- const hydrate = (0, import_react14.useCallback)(async () => {
3503
+ const hydrate = (0, import_react12.useCallback)(async () => {
3570
3504
  var _a, _b, _c;
3571
3505
  setHydrating(true);
3572
3506
  setError("");
@@ -3589,7 +3523,7 @@ function SuiteAiPanel({
3589
3523
  setHydrating(false);
3590
3524
  }
3591
3525
  }, [fetchChat]);
3592
- (0, import_react14.useEffect)(() => {
3526
+ (0, import_react12.useEffect)(() => {
3593
3527
  var _a;
3594
3528
  if (!open) return;
3595
3529
  const queued = (_a = pendingPromptRef.current) != null ? _a : consumePendingAskAiPrompt();
@@ -3600,14 +3534,14 @@ function SuiteAiPanel({
3600
3534
  if (pending) setPrompt(pending);
3601
3535
  });
3602
3536
  }, [open, hydrate]);
3603
- (0, import_react14.useEffect)(() => {
3537
+ (0, import_react12.useEffect)(() => {
3604
3538
  if (open && atBottom) scrollToBottom();
3605
3539
  }, [messages, waiting, open, atBottom, scrollToBottom]);
3606
- (0, import_react14.useEffect)(() => {
3540
+ (0, import_react12.useEffect)(() => {
3607
3541
  var _a;
3608
3542
  if (open && !hydrating) (_a = textareaRef.current) == null ? void 0 : _a.focus();
3609
3543
  }, [open, hydrating]);
3610
- (0, import_react14.useLayoutEffect)(() => {
3544
+ (0, import_react12.useLayoutEffect)(() => {
3611
3545
  const el = textareaRef.current;
3612
3546
  if (!el) return;
3613
3547
  el.style.height = "auto";
@@ -3822,7 +3756,7 @@ function SuiteAiPanel({
3822
3756
  ),
3823
3757
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "min-w-0 max-w-[85%] space-y-2", children: [
3824
3758
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "rounded-2xl rounded-bl-md bg-ph-muted px-3 py-2 text-sm leading-relaxed text-ph-ink", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3825
- import_react14.Suspense,
3759
+ import_react12.Suspense,
3826
3760
  {
3827
3761
  fallback: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3828
3762
  "div",
@@ -3838,7 +3772,7 @@ function SuiteAiPanel({
3838
3772
  ]
3839
3773
  }
3840
3774
  ),
3841
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SuiteAiBlockNoteMessage2, { markdown: message.content })
3775
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SuiteAiMarkdownMessage2, { markdown: message.content })
3842
3776
  }
3843
3777
  ) }),
3844
3778
  ((_a = message.actions) != null ? _a : []).map((action) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
@@ -4005,7 +3939,7 @@ function SuiteAiPanel({
4005
3939
  }
4006
3940
 
4007
3941
  // src/suite/components/workspace-switcher.tsx
4008
- var import_react15 = require("react");
3942
+ var import_react13 = require("react");
4009
3943
  var import_iconoir_react9 = require("iconoir-react");
4010
3944
  var import_jsx_runtime25 = require("react/jsx-runtime");
4011
3945
  function SuiteWorkspaceSwitcher({
@@ -4023,7 +3957,7 @@ function SuiteWorkspaceSwitcher({
4023
3957
  footer
4024
3958
  }) {
4025
3959
  var _a;
4026
- const [open, setOpen] = (0, import_react15.useState)(false);
3960
+ const [open, setOpen] = (0, import_react13.useState)(false);
4027
3961
  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 }] : [];
4028
3962
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4029
3963
  DropdownMenu2,
@@ -4168,8 +4102,7 @@ function SuiteIcon({
4168
4102
  }
4169
4103
 
4170
4104
  // src/suite/lib/use-sidebar-width.ts
4171
- var import_react16 = require("react");
4172
- init_cookies();
4105
+ var import_react14 = require("react");
4173
4106
  var SIDEBAR_RAIL_WIDTH = 56;
4174
4107
  var SIDEBAR_COLLAPSE_THRESHOLD = 80;
4175
4108
  var SIDEBAR_MIN_EXPANDED_WIDTH = 180;
@@ -4254,10 +4187,10 @@ function resetSuiteSidebarWidth() {
4254
4187
  }
4255
4188
  function useSidebarWidth(storageKey = SUITE_SIDEBAR_WIDTH_KEY, defaultWidth = SIDEBAR_DEFAULT_WIDTH) {
4256
4189
  const fallbackWidth = snapWidth(clampWidth(defaultWidth));
4257
- const [width, setWidth] = (0, import_react16.useState)(fallbackWidth);
4258
- const [narrowViewport, setNarrowViewport] = (0, import_react16.useState)(false);
4190
+ const [width, setWidth] = (0, import_react14.useState)(fallbackWidth);
4191
+ const [narrowViewport, setNarrowViewport] = (0, import_react14.useState)(false);
4259
4192
  const collapsed = narrowViewport || width <= SIDEBAR_COLLAPSE_THRESHOLD;
4260
- (0, import_react16.useLayoutEffect)(() => {
4193
+ (0, import_react14.useLayoutEffect)(() => {
4261
4194
  const sync = () => {
4262
4195
  const stored = readSidebarWidth(storageKey);
4263
4196
  if (stored == null) return;
@@ -4273,20 +4206,20 @@ function useSidebarWidth(storageKey = SUITE_SIDEBAR_WIDTH_KEY, defaultWidth = SI
4273
4206
  document.removeEventListener("visibilitychange", sync);
4274
4207
  };
4275
4208
  }, [storageKey]);
4276
- (0, import_react16.useLayoutEffect)(() => {
4209
+ (0, import_react14.useLayoutEffect)(() => {
4277
4210
  const media = window.matchMedia("(max-width: 639px)");
4278
4211
  const sync = () => setNarrowViewport(media.matches);
4279
4212
  sync();
4280
4213
  media.addEventListener("change", sync);
4281
4214
  return () => media.removeEventListener("change", sync);
4282
4215
  }, []);
4283
- const persist = (0, import_react16.useCallback)(
4216
+ const persist = (0, import_react14.useCallback)(
4284
4217
  (value) => {
4285
4218
  persistSidebarWidth(storageKey, value);
4286
4219
  },
4287
4220
  [storageKey]
4288
4221
  );
4289
- const setCollapsed = (0, import_react16.useCallback)(
4222
+ const setCollapsed = (0, import_react14.useCallback)(
4290
4223
  (value) => {
4291
4224
  setWidth((current) => {
4292
4225
  const next = value ? SIDEBAR_RAIL_WIDTH : current <= SIDEBAR_COLLAPSE_THRESHOLD ? fallbackWidth : snapWidth(current);
@@ -4296,11 +4229,11 @@ function useSidebarWidth(storageKey = SUITE_SIDEBAR_WIDTH_KEY, defaultWidth = SI
4296
4229
  },
4297
4230
  [fallbackWidth, persist]
4298
4231
  );
4299
- const resetWidth = (0, import_react16.useCallback)(() => {
4232
+ const resetWidth = (0, import_react14.useCallback)(() => {
4300
4233
  setWidth(fallbackWidth);
4301
4234
  persist(fallbackWidth);
4302
4235
  }, [fallbackWidth, persist]);
4303
- const startResize = (0, import_react16.useCallback)(
4236
+ const startResize = (0, import_react14.useCallback)(
4304
4237
  (event) => {
4305
4238
  event.preventDefault();
4306
4239
  const startX = event.clientX;
@@ -4322,7 +4255,7 @@ function useSidebarWidth(storageKey = SUITE_SIDEBAR_WIDTH_KEY, defaultWidth = SI
4322
4255
  },
4323
4256
  [persist, width]
4324
4257
  );
4325
- const resizeBy = (0, import_react16.useCallback)(
4258
+ const resizeBy = (0, import_react14.useCallback)(
4326
4259
  (delta) => {
4327
4260
  setWidth((current) => {
4328
4261
  const next = clampWidth(current + delta);
@@ -4336,10 +4269,10 @@ function useSidebarWidth(storageKey = SUITE_SIDEBAR_WIDTH_KEY, defaultWidth = SI
4336
4269
  }
4337
4270
 
4338
4271
  // src/suite/lib/motion.tsx
4339
- var import_react17 = require("motion/react");
4272
+ var import_react15 = require("motion/react");
4340
4273
  var import_jsx_runtime27 = require("react/jsx-runtime");
4341
4274
  function SuiteMotionProvider({ children }) {
4342
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react17.LazyMotion, { features: import_react17.domAnimation, strict: true, children });
4275
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react15.LazyMotion, { features: import_react15.domAnimation, strict: true, children });
4343
4276
  }
4344
4277
  var SUITE_SPRINGS = {
4345
4278
  /** Snappy panel/sheet entrances — small overshoot. */
@@ -4496,7 +4429,7 @@ function SuiteEmptyState({
4496
4429
  }
4497
4430
 
4498
4431
  // src/suite/components/suite-settings-mobile-nav.tsx
4499
- var import_react18 = require("react");
4432
+ var import_react16 = require("react");
4500
4433
  var import_jsx_runtime29 = require("react/jsx-runtime");
4501
4434
  function SuiteSettingsMobileNav({
4502
4435
  items,
@@ -4515,7 +4448,7 @@ function SuiteSettingsMobileNav({
4515
4448
  children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex snap-x gap-2 overflow-x-auto pb-3 pt-1 scrollbar-hide [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: items.map((item) => {
4516
4449
  const Icon = item.icon;
4517
4450
  const active = activeHref === item.href || activeHref.startsWith(`${item.href}/`);
4518
- const iconNode = (0, import_react18.isValidElement)(item.icon) ? item.icon : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4451
+ const iconNode = (0, import_react16.isValidElement)(item.icon) ? item.icon : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4519
4452
  Icon,
4520
4453
  {
4521
4454
  className: cn(
@@ -4553,7 +4486,7 @@ function SuiteSettingsMobileNav({
4553
4486
 
4554
4487
  // src/suite/components/suite-sidebar.tsx
4555
4488
  var import_link2 = __toESM(require("next/link"));
4556
- var import_react19 = require("react");
4489
+ var import_react17 = require("react");
4557
4490
  var import_iconoir_react10 = require("iconoir-react");
4558
4491
  var import_jsx_runtime30 = require("react/jsx-runtime");
4559
4492
  function renderNode(node, collapsed) {
@@ -4578,14 +4511,14 @@ function SuiteSidebar({
4578
4511
  }) {
4579
4512
  const showAskAi = Boolean(onAskAiOpenChange && askAi);
4580
4513
  const chatOpen = showAskAi && askAiOpen && !collapsed;
4581
- const setAskAi = (0, import_react19.useCallback)(
4514
+ const setAskAi = (0, import_react17.useCallback)(
4582
4515
  (next) => {
4583
4516
  persistSuiteAskAiOpen(next);
4584
4517
  onAskAiOpenChange == null ? void 0 : onAskAiOpenChange(next);
4585
4518
  },
4586
4519
  [onAskAiOpenChange]
4587
4520
  );
4588
- (0, import_react19.useEffect)(() => {
4521
+ (0, import_react17.useEffect)(() => {
4589
4522
  if (!onAskAiOpenChange) return;
4590
4523
  function onOpen() {
4591
4524
  onRequestExpand == null ? void 0 : onRequestExpand();
@@ -4594,7 +4527,7 @@ function SuiteSidebar({
4594
4527
  window.addEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
4595
4528
  return () => window.removeEventListener(SUITE_OPEN_ASK_AI_EVENT, onOpen);
4596
4529
  }, [onAskAiOpenChange, onRequestExpand, setAskAi]);
4597
- (0, import_react19.useEffect)(() => {
4530
+ (0, import_react17.useEffect)(() => {
4598
4531
  if (!chatOpen) return;
4599
4532
  function onKey(event) {
4600
4533
  if (event.key === "Escape") setAskAi(false);
@@ -4909,11 +4842,11 @@ function SuiteAppLayout({
4909
4842
  }
4910
4843
 
4911
4844
  // src/suite/components/suite-integration-picker.tsx
4912
- var import_react27 = require("react");
4845
+ var import_react25 = require("react");
4913
4846
  var import_iconoir_react12 = require("iconoir-react");
4914
4847
 
4915
4848
  // src/components/ui/Button.tsx
4916
- var import_react20 = require("react");
4849
+ var import_react18 = require("react");
4917
4850
  var import_jsx_runtime32 = require("react/jsx-runtime");
4918
4851
  var variantClass = {
4919
4852
  primary: "ph-btn-primary",
@@ -4941,7 +4874,7 @@ var shapeClass = {
4941
4874
  square: "ph-btn-square",
4942
4875
  wide: "ph-btn-wide"
4943
4876
  };
4944
- var Button = (0, import_react20.forwardRef)(function Button2(_a, ref) {
4877
+ var Button = (0, import_react18.forwardRef)(function Button2(_a, ref) {
4945
4878
  var _b = _a, {
4946
4879
  variant = "secondary",
4947
4880
  size = "md",
@@ -5005,7 +4938,7 @@ var Button = (0, import_react20.forwardRef)(function Button2(_a, ref) {
5005
4938
  Button.displayName = "Button";
5006
4939
 
5007
4940
  // src/components/ui/Alert.tsx
5008
- var import_react21 = require("react");
4941
+ var import_react19 = require("react");
5009
4942
  var import_jsx_runtime33 = require("react/jsx-runtime");
5010
4943
  var statusConfig = {
5011
4944
  info: { icon: IconInfo },
@@ -5019,7 +4952,7 @@ var statusClassMap = {
5019
4952
  warning: "ph-alert-warning",
5020
4953
  danger: "ph-alert-danger"
5021
4954
  };
5022
- var Alert = (0, import_react21.forwardRef)(function Alert2(_a, ref) {
4955
+ var Alert = (0, import_react19.forwardRef)(function Alert2(_a, ref) {
5023
4956
  var _b = _a, {
5024
4957
  status = "info",
5025
4958
  title,
@@ -5077,7 +5010,7 @@ var Alert = (0, import_react21.forwardRef)(function Alert2(_a, ref) {
5077
5010
  Alert.displayName = "Alert";
5078
5011
 
5079
5012
  // src/components/ui/Badge.tsx
5080
- var import_react22 = require("react");
5013
+ var import_react20 = require("react");
5081
5014
  var import_jsx_runtime34 = require("react/jsx-runtime");
5082
5015
  var variantMap = {
5083
5016
  brand: "ph-badge-brand",
@@ -5092,7 +5025,7 @@ var sizeMap = {
5092
5025
  sm: "text-[10px] px-1.5 py-0.5",
5093
5026
  md: ""
5094
5027
  };
5095
- var Badge = (0, import_react22.forwardRef)(function Badge2(_a, ref) {
5028
+ var Badge = (0, import_react20.forwardRef)(function Badge2(_a, ref) {
5096
5029
  var _b = _a, {
5097
5030
  variant = "neutral",
5098
5031
  size = "md",
@@ -5122,7 +5055,7 @@ var Badge = (0, import_react22.forwardRef)(function Badge2(_a, ref) {
5122
5055
  Badge.displayName = "Badge";
5123
5056
 
5124
5057
  // src/components/ui/Card.tsx
5125
- var import_react23 = require("react");
5058
+ var import_react21 = require("react");
5126
5059
  var import_jsx_runtime35 = require("react/jsx-runtime");
5127
5060
  var variantMap2 = {
5128
5061
  default: "",
@@ -5130,7 +5063,7 @@ var variantMap2 = {
5130
5063
  elevated: "ph-card-elevated",
5131
5064
  highlighted: "ph-card-highlighted"
5132
5065
  };
5133
- var Card = (0, import_react23.forwardRef)(function Card2(_a, ref) {
5066
+ var Card = (0, import_react21.forwardRef)(function Card2(_a, ref) {
5134
5067
  var _b = _a, {
5135
5068
  children,
5136
5069
  title,
@@ -5217,11 +5150,11 @@ var Card = (0, import_react23.forwardRef)(function Card2(_a, ref) {
5217
5150
  Card.displayName = "Card";
5218
5151
 
5219
5152
  // src/components/ui/Input.tsx
5220
- var import_react25 = require("react");
5153
+ var import_react23 = require("react");
5221
5154
  var import_iconoir_react11 = require("iconoir-react");
5222
5155
 
5223
5156
  // src/components/ui/FormField.tsx
5224
- var import_react24 = require("react");
5157
+ var import_react22 = require("react");
5225
5158
  var import_jsx_runtime36 = require("react/jsx-runtime");
5226
5159
  function FormField(_a) {
5227
5160
  var _b = _a, {
@@ -5245,7 +5178,7 @@ function FormField(_a) {
5245
5178
  "children",
5246
5179
  "className"
5247
5180
  ]);
5248
- const generatedId = (0, import_react24.useId)();
5181
+ const generatedId = (0, import_react22.useId)();
5249
5182
  const id = controlId != null ? controlId : generatedId;
5250
5183
  const descriptionId = helperText && !error ? `${id}-description` : void 0;
5251
5184
  const errorId = error ? `${id}-error` : void 0;
@@ -5284,7 +5217,7 @@ function joinIds(...ids) {
5284
5217
  const value = ids.filter(Boolean).join(" ");
5285
5218
  return value || void 0;
5286
5219
  }
5287
- var Input = (0, import_react25.forwardRef)(function Input2(_a, ref) {
5220
+ var Input = (0, import_react23.forwardRef)(function Input2(_a, ref) {
5288
5221
  var _b = _a, {
5289
5222
  id: idProp,
5290
5223
  label,
@@ -5314,11 +5247,11 @@ var Input = (0, import_react25.forwardRef)(function Input2(_a, ref) {
5314
5247
  "required",
5315
5248
  "aria-describedby"
5316
5249
  ]);
5317
- const autoId = (0, import_react25.useId)();
5250
+ const autoId = (0, import_react23.useId)();
5318
5251
  const id = idProp != null ? idProp : autoId;
5319
5252
  const hasError = Boolean(error);
5320
5253
  const isPassword = type === "password";
5321
- const [revealed, setRevealed] = (0, import_react25.useState)(false);
5254
+ const [revealed, setRevealed] = (0, import_react23.useState)(false);
5322
5255
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
5323
5256
  FormField,
5324
5257
  {
@@ -5367,7 +5300,7 @@ var Input = (0, import_react25.forwardRef)(function Input2(_a, ref) {
5367
5300
  );
5368
5301
  });
5369
5302
  Input.displayName = "Input";
5370
- var Select = (0, import_react25.forwardRef)(function Select2(_a, ref) {
5303
+ var Select = (0, import_react23.forwardRef)(function Select2(_a, ref) {
5371
5304
  var _b = _a, {
5372
5305
  id: idProp,
5373
5306
  label,
@@ -5395,7 +5328,7 @@ var Select = (0, import_react25.forwardRef)(function Select2(_a, ref) {
5395
5328
  "required",
5396
5329
  "aria-describedby"
5397
5330
  ]);
5398
- const autoId = (0, import_react25.useId)();
5331
+ const autoId = (0, import_react23.useId)();
5399
5332
  const id = idProp != null ? idProp : autoId;
5400
5333
  const hasError = Boolean(error);
5401
5334
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FormField, { controlId: id, label, hideLabel, helperText, error, required, disabled, className: wrapperClassName, children: (fieldProps) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -5418,7 +5351,7 @@ var Select = (0, import_react25.forwardRef)(function Select2(_a, ref) {
5418
5351
  ) });
5419
5352
  });
5420
5353
  Select.displayName = "Select";
5421
- var Textarea = (0, import_react25.forwardRef)(function Textarea2(_a, ref) {
5354
+ var Textarea = (0, import_react23.forwardRef)(function Textarea2(_a, ref) {
5422
5355
  var _b = _a, {
5423
5356
  id: idProp,
5424
5357
  label,
@@ -5444,7 +5377,7 @@ var Textarea = (0, import_react25.forwardRef)(function Textarea2(_a, ref) {
5444
5377
  "required",
5445
5378
  "aria-describedby"
5446
5379
  ]);
5447
- const autoId = (0, import_react25.useId)();
5380
+ const autoId = (0, import_react23.useId)();
5448
5381
  const id = idProp != null ? idProp : autoId;
5449
5382
  const hasError = Boolean(error);
5450
5383
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FormField, { controlId: id, label, hideLabel, helperText, error, required, disabled, className: wrapperClassName, children: (fieldProps) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -5465,7 +5398,7 @@ var Textarea = (0, import_react25.forwardRef)(function Textarea2(_a, ref) {
5465
5398
  ) });
5466
5399
  });
5467
5400
  Textarea.displayName = "Textarea";
5468
- var Checkbox = (0, import_react25.forwardRef)(function Checkbox2(_a, ref) {
5401
+ var Checkbox = (0, import_react23.forwardRef)(function Checkbox2(_a, ref) {
5469
5402
  var _b = _a, {
5470
5403
  id: idProp,
5471
5404
  label,
@@ -5485,7 +5418,7 @@ var Checkbox = (0, import_react25.forwardRef)(function Checkbox2(_a, ref) {
5485
5418
  "disabled",
5486
5419
  "aria-describedby"
5487
5420
  ]);
5488
- const autoId = (0, import_react25.useId)();
5421
+ const autoId = (0, import_react23.useId)();
5489
5422
  const id = idProp != null ? idProp : autoId;
5490
5423
  const hasError = Boolean(error);
5491
5424
  const descriptionId = helperText && !hasError ? `${id}-description` : void 0;
@@ -5520,7 +5453,7 @@ var Checkbox = (0, import_react25.forwardRef)(function Checkbox2(_a, ref) {
5520
5453
  ] });
5521
5454
  });
5522
5455
  Checkbox.displayName = "Checkbox";
5523
- var Radio = (0, import_react25.forwardRef)(function Radio2(_a, ref) {
5456
+ var Radio = (0, import_react23.forwardRef)(function Radio2(_a, ref) {
5524
5457
  var _b = _a, {
5525
5458
  id: idProp,
5526
5459
  label,
@@ -5534,7 +5467,7 @@ var Radio = (0, import_react25.forwardRef)(function Radio2(_a, ref) {
5534
5467
  "wrapperClassName",
5535
5468
  "disabled"
5536
5469
  ]);
5537
- const autoId = (0, import_react25.useId)();
5470
+ const autoId = (0, import_react23.useId)();
5538
5471
  const id = idProp != null ? idProp : autoId;
5539
5472
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn2("ph-control-row", wrapperClassName, disabled && "opacity-60"), children: [
5540
5473
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -5551,7 +5484,7 @@ var Radio = (0, import_react25.forwardRef)(function Radio2(_a, ref) {
5551
5484
  ] });
5552
5485
  });
5553
5486
  Radio.displayName = "Radio";
5554
- var Toggle = (0, import_react25.forwardRef)(function Toggle2(_a, ref) {
5487
+ var Toggle = (0, import_react23.forwardRef)(function Toggle2(_a, ref) {
5555
5488
  var _b = _a, {
5556
5489
  id: idProp,
5557
5490
  label,
@@ -5565,7 +5498,7 @@ var Toggle = (0, import_react25.forwardRef)(function Toggle2(_a, ref) {
5565
5498
  "wrapperClassName",
5566
5499
  "disabled"
5567
5500
  ]);
5568
- const autoId = (0, import_react25.useId)();
5501
+ const autoId = (0, import_react23.useId)();
5569
5502
  const id = idProp != null ? idProp : autoId;
5570
5503
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("label", { className: cn2("ph-control-row-between", wrapperClassName, disabled && "opacity-60"), children: [
5571
5504
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: disabled ? "opacity-60" : void 0, children: label }),
@@ -5583,7 +5516,7 @@ var Toggle = (0, import_react25.forwardRef)(function Toggle2(_a, ref) {
5583
5516
  ] });
5584
5517
  });
5585
5518
  Toggle.displayName = "Toggle";
5586
- var Range = (0, import_react25.forwardRef)(function Range2(_a, ref) {
5519
+ var Range = (0, import_react23.forwardRef)(function Range2(_a, ref) {
5587
5520
  var _b = _a, {
5588
5521
  id: idProp,
5589
5522
  label,
@@ -5601,7 +5534,7 @@ var Range = (0, import_react25.forwardRef)(function Range2(_a, ref) {
5601
5534
  "wrapperClassName",
5602
5535
  "className"
5603
5536
  ]);
5604
- const autoId = (0, import_react25.useId)();
5537
+ const autoId = (0, import_react23.useId)();
5605
5538
  const id = idProp != null ? idProp : autoId;
5606
5539
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn2("ph-field", wrapperClassName), children: [
5607
5540
  label && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: id, className: "ph-label", children: label }),
@@ -5614,7 +5547,7 @@ var Range = (0, import_react25.forwardRef)(function Range2(_a, ref) {
5614
5547
  ] });
5615
5548
  });
5616
5549
  Range.displayName = "Range";
5617
- var FileUpload = (0, import_react25.forwardRef)(function FileUpload2(_a, ref) {
5550
+ var FileUpload = (0, import_react23.forwardRef)(function FileUpload2(_a, ref) {
5618
5551
  var _b = _a, {
5619
5552
  id: idProp,
5620
5553
  label,
@@ -5628,7 +5561,7 @@ var FileUpload = (0, import_react25.forwardRef)(function FileUpload2(_a, ref) {
5628
5561
  "wrapperClassName",
5629
5562
  "className"
5630
5563
  ]);
5631
- const autoId = (0, import_react25.useId)();
5564
+ const autoId = (0, import_react23.useId)();
5632
5565
  const id = idProp != null ? idProp : autoId;
5633
5566
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn2("ph-field", wrapperClassName), children: [
5634
5567
  label && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: id, className: "ph-label", children: label }),
@@ -5642,7 +5575,7 @@ FileUpload.displayName = "FileUpload";
5642
5575
 
5643
5576
  // src/components/ui/Modal.tsx
5644
5577
  var Dialog2 = __toESM(require("@radix-ui/react-dialog"));
5645
- var import_react26 = require("react");
5578
+ var import_react24 = require("react");
5646
5579
  var import_jsx_runtime38 = require("react/jsx-runtime");
5647
5580
  var sizeMap3 = {
5648
5581
  sm: "max-w-sm",
@@ -5673,7 +5606,7 @@ function Modal({
5673
5606
  "aria-labelledby": ariaLabelledBy
5674
5607
  }) {
5675
5608
  const canDismiss = Boolean(onClose);
5676
- const restoreFocusRef = (0, import_react26.useRef)(null);
5609
+ const restoreFocusRef = (0, import_react24.useRef)(null);
5677
5610
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
5678
5611
  Dialog2.Root,
5679
5612
  {
@@ -5836,33 +5769,33 @@ function SuiteIntegrationPicker({
5836
5769
  description = "Connect an app to this workspace securely.",
5837
5770
  dataTest = "suite-integration-picker"
5838
5771
  }) {
5839
- const [query, setQuery] = (0, import_react27.useState)("");
5840
- const [category, setCategory] = (0, import_react27.useState)("all");
5841
- const [categoryQuery, setCategoryQuery] = (0, import_react27.useState)("");
5842
- const [categoryMenuOpen, setCategoryMenuOpen] = (0, import_react27.useState)(false);
5843
- const [expanded, setExpanded] = (0, import_react27.useState)(null);
5844
- const categoryMenuRef = (0, import_react27.useRef)(null);
5845
- const categoryTriggerRef = (0, import_react27.useRef)(null);
5846
- const categorySearchRef = (0, import_react27.useRef)(null);
5847
- const categoryOptionRefs = (0, import_react27.useRef)({});
5848
- const pendingCategoryFocus = (0, import_react27.useRef)(
5772
+ const [query, setQuery] = (0, import_react25.useState)("");
5773
+ const [category, setCategory] = (0, import_react25.useState)("all");
5774
+ const [categoryQuery, setCategoryQuery] = (0, import_react25.useState)("");
5775
+ const [categoryMenuOpen, setCategoryMenuOpen] = (0, import_react25.useState)(false);
5776
+ const [expanded, setExpanded] = (0, import_react25.useState)(null);
5777
+ const categoryMenuRef = (0, import_react25.useRef)(null);
5778
+ const categoryTriggerRef = (0, import_react25.useRef)(null);
5779
+ const categorySearchRef = (0, import_react25.useRef)(null);
5780
+ const categoryOptionRefs = (0, import_react25.useRef)({});
5781
+ const pendingCategoryFocus = (0, import_react25.useRef)(
5849
5782
  null
5850
5783
  );
5851
- const scrollViewportRef = (0, import_react27.useRef)(null);
5852
- const loadMoreSentinelRef = (0, import_react27.useRef)(null);
5853
- const loadMoreInFlightRef = (0, import_react27.useRef)(false);
5854
- const authRequestRef = (0, import_react27.useRef)(0);
5855
- const [methodItem, setMethodItem] = (0, import_react27.useState)(null);
5856
- const [authItem, setAuthItem] = (0, import_react27.useState)(null);
5857
- const [authValues, setAuthValues] = (0, import_react27.useState)({});
5858
- const [authLoading, setAuthLoading] = (0, import_react27.useState)(false);
5859
- const [authSubmitting, setAuthSubmitting] = (0, import_react27.useState)(false);
5860
- const [authError, setAuthError] = (0, import_react27.useState)(null);
5861
- const [connectionError, setConnectionError] = (0, import_react27.useState)(null);
5862
- const [itemToDisconnect, setItemToDisconnect] = (0, import_react27.useState)(null);
5863
- const [disconnecting, setDisconnecting] = (0, import_react27.useState)(false);
5864
- const [disconnectError, setDisconnectError] = (0, import_react27.useState)(null);
5865
- const itemCategories = (0, import_react27.useMemo)(
5784
+ const scrollViewportRef = (0, import_react25.useRef)(null);
5785
+ const loadMoreSentinelRef = (0, import_react25.useRef)(null);
5786
+ const loadMoreInFlightRef = (0, import_react25.useRef)(false);
5787
+ const authRequestRef = (0, import_react25.useRef)(0);
5788
+ const [methodItem, setMethodItem] = (0, import_react25.useState)(null);
5789
+ const [authItem, setAuthItem] = (0, import_react25.useState)(null);
5790
+ const [authValues, setAuthValues] = (0, import_react25.useState)({});
5791
+ const [authLoading, setAuthLoading] = (0, import_react25.useState)(false);
5792
+ const [authSubmitting, setAuthSubmitting] = (0, import_react25.useState)(false);
5793
+ const [authError, setAuthError] = (0, import_react25.useState)(null);
5794
+ const [connectionError, setConnectionError] = (0, import_react25.useState)(null);
5795
+ const [itemToDisconnect, setItemToDisconnect] = (0, import_react25.useState)(null);
5796
+ const [disconnecting, setDisconnecting] = (0, import_react25.useState)(false);
5797
+ const [disconnectError, setDisconnectError] = (0, import_react25.useState)(null);
5798
+ const itemCategories = (0, import_react25.useMemo)(
5866
5799
  () => Array.from(
5867
5800
  new Set(items.flatMap((item) => {
5868
5801
  var _a;
@@ -6043,7 +5976,7 @@ function SuiteIntegrationPicker({
6043
5976
  setAuthSubmitting(false);
6044
5977
  }
6045
5978
  }
6046
- (0, import_react27.useEffect)(() => {
5979
+ (0, import_react25.useEffect)(() => {
6047
5980
  if (!categoryMenuOpen) return;
6048
5981
  const handlePointerDown = (event) => {
6049
5982
  var _a;
@@ -6061,7 +5994,7 @@ function SuiteIntegrationPicker({
6061
5994
  document.removeEventListener("keydown", handleKeyDown);
6062
5995
  };
6063
5996
  }, [categoryMenuOpen]);
6064
- (0, import_react27.useEffect)(() => {
5997
+ (0, import_react25.useEffect)(() => {
6065
5998
  var _a, _b, _c;
6066
5999
  const target = pendingCategoryFocus.current;
6067
6000
  if (!target) return;
@@ -6070,10 +6003,10 @@ function SuiteIntegrationPicker({
6070
6003
  else if (target === "search") (_b = categorySearchRef.current) == null ? void 0 : _b.focus();
6071
6004
  else (_c = categoryOptionRefs.current[target]) == null ? void 0 : _c.focus();
6072
6005
  }, [activeCategory, categoryMenuOpen, categoryQuery, visibleCategories]);
6073
- (0, import_react27.useEffect)(() => {
6006
+ (0, import_react25.useEffect)(() => {
6074
6007
  if (!loadingMore) loadMoreInFlightRef.current = false;
6075
6008
  }, [loadingMore]);
6076
- (0, import_react27.useEffect)(() => {
6009
+ (0, import_react25.useEffect)(() => {
6077
6010
  const root = scrollViewportRef.current;
6078
6011
  const sentinel = loadMoreSentinelRef.current;
6079
6012
  if (!open || !root || !sentinel || !hasMore || !onEndReached || loading || catalogLoading || loadingMore) {
@@ -6509,7 +6442,7 @@ function SuiteIntegrationPicker({
6509
6442
  }
6510
6443
 
6511
6444
  // src/suite/components/suite-integration-rules.tsx
6512
- var import_react28 = require("react");
6445
+ var import_react26 = require("react");
6513
6446
  var import_iconoir_react13 = require("iconoir-react");
6514
6447
  var import_jsx_runtime40 = require("react/jsx-runtime");
6515
6448
  var ACTION_LABELS = {
@@ -6541,18 +6474,18 @@ function SuiteIntegrationRules({
6541
6474
  onRefresh,
6542
6475
  dataTest = "integration-rules"
6543
6476
  }) {
6544
- const [formOpen, setFormOpen] = (0, import_react28.useState)(false);
6545
- const [name, setName] = (0, import_react28.useState)("");
6546
- const [trigger, setTrigger] = (0, import_react28.useState)("");
6547
- const [actionType, setActionType] = (0, import_react28.useState)("create_tides_task");
6548
- const [projectId, setProjectId] = (0, import_react28.useState)("");
6549
- const [minutes, setMinutes] = (0, import_react28.useState)("");
6550
- const [priority, setPriority] = (0, import_react28.useState)("low");
6551
- const [submitting, setSubmitting] = (0, import_react28.useState)(false);
6552
- const [formError, setFormError] = (0, import_react28.useState)(null);
6553
- const [busyId, setBusyId] = (0, import_react28.useState)(null);
6554
- const [ruleToDelete, setRuleToDelete] = (0, import_react28.useState)(null);
6555
- const [deleteError, setDeleteError] = (0, import_react28.useState)(null);
6477
+ const [formOpen, setFormOpen] = (0, import_react26.useState)(false);
6478
+ const [name, setName] = (0, import_react26.useState)("");
6479
+ const [trigger, setTrigger] = (0, import_react26.useState)("");
6480
+ const [actionType, setActionType] = (0, import_react26.useState)("create_tides_task");
6481
+ const [projectId, setProjectId] = (0, import_react26.useState)("");
6482
+ const [minutes, setMinutes] = (0, import_react26.useState)("");
6483
+ const [priority, setPriority] = (0, import_react26.useState)("low");
6484
+ const [submitting, setSubmitting] = (0, import_react26.useState)(false);
6485
+ const [formError, setFormError] = (0, import_react26.useState)(null);
6486
+ const [busyId, setBusyId] = (0, import_react26.useState)(null);
6487
+ const [ruleToDelete, setRuleToDelete] = (0, import_react26.useState)(null);
6488
+ const [deleteError, setDeleteError] = (0, import_react26.useState)(null);
6556
6489
  const needsProject = actionType === "create_tides_task" || actionType === "draft_time_entry";
6557
6490
  async function submitForm(event) {
6558
6491
  event.preventDefault();
@@ -6907,7 +6840,7 @@ function SuiteIntegrationRules({
6907
6840
  }
6908
6841
 
6909
6842
  // src/suite/components/suite-clients-projects-directory.tsx
6910
- var import_react29 = require("react");
6843
+ var import_react27 = require("react");
6911
6844
  var import_iconoir_react14 = require("iconoir-react");
6912
6845
  var import_jsx_runtime41 = require("react/jsx-runtime");
6913
6846
  var DEFAULT_ICON = "castle-emblem";
@@ -6988,7 +6921,7 @@ function DirectoryIconPicker({
6988
6921
  onClear,
6989
6922
  onChange
6990
6923
  }) {
6991
- const iconRefs = (0, import_react29.useRef)({});
6924
+ const iconRefs = (0, import_react27.useRef)({});
6992
6925
  function moveSelection(event, index) {
6993
6926
  var _a;
6994
6927
  let nextIndex = null;
@@ -7133,31 +7066,31 @@ function SuiteClientsProjectsDirectory({
7133
7066
  dataTest = "suite-clients-projects-directory"
7134
7067
  }) {
7135
7068
  var _a;
7136
- const [query, setQuery] = (0, import_react29.useState)("");
7137
- const [selectedClientId, setSelectedClientId] = (0, import_react29.useState)(null);
7138
- const [mobileDetail, setMobileDetail] = (0, import_react29.useState)(false);
7139
- const [editing, setEditing] = (0, import_react29.useState)(null);
7140
- const [draft, setDraft] = (0, import_react29.useState)({
7069
+ const [query, setQuery] = (0, import_react27.useState)("");
7070
+ const [selectedClientId, setSelectedClientId] = (0, import_react27.useState)(null);
7071
+ const [mobileDetail, setMobileDetail] = (0, import_react27.useState)(false);
7072
+ const [editing, setEditing] = (0, import_react27.useState)(null);
7073
+ const [draft, setDraft] = (0, import_react27.useState)({
7141
7074
  name: "",
7142
7075
  icon: DEFAULT_ICON,
7143
7076
  color: DEFAULT_COLOR
7144
7077
  });
7145
- const [draftClientId, setDraftClientId] = (0, import_react29.useState)(null);
7146
- const [preview, setPreview] = (0, import_react29.useState)(null);
7147
- const [draftArchived, setDraftArchived] = (0, import_react29.useState)(false);
7148
- const [confirming, setConfirming] = (0, import_react29.useState)(null);
7149
- const [saving, setSaving] = (0, import_react29.useState)(false);
7150
- const [mutationError, setMutationError] = (0, import_react29.useState)(null);
7151
- const clientButtonRefs = (0, import_react29.useRef)({});
7152
- const backToClientsRef = (0, import_react29.useRef)(null);
7153
- const mobileFocusTarget = (0, import_react29.useRef)(null);
7154
- (0, import_react29.useEffect)(() => {
7078
+ const [draftClientId, setDraftClientId] = (0, import_react27.useState)(null);
7079
+ const [preview, setPreview] = (0, import_react27.useState)(null);
7080
+ const [draftArchived, setDraftArchived] = (0, import_react27.useState)(false);
7081
+ const [confirming, setConfirming] = (0, import_react27.useState)(null);
7082
+ const [saving, setSaving] = (0, import_react27.useState)(false);
7083
+ const [mutationError, setMutationError] = (0, import_react27.useState)(null);
7084
+ const clientButtonRefs = (0, import_react27.useRef)({});
7085
+ const backToClientsRef = (0, import_react27.useRef)(null);
7086
+ const mobileFocusTarget = (0, import_react27.useRef)(null);
7087
+ (0, import_react27.useEffect)(() => {
7155
7088
  var _a2, _b;
7156
7089
  if (selectedClientId && clients.some((client) => client.id === selectedClientId))
7157
7090
  return;
7158
7091
  setSelectedClientId((_b = (_a2 = clients[0]) == null ? void 0 : _a2.id) != null ? _b : null);
7159
7092
  }, [clients, selectedClientId]);
7160
- (0, import_react29.useEffect)(() => {
7093
+ (0, import_react27.useEffect)(() => {
7161
7094
  var _a2, _b;
7162
7095
  const target = mobileFocusTarget.current;
7163
7096
  if (!target) return;
@@ -7166,7 +7099,7 @@ function SuiteClientsProjectsDirectory({
7166
7099
  else if (selectedClientId)
7167
7100
  (_b = clientButtonRefs.current[selectedClientId]) == null ? void 0 : _b.focus();
7168
7101
  }, [mobileDetail, selectedClientId]);
7169
- const filteredClients = (0, import_react29.useMemo)(() => {
7102
+ const filteredClients = (0, import_react27.useMemo)(() => {
7170
7103
  const value = query.trim().toLowerCase();
7171
7104
  return [...clients].sort((a, b) => a.name.localeCompare(b.name)).filter((client) => !value || client.name.toLowerCase().includes(value));
7172
7105
  }, [clients, query]);