dsh-workspace-kit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js ADDED
@@ -0,0 +1,2642 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-workspace-kit",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+
8
+ "use strict";
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
13
+ var __export = (target, all) => {
14
+ for (var name2 in all)
15
+ __defProp(target, name2, { get: all[name2], enumerable: true });
16
+ };
17
+ var __copyProps = (to, from, except, desc) => {
18
+ if (from && typeof from === "object" || typeof from === "function") {
19
+ for (let key of __getOwnPropNames(from))
20
+ if (!__hasOwnProp.call(to, key) && key !== except)
21
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
+ }
23
+ return to;
24
+ };
25
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
+
27
+ // src/client/index.ts
28
+ var index_exports = {};
29
+ __export(index_exports, {
30
+ apply: () => apply,
31
+ inject: () => inject,
32
+ name: () => name
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/client/archive-store.ts
37
+ var import_client = require("@deepseek-ai/dsh-client-runtime/client");
38
+ function createArchiveStore() {
39
+ return (0, import_client.defineStore)({
40
+ init: () => ({ archived: {}, appearance: {}, officialSidebar: false }),
41
+ persist: "dsh.workspace-kit.archive.v1",
42
+ actions: {
43
+ /** Mark one workspace archived. */
44
+ archive(draft, workspaceId, at) {
45
+ draft.archived[workspaceId] = { at };
46
+ },
47
+ /** Restore one workspace to the active set. */
48
+ restore(draft, workspaceId) {
49
+ delete draft.archived[workspaceId];
50
+ },
51
+ /** Set (or clear, when `null`) one workspace's icon/color look. */
52
+ setAppearance(draft, workspaceId, appearance) {
53
+ const state = draft;
54
+ if (!state.appearance) state.appearance = {};
55
+ if (appearance === null) {
56
+ delete state.appearance[workspaceId];
57
+ } else {
58
+ state.appearance[workspaceId] = appearance;
59
+ }
60
+ },
61
+ /** Switch between the plugin sidebar and the official sidebar browser. */
62
+ setOfficialSidebar(draft, official) {
63
+ const state = draft;
64
+ state.officialSidebar = official;
65
+ }
66
+ }
67
+ });
68
+ }
69
+
70
+ // src/client/dialogs.tsx
71
+ var import_react = require("react");
72
+
73
+ // src/shared/i18n.ts
74
+ function localize(locale, zh, en, vars) {
75
+ const template = locale === "zh" ? zh : en;
76
+ if (!vars) return template;
77
+ return template.replace(
78
+ /\{(\w+)\}/g,
79
+ (raw, name2) => vars[name2] !== void 0 ? String(vars[name2]) : raw
80
+ );
81
+ }
82
+ function normalizeLocale(raw) {
83
+ const tag = (raw ?? "").toLowerCase();
84
+ if (tag.startsWith("zh")) return "zh";
85
+ return "en";
86
+ }
87
+
88
+ // src/client/locale.ts
89
+ var LOCALE_STORAGE_KEY = "dsh.workspace-kit.locale";
90
+ var explicit = null;
91
+ function detectLocale() {
92
+ if (explicit) return explicit;
93
+ try {
94
+ const stored = window.localStorage.getItem(LOCALE_STORAGE_KEY);
95
+ if (stored === "zh" || stored === "en") return stored;
96
+ } catch {
97
+ }
98
+ const nav = typeof navigator !== "undefined" ? navigator : void 0;
99
+ const tags = nav?.languages && nav.languages.length > 0 ? [...nav.languages] : nav?.language ? [nav.language] : [];
100
+ for (const tag of tags) {
101
+ const locale = normalizeLocale(tag);
102
+ if (locale === "zh") return locale;
103
+ }
104
+ return "en";
105
+ }
106
+ function L(zh, en, vars) {
107
+ return localize(detectLocale(), zh, en, vars);
108
+ }
109
+
110
+ // src/client/dialogs.tsx
111
+ var import_jsx_runtime = require("react/jsx-runtime");
112
+ var pending = null;
113
+ var listeners = /* @__PURE__ */ new Set();
114
+ function emit() {
115
+ for (const listener of listeners) listener();
116
+ }
117
+ function settle(value) {
118
+ if (!pending) return;
119
+ const p = pending;
120
+ pending = null;
121
+ emit();
122
+ p.resolve(value);
123
+ }
124
+ function subscribe(listener) {
125
+ listeners.add(listener);
126
+ return () => listeners.delete(listener);
127
+ }
128
+ function getSnapshot() {
129
+ return pending?.request ?? null;
130
+ }
131
+ function requestConfirm(request) {
132
+ return new Promise((resolve) => {
133
+ pending = { request: { kind: "confirm", ...request }, resolve };
134
+ emit();
135
+ });
136
+ }
137
+ function requestPrompt(request) {
138
+ return new Promise((resolve) => {
139
+ pending = { request: { kind: "prompt", ...request }, resolve };
140
+ emit();
141
+ });
142
+ }
143
+ function DialogHost() {
144
+ const request = (0, import_react.useSyncExternalStore)(subscribe, getSnapshot);
145
+ const inputRef = (0, import_react.useRef)(null);
146
+ (0, import_react.useEffect)(() => {
147
+ if (!request) return;
148
+ if (request.kind === "prompt") {
149
+ const frame = requestAnimationFrame(() => inputRef.current?.select());
150
+ return () => cancelAnimationFrame(frame);
151
+ }
152
+ }, [request]);
153
+ (0, import_react.useEffect)(() => {
154
+ if (!request) return;
155
+ const onKeyDown = (event) => {
156
+ if (event.key === "Escape") {
157
+ event.preventDefault();
158
+ settle(null);
159
+ }
160
+ };
161
+ window.addEventListener("keydown", onKeyDown);
162
+ return () => window.removeEventListener("keydown", onKeyDown);
163
+ }, [request]);
164
+ if (!request) return null;
165
+ const ok = () => {
166
+ if (request.kind === "prompt") {
167
+ const value = (inputRef.current?.value ?? "").trim();
168
+ settle(value.length > 0 ? value : null);
169
+ } else {
170
+ settle(true);
171
+ }
172
+ };
173
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.backdrop, onMouseDown: () => settle(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.card, role: "dialog", "aria-label": request.title, onMouseDown: (e) => e.stopPropagation(), children: [
174
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.title, children: request.title }),
175
+ request.kind === "confirm" && request.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.message, children: request.message }),
176
+ request.kind === "prompt" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
177
+ request.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.message, children: request.message }),
178
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
+ "input",
180
+ {
181
+ ref: inputRef,
182
+ style: styles.input,
183
+ defaultValue: request.initial,
184
+ placeholder: request.placeholder,
185
+ onKeyDown: (e) => {
186
+ if (e.key === "Enter") ok();
187
+ }
188
+ }
189
+ )
190
+ ] }),
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.actions, children: [
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: styles.button, onClick: () => settle(null), children: L("\u53D6\u6D88", "Cancel") }),
193
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
194
+ "button",
195
+ {
196
+ style: { ...styles.button, ...styles.primary },
197
+ onClick: ok,
198
+ autoFocus: request.kind === "confirm",
199
+ children: request.okLabel ?? L("\u786E\u5B9A", "OK")
200
+ }
201
+ )
202
+ ] })
203
+ ] }) });
204
+ }
205
+ var styles = {
206
+ backdrop: {
207
+ position: "fixed",
208
+ inset: 0,
209
+ zIndex: 1e4,
210
+ display: "flex",
211
+ alignItems: "center",
212
+ justifyContent: "center",
213
+ background: "rgba(15, 18, 26, 0.35)"
214
+ },
215
+ card: {
216
+ width: 360,
217
+ maxWidth: "calc(100vw - 48px)",
218
+ background: "#ffffff",
219
+ color: "#1c2333",
220
+ borderRadius: 12,
221
+ padding: 16,
222
+ boxShadow: "0 18px 48px rgba(15, 18, 26, 0.3)"
223
+ },
224
+ title: { fontSize: 14, fontWeight: 700, marginBottom: 8 },
225
+ message: { fontSize: 12.5, color: "#3c4659", lineHeight: 1.5, marginBottom: 10, whiteSpace: "pre-wrap" },
226
+ input: {
227
+ width: "100%",
228
+ boxSizing: "border-box",
229
+ fontSize: 13,
230
+ padding: "7px 10px",
231
+ borderRadius: 8,
232
+ border: "1px solid rgba(28, 35, 51, 0.2)",
233
+ outline: "none",
234
+ marginBottom: 12
235
+ },
236
+ actions: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 },
237
+ button: {
238
+ fontSize: 12.5,
239
+ padding: "5px 14px",
240
+ borderRadius: 8,
241
+ border: "1px solid rgba(28, 35, 51, 0.14)",
242
+ background: "#ffffff",
243
+ color: "#3c4659",
244
+ cursor: "pointer"
245
+ },
246
+ primary: {
247
+ background: "#2d66f7",
248
+ borderColor: "#2d66f7",
249
+ color: "#ffffff"
250
+ }
251
+ };
252
+
253
+ // src/client/SidebarToggle.tsx
254
+ var import_jsx_runtime2 = require("react/jsx-runtime");
255
+ function SidebarToggle(props) {
256
+ const { wide, useStore, actions } = props;
257
+ const official = Boolean(useStore((state) => state.officialSidebar ?? false));
258
+ const toggle = () => {
259
+ const next = !official;
260
+ actions.setOfficialSidebar(next);
261
+ window.dispatchEvent(new CustomEvent("dsh-workspace-kit:sidebar-mode", { detail: { official: next } }));
262
+ };
263
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
264
+ "button",
265
+ {
266
+ type: "button",
267
+ style: wide ? styles2.wide : styles2.rail,
268
+ title: official ? L(
269
+ "\u5F53\u524D\u4E3A\u5B98\u65B9\u4FA7\u680F \u2014\u2014 \u70B9\u51FB\u5207\u6362\u5230\u589E\u5F3A\u4FA7\u680F\uFF08\u5F52\u6863\u6298\u53E0 / \u62D6\u62FD\u6392\u5E8F / \u56FE\u6807\u989C\u8272\uFF09",
270
+ "Currently the official sidebar \u2014 click to switch to the enhanced sidebar (archive folding / drag reorder / icon colors)"
271
+ ) : L("\u5F53\u524D\u4E3A\u589E\u5F3A\u4FA7\u680F \u2014\u2014 \u70B9\u51FB\u5207\u6362\u5230\u5B98\u65B9\u4FA7\u680F", "Currently the enhanced sidebar \u2014 click to switch to the official sidebar"),
272
+ onClick: toggle,
273
+ children: [
274
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles2.glyph, children: official ? "\u25D0" : "\u25D1" }),
275
+ wide && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: official ? L("\u589E\u5F3A\u4FA7\u680F", "Enhanced sidebar") : L("\u5B98\u65B9\u4FA7\u680F", "Official sidebar") })
276
+ ]
277
+ }
278
+ );
279
+ }
280
+ var styles2 = {
281
+ wide: {
282
+ display: "flex",
283
+ alignItems: "center",
284
+ gap: 6,
285
+ width: "100%",
286
+ padding: "6px 10px",
287
+ fontSize: 11,
288
+ border: "none",
289
+ background: "transparent",
290
+ color: "#5a6478",
291
+ cursor: "pointer",
292
+ textAlign: "left"
293
+ },
294
+ rail: {
295
+ display: "flex",
296
+ alignItems: "center",
297
+ justifyContent: "center",
298
+ width: 36,
299
+ height: 32,
300
+ fontSize: 14,
301
+ border: "none",
302
+ background: "transparent",
303
+ color: "#5a6478",
304
+ cursor: "pointer"
305
+ },
306
+ glyph: {
307
+ fontSize: 13,
308
+ lineHeight: 1
309
+ }
310
+ };
311
+
312
+ // src/client/Spotlight.tsx
313
+ var import_react5 = require("react");
314
+
315
+ // node_modules/lucide-react/dist/esm/createLucideIcon.mjs
316
+ var import_react4 = require("react");
317
+
318
+ // node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs
319
+ var mergeClasses = (...classes) => classes.filter((className, index, array) => {
320
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
321
+ }).join(" ").trim();
322
+
323
+ // node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs
324
+ var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
325
+
326
+ // node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs
327
+ var toCamelCase = (string) => string.replace(
328
+ /^([A-Z])|[\s-_]+(\w)/g,
329
+ (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()
330
+ );
331
+
332
+ // node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs
333
+ var toPascalCase = (string) => {
334
+ const camelCase = toCamelCase(string);
335
+ return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
336
+ };
337
+
338
+ // node_modules/lucide-react/dist/esm/Icon.mjs
339
+ var import_react3 = require("react");
340
+
341
+ // node_modules/lucide-react/dist/esm/defaultAttributes.mjs
342
+ var defaultAttributes = {
343
+ xmlns: "http://www.w3.org/2000/svg",
344
+ width: 24,
345
+ height: 24,
346
+ viewBox: "0 0 24 24",
347
+ fill: "none",
348
+ stroke: "currentColor",
349
+ strokeWidth: 2,
350
+ strokeLinecap: "round",
351
+ strokeLinejoin: "round"
352
+ };
353
+
354
+ // node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs
355
+ var hasA11yProp = (props) => {
356
+ for (const prop in props) {
357
+ if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
358
+ return true;
359
+ }
360
+ }
361
+ return false;
362
+ };
363
+
364
+ // node_modules/lucide-react/dist/esm/context.mjs
365
+ var import_react2 = require("react");
366
+ var LucideContext = (0, import_react2.createContext)({});
367
+ var useLucideContext = () => (0, import_react2.useContext)(LucideContext);
368
+
369
+ // node_modules/lucide-react/dist/esm/Icon.mjs
370
+ var Icon = (0, import_react3.forwardRef)(
371
+ ({ color, size, strokeWidth, absoluteStrokeWidth, className = "", children, iconNode, ...rest }, ref) => {
372
+ const {
373
+ size: contextSize = 24,
374
+ strokeWidth: contextStrokeWidth = 2,
375
+ absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,
376
+ color: contextColor = "currentColor",
377
+ className: contextClass = ""
378
+ } = useLucideContext() ?? {};
379
+ const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;
380
+ return (0, import_react3.createElement)(
381
+ "svg",
382
+ {
383
+ ref,
384
+ ...defaultAttributes,
385
+ width: size ?? contextSize ?? defaultAttributes.width,
386
+ height: size ?? contextSize ?? defaultAttributes.height,
387
+ stroke: color ?? contextColor,
388
+ strokeWidth: calculatedStrokeWidth,
389
+ className: mergeClasses("lucide", contextClass, className),
390
+ ...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
391
+ ...rest
392
+ },
393
+ [
394
+ ...iconNode.map(([tag, attrs]) => (0, import_react3.createElement)(tag, attrs)),
395
+ ...Array.isArray(children) ? children : [children]
396
+ ]
397
+ );
398
+ }
399
+ );
400
+
401
+ // node_modules/lucide-react/dist/esm/createLucideIcon.mjs
402
+ var createLucideIcon = (iconName, iconNode) => {
403
+ const Component = (0, import_react4.forwardRef)(
404
+ ({ className, ...props }, ref) => (0, import_react4.createElement)(Icon, {
405
+ ref,
406
+ iconNode,
407
+ className: mergeClasses(
408
+ `lucide-${toKebabCase(toPascalCase(iconName))}`,
409
+ `lucide-${iconName}`,
410
+ className
411
+ ),
412
+ ...props
413
+ })
414
+ );
415
+ Component.displayName = toPascalCase(iconName);
416
+ return Component;
417
+ };
418
+
419
+ // node_modules/lucide-react/dist/esm/icons/book-open.mjs
420
+ var __iconNode = [
421
+ ["path", { d: "M12 5v16", key: "1f6ucr" }],
422
+ [
423
+ "path",
424
+ {
425
+ d: "M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",
426
+ key: "1fyvmf"
427
+ }
428
+ ]
429
+ ];
430
+ var BookOpen = createLucideIcon("book-open", __iconNode);
431
+
432
+ // node_modules/lucide-react/dist/esm/icons/bot.mjs
433
+ var __iconNode2 = [
434
+ ["path", { d: "M12 8V4H8", key: "hb8ula" }],
435
+ ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
436
+ ["path", { d: "M2 14h2", key: "vft8re" }],
437
+ ["path", { d: "M20 14h2", key: "4cs60a" }],
438
+ ["path", { d: "M15 13v2", key: "1xurst" }],
439
+ ["path", { d: "M9 13v2", key: "rq6x2g" }]
440
+ ];
441
+ var Bot = createLucideIcon("bot", __iconNode2);
442
+
443
+ // node_modules/lucide-react/dist/esm/icons/brain.mjs
444
+ var __iconNode3 = [
445
+ ["path", { d: "M12 18V5", key: "adv99a" }],
446
+ ["path", { d: "M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4", key: "1e3is1" }],
447
+ ["path", { d: "M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5", key: "1gqd8o" }],
448
+ ["path", { d: "M17.997 5.125a4 4 0 0 1 2.526 5.77", key: "iwvgf7" }],
449
+ ["path", { d: "M18 18a4 4 0 0 0 2-7.464", key: "efp6ie" }],
450
+ ["path", { d: "M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517", key: "1gq6am" }],
451
+ ["path", { d: "M6 18a4 4 0 0 1-2-7.464", key: "k1g0md" }],
452
+ ["path", { d: "M6.003 5.125a4 4 0 0 0-2.526 5.77", key: "q97ue3" }]
453
+ ];
454
+ var Brain = createLucideIcon("brain", __iconNode3);
455
+
456
+ // node_modules/lucide-react/dist/esm/icons/chart-column.mjs
457
+ var __iconNode4 = [
458
+ ["path", { d: "M3 3v16a2 2 0 0 0 2 2h16", key: "c24i48" }],
459
+ ["path", { d: "M18 17V9", key: "2bz60n" }],
460
+ ["path", { d: "M13 17V5", key: "1frdt8" }],
461
+ ["path", { d: "M8 17v-3", key: "17ska0" }]
462
+ ];
463
+ var ChartColumn = createLucideIcon("chart-column", __iconNode4);
464
+
465
+ // node_modules/lucide-react/dist/esm/icons/chevron-down.mjs
466
+ var __iconNode5 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
467
+ var ChevronDown = createLucideIcon("chevron-down", __iconNode5);
468
+
469
+ // node_modules/lucide-react/dist/esm/icons/chevron-right.mjs
470
+ var __iconNode6 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
471
+ var ChevronRight = createLucideIcon("chevron-right", __iconNode6);
472
+
473
+ // node_modules/lucide-react/dist/esm/icons/chevrons-right.mjs
474
+ var __iconNode7 = [
475
+ ["path", { d: "m6 17 5-5-5-5", key: "xnjwq" }],
476
+ ["path", { d: "m13 17 5-5-5-5", key: "17xmmf" }]
477
+ ];
478
+ var ChevronsRight = createLucideIcon("chevrons-right", __iconNode7);
479
+
480
+ // node_modules/lucide-react/dist/esm/icons/coins.mjs
481
+ var __iconNode8 = [
482
+ ["path", { d: "M13.744 17.736a6 6 0 1 1-7.48-7.48", key: "bq4yh3" }],
483
+ ["path", { d: "M15 6h1v4", key: "11y1tn" }],
484
+ ["path", { d: "m6.134 14.768.866-.5 2 3.464", key: "17snzx" }],
485
+ ["circle", { cx: "16", cy: "8", r: "6", key: "14bfc9" }]
486
+ ];
487
+ var Coins = createLucideIcon("coins", __iconNode8);
488
+
489
+ // node_modules/lucide-react/dist/esm/icons/command.mjs
490
+ var __iconNode9 = [
491
+ [
492
+ "path",
493
+ { d: "M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3", key: "11bfej" }
494
+ ]
495
+ ];
496
+ var Command = createLucideIcon("command", __iconNode9);
497
+
498
+ // node_modules/lucide-react/dist/esm/icons/construction.mjs
499
+ var __iconNode10 = [
500
+ ["rect", { x: "2", y: "6", width: "20", height: "8", rx: "1", key: "1estib" }],
501
+ ["path", { d: "M17 14v7", key: "7m2elx" }],
502
+ ["path", { d: "M7 14v7", key: "1cm7wv" }],
503
+ ["path", { d: "M17 3v3", key: "1v4jwn" }],
504
+ ["path", { d: "M7 3v3", key: "7o6guu" }],
505
+ ["path", { d: "M10 14 2.3 6.3", key: "1023jk" }],
506
+ ["path", { d: "m14 6 7.7 7.7", key: "1s8pl2" }],
507
+ ["path", { d: "m8 6 8 8", key: "hl96qh" }]
508
+ ];
509
+ var Construction = createLucideIcon("construction", __iconNode10);
510
+
511
+ // node_modules/lucide-react/dist/esm/icons/copy.mjs
512
+ var __iconNode11 = [
513
+ ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
514
+ ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
515
+ ];
516
+ var Copy = createLucideIcon("copy", __iconNode11);
517
+
518
+ // node_modules/lucide-react/dist/esm/icons/database.mjs
519
+ var __iconNode12 = [
520
+ ["ellipse", { cx: "12", cy: "5", rx: "9", ry: "3", key: "msslwz" }],
521
+ ["path", { d: "M3 5V19A9 3 0 0 0 21 19V5", key: "1wlel7" }],
522
+ ["path", { d: "M3 12A9 3 0 0 0 21 12", key: "mv7ke4" }]
523
+ ];
524
+ var Database = createLucideIcon("database", __iconNode12);
525
+
526
+ // node_modules/lucide-react/dist/esm/icons/file-text.mjs
527
+ var __iconNode13 = [
528
+ [
529
+ "path",
530
+ {
531
+ d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
532
+ key: "1oefj6"
533
+ }
534
+ ],
535
+ ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
536
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
537
+ ["path", { d: "M16 13H8", key: "t4e002" }],
538
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
539
+ ];
540
+ var FileText = createLucideIcon("file-text", __iconNode13);
541
+
542
+ // node_modules/lucide-react/dist/esm/icons/files.mjs
543
+ var __iconNode14 = [
544
+ ["path", { d: "M15 2h-4a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8", key: "14sh0y" }],
545
+ [
546
+ "path",
547
+ {
548
+ d: "M16.706 2.706A2.4 2.4 0 0 0 15 2v5a1 1 0 0 0 1 1h5a2.4 2.4 0 0 0-.706-1.706z",
549
+ key: "1970lx"
550
+ }
551
+ ],
552
+ ["path", { d: "M5 7a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h8a2 2 0 0 0 1.732-1", key: "l4dndm" }]
553
+ ];
554
+ var Files = createLucideIcon("files", __iconNode14);
555
+
556
+ // node_modules/lucide-react/dist/esm/icons/flame.mjs
557
+ var __iconNode15 = [
558
+ [
559
+ "path",
560
+ {
561
+ d: "M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4",
562
+ key: "1slcih"
563
+ }
564
+ ]
565
+ ];
566
+ var Flame = createLucideIcon("flame", __iconNode15);
567
+
568
+ // node_modules/lucide-react/dist/esm/icons/flask-conical.mjs
569
+ var __iconNode16 = [
570
+ [
571
+ "path",
572
+ {
573
+ d: "M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2",
574
+ key: "18mbvz"
575
+ }
576
+ ],
577
+ ["path", { d: "M6.453 15h11.094", key: "3shlmq" }],
578
+ ["path", { d: "M8.5 2h7", key: "csnxdl" }]
579
+ ];
580
+ var FlaskConical = createLucideIcon("flask-conical", __iconNode16);
581
+
582
+ // node_modules/lucide-react/dist/esm/icons/folder-open.mjs
583
+ var __iconNode17 = [
584
+ [
585
+ "path",
586
+ {
587
+ d: "m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",
588
+ key: "usdka0"
589
+ }
590
+ ]
591
+ ];
592
+ var FolderOpen = createLucideIcon("folder-open", __iconNode17);
593
+
594
+ // node_modules/lucide-react/dist/esm/icons/folder.mjs
595
+ var __iconNode18 = [
596
+ [
597
+ "path",
598
+ {
599
+ d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",
600
+ key: "1kt360"
601
+ }
602
+ ]
603
+ ];
604
+ var Folder = createLucideIcon("folder", __iconNode18);
605
+
606
+ // node_modules/lucide-react/dist/esm/icons/gamepad-2.mjs
607
+ var __iconNode19 = [
608
+ ["line", { x1: "6", x2: "10", y1: "11", y2: "11", key: "1gktln" }],
609
+ ["line", { x1: "8", x2: "8", y1: "9", y2: "13", key: "qnk9ow" }],
610
+ ["line", { x1: "15", x2: "15.01", y1: "12", y2: "12", key: "krot7o" }],
611
+ ["line", { x1: "18", x2: "18.01", y1: "10", y2: "10", key: "1lcuu1" }],
612
+ [
613
+ "path",
614
+ {
615
+ d: "M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z",
616
+ key: "mfqc10"
617
+ }
618
+ ]
619
+ ];
620
+ var Gamepad2 = createLucideIcon("gamepad-2", __iconNode19);
621
+
622
+ // node_modules/lucide-react/dist/esm/icons/ghost.mjs
623
+ var __iconNode20 = [
624
+ ["path", { d: "M15 10v1", key: "oj8wfp" }],
625
+ [
626
+ "path",
627
+ {
628
+ d: "M7.528 20.472a1.6 1.6 0 012.277 0l1.057 1.056a1.6 1.6 0 002.276 0l1.057-1.056a1.6 1.6 0 012.277 0l1.114 1.114a1.4 1.4 0 002.414-1V10a8 8 0 00-16 0v10.586a1.4 1.4 0 002.414 1z",
629
+ key: "13lou3"
630
+ }
631
+ ],
632
+ ["path", { d: "M9 10v1", key: "1e14fa" }]
633
+ ];
634
+ var Ghost = createLucideIcon("ghost", __iconNode20);
635
+
636
+ // node_modules/lucide-react/dist/esm/icons/globe.mjs
637
+ var __iconNode21 = [
638
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
639
+ ["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
640
+ ["path", { d: "M2 12h20", key: "9i4pu4" }]
641
+ ];
642
+ var Globe = createLucideIcon("globe", __iconNode21);
643
+
644
+ // node_modules/lucide-react/dist/esm/icons/joystick.mjs
645
+ var __iconNode22 = [
646
+ [
647
+ "path",
648
+ {
649
+ d: "M21 17a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-2Z",
650
+ key: "jg2n2t"
651
+ }
652
+ ],
653
+ ["path", { d: "M6 15v-2", key: "gd6mvg" }],
654
+ ["path", { d: "M12 15V9", key: "8c7uyn" }],
655
+ ["circle", { cx: "12", cy: "6", r: "3", key: "1gm2ql" }]
656
+ ];
657
+ var Joystick = createLucideIcon("joystick", __iconNode22);
658
+
659
+ // node_modules/lucide-react/dist/esm/icons/lightbulb.mjs
660
+ var __iconNode23 = [
661
+ [
662
+ "path",
663
+ {
664
+ d: "M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5",
665
+ key: "1gvzjb"
666
+ }
667
+ ],
668
+ ["path", { d: "M9 18h6", key: "x1upvd" }],
669
+ ["path", { d: "M10 22h4", key: "ceow96" }]
670
+ ];
671
+ var Lightbulb = createLucideIcon("lightbulb", __iconNode23);
672
+
673
+ // node_modules/lucide-react/dist/esm/icons/map.mjs
674
+ var __iconNode24 = [
675
+ [
676
+ "path",
677
+ {
678
+ d: "M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z",
679
+ key: "169xi5"
680
+ }
681
+ ],
682
+ ["path", { d: "M15 5.764v15", key: "1pn4in" }],
683
+ ["path", { d: "M9 3.236v15", key: "1uimfh" }]
684
+ ];
685
+ var Map2 = createLucideIcon("map", __iconNode24);
686
+
687
+ // node_modules/lucide-react/dist/esm/icons/package.mjs
688
+ var __iconNode25 = [
689
+ [
690
+ "path",
691
+ {
692
+ d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",
693
+ key: "1a0edw"
694
+ }
695
+ ],
696
+ ["path", { d: "M12 22V12", key: "d0xqtd" }],
697
+ ["polyline", { points: "3.29 7 12 12 20.71 7", key: "ousv84" }],
698
+ ["path", { d: "m7.5 4.27 9 5.15", key: "1c824w" }]
699
+ ];
700
+ var Package = createLucideIcon("package", __iconNode25);
701
+
702
+ // node_modules/lucide-react/dist/esm/icons/palette.mjs
703
+ var __iconNode26 = [
704
+ [
705
+ "path",
706
+ {
707
+ d: "M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",
708
+ key: "e79jfc"
709
+ }
710
+ ],
711
+ ["circle", { cx: "13.5", cy: "6.5", r: ".5", fill: "currentColor", key: "1okk4w" }],
712
+ ["circle", { cx: "17.5", cy: "10.5", r: ".5", fill: "currentColor", key: "f64h9f" }],
713
+ ["circle", { cx: "6.5", cy: "12.5", r: ".5", fill: "currentColor", key: "qy21gx" }],
714
+ ["circle", { cx: "8.5", cy: "7.5", r: ".5", fill: "currentColor", key: "fotxhn" }]
715
+ ];
716
+ var Palette = createLucideIcon("palette", __iconNode26);
717
+
718
+ // node_modules/lucide-react/dist/esm/icons/pencil.mjs
719
+ var __iconNode27 = [
720
+ [
721
+ "path",
722
+ {
723
+ d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
724
+ key: "1a8usu"
725
+ }
726
+ ],
727
+ ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
728
+ ];
729
+ var Pencil = createLucideIcon("pencil", __iconNode27);
730
+
731
+ // node_modules/lucide-react/dist/esm/icons/plus.mjs
732
+ var __iconNode28 = [
733
+ ["path", { d: "M5 12h14", key: "1ays0h" }],
734
+ ["path", { d: "M12 5v14", key: "s699le" }]
735
+ ];
736
+ var Plus = createLucideIcon("plus", __iconNode28);
737
+
738
+ // node_modules/lucide-react/dist/esm/icons/puzzle.mjs
739
+ var __iconNode29 = [
740
+ [
741
+ "path",
742
+ {
743
+ d: "M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",
744
+ key: "w46dr5"
745
+ }
746
+ ]
747
+ ];
748
+ var Puzzle = createLucideIcon("puzzle", __iconNode29);
749
+
750
+ // node_modules/lucide-react/dist/esm/icons/rocket.mjs
751
+ var __iconNode30 = [
752
+ ["path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5", key: "qeys4" }],
753
+ [
754
+ "path",
755
+ {
756
+ d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09",
757
+ key: "u4xsad"
758
+ }
759
+ ],
760
+ [
761
+ "path",
762
+ {
763
+ d: "M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z",
764
+ key: "676m9"
765
+ }
766
+ ],
767
+ ["path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05", key: "92ym6u" }]
768
+ ];
769
+ var Rocket = createLucideIcon("rocket", __iconNode30);
770
+
771
+ // node_modules/lucide-react/dist/esm/icons/search.mjs
772
+ var __iconNode31 = [
773
+ ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
774
+ ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
775
+ ];
776
+ var Search = createLucideIcon("search", __iconNode31);
777
+
778
+ // node_modules/lucide-react/dist/esm/icons/settings.mjs
779
+ var __iconNode32 = [
780
+ [
781
+ "path",
782
+ {
783
+ d: "M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",
784
+ key: "1i5ecw"
785
+ }
786
+ ],
787
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
788
+ ];
789
+ var Settings = createLucideIcon("settings", __iconNode32);
790
+
791
+ // node_modules/lucide-react/dist/esm/icons/sliders-horizontal.mjs
792
+ var __iconNode33 = [
793
+ ["path", { d: "M10 5H3", key: "1qgfaw" }],
794
+ ["path", { d: "M12 19H3", key: "yhmn1j" }],
795
+ ["path", { d: "M14 3v4", key: "1sua03" }],
796
+ ["path", { d: "M16 17v4", key: "1q0r14" }],
797
+ ["path", { d: "M21 12h-9", key: "1o4lsq" }],
798
+ ["path", { d: "M21 19h-5", key: "1rlt1p" }],
799
+ ["path", { d: "M21 5h-7", key: "1oszz2" }],
800
+ ["path", { d: "M8 10v4", key: "tgpxqk" }],
801
+ ["path", { d: "M8 12H3", key: "a7s4jb" }]
802
+ ];
803
+ var SlidersHorizontal = createLucideIcon("sliders-horizontal", __iconNode33);
804
+
805
+ // node_modules/lucide-react/dist/esm/icons/snowflake.mjs
806
+ var __iconNode34 = [
807
+ ["path", { d: "m10 20-1.25-2.5L6 18", key: "18frcb" }],
808
+ ["path", { d: "M10 4 8.75 6.5 6 6", key: "7mghy3" }],
809
+ ["path", { d: "m14 20 1.25-2.5L18 18", key: "1chtki" }],
810
+ ["path", { d: "m14 4 1.25 2.5L18 6", key: "1b4wsy" }],
811
+ ["path", { d: "m17 21-3-6h-4", key: "15hhxa" }],
812
+ ["path", { d: "m17 3-3 6 1.5 3", key: "11697g" }],
813
+ ["path", { d: "M2 12h6.5L10 9", key: "kv9z4n" }],
814
+ ["path", { d: "m20 10-1.5 2 1.5 2", key: "1swlpi" }],
815
+ ["path", { d: "M22 12h-6.5L14 15", key: "1mxi28" }],
816
+ ["path", { d: "m4 10 1.5 2L4 14", key: "k9enpj" }],
817
+ ["path", { d: "m7 21 3-6-1.5-3", key: "j8hb9u" }],
818
+ ["path", { d: "m7 3 3 6h4", key: "1otusx" }]
819
+ ];
820
+ var Snowflake = createLucideIcon("snowflake", __iconNode34);
821
+
822
+ // node_modules/lucide-react/dist/esm/icons/sprout.mjs
823
+ var __iconNode35 = [
824
+ [
825
+ "path",
826
+ {
827
+ d: "M14 9.536V7a4 4 0 0 1 4-4h1.5a.5.5 0 0 1 .5.5V5a4 4 0 0 1-4 4 4 4 0 0 0-4 4c0 2 1 3 1 5a5 5 0 0 1-1 3",
828
+ key: "139s4v"
829
+ }
830
+ ],
831
+ ["path", { d: "M4 9a5 5 0 0 1 8 4 5 5 0 0 1-8-4", key: "1dlkgp" }],
832
+ ["path", { d: "M5 21h14", key: "11awu3" }]
833
+ ];
834
+ var Sprout = createLucideIcon("sprout", __iconNode35);
835
+
836
+ // node_modules/lucide-react/dist/esm/icons/star.mjs
837
+ var __iconNode36 = [
838
+ [
839
+ "path",
840
+ {
841
+ d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",
842
+ key: "r04s7s"
843
+ }
844
+ ]
845
+ ];
846
+ var Star = createLucideIcon("star", __iconNode36);
847
+
848
+ // node_modules/lucide-react/dist/esm/icons/target.mjs
849
+ var __iconNode37 = [
850
+ ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
851
+ ["circle", { cx: "12", cy: "12", r: "6", key: "1vlfrh" }],
852
+ ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }]
853
+ ];
854
+ var Target = createLucideIcon("target", __iconNode37);
855
+
856
+ // node_modules/lucide-react/dist/esm/icons/trash.mjs
857
+ var __iconNode38 = [
858
+ ["path", { d: "M10 11v6", key: "nco0om" }],
859
+ ["path", { d: "M14 11v6", key: "outv1u" }],
860
+ ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
861
+ ["path", { d: "M3 6h18", key: "d0wm0j" }],
862
+ ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
863
+ ];
864
+ var Trash = createLucideIcon("trash", __iconNode38);
865
+
866
+ // node_modules/lucide-react/dist/esm/icons/trending-up.mjs
867
+ var __iconNode39 = [
868
+ ["path", { d: "M16 7h6v6", key: "box55l" }],
869
+ ["path", { d: "m22 7-8.5 8.5-5-5L2 17", key: "1t1m79" }]
870
+ ];
871
+ var TrendingUp = createLucideIcon("trending-up", __iconNode39);
872
+
873
+ // node_modules/lucide-react/dist/esm/icons/wrench.mjs
874
+ var __iconNode40 = [
875
+ [
876
+ "path",
877
+ {
878
+ d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",
879
+ key: "1ngwbx"
880
+ }
881
+ ]
882
+ ];
883
+ var Wrench = createLucideIcon("wrench", __iconNode40);
884
+
885
+ // node_modules/lucide-react/dist/esm/icons/zap.mjs
886
+ var __iconNode41 = [
887
+ [
888
+ "path",
889
+ {
890
+ d: "M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z",
891
+ key: "1v7up4"
892
+ }
893
+ ]
894
+ ];
895
+ var Zap = createLucideIcon("zap", __iconNode41);
896
+
897
+ // src/client/icons.tsx
898
+ var import_jsx_runtime3 = require("react/jsx-runtime");
899
+ var WORKSPACE_ICON_KEYS = [
900
+ "folder",
901
+ "folder-open",
902
+ "files",
903
+ "star",
904
+ "flame",
905
+ "rocket",
906
+ "flask",
907
+ "settings",
908
+ "package",
909
+ "file-text",
910
+ "target",
911
+ "brain",
912
+ "lightbulb",
913
+ "wrench",
914
+ "globe",
915
+ "database",
916
+ "puzzle",
917
+ "palette",
918
+ "chart",
919
+ "trending-up",
920
+ "bot",
921
+ "ghost",
922
+ "zap",
923
+ "sliders",
924
+ "joystick",
925
+ "sprout",
926
+ "construction",
927
+ "book",
928
+ "coins",
929
+ "gamepad",
930
+ "map",
931
+ "snowflake"
932
+ ];
933
+ var ICONS = {
934
+ "folder": Folder,
935
+ "folder-open": FolderOpen,
936
+ "files": Files,
937
+ "star": Star,
938
+ "flame": Flame,
939
+ "rocket": Rocket,
940
+ "flask": FlaskConical,
941
+ "settings": Settings,
942
+ "package": Package,
943
+ "file-text": FileText,
944
+ "target": Target,
945
+ "brain": Brain,
946
+ "lightbulb": Lightbulb,
947
+ "wrench": Wrench,
948
+ "globe": Globe,
949
+ "database": Database,
950
+ "puzzle": Puzzle,
951
+ "palette": Palette,
952
+ "chart": ChartColumn,
953
+ "trending-up": TrendingUp,
954
+ "bot": Bot,
955
+ "ghost": Ghost,
956
+ "zap": Zap,
957
+ "sliders": SlidersHorizontal,
958
+ "joystick": Joystick,
959
+ "sprout": Sprout,
960
+ "construction": Construction,
961
+ "book": BookOpen,
962
+ "coins": Coins,
963
+ "gamepad": Gamepad2,
964
+ "map": Map2,
965
+ "snowflake": Snowflake
966
+ };
967
+ var LEGACY_EMOJI_CHOICES = [
968
+ "\u{1F4C1}",
969
+ "\u{1F5C2}\uFE0F",
970
+ "\u{1F4C2}",
971
+ "\u2B50",
972
+ "\u{1F525}",
973
+ "\u{1F680}",
974
+ "\u{1F9EA}",
975
+ "\u2699\uFE0F",
976
+ "\u{1F4E6}",
977
+ "\u{1F4C4}",
978
+ "\u{1F3AF}",
979
+ "\u{1F9E0}",
980
+ "\u{1F4A1}",
981
+ "\u{1F6E0}\uFE0F",
982
+ "\u{1F310}",
983
+ "\u{1F5C4}\uFE0F",
984
+ "\u{1F9E9}",
985
+ "\u{1F3A8}",
986
+ "\u{1F4CA}",
987
+ "\u{1F4C8}",
988
+ "\u{1F916}",
989
+ "\u{1F47E}",
990
+ "\u26A1",
991
+ "\u{1F39B}\uFE0F",
992
+ "\u{1F579}\uFE0F",
993
+ "\u{1F331}",
994
+ "\u{1F3D7}\uFE0F",
995
+ "\u{1F4DA}",
996
+ "\u{1F4B0}",
997
+ "\u{1F3AE}",
998
+ "\u{1F5FA}\uFE0F",
999
+ "\u{1F9CA}"
1000
+ ];
1001
+ function iconKeyOf(icon) {
1002
+ if (!icon) return void 0;
1003
+ if (icon in ICONS) return icon;
1004
+ const legacyIndex = LEGACY_EMOJI_CHOICES.indexOf(icon);
1005
+ return legacyIndex >= 0 ? WORKSPACE_ICON_KEYS[legacyIndex] : void 0;
1006
+ }
1007
+ function WorkspaceGlyph(props) {
1008
+ const { icon, color, size = 14, strokeWidth = 1.8, style } = props;
1009
+ const key = iconKeyOf(icon);
1010
+ if (key) {
1011
+ const IconComponent = ICONS[key];
1012
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconComponent, { size, strokeWidth, "aria-hidden": true, style });
1013
+ }
1014
+ if (color) {
1015
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { width: size - 4, height: size - 4, borderRadius: size / 2, background: color, ...style } });
1016
+ }
1017
+ return null;
1018
+ }
1019
+
1020
+ // src/client/Spotlight.tsx
1021
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1022
+ var MAX_ROWS = 40;
1023
+ function norm(text) {
1024
+ return text.trim().toLowerCase().replace(/\s+/g, " ");
1025
+ }
1026
+ function scoreText(field, query) {
1027
+ const f = field.toLowerCase();
1028
+ const q = norm(query);
1029
+ if (q.length === 0) return 0;
1030
+ const terms = q.split(" ");
1031
+ let total = 0;
1032
+ for (const term of terms) {
1033
+ const at = f.indexOf(term);
1034
+ if (at < 0) return Number.POSITIVE_INFINITY;
1035
+ total += at === 0 ? 1 : f[at - 1] === " " || f[at - 1] === "/" ? 2 : at + 3;
1036
+ }
1037
+ return total;
1038
+ }
1039
+ function bestScore(query, fields) {
1040
+ let best = Number.POSITIVE_INFINITY;
1041
+ for (const field of fields) {
1042
+ const score = scoreText(field, query);
1043
+ if (score < best) best = score;
1044
+ }
1045
+ return best;
1046
+ }
1047
+ function byRecencyDesc(a, b) {
1048
+ return a < b ? 1 : a > b ? -1 : 0;
1049
+ }
1050
+ function workspaceIdOfSession(workspaceItems, sessionId) {
1051
+ for (const item of workspaceItems) {
1052
+ if (Array.isArray(item.sessionIds) && item.sessionIds.includes(sessionId)) {
1053
+ return item.workspaceId;
1054
+ }
1055
+ }
1056
+ return void 0;
1057
+ }
1058
+ function buildSections(query, sessionsState, workspacesState, archived, showArchived, kind) {
1059
+ const q = norm(query);
1060
+ const byId = sessionsState?.byId ?? {};
1061
+ const sessionIds = Array.isArray(sessionsState?.ids) ? sessionsState.ids : [];
1062
+ const workspaceItems = workspacesState?.items ?? [];
1063
+ const builtinArchivedSessionIds = new Set(workspacesState?.archivedSessionIds ?? []);
1064
+ const searching = q.length > 0;
1065
+ const activeWs = [];
1066
+ const archivedWs = [];
1067
+ for (const item of workspaceItems) {
1068
+ const id = item.workspaceId;
1069
+ const rec = archived[id];
1070
+ const score = searching ? bestScore(q, [item.title, item.path]) : 0;
1071
+ if (searching && !Number.isFinite(score)) continue;
1072
+ const row = {
1073
+ kind: "workspace",
1074
+ id,
1075
+ title: item.title,
1076
+ path: item.path,
1077
+ updatedAt: item.updatedAt,
1078
+ archivedAt: rec?.at,
1079
+ sessionCount: Array.isArray(item.sessionIds) ? item.sessionIds.length : 0,
1080
+ archived: Boolean(rec),
1081
+ score
1082
+ };
1083
+ if (rec) archivedWs.push(row);
1084
+ else activeWs.push(row);
1085
+ }
1086
+ const sortWs = (list) => [...list].sort((a, b) => {
1087
+ if (a.score !== b.score) return a.score - b.score;
1088
+ if (a.archivedAt && b.archivedAt) return byRecencyDesc(a.archivedAt, b.archivedAt);
1089
+ return byRecencyDesc(a.updatedAt, b.updatedAt);
1090
+ });
1091
+ const activeSorted = sortWs(activeWs);
1092
+ const archivedSorted = sortWs(archivedWs);
1093
+ const archivedWorkspaceIds = new Set(archivedSorted.map((r) => String(r.id)));
1094
+ const workspaceTitleById = /* @__PURE__ */ new Map();
1095
+ for (const item of workspaceItems) {
1096
+ for (const sid of item.sessionIds ?? []) workspaceTitleById.set(sid, item.title);
1097
+ }
1098
+ const sessions = [];
1099
+ for (const id of sessionIds) {
1100
+ const session = byId[id];
1101
+ if (!session || session.origin === "subagent" || session.blank) continue;
1102
+ const wsId = workspaceIdOfSession(workspaceItems, String(id));
1103
+ const workspaceArchived = wsId !== void 0 && archivedWorkspaceIds.has(wsId);
1104
+ const grouped = workspaceTitleById.has(String(id));
1105
+ const allowUngrouped = kind === "sessions";
1106
+ if (!searching) {
1107
+ if (workspaceArchived || builtinArchivedSessionIds.has(String(id)) || !grouped && !allowUngrouped) {
1108
+ continue;
1109
+ }
1110
+ }
1111
+ const score = searching ? bestScore(q, [session.displayTitle ?? "", session.title ?? "", session.cwd ?? ""]) : 1;
1112
+ if (searching && !Number.isFinite(score)) continue;
1113
+ sessions.push({
1114
+ kind: "session",
1115
+ id,
1116
+ title: session.displayTitle ?? session.title ?? id,
1117
+ cwd: session.cwd,
1118
+ workspaceTitle: workspaceTitleById.get(String(id)),
1119
+ workspaceArchived,
1120
+ updatedAt: session.updatedAt ?? 0,
1121
+ running: Boolean(session.running),
1122
+ score
1123
+ });
1124
+ }
1125
+ sessions.sort((a, b) => {
1126
+ if (a.score !== b.score) return a.score - b.score;
1127
+ if (a.updatedAt !== b.updatedAt) return a.updatedAt > b.updatedAt ? -1 : 1;
1128
+ return a.title < b.title ? -1 : 1;
1129
+ });
1130
+ const showWorkspaces = kind !== "sessions";
1131
+ const showSessions = kind !== "workspaces";
1132
+ if (searching) {
1133
+ const secs2 = [];
1134
+ const wsRows = [...activeSorted, ...archivedSorted].slice(0, MAX_ROWS);
1135
+ if (showWorkspaces && wsRows.length > 0) secs2.push({ key: "workspaces", label: L("\u5DE5\u4F5C\u533A", "Workspaces"), rows: wsRows });
1136
+ if (showSessions && sessions.length > 0) secs2.push({ key: "sessions", label: L("\u4F1A\u8BDD", "Sessions"), rows: sessions });
1137
+ return secs2;
1138
+ }
1139
+ const secs = [];
1140
+ if (showWorkspaces && activeSorted.length > 0) {
1141
+ secs.push({ key: "workspaces", label: L("\u5DE5\u4F5C\u533A", "Workspaces"), rows: activeSorted.slice(0, MAX_ROWS) });
1142
+ }
1143
+ if (showSessions) {
1144
+ const idleSessions = sessions.filter((s) => !s.workspaceArchived).slice(0, 30);
1145
+ if (idleSessions.length > 0) secs.push({ key: "sessions", label: L("\u4F1A\u8BDD", "Sessions"), rows: idleSessions });
1146
+ }
1147
+ if (showWorkspaces && archivedSorted.length > 0 && showArchived) {
1148
+ secs.push({ key: "archived", label: L("\u5DF2\u5F52\u6863", "Archived"), rows: archivedSorted.slice(0, MAX_ROWS) });
1149
+ }
1150
+ return secs;
1151
+ }
1152
+ function SpotlightPalette(props) {
1153
+ const { useSessions, useWorkspaces, useStore, actions, openWorkspace, openSession, archiveSession } = props;
1154
+ const [open, setOpen] = (0, import_react5.useState)(false);
1155
+ const [query, setQuery] = (0, import_react5.useState)("");
1156
+ const [cursor, setCursor] = (0, import_react5.useState)(0);
1157
+ const [showArchived, setShowArchived] = (0, import_react5.useState)(false);
1158
+ const [kind, setKind] = (0, import_react5.useState)("all");
1159
+ const inputRef = (0, import_react5.useRef)(null);
1160
+ const flatRef = (0, import_react5.useRef)([]);
1161
+ const cursorRef = (0, import_react5.useRef)(0);
1162
+ cursorRef.current = cursor;
1163
+ const archived = useStore((state) => state.archived ?? {});
1164
+ const appearanceMap = useStore((state) => state.appearance ?? {});
1165
+ const sessionsState = typeof useSessions === "function" ? useSessions((state) => state) : void 0;
1166
+ const workspacesState = typeof useWorkspaces === "function" ? useWorkspaces((state) => state) : void 0;
1167
+ (0, import_react5.useEffect)(() => {
1168
+ const onKeyDown = (event) => {
1169
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
1170
+ event.preventDefault();
1171
+ setOpen((prev) => !prev);
1172
+ }
1173
+ };
1174
+ const onOpenRequest = () => setOpen(true);
1175
+ window.addEventListener("keydown", onKeyDown);
1176
+ window.addEventListener("dsh-workspace-kit:open", onOpenRequest);
1177
+ return () => {
1178
+ window.removeEventListener("keydown", onKeyDown);
1179
+ window.removeEventListener("dsh-workspace-kit:open", onOpenRequest);
1180
+ };
1181
+ }, []);
1182
+ (0, import_react5.useEffect)(() => {
1183
+ if (!open) return;
1184
+ setQuery("");
1185
+ setCursor(0);
1186
+ setShowArchived(false);
1187
+ setKind("all");
1188
+ const frame = requestAnimationFrame(() => inputRef.current?.focus());
1189
+ return () => cancelAnimationFrame(frame);
1190
+ }, [open]);
1191
+ const sections = (0, import_react5.useMemo)(
1192
+ () => buildSections(query, sessionsState, workspacesState, archived, showArchived, kind),
1193
+ [query, sessionsState, workspacesState, archived, showArchived, kind]
1194
+ );
1195
+ const display = (0, import_react5.useMemo)(() => {
1196
+ const displaySections = [];
1197
+ const flatRows = [];
1198
+ let budget = MAX_ROWS;
1199
+ for (const section of sections) {
1200
+ if (budget <= 0) break;
1201
+ const take = section.rows.slice(0, budget);
1202
+ displaySections.push({ ...section, rows: take });
1203
+ flatRows.push(...take);
1204
+ budget -= take.length;
1205
+ }
1206
+ return { sections: displaySections, flat: flatRows };
1207
+ }, [sections]);
1208
+ (0, import_react5.useEffect)(() => {
1209
+ flatRef.current = display.flat;
1210
+ const max = Math.max(0, display.flat.length - 1);
1211
+ if (cursor > max) setCursor(max);
1212
+ }, [display.flat, cursor]);
1213
+ function activate(row) {
1214
+ if (row.kind === "workspace") openWorkspace(row.id);
1215
+ else openSession(row.id);
1216
+ setOpen(false);
1217
+ }
1218
+ function toggleArchived(row) {
1219
+ if (row.kind !== "workspace") return;
1220
+ if (row.archived) actions.restore(row.id);
1221
+ else actions.archive(row.id, (/* @__PURE__ */ new Date()).toISOString());
1222
+ }
1223
+ (0, import_react5.useEffect)(() => {
1224
+ if (!open) return;
1225
+ const onKeyDown = (event) => {
1226
+ const rowsNow = flatRef.current;
1227
+ if (event.key === "Escape") {
1228
+ event.preventDefault();
1229
+ setOpen(false);
1230
+ return;
1231
+ }
1232
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1233
+ event.preventDefault();
1234
+ const delta = event.key === "ArrowDown" ? 1 : -1;
1235
+ setCursor((c) => Math.max(0, Math.min(c + delta, Math.max(0, rowsNow.length - 1))));
1236
+ return;
1237
+ }
1238
+ if (event.key === "Enter" && rowsNow.length > 0) {
1239
+ event.preventDefault();
1240
+ const target = rowsNow[Math.max(0, Math.min(cursorRef.current, rowsNow.length - 1))];
1241
+ if (target) activate(target);
1242
+ }
1243
+ };
1244
+ window.addEventListener("keydown", onKeyDown);
1245
+ return () => window.removeEventListener("keydown", onKeyDown);
1246
+ }, [open]);
1247
+ if (!open) return null;
1248
+ const searching = norm(query).length > 0;
1249
+ const rowCount = display.flat.length;
1250
+ const archivedTotal = workspaceItemsArchivedCount(workspacesState, archived);
1251
+ const idleArchivedHidden = !searching && archivedTotal > 0 && !showArchived;
1252
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.backdrop, onMouseDown: () => setOpen(false), role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1253
+ "div",
1254
+ {
1255
+ style: styles3.panel,
1256
+ role: "dialog",
1257
+ "aria-label": L("Spotlight \u5DE5\u4F5C\u533A\u641C\u7D22", "Spotlight workspace search"),
1258
+ onMouseDown: (e) => e.stopPropagation(),
1259
+ children: [
1260
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1261
+ "input",
1262
+ {
1263
+ ref: inputRef,
1264
+ style: styles3.input,
1265
+ placeholder: L("\u641C\u7D22\u5DE5\u4F5C\u533A\u6216\u4F1A\u8BDD\u2026\uFF08Esc \u5173\u95ED\uFF09", "Search workspaces or sessions\u2026 (Esc to close)"),
1266
+ value: query,
1267
+ onChange: (e) => {
1268
+ setQuery(e.target.value);
1269
+ setCursor(0);
1270
+ },
1271
+ "aria-label": L("\u641C\u7D22", "Search")
1272
+ }
1273
+ ),
1274
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.chips, children: ["all", "workspaces", "sessions"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1275
+ "button",
1276
+ {
1277
+ type: "button",
1278
+ style: { ...styles3.chip, ...kind === k ? styles3.chipActive : {} },
1279
+ onClick: () => {
1280
+ setKind(k);
1281
+ setCursor(0);
1282
+ },
1283
+ children: k === "all" ? L("\u5168\u90E8", "All") : k === "workspaces" ? L("\u5DE5\u4F5C\u533A", "Workspaces") : L("\u4F1A\u8BDD", "Sessions")
1284
+ },
1285
+ k
1286
+ )) }),
1287
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.body, children: [
1288
+ rowCount === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.empty, children: query.trim() ? L("\u6CA1\u6709\u5339\u914D\u300C{q}\u300D\u7684\u5DE5\u4F5C\u533A\u6216\u4F1A\u8BDD", 'No workspaces or sessions match "{q}"', { q: query.trim() }) : L("\u8FD8\u6CA1\u6709\u5DE5\u4F5C\u533A\u3002\u4ECE\u4E00\u4E2A\u9879\u76EE\u76EE\u5F55\u5F00\u59CB\u4F1A\u8BDD\u540E\u4F1A\u81EA\u52A8\u51FA\u73B0\u3002", "No workspaces yet. Start a session from a project directory and one will appear automatically.") }),
1289
+ display.sections.map((section) => {
1290
+ const rowsInSection = section.rows;
1291
+ if (rowsInSection.length === 0) return null;
1292
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1293
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.sectionHeader, children: section.label }),
1294
+ rowsInSection.map((row) => {
1295
+ const index = display.flat.indexOf(row);
1296
+ const selected = index === cursor;
1297
+ const isArchivedWs = row.kind === "workspace" && row.archived;
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1299
+ "div",
1300
+ {
1301
+ style: { ...styles3.row, ...selected ? styles3.rowSelected : {} },
1302
+ onMouseEnter: () => setCursor(index),
1303
+ onMouseDown: (e) => {
1304
+ e.stopPropagation();
1305
+ activate(row);
1306
+ },
1307
+ children: [
1308
+ row.kind === "workspace" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.rowIconSlot, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1309
+ WorkspaceGlyph,
1310
+ {
1311
+ icon: appearanceMap[String(row.id)]?.icon,
1312
+ color: appearanceMap[String(row.id)]?.color,
1313
+ size: 14
1314
+ }
1315
+ ) }),
1316
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.rowMain, children: [
1317
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.rowTitle, children: [
1318
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.rowTitleText, children: row.kind === "workspace" ? row.title : row.title }),
1319
+ isArchivedWs && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.badgeArchived, children: L("\u5DF2\u5F52\u6863", "Archived") }),
1320
+ row.kind === "session" && row.running && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles3.badgeRunning, children: L("\u8FD0\u884C\u4E2D", "Running") })
1321
+ ] }),
1322
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: styles3.rowSub, children: row.kind === "workspace" ? `${row.path} \xB7 ${L("{n} \u4E2A\u4F1A\u8BDD", "{n} sessions", { n: row.sessionCount })} \xB7 ${row.updatedAt.slice(0, 10)}` : row.cwd ?? "" })
1323
+ ] }),
1324
+ row.kind === "workspace" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1325
+ "button",
1326
+ {
1327
+ style: styles3.actionButton,
1328
+ title: isArchivedWs ? L("\u6062\u590D\u5DE5\u4F5C\u533A", "Restore workspace") : L("\u5F52\u6863\u5DE5\u4F5C\u533A\uFF08\u8F6F\u5F52\u6863\uFF0C\u53EF\u6062\u590D\uFF09", "Archive workspace (soft archive, restorable)"),
1329
+ onMouseDown: (e) => {
1330
+ e.stopPropagation();
1331
+ toggleArchived(row);
1332
+ },
1333
+ children: isArchivedWs ? L("\u6062\u590D", "Restore") : L("\u5F52\u6863", "Archive")
1334
+ }
1335
+ ),
1336
+ row.kind === "session" && selected && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1337
+ "button",
1338
+ {
1339
+ style: styles3.actionButton,
1340
+ title: L("\u5F52\u6863\u4F1A\u8BDD\uFF08\u5B98\u65B9\u5F52\u6863\u96C6\uFF0C\u4E0D\u53EF\u9006\uFF1A\u4F1A\u4ECE\u6240\u6709\u5217\u8868\u9690\u85CF\uFF0C\u4ECD\u53EF\u4ECE\u641C\u7D22\u6253\u5F00\uFF09", "Archive session (official archive set \u2014 irreversible: hidden from every list, still reachable via search)"),
1341
+ onMouseDown: (e) => {
1342
+ e.stopPropagation();
1343
+ archiveSession(row.id);
1344
+ },
1345
+ children: L("\u5F52\u6863\u4F1A\u8BDD", "Archive session")
1346
+ }
1347
+ )
1348
+ ]
1349
+ },
1350
+ `${row.kind}-${row.id}`
1351
+ );
1352
+ })
1353
+ ] }, section.key);
1354
+ }),
1355
+ idleArchivedHidden && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1356
+ "div",
1357
+ {
1358
+ style: styles3.expandArchived,
1359
+ role: "button",
1360
+ tabIndex: 0,
1361
+ onClick: () => setShowArchived(true),
1362
+ onKeyDown: (e) => {
1363
+ if (e.key === "Enter") setShowArchived(true);
1364
+ },
1365
+ children: [
1366
+ "\u25B8 ",
1367
+ L("\u5DF2\u5F52\u6863 {n} \u9879\uFF08\u70B9\u51FB\u5C55\u5F00\u67E5\u770B / \u6062\u590D\uFF09", "Archived {n} \u2014 click to expand / restore", { n: archivedTotal })
1368
+ ]
1369
+ }
1370
+ )
1371
+ ] }),
1372
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles3.footer, children: [
1373
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: L("\u2191\u2193 \u9009\u62E9", "\u2191\u2193 Navigate") }),
1374
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: L("\u21B5 \u6253\u5F00", "\u21B5 Open") }),
1375
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: searching ? L("{n} \u4E2A\u5339\u914D", "{n} matches", { n: rowCount }) : L("{n} \u9879", "{n} items", { n: rowCount }) }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { marginLeft: "auto" }, children: L("Esc \u5173\u95ED", "Esc Close") })
1377
+ ] })
1378
+ ]
1379
+ }
1380
+ ) });
1381
+ }
1382
+ function workspaceItemsArchivedCount(workspacesState, archived) {
1383
+ const items = workspacesState?.items ?? [];
1384
+ let count = 0;
1385
+ for (const item of items) {
1386
+ if (archived[item.workspaceId]) count += 1;
1387
+ }
1388
+ return count;
1389
+ }
1390
+ var styles3 = {
1391
+ backdrop: {
1392
+ position: "fixed",
1393
+ inset: 0,
1394
+ zIndex: 9999,
1395
+ display: "flex",
1396
+ alignItems: "flex-start",
1397
+ justifyContent: "center",
1398
+ paddingTop: "12vh",
1399
+ background: "rgba(15, 18, 26, 0.42)",
1400
+ backdropFilter: "blur(2px)"
1401
+ },
1402
+ panel: {
1403
+ width: 620,
1404
+ maxWidth: "calc(100vw - 48px)",
1405
+ background: "#ffffff",
1406
+ color: "#1c2333",
1407
+ borderRadius: 14,
1408
+ boxShadow: "0 24px 64px rgba(15, 18, 26, 0.35)",
1409
+ overflow: "hidden",
1410
+ display: "flex",
1411
+ flexDirection: "column"
1412
+ },
1413
+ input: {
1414
+ width: "100%",
1415
+ boxSizing: "border-box",
1416
+ padding: "16px 18px",
1417
+ fontSize: 16,
1418
+ border: "none",
1419
+ outline: "none",
1420
+ background: "transparent",
1421
+ color: "inherit",
1422
+ borderBottom: "1px solid rgba(28, 35, 51, 0.08)"
1423
+ },
1424
+ chips: {
1425
+ display: "flex",
1426
+ gap: 6,
1427
+ padding: "8px 12px 2px"
1428
+ },
1429
+ chip: {
1430
+ fontSize: 12,
1431
+ lineHeight: "22px",
1432
+ padding: "0 12px",
1433
+ borderRadius: 11,
1434
+ border: "1px solid rgba(28, 35, 51, 0.14)",
1435
+ background: "transparent",
1436
+ color: "#5a6478",
1437
+ cursor: "pointer"
1438
+ },
1439
+ chipActive: {
1440
+ background: "rgba(45, 102, 247, 0.12)",
1441
+ borderColor: "rgba(45, 102, 247, 0.5)",
1442
+ color: "#2d66f7",
1443
+ fontWeight: 600
1444
+ },
1445
+ body: {
1446
+ maxHeight: "52vh",
1447
+ overflowY: "auto",
1448
+ padding: "6px"
1449
+ },
1450
+ sectionHeader: {
1451
+ padding: "8px 12px 4px",
1452
+ fontSize: 11,
1453
+ fontWeight: 600,
1454
+ letterSpacing: "0.04em",
1455
+ color: "#8a93a6",
1456
+ textTransform: "uppercase"
1457
+ },
1458
+ empty: {
1459
+ padding: "28px 16px",
1460
+ textAlign: "center",
1461
+ color: "#7a8499",
1462
+ fontSize: 13
1463
+ },
1464
+ row: {
1465
+ display: "flex",
1466
+ alignItems: "center",
1467
+ gap: 8,
1468
+ padding: "9px 12px",
1469
+ borderRadius: 9,
1470
+ cursor: "pointer"
1471
+ },
1472
+ rowSelected: {
1473
+ background: "rgba(45, 102, 247, 0.10)"
1474
+ },
1475
+ rowMain: {
1476
+ flex: 1,
1477
+ minWidth: 0
1478
+ },
1479
+ rowIconSlot: {
1480
+ width: 18,
1481
+ height: 18,
1482
+ flexShrink: 0,
1483
+ display: "flex",
1484
+ alignItems: "center",
1485
+ justifyContent: "center"
1486
+ },
1487
+ rowColorDot: {
1488
+ width: 10,
1489
+ height: 10,
1490
+ borderRadius: 5
1491
+ },
1492
+ rowTitle: {
1493
+ fontSize: 14,
1494
+ fontWeight: 600,
1495
+ display: "flex",
1496
+ alignItems: "center",
1497
+ gap: 6
1498
+ },
1499
+ rowTitleText: {
1500
+ whiteSpace: "nowrap",
1501
+ overflow: "hidden",
1502
+ textOverflow: "ellipsis"
1503
+ },
1504
+ rowSub: {
1505
+ fontSize: 12,
1506
+ color: "#7a8499",
1507
+ whiteSpace: "nowrap",
1508
+ overflow: "hidden",
1509
+ textOverflow: "ellipsis"
1510
+ },
1511
+ badgeArchived: {
1512
+ fontSize: 10,
1513
+ lineHeight: "16px",
1514
+ padding: "0 6px",
1515
+ borderRadius: 8,
1516
+ background: "#eef1f6",
1517
+ color: "#5a6478",
1518
+ flexShrink: 0
1519
+ },
1520
+ badgeRunning: {
1521
+ fontSize: 10,
1522
+ lineHeight: "16px",
1523
+ padding: "0 6px",
1524
+ borderRadius: 8,
1525
+ background: "rgba(45, 102, 247, 0.12)",
1526
+ color: "#2d66f7",
1527
+ flexShrink: 0
1528
+ },
1529
+ actionButton: {
1530
+ flexShrink: 0,
1531
+ fontSize: 12,
1532
+ padding: "3px 10px",
1533
+ borderRadius: 8,
1534
+ border: "1px solid rgba(28, 35, 51, 0.14)",
1535
+ background: "#ffffff",
1536
+ color: "#3c4659",
1537
+ cursor: "pointer"
1538
+ },
1539
+ expandArchived: {
1540
+ margin: "6px 8px",
1541
+ padding: "8px 12px",
1542
+ borderRadius: 9,
1543
+ fontSize: 12,
1544
+ color: "#5a6478",
1545
+ background: "#f5f7fa",
1546
+ cursor: "pointer",
1547
+ textAlign: "center"
1548
+ },
1549
+ footer: {
1550
+ display: "flex",
1551
+ gap: 14,
1552
+ padding: "8px 16px",
1553
+ borderTop: "1px solid rgba(28, 35, 51, 0.08)",
1554
+ fontSize: 11,
1555
+ color: "#8a93a6"
1556
+ }
1557
+ };
1558
+
1559
+ // src/client/WorkspaceSidebar.tsx
1560
+ var import_react6 = require("react");
1561
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1562
+ var COLOR_CHOICES = [
1563
+ "#2d66f7",
1564
+ "#7c3aed",
1565
+ "#0e9f6e",
1566
+ "#d97706",
1567
+ "#dc2626",
1568
+ "#db2777",
1569
+ "#0891b2",
1570
+ "#52525b",
1571
+ "#8a93a6"
1572
+ ];
1573
+ var STATUS_DOT_COLOR = {
1574
+ warning: "#d97706",
1575
+ done: "#0e9f6e"
1576
+ };
1577
+ var CHASE_CELLS = [
1578
+ [0, 0],
1579
+ [4, 0],
1580
+ [8, 0],
1581
+ [8, 4],
1582
+ [8, 8],
1583
+ [4, 8],
1584
+ [0, 8],
1585
+ [0, 4]
1586
+ ];
1587
+ var STATUS_STYLE_ID = "dsh-workspace-kit-status";
1588
+ var STATUS_CSS = [
1589
+ "@keyframes dsh-wskit-chase{0%,12.4%{opacity:1}12.5%,24.9%{opacity:.6}25%,37.4%{opacity:.35}37.5%,to{opacity:.15}}",
1590
+ ".dsh-wskit-ongoing{position:relative;display:inline-flex;align-items:center;justify-content:center;color:#2d66f7}",
1591
+ ".dsh-wskit-matrix{display:block}",
1592
+ ".dsh-wskit-cell{fill:currentColor;opacity:.15;animation:dsh-wskit-chase 1s linear infinite}",
1593
+ '@media (prefers-reduced-motion:reduce){.dsh-wskit-cell{animation:none}.dsh-wskit-matrix{display:none}.dsh-wskit-ongoing:before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}}'
1594
+ ].join("\n");
1595
+ function ensureStatusStyles() {
1596
+ if (typeof document === "undefined" || document.getElementById(STATUS_STYLE_ID)) return;
1597
+ const el = document.createElement("style");
1598
+ el.id = STATUS_STYLE_ID;
1599
+ el.textContent = STATUS_CSS;
1600
+ document.head.appendChild(el);
1601
+ }
1602
+ ensureStatusStyles();
1603
+ function sessionStatusOf(s) {
1604
+ switch (s?.pendingInteraction) {
1605
+ case "approval":
1606
+ return { kind: "warning", label: L("\u7B49\u5F85\u5BA1\u6279", "Waiting for approval") };
1607
+ case "plan-review":
1608
+ return { kind: "warning", label: L("\u8BA1\u5212\u5F85\u5BA1", "Plan awaiting review") };
1609
+ case "question":
1610
+ return { kind: "warning", label: L("\u7B49\u5F85\u56DE\u7B54", "Waiting for answer") };
1611
+ }
1612
+ if (s?.running) return { kind: "ongoing", label: L("\u8FDB\u884C\u4E2D", "Running") };
1613
+ if (s?.completed) return { kind: "done", label: L("\u5DF2\u5B8C\u6210", "Completed") };
1614
+ return void 0;
1615
+ }
1616
+ function StatusGlyph({ status }) {
1617
+ if (!status) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.statusSlot, "aria-hidden": "true" });
1618
+ if (status.kind === "ongoing") {
1619
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.statusSlot, className: "dsh-wskit-ongoing", role: "img", "aria-label": status.label, title: status.label, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "dsh-wskit-matrix", width: 10, height: 10, viewBox: "0 0 10 10", shapeRendering: "crispEdges", "aria-hidden": "true", children: CHASE_CELLS.map(([x, y], i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1620
+ "rect",
1621
+ {
1622
+ className: "dsh-wskit-cell",
1623
+ x,
1624
+ y,
1625
+ width: 2,
1626
+ height: 2,
1627
+ style: { animationDelay: `${(i - CHASE_CELLS.length) * 125}ms` }
1628
+ },
1629
+ `${x}-${y}`
1630
+ )) }) });
1631
+ }
1632
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.statusSlot, role: "img", "aria-label": status.label, title: status.label, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { ...styles4.stateDot, background: STATUS_DOT_COLOR[status.kind] } }) });
1633
+ }
1634
+ function byUpdatedDesc(a, b) {
1635
+ return a.updatedAt !== b.updatedAt ? a.updatedAt > b.updatedAt ? -1 : 1 : 0;
1636
+ }
1637
+ function collectRows(workspacesState, sessionsState, archived) {
1638
+ const byId = sessionsState?.byId ?? {};
1639
+ const sessionIds = Array.isArray(sessionsState?.ids) ? sessionsState.ids : [];
1640
+ const items = workspacesState?.items ?? [];
1641
+ const builtinArchived = new Set(workspacesState?.archivedSessionIds ?? []);
1642
+ const toSession = (id) => {
1643
+ const s = byId[id];
1644
+ if (!s || s.origin === "subagent" || s.blank) return void 0;
1645
+ return {
1646
+ id,
1647
+ title: s.displayTitle ?? s.title ?? id,
1648
+ updatedAt: s.updatedAt ?? 0,
1649
+ status: sessionStatusOf(s)
1650
+ };
1651
+ };
1652
+ const accounted = /* @__PURE__ */ new Set();
1653
+ const byWorkspace = /* @__PURE__ */ new Map();
1654
+ for (const item of items) {
1655
+ const wsId = String(item.workspaceId);
1656
+ const list = [];
1657
+ for (const sid of item.sessionIds ?? []) {
1658
+ accounted.add(String(sid));
1659
+ if (builtinArchived.has(String(sid))) continue;
1660
+ const row = toSession(String(sid));
1661
+ if (row) list.push(row);
1662
+ }
1663
+ byWorkspace.set(wsId, list);
1664
+ }
1665
+ const build = (item) => {
1666
+ const wsId = String(item.workspaceId);
1667
+ const sessions = byWorkspace.get(wsId) ?? [];
1668
+ return {
1669
+ id: item.workspaceId,
1670
+ title: item.title,
1671
+ path: item.path,
1672
+ sessionCount: sessions.length,
1673
+ archived: Boolean(archived[wsId]),
1674
+ sessions
1675
+ };
1676
+ };
1677
+ const active = [];
1678
+ const archivedWs = [];
1679
+ for (const item of items) {
1680
+ const data = build(item);
1681
+ if (data.archived) archivedWs.push(data);
1682
+ else active.push(data);
1683
+ }
1684
+ const ungrouped = [];
1685
+ for (const id of sessionIds) {
1686
+ if (accounted.has(String(id)) || builtinArchived.has(String(id))) continue;
1687
+ const row = toSession(String(id));
1688
+ if (row) ungrouped.push(row);
1689
+ }
1690
+ ungrouped.sort(byUpdatedDesc);
1691
+ return { active, archivedWs, ungrouped };
1692
+ }
1693
+ function buildSearchHits(workspacesState, sessionsState, archived, query) {
1694
+ const q = query.trim().toLowerCase();
1695
+ if (q.length === 0) return [];
1696
+ const terms = q.split(/\s+/).filter(Boolean);
1697
+ const match = (text) => {
1698
+ const t = text.toLowerCase();
1699
+ return terms.every((term) => t.includes(term));
1700
+ };
1701
+ const byId = sessionsState?.byId ?? {};
1702
+ const sessionIds = Array.isArray(sessionsState?.ids) ? sessionsState.ids : [];
1703
+ const items = workspacesState?.items ?? [];
1704
+ const builtinArchived = new Set(workspacesState?.archivedSessionIds ?? []);
1705
+ const hits = [];
1706
+ const wsBySession = /* @__PURE__ */ new Map();
1707
+ const wsTitleBySession = /* @__PURE__ */ new Map();
1708
+ const archivedWsIds = /* @__PURE__ */ new Set();
1709
+ for (const item of items) {
1710
+ const wsId = String(item.workspaceId);
1711
+ if (archived[wsId]) archivedWsIds.add(wsId);
1712
+ else if (match(`${item.title} ${item.path}`)) {
1713
+ hits.push({ kind: "workspace", id: wsId, title: item.title, sub: item.path });
1714
+ }
1715
+ for (const sid of item.sessionIds ?? []) {
1716
+ wsBySession.set(String(sid), wsId);
1717
+ wsTitleBySession.set(String(sid), item.title);
1718
+ }
1719
+ }
1720
+ for (const id of sessionIds) {
1721
+ const s = byId[id];
1722
+ if (!s || s.origin === "subagent" || s.blank) continue;
1723
+ if (builtinArchived.has(String(id))) continue;
1724
+ const wsId = wsBySession.get(String(id));
1725
+ if (wsId && archivedWsIds.has(wsId)) continue;
1726
+ const title = s.displayTitle ?? s.title ?? String(id);
1727
+ if (!match(`${title} ${s.cwd ?? ""}`)) continue;
1728
+ hits.push({
1729
+ kind: "session",
1730
+ id: String(id),
1731
+ title,
1732
+ sub: wsId ? wsTitleBySession.get(String(id)) ?? "" : s.cwd ?? L("\u672A\u5F52\u7EC4", "Ungrouped")
1733
+ });
1734
+ }
1735
+ return hits.slice(0, 40);
1736
+ }
1737
+ function WorkspaceSidebar(props) {
1738
+ const {
1739
+ wide,
1740
+ expandSidebar,
1741
+ useSessions,
1742
+ useWorkspaces,
1743
+ useStore,
1744
+ actions,
1745
+ openSession,
1746
+ startSession,
1747
+ renameSession,
1748
+ forkSession,
1749
+ addWorkspace,
1750
+ renameWorkspace,
1751
+ deleteWorkspace,
1752
+ archiveSession,
1753
+ reorderWorkspace,
1754
+ reorderSession,
1755
+ searchContent
1756
+ } = props;
1757
+ const archived = useStore((state) => state.archived ?? {});
1758
+ const appearanceMap = useStore((state) => state.appearance ?? {});
1759
+ const sessionsState = typeof useSessions === "function" ? useSessions((state) => state) : void 0;
1760
+ const workspacesState = typeof useWorkspaces === "function" ? useWorkspaces((state) => state) : void 0;
1761
+ const [expanded, setExpanded] = (0, import_react6.useState)({});
1762
+ const [archivedOpen, setArchivedOpen] = (0, import_react6.useState)(false);
1763
+ const [ungroupedOpen, setUngroupedOpen] = (0, import_react6.useState)(false);
1764
+ const [hovered, setHovered] = (0, import_react6.useState)(null);
1765
+ const [searchOpen, setSearchOpen] = (0, import_react6.useState)(false);
1766
+ const [searchQ, setSearchQ] = (0, import_react6.useState)("");
1767
+ const [sortMode, setSortMode] = (0, import_react6.useState)("updated");
1768
+ const [contentHits, setContentHits] = (0, import_react6.useState)([]);
1769
+ const [contentLoading, setContentLoading] = (0, import_react6.useState)(false);
1770
+ const [drag, setDrag] = (0, import_react6.useState)(null);
1771
+ const [over, setOver] = (0, import_react6.useState)(null);
1772
+ const [pickerWs, setPickerWs] = (0, import_react6.useState)(null);
1773
+ const { active, archivedWs, ungrouped } = (0, import_react6.useMemo)(
1774
+ () => collectRows(workspacesState, sessionsState, archived),
1775
+ [workspacesState, sessionsState, archived]
1776
+ );
1777
+ const displaySessionsByWs = (0, import_react6.useMemo)(() => {
1778
+ const map = {};
1779
+ for (const ws of [...active, ...archivedWs]) {
1780
+ const key = String(ws.id);
1781
+ map[key] = sortMode === "manual" ? ws.sessions : [...ws.sessions].sort(byUpdatedDesc);
1782
+ }
1783
+ return map;
1784
+ }, [active, archivedWs, sortMode]);
1785
+ const searchHits = (0, import_react6.useMemo)(
1786
+ () => buildSearchHits(workspacesState, sessionsState, archived, searchQ),
1787
+ [workspacesState, sessionsState, archived, searchQ]
1788
+ );
1789
+ const searching = searchOpen && searchQ.trim().length > 0;
1790
+ (0, import_react6.useEffect)(() => {
1791
+ if (!searchOpen) {
1792
+ setContentHits([]);
1793
+ setContentLoading(false);
1794
+ return;
1795
+ }
1796
+ const q = searchQ.trim();
1797
+ if (q.length < 2) {
1798
+ setContentHits([]);
1799
+ setContentLoading(false);
1800
+ return;
1801
+ }
1802
+ const ac = new AbortController();
1803
+ setContentLoading(true);
1804
+ const timer = setTimeout(() => {
1805
+ searchContent(q, ac.signal).then((items) => {
1806
+ if (!ac.signal.aborted) {
1807
+ setContentHits(items);
1808
+ setContentLoading(false);
1809
+ }
1810
+ }).catch(() => {
1811
+ if (!ac.signal.aborted) {
1812
+ setContentHits([]);
1813
+ setContentLoading(false);
1814
+ }
1815
+ });
1816
+ }, 250);
1817
+ return () => {
1818
+ clearTimeout(timer);
1819
+ ac.abort();
1820
+ };
1821
+ }, [searchOpen, searchQ, searchContent]);
1822
+ const toggle = (id) => setExpanded((prev) => ({ ...prev, [id]: !prev[id] }));
1823
+ const openSpotlight = () => {
1824
+ window.dispatchEvent(new CustomEvent("dsh-workspace-kit:open"));
1825
+ if (!wide) expandSidebar();
1826
+ };
1827
+ const applyAppearance = (wsId, patch) => {
1828
+ actions.setAppearance(wsId, patch === null ? null : { ...appearanceMap[wsId] ?? {}, ...patch });
1829
+ };
1830
+ const stop = (e) => e.preventDefault();
1831
+ const onWsDrop = (targetId) => (e) => {
1832
+ e.preventDefault();
1833
+ e.stopPropagation();
1834
+ const d = drag;
1835
+ setDrag(null);
1836
+ setOver(null);
1837
+ if (!d || d.kind !== "workspace" || d.id === targetId) return;
1838
+ reorderWorkspace(d.id, targetId);
1839
+ };
1840
+ const onSessionDrop = (wsId, targetId) => (e) => {
1841
+ e.preventDefault();
1842
+ e.stopPropagation();
1843
+ const d = drag;
1844
+ setDrag(null);
1845
+ setOver(null);
1846
+ if (!d || d.kind !== "session" || d.wsId !== String(wsId) || d.id === targetId) return;
1847
+ setSortMode("manual");
1848
+ reorderSession(wsId, d.id, targetId);
1849
+ };
1850
+ if (!wide) {
1851
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.rail, children: [
1852
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.railButton, title: L("Spotlight \u641C\u7D22\uFF08\u2318K\uFF09", "Spotlight search (\u2318K)"), onClick: openSpotlight, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Command, { size: 16 }) }),
1853
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1854
+ "button",
1855
+ {
1856
+ style: styles4.railButton,
1857
+ title: L("\u65B0\u5EFA\u4F1A\u8BDD", "New session"),
1858
+ onClick: () => {
1859
+ startSession();
1860
+ expandSidebar();
1861
+ },
1862
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Plus, { size: 16 })
1863
+ }
1864
+ ),
1865
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.railButton, title: L("\u5C55\u5F00\u4FA7\u680F", "Expand sidebar"), onClick: expandSidebar, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronsRight, { size: 16 }) })
1866
+ ] });
1867
+ }
1868
+ const renderSessions = (wsId, sessions) => sessions.map((s) => {
1869
+ const dragKey = wsId ? `s:${wsId}:${s.id}` : `s:${s.id}`;
1870
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1871
+ "div",
1872
+ {
1873
+ style: {
1874
+ ...styles4.sessionRow,
1875
+ ...drag && drag.kind === "session" && drag.id === String(s.id) ? styles4.rowDragging : {},
1876
+ ...over === dragKey ? styles4.rowDropOver : {}
1877
+ },
1878
+ title: s.title,
1879
+ draggable: wsId !== void 0,
1880
+ onMouseEnter: () => setHovered(dragKey),
1881
+ onMouseDown: (e) => {
1882
+ e.stopPropagation();
1883
+ openSession(s.id);
1884
+ },
1885
+ onDragStart: (e) => {
1886
+ if (wsId === void 0) return;
1887
+ e.stopPropagation();
1888
+ setDrag({ kind: "session", id: String(s.id), wsId: String(wsId) });
1889
+ e.dataTransfer.effectAllowed = "move";
1890
+ },
1891
+ onDragOver: (e) => {
1892
+ if (drag?.kind === "session" && drag.wsId === String(wsId) && drag.id !== String(s.id)) {
1893
+ stop(e);
1894
+ setOver(dragKey);
1895
+ }
1896
+ },
1897
+ onDragLeave: () => setOver((v) => v === dragKey ? null : v),
1898
+ onDrop: wsId ? onSessionDrop(wsId, s.id) : void 0,
1899
+ onDragEnd: () => {
1900
+ setDrag(null);
1901
+ setOver(null);
1902
+ },
1903
+ children: [
1904
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusGlyph, { status: s.status }),
1905
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.sessionTitle, children: s.title }),
1906
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1907
+ "span",
1908
+ {
1909
+ style: { ...styles4.sessionActions, display: hovered === dragKey ? "flex" : "none" },
1910
+ onMouseDown: (e) => e.stopPropagation(),
1911
+ children: [
1912
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u91CD\u547D\u540D", "Rename"), onClick: (e) => {
1913
+ e.stopPropagation();
1914
+ void renameSession(s.id, s.title);
1915
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pencil, { size: 11 }) }),
1916
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u590D\u5236\u4F1A\u8BDD\uFF08fork\uFF09", "Duplicate session (fork)"), onClick: (e) => {
1917
+ e.stopPropagation();
1918
+ forkSession(s.id);
1919
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Copy, { size: 11 }) }),
1920
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u5F52\u6863\u4F1A\u8BDD\uFF08\u4E0D\u53EF\u9006\uFF0C\u4ECD\u53EF\u4ECE\u641C\u7D22\u6253\u5F00\uFF09", "Archive session (irreversible, still searchable)"), onClick: (e) => {
1921
+ e.stopPropagation();
1922
+ archiveSession(s.id);
1923
+ }, children: L("\u5F52\u6863", "Archive") })
1924
+ ]
1925
+ }
1926
+ )
1927
+ ]
1928
+ },
1929
+ dragKey
1930
+ );
1931
+ });
1932
+ const renderWsRow = (ws, draggable) => {
1933
+ const wsKey = `w:${ws.id}`;
1934
+ const isOpen = Boolean(expanded[wsKey]);
1935
+ const sessions = displaySessionsByWs[String(ws.id)] ?? [];
1936
+ const app = appearanceMap[String(ws.id)] ?? {};
1937
+ const picking = pickerWs === String(ws.id);
1938
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1939
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1940
+ "div",
1941
+ {
1942
+ style: {
1943
+ ...styles4.wsRow,
1944
+ ...drag && drag.kind === "workspace" && drag.id === String(ws.id) ? styles4.rowDragging : {},
1945
+ ...over === wsKey ? styles4.rowDropOver : {}
1946
+ },
1947
+ draggable,
1948
+ onMouseEnter: () => setHovered(wsKey),
1949
+ onMouseDown: (e) => {
1950
+ e.stopPropagation();
1951
+ toggle(wsKey);
1952
+ },
1953
+ onDragStart: (e) => {
1954
+ if (!draggable) return;
1955
+ e.stopPropagation();
1956
+ setDrag({ kind: "workspace", id: String(ws.id) });
1957
+ e.dataTransfer.effectAllowed = "move";
1958
+ },
1959
+ onDragOver: (e) => {
1960
+ if (draggable && drag?.kind === "workspace" && drag.id !== String(ws.id)) {
1961
+ stop(e);
1962
+ setOver(wsKey);
1963
+ }
1964
+ },
1965
+ onDragLeave: () => setOver((v) => v === wsKey ? null : v),
1966
+ onDrop: draggable ? onWsDrop(ws.id) : void 0,
1967
+ onDragEnd: () => {
1968
+ setDrag(null);
1969
+ setOver(null);
1970
+ },
1971
+ children: [
1972
+ (app.icon || app.color) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1973
+ "span",
1974
+ {
1975
+ style: styles4.wsIconSlot,
1976
+ onMouseDown: (e) => {
1977
+ e.stopPropagation();
1978
+ setPickerWs(picking ? null : String(ws.id));
1979
+ },
1980
+ title: L("\u70B9\u51FB\u4FEE\u6539\u56FE\u6807 / \u989C\u8272", "Click to change icon / color"),
1981
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkspaceGlyph, { icon: app.icon, color: app.color, size: 15 })
1982
+ }
1983
+ ),
1984
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsChevron, children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDown, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronRight, { size: 13 }) }),
1985
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsTitle, children: ws.title }),
1986
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsCount, children: ws.sessionCount }),
1987
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { ...styles4.wsActions, display: hovered === wsKey ? "flex" : "none" }, onMouseDown: (e) => e.stopPropagation(), children: [
1988
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1989
+ "button",
1990
+ {
1991
+ style: styles4.miniButton,
1992
+ title: L("\u8BBE\u7F6E\u56FE\u6807 / \u989C\u8272", "Set icon / color"),
1993
+ onClick: (e) => {
1994
+ e.stopPropagation();
1995
+ setPickerWs(picking ? null : String(ws.id));
1996
+ },
1997
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Palette, { size: 11 })
1998
+ }
1999
+ ),
2000
+ !ws.archived && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u5728\u6B64\u5DE5\u4F5C\u533A\u65B0\u5EFA\u4F1A\u8BDD", "New session in this workspace"), onClick: (e) => {
2001
+ e.stopPropagation();
2002
+ startSession(ws.id);
2003
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Plus, { size: 11 }) }),
2004
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2005
+ "button",
2006
+ {
2007
+ style: ws.archived ? styles4.restoreButton : styles4.miniButton,
2008
+ onClick: (e) => {
2009
+ e.stopPropagation();
2010
+ if (ws.archived) actions.restore(String(ws.id));
2011
+ else actions.archive(String(ws.id), (/* @__PURE__ */ new Date()).toISOString());
2012
+ },
2013
+ children: ws.archived ? L("\u6062\u590D", "Restore") : L("\u5F52\u6863", "Archive")
2014
+ }
2015
+ ),
2016
+ !ws.archived && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u91CD\u547D\u540D\u5DE5\u4F5C\u533A", "Rename workspace"), onClick: (e) => {
2017
+ e.stopPropagation();
2018
+ void renameWorkspace(ws.id, ws.title);
2019
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Pencil, { size: 11 }) }),
2020
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.miniButton, title: L("\u5220\u9664\u5DE5\u4F5C\u533A\u6CE8\u518C\uFF08\u76EE\u5F55\u4E0E\u5386\u53F2\u4F1A\u8BDD\u4FDD\u7559\uFF09", "Remove workspace registration (directory and past sessions kept)"), onClick: (e) => {
2021
+ e.stopPropagation();
2022
+ deleteWorkspace(ws.id);
2023
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Trash, { size: 11 }) })
2024
+ ] })
2025
+ ]
2026
+ }
2027
+ ),
2028
+ picking && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.pickerPanel, onMouseDown: (e) => e.stopPropagation(), children: [
2029
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.pickerLabel, children: L("\u56FE\u6807", "Icon") }),
2030
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.pickerGrid, children: WORKSPACE_ICON_KEYS.map((key) => {
2031
+ const selected = iconKeyOf(app.icon) === key;
2032
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2033
+ "button",
2034
+ {
2035
+ title: key,
2036
+ style: { ...styles4.pickerIcon, ...selected ? styles4.pickerSelected : {} },
2037
+ onClick: () => applyAppearance(String(ws.id), { icon: key }),
2038
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WorkspaceGlyph, { icon: key, size: 15 })
2039
+ },
2040
+ key
2041
+ );
2042
+ }) }),
2043
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.pickerLabel, children: L("\u989C\u8272", "Color") }),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.pickerGrid, children: COLOR_CHOICES.map((color) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2045
+ "button",
2046
+ {
2047
+ style: { ...styles4.pickerSwatch, background: color, ...app.color === color ? styles4.pickerSelected : {} },
2048
+ title: color,
2049
+ onClick: () => applyAppearance(String(ws.id), { color })
2050
+ },
2051
+ color
2052
+ )) }),
2053
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2054
+ "button",
2055
+ {
2056
+ style: styles4.pickerClear,
2057
+ onClick: () => {
2058
+ applyAppearance(String(ws.id), null);
2059
+ setPickerWs(null);
2060
+ },
2061
+ children: L("\u6E05\u9664\u56FE\u6807\u4E0E\u989C\u8272", "Clear icon and color")
2062
+ }
2063
+ )
2064
+ ] }),
2065
+ isOpen && sessions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2066
+ "div",
2067
+ {
2068
+ style: styles4.sessionList,
2069
+ onDragOver: (e) => {
2070
+ if (drag?.kind === "session" && drag.wsId === String(ws.id)) stop(e);
2071
+ },
2072
+ onDrop: onSessionDrop(ws.id, void 0),
2073
+ children: renderSessions(ws.id, sessions)
2074
+ }
2075
+ )
2076
+ ] }, wsKey);
2077
+ };
2078
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.root, onMouseLeave: () => setHovered(null), children: [
2079
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.header, children: [
2080
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.headerTitle, children: L("\u5DE5\u4F5C\u533A", "Workspaces") }),
2081
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: styles4.headerActions, children: [
2082
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2083
+ "button",
2084
+ {
2085
+ style: styles4.headerAction,
2086
+ title: L("\u641C\u7D22\u5DE5\u4F5C\u533A / \u4F1A\u8BDD\uFF08\u6807\u9898\u3001\u8DEF\u5F84\uFF09", "Search workspaces / sessions (title, path)"),
2087
+ onClick: () => {
2088
+ setSearchOpen((v) => !v);
2089
+ if (searchOpen) setSearchQ("");
2090
+ },
2091
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Search, { size: 13 })
2092
+ }
2093
+ ),
2094
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.headerAction, title: L("\u65B0\u5EFA\u5DE5\u4F5C\u533A\uFF08\u9009\u62E9\u76EE\u5F55\uFF09", "New workspace (pick a directory)"), onClick: addWorkspace, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Plus, { size: 14 }) }),
2095
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { style: styles4.headerAction, title: L("Spotlight\uFF08\u2318K\uFF09", "Spotlight (\u2318K)"), onClick: openSpotlight, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Command, { size: 13 }) })
2096
+ ] })
2097
+ ] }),
2098
+ searchOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.searchRow, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2099
+ "input",
2100
+ {
2101
+ style: styles4.searchInput,
2102
+ placeholder: L("\u641C\u7D22\u5DE5\u4F5C\u533A / \u4F1A\u8BDD\u2026", "Search workspaces / sessions\u2026"),
2103
+ value: searchQ,
2104
+ onChange: (e) => setSearchQ(e.target.value),
2105
+ autoFocus: true
2106
+ }
2107
+ ) }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.scroll, children: searching ? searchHits.length === 0 && contentHits.length === 0 && !contentLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.empty, children: L("\u6CA1\u6709\u5339\u914D\u300C{q}\u300D\u7684\u5DE5\u4F5C\u533A\u6216\u4F1A\u8BDD", 'No workspaces or sessions match "{q}"', { q: searchQ.trim() }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2109
+ contentLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.empty, children: L("\u6B63\u5728\u641C\u7D22\u4F1A\u8BDD\u5185\u5BB9\u2026", "Searching session content\u2026") }),
2110
+ searchHits.map((hit) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2111
+ "div",
2112
+ {
2113
+ style: styles4.hitRow,
2114
+ title: hit.sub,
2115
+ onMouseDown: (e) => {
2116
+ e.stopPropagation();
2117
+ if (hit.kind === "workspace") startSession(hit.id);
2118
+ else openSession(hit.id);
2119
+ },
2120
+ children: [
2121
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsTitle, children: hit.title }),
2122
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.hitSub, children: hit.sub })
2123
+ ]
2124
+ },
2125
+ `${hit.kind}-${hit.id}`
2126
+ )),
2127
+ contentHits.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2128
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.contentLabel, children: L("\u4F1A\u8BDD\u5185\u5BB9\u547D\u4E2D\uFF08{n}\uFF09", "Session content hits ({n})", { n: contentHits.length }) }),
2129
+ contentHits.map((hit) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2130
+ "div",
2131
+ {
2132
+ style: styles4.hitRow,
2133
+ title: hit.snippet,
2134
+ onMouseDown: (e) => {
2135
+ e.stopPropagation();
2136
+ openSession(hit.sessionId);
2137
+ },
2138
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.contentSnippet, children: hit.snippet })
2139
+ },
2140
+ `content-${hit.sessionId}`
2141
+ ))
2142
+ ] })
2143
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2144
+ active.length === 0 && ungrouped.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.empty, children: L("\u8FD8\u6CA1\u6709\u5DE5\u4F5C\u533A\uFF0C\u70B9\u53F3\u4E0A\u89D2\u65B0\u5EFA\u6309\u94AE\u3002", "No workspaces yet \u2014 use the new-workspace button in the top right.") }),
2145
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2146
+ "div",
2147
+ {
2148
+ onDragOver: (e) => {
2149
+ if (drag?.kind === "workspace") stop(e);
2150
+ },
2151
+ onDrop: onWsDrop(void 0),
2152
+ children: active.map((ws) => renderWsRow(ws, true))
2153
+ }
2154
+ ),
2155
+ ungrouped.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2156
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2157
+ "div",
2158
+ {
2159
+ style: styles4.wsRow,
2160
+ onMouseEnter: () => setHovered("bucket-ungrouped"),
2161
+ onMouseDown: (e) => {
2162
+ e.stopPropagation();
2163
+ setUngroupedOpen((v) => !v);
2164
+ },
2165
+ children: [
2166
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsChevron, children: ungroupedOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDown, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronRight, { size: 13 }) }),
2167
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsTitle, children: L("\u672A\u5F52\u7EC4", "Ungrouped") }),
2168
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.wsCount, children: ungrouped.length })
2169
+ ]
2170
+ }
2171
+ ),
2172
+ ungroupedOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles4.sessionList, children: renderSessions(void 0, ungrouped) })
2173
+ ] }),
2174
+ archivedWs.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2175
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles4.sectionToggle, onClick: () => setArchivedOpen((v) => !v), children: [
2176
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: styles4.sectionChevron, children: archivedOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChevronRight, { size: 12 }) }),
2177
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: L("\u5DF2\u5F52\u6863\uFF08{n}\uFF09", "Archived ({n})", { n: archivedWs.length }) })
2178
+ ] }),
2179
+ archivedOpen && archivedWs.map((ws) => renderWsRow(ws, false))
2180
+ ] })
2181
+ ] }) })
2182
+ ] });
2183
+ }
2184
+ var styles4 = {
2185
+ root: { display: "flex", flexDirection: "column", height: "100%", minWidth: 0 },
2186
+ rail: { display: "flex", flexDirection: "column", alignItems: "center", gap: 6, paddingTop: 8 },
2187
+ railButton: {
2188
+ width: 36,
2189
+ height: 36,
2190
+ borderRadius: 10,
2191
+ border: "none",
2192
+ background: "transparent",
2193
+ color: "#5a6478",
2194
+ fontSize: 16,
2195
+ cursor: "pointer",
2196
+ display: "inline-flex",
2197
+ alignItems: "center",
2198
+ justifyContent: "center"
2199
+ },
2200
+ header: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px 12px 4px" },
2201
+ headerTitle: {
2202
+ fontSize: 12,
2203
+ fontWeight: 700,
2204
+ color: "#8a93a6",
2205
+ letterSpacing: "0.04em",
2206
+ textTransform: "uppercase"
2207
+ },
2208
+ headerActions: { display: "flex", gap: 2, alignItems: "center" },
2209
+ headerAction: {
2210
+ width: 24,
2211
+ height: 24,
2212
+ fontSize: 13,
2213
+ lineHeight: "22px",
2214
+ borderRadius: 7,
2215
+ border: "none",
2216
+ background: "transparent",
2217
+ color: "#5a6478",
2218
+ cursor: "pointer",
2219
+ display: "inline-flex",
2220
+ alignItems: "center",
2221
+ justifyContent: "center"
2222
+ },
2223
+ searchRow: { padding: "0 10px 6px" },
2224
+ contentLabel: {
2225
+ padding: "8px 6px 4px",
2226
+ fontSize: 11,
2227
+ fontWeight: 600,
2228
+ color: "#8a93a6"
2229
+ },
2230
+ contentSnippet: {
2231
+ flex: 1,
2232
+ minWidth: 0,
2233
+ fontSize: 12,
2234
+ color: "#3c4659",
2235
+ display: "-webkit-box",
2236
+ WebkitLineClamp: 2,
2237
+ WebkitBoxOrient: "vertical",
2238
+ overflow: "hidden",
2239
+ textOverflow: "ellipsis",
2240
+ lineHeight: 1.4
2241
+ },
2242
+ searchInput: {
2243
+ width: "100%",
2244
+ boxSizing: "border-box",
2245
+ fontSize: 12,
2246
+ padding: "5px 10px",
2247
+ borderRadius: 8,
2248
+ border: "1px solid rgba(45, 102, 247, 0.5)",
2249
+ outline: "none",
2250
+ color: "#1c2333"
2251
+ },
2252
+ scroll: { flex: 1, overflowY: "auto", padding: "0 6px 12px" },
2253
+ sectionToggle: {
2254
+ display: "flex",
2255
+ alignItems: "center",
2256
+ gap: 5,
2257
+ marginTop: 6,
2258
+ padding: "8px 6px 4px",
2259
+ fontSize: 11,
2260
+ fontWeight: 600,
2261
+ color: "#8a93a6",
2262
+ cursor: "pointer",
2263
+ borderTop: "1px solid rgba(28, 35, 51, 0.06)"
2264
+ },
2265
+ sectionChevron: { display: "inline-flex", color: "#a2aabe" },
2266
+ empty: { padding: "14px 8px", fontSize: 12, color: "#a2aabe" },
2267
+ wsRow: {
2268
+ display: "flex",
2269
+ alignItems: "center",
2270
+ gap: 4,
2271
+ padding: "7px 4px",
2272
+ borderRadius: 7,
2273
+ cursor: "pointer",
2274
+ userSelect: "none"
2275
+ },
2276
+ wsChevron: {
2277
+ width: 14,
2278
+ flexShrink: 0,
2279
+ display: "inline-flex",
2280
+ alignItems: "center",
2281
+ justifyContent: "center",
2282
+ color: "#9aa3b5"
2283
+ },
2284
+ wsTitle: {
2285
+ flex: 1,
2286
+ minWidth: 0,
2287
+ fontSize: 14,
2288
+ fontWeight: 600,
2289
+ color: "#2e3a4d",
2290
+ lineHeight: "20px",
2291
+ whiteSpace: "nowrap",
2292
+ overflow: "hidden",
2293
+ textOverflow: "ellipsis"
2294
+ },
2295
+ wsCount: { fontSize: 12, fontWeight: 500, color: "#8a93a6", flexShrink: 0 },
2296
+ wsActions: { display: "none", gap: 2, alignItems: "center", flexShrink: 0 },
2297
+ sessionActions: { display: "none", gap: 2, alignItems: "center", flexShrink: 0 },
2298
+ sessionList: { marginLeft: 10, borderLeft: "1px solid rgba(28, 35, 51, 0.07)" },
2299
+ sessionRow: {
2300
+ display: "flex",
2301
+ alignItems: "center",
2302
+ gap: 6,
2303
+ padding: "3px 4px",
2304
+ borderRadius: 6,
2305
+ cursor: "pointer",
2306
+ fontSize: 12,
2307
+ color: "#3c4659",
2308
+ userSelect: "none"
2309
+ },
2310
+ statusSlot: { width: 10, height: 10, flexShrink: 0, display: "inline-flex", alignItems: "center", justifyContent: "center" },
2311
+ stateDot: { width: 6, height: 6, borderRadius: 3, flexShrink: 0 },
2312
+ sessionTitle: { flex: 1, minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" },
2313
+ miniButton: {
2314
+ fontSize: 11,
2315
+ lineHeight: "16px",
2316
+ padding: "0 6px",
2317
+ borderRadius: 6,
2318
+ border: "1px solid rgba(28, 35, 51, 0.12)",
2319
+ background: "#ffffff",
2320
+ color: "#5a6478",
2321
+ cursor: "pointer",
2322
+ display: "inline-flex",
2323
+ alignItems: "center",
2324
+ justifyContent: "center",
2325
+ gap: 4
2326
+ },
2327
+ restoreButton: {
2328
+ fontSize: 11,
2329
+ lineHeight: "16px",
2330
+ padding: "0 8px",
2331
+ borderRadius: 6,
2332
+ border: "1px solid rgba(45, 102, 247, 0.4)",
2333
+ background: "rgba(45, 102, 247, 0.08)",
2334
+ color: "#2d66f7",
2335
+ cursor: "pointer"
2336
+ },
2337
+ rowDragging: { opacity: 0.45 },
2338
+ rowDropOver: { background: "rgba(45, 102, 247, 0.12)", outline: "1px dashed rgba(45, 102, 247, 0.6)" },
2339
+ hitRow: { display: "flex", alignItems: "center", gap: 6, padding: "6px 8px", borderRadius: 8, cursor: "pointer" },
2340
+ hitSub: {
2341
+ fontSize: 11,
2342
+ color: "#a2aabe",
2343
+ whiteSpace: "nowrap",
2344
+ overflow: "hidden",
2345
+ textOverflow: "ellipsis",
2346
+ maxWidth: "45%"
2347
+ },
2348
+ wsIconSlot: {
2349
+ width: 20,
2350
+ height: 20,
2351
+ flexShrink: 0,
2352
+ display: "flex",
2353
+ alignItems: "center",
2354
+ justifyContent: "center",
2355
+ borderRadius: 6,
2356
+ cursor: "pointer"
2357
+ },
2358
+ pickerPanel: {
2359
+ margin: "2px 4px 6px 26px",
2360
+ padding: 8,
2361
+ borderRadius: 10,
2362
+ background: "#f5f7fa",
2363
+ border: "1px solid rgba(28, 35, 51, 0.08)"
2364
+ },
2365
+ pickerLabel: { fontSize: 11, fontWeight: 600, color: "#8a93a6", margin: "4px 0" },
2366
+ pickerGrid: { display: "flex", flexWrap: "wrap", gap: 4, marginBottom: 2 },
2367
+ pickerIcon: {
2368
+ width: 26,
2369
+ height: 26,
2370
+ borderRadius: 7,
2371
+ border: "1px solid transparent",
2372
+ background: "transparent",
2373
+ cursor: "pointer",
2374
+ display: "inline-flex",
2375
+ alignItems: "center",
2376
+ justifyContent: "center"
2377
+ },
2378
+ pickerSwatch: {
2379
+ width: 22,
2380
+ height: 22,
2381
+ borderRadius: 7,
2382
+ border: "1px solid rgba(28, 35, 51, 0.14)",
2383
+ cursor: "pointer"
2384
+ },
2385
+ pickerSelected: { outline: "2px solid #2d66f7", outlineOffset: 1 },
2386
+ pickerClear: {
2387
+ marginTop: 6,
2388
+ fontSize: 11,
2389
+ padding: "2px 10px",
2390
+ borderRadius: 7,
2391
+ border: "1px solid rgba(28, 35, 51, 0.14)",
2392
+ background: "#ffffff",
2393
+ color: "#5a6478",
2394
+ cursor: "pointer"
2395
+ }
2396
+ };
2397
+
2398
+ // src/client/index.ts
2399
+ var name = "workspace-kit";
2400
+ var inject = ["slots", "sessions", "workspaces"];
2401
+ var PERSIST_KEY = "dsh.workspace-kit.archive.v1";
2402
+ function readPersistedOfficialSidebar() {
2403
+ try {
2404
+ const raw = typeof localStorage !== "undefined" ? localStorage.getItem(PERSIST_KEY) : null;
2405
+ if (!raw) return false;
2406
+ return Boolean(JSON.parse(raw).officialSidebar);
2407
+ } catch {
2408
+ return false;
2409
+ }
2410
+ }
2411
+ function alertError(prefix, error) {
2412
+ void requestConfirm({ title: prefix, message: String(error), okLabel: L("\u77E5\u9053\u4E86", "Got it") });
2413
+ }
2414
+ function apply(raw) {
2415
+ const ctx = raw;
2416
+ const log = ctx.logger("workspace-kit:client");
2417
+ const store = createArchiveStore();
2418
+ const openSession = (sessionId) => {
2419
+ ctx.sessions.open(sessionId);
2420
+ };
2421
+ const startSession = (workspaceId) => {
2422
+ ctx.workspaces.startSession(workspaceId);
2423
+ };
2424
+ const renameSession = async (sessionId, initial) => {
2425
+ const title = await requestPrompt({ title: L("\u91CD\u547D\u540D\u4F1A\u8BDD", "Rename session"), initial, placeholder: L("\u8F93\u5165\u65B0\u540D\u79F0", "Enter a new name") });
2426
+ if (title == null) return;
2427
+ const session = ctx.sessions.binding(sessionId)?.session;
2428
+ if (!session) {
2429
+ alertError(L("\u91CD\u547D\u540D\u5931\u8D25", "Rename failed"), new Error(`unknown session "${sessionId}"`));
2430
+ return;
2431
+ }
2432
+ const result = await session.rename(title);
2433
+ if (!result.ok) alertError(L("\u91CD\u547D\u540D\u5931\u8D25", "Rename failed"), new Error(result.error.message));
2434
+ };
2435
+ const forkSession = (sessionId) => {
2436
+ ctx.sessions.fork({ sessionId, increaseTitle: true }).then((childId) => ctx.sessions.open(childId)).catch((error) => log.info("fork failed", String(error)));
2437
+ };
2438
+ const archiveSession = (sessionId) => {
2439
+ void (async () => {
2440
+ const ok = await requestConfirm({
2441
+ title: L("\u5F52\u6863\u4F1A\u8BDD", "Archive session"),
2442
+ message: L(
2443
+ "\u5F52\u6863\u540E\u8BE5\u4F1A\u8BDD\u4F1A\u4ECE\u5DE5\u4F5C\u533A\u5206\u7EC4\u3001\u4FA7\u680F\u548C\u6240\u6709\u5217\u8868\u9690\u85CF\uFF08\u5B98\u65B9\u5F52\u6863\u96C6\uFF0C\u4E0D\u53EF\u9006\uFF0C\u6682\u65E0\u6062\u590D\u5165\u53E3\uFF1B\u4ECD\u53EF\u901A\u8FC7\u641C\u7D22\u6253\u5F00\uFF09\u3002\u786E\u5B9A\u5F52\u6863\uFF1F",
2444
+ "Archiving hides this session from workspace groups, the sidebar, and every list (official archive set \u2014 irreversible, no restore entry yet; it stays reachable via search). Archive now?"
2445
+ ),
2446
+ okLabel: L("\u5F52\u6863", "Archive")
2447
+ });
2448
+ if (!ok) return;
2449
+ ctx.workspaces.archiveSession(sessionId).catch((error) => log.info("archive session failed", String(error)));
2450
+ })();
2451
+ };
2452
+ const addWorkspace = () => {
2453
+ void (async () => {
2454
+ try {
2455
+ const path = await ctx.workspaces.pickDirectory();
2456
+ if (!path) return;
2457
+ const view = await ctx.workspaces.create({ path });
2458
+ startSession(view.workspaceId);
2459
+ } catch (error) {
2460
+ alertError(L("\u65B0\u5EFA\u5DE5\u4F5C\u533A\u5931\u8D25", "Failed to create workspace"), error);
2461
+ }
2462
+ })();
2463
+ };
2464
+ const renameWorkspace = async (workspaceId, initial) => {
2465
+ const title = await requestPrompt({ title: L("\u91CD\u547D\u540D\u5DE5\u4F5C\u533A", "Rename workspace"), initial, placeholder: L("\u8F93\u5165\u65B0\u540D\u79F0", "Enter a new name") });
2466
+ if (title == null) return;
2467
+ try {
2468
+ await ctx.workspaces.rename(workspaceId, title);
2469
+ } catch (error) {
2470
+ alertError(L("\u91CD\u547D\u540D\u5931\u8D25", "Rename failed"), error);
2471
+ }
2472
+ };
2473
+ const deleteWorkspace = (workspaceId) => {
2474
+ void (async () => {
2475
+ const ok = await requestConfirm({
2476
+ title: L("\u5220\u9664\u5DE5\u4F5C\u533A\u6CE8\u518C", "Remove workspace registration"),
2477
+ message: L(
2478
+ "\u9879\u76EE\u76EE\u5F55\u4E0E\u5386\u53F2\u4F1A\u8BDD\u90FD\u4F1A\u4FDD\u7559\uFF08\u4F1A\u8BDD\u56DE\u5230\u672A\u5F52\u7EC4\uFF09\u3002\u786E\u5B9A\u5220\u9664\u8BE5\u5DE5\u4F5C\u533A\u6CE8\u518C\uFF1F",
2479
+ "The project directory and past sessions are kept (sessions return to ungrouped). Remove this workspace registration?"
2480
+ ),
2481
+ okLabel: L("\u5220\u9664", "Remove")
2482
+ });
2483
+ if (!ok) return;
2484
+ ctx.workspaces.delete(workspaceId).catch((error) => alertError(L("\u5220\u9664\u5931\u8D25", "Remove failed"), error));
2485
+ })();
2486
+ };
2487
+ const reorderWorkspace = (workspaceId, beforeWorkspaceId) => {
2488
+ ctx.workspaces.insertBefore(workspaceId, beforeWorkspaceId).catch((error) => alertError(L("\u6392\u5E8F\u5931\u8D25", "Reorder failed"), error));
2489
+ };
2490
+ const reorderSession = (workspaceId, sessionId, beforeSessionId) => {
2491
+ ctx.workspaces.insertSessionBefore(workspaceId, sessionId, beforeSessionId).catch((error) => alertError(L("\u6392\u5E8F\u5931\u8D25", "Reorder failed"), error));
2492
+ };
2493
+ const searchContent = async (query, signal) => {
2494
+ const result = await ctx.sessions.search(query, signal);
2495
+ if (!result.ok) throw new Error(result.error.message);
2496
+ return result.value.items;
2497
+ };
2498
+ const sidebarInject = () => ({
2499
+ openSession,
2500
+ startSession,
2501
+ renameSession,
2502
+ forkSession,
2503
+ addWorkspace,
2504
+ renameWorkspace,
2505
+ deleteWorkspace,
2506
+ archiveSession,
2507
+ reorderWorkspace,
2508
+ reorderSession,
2509
+ searchContent
2510
+ });
2511
+ let officialSidebar = readPersistedOfficialSidebar();
2512
+ let oursReg = null;
2513
+ const registerOurs = () => {
2514
+ if (oursReg) return;
2515
+ oursReg = ctx.slots.register(
2516
+ { name: "sidebar.workspaces", priority: -1, store, inject: sidebarInject },
2517
+ WorkspaceSidebar
2518
+ );
2519
+ };
2520
+ const dropOurs = () => {
2521
+ if (oursReg) {
2522
+ oursReg();
2523
+ oursReg = null;
2524
+ }
2525
+ };
2526
+ const syncSidebar = () => {
2527
+ if (officialSidebar) dropOurs();
2528
+ else registerOurs();
2529
+ };
2530
+ ctx.slots.inject("sidebar.workspaces", () => {
2531
+ syncSidebar();
2532
+ return () => {
2533
+ oursReg?.();
2534
+ oursReg = null;
2535
+ };
2536
+ });
2537
+ ctx.slots.inject(
2538
+ "sidebar.footer.action",
2539
+ () => ctx.slots.register(
2540
+ { name: "sidebar.footer.action", id: "workspace-kit.sidebar-toggle", order: 0, store },
2541
+ SidebarToggle
2542
+ )
2543
+ );
2544
+ ctx.effect(() => {
2545
+ const onMode = (event) => {
2546
+ const detail = event.detail;
2547
+ const next = Boolean(detail?.official);
2548
+ if (next === officialSidebar) return;
2549
+ officialSidebar = next;
2550
+ syncSidebar();
2551
+ log.info(`sidebar: ${officialSidebar ? "official" : "plugin"}`);
2552
+ };
2553
+ window.addEventListener("dsh-workspace-kit:sidebar-mode", onMode);
2554
+ return () => window.removeEventListener("dsh-workspace-kit:sidebar-mode", onMode);
2555
+ }, "workspace-kit: sidebar-mode");
2556
+ ctx.slots.inject("shell.overlay", () => {
2557
+ const disposePalette = ctx.slots.register(
2558
+ {
2559
+ name: "shell.overlay",
2560
+ id: "workspace-kit.spotlight",
2561
+ order: 100,
2562
+ store,
2563
+ inject: () => ({ openWorkspace: startSession, openSession, archiveSession })
2564
+ },
2565
+ SpotlightPalette
2566
+ );
2567
+ const disposeDialogs = ctx.slots.register(
2568
+ { name: "shell.overlay", id: "workspace-kit.dialogs", order: 200 },
2569
+ DialogHost
2570
+ );
2571
+ return () => {
2572
+ disposePalette();
2573
+ disposeDialogs();
2574
+ };
2575
+ });
2576
+ log.info(`Workspace kit client ready (sidebar: ${officialSidebar ? "official" : "plugin"})`);
2577
+ }
2578
+ /*! Bundled license information:
2579
+
2580
+ lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs:
2581
+ lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs:
2582
+ lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs:
2583
+ lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs:
2584
+ lucide-react/dist/esm/defaultAttributes.mjs:
2585
+ lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs:
2586
+ lucide-react/dist/esm/context.mjs:
2587
+ lucide-react/dist/esm/Icon.mjs:
2588
+ lucide-react/dist/esm/createLucideIcon.mjs:
2589
+ lucide-react/dist/esm/icons/book-open.mjs:
2590
+ lucide-react/dist/esm/icons/bot.mjs:
2591
+ lucide-react/dist/esm/icons/brain.mjs:
2592
+ lucide-react/dist/esm/icons/chart-column.mjs:
2593
+ lucide-react/dist/esm/icons/chevron-down.mjs:
2594
+ lucide-react/dist/esm/icons/chevron-right.mjs:
2595
+ lucide-react/dist/esm/icons/chevrons-right.mjs:
2596
+ lucide-react/dist/esm/icons/coins.mjs:
2597
+ lucide-react/dist/esm/icons/command.mjs:
2598
+ lucide-react/dist/esm/icons/construction.mjs:
2599
+ lucide-react/dist/esm/icons/copy.mjs:
2600
+ lucide-react/dist/esm/icons/database.mjs:
2601
+ lucide-react/dist/esm/icons/file-text.mjs:
2602
+ lucide-react/dist/esm/icons/files.mjs:
2603
+ lucide-react/dist/esm/icons/flame.mjs:
2604
+ lucide-react/dist/esm/icons/flask-conical.mjs:
2605
+ lucide-react/dist/esm/icons/folder-open.mjs:
2606
+ lucide-react/dist/esm/icons/folder.mjs:
2607
+ lucide-react/dist/esm/icons/gamepad-2.mjs:
2608
+ lucide-react/dist/esm/icons/ghost.mjs:
2609
+ lucide-react/dist/esm/icons/globe.mjs:
2610
+ lucide-react/dist/esm/icons/joystick.mjs:
2611
+ lucide-react/dist/esm/icons/lightbulb.mjs:
2612
+ lucide-react/dist/esm/icons/map.mjs:
2613
+ lucide-react/dist/esm/icons/package.mjs:
2614
+ lucide-react/dist/esm/icons/palette.mjs:
2615
+ lucide-react/dist/esm/icons/pencil.mjs:
2616
+ lucide-react/dist/esm/icons/plus.mjs:
2617
+ lucide-react/dist/esm/icons/puzzle.mjs:
2618
+ lucide-react/dist/esm/icons/rocket.mjs:
2619
+ lucide-react/dist/esm/icons/search.mjs:
2620
+ lucide-react/dist/esm/icons/settings.mjs:
2621
+ lucide-react/dist/esm/icons/sliders-horizontal.mjs:
2622
+ lucide-react/dist/esm/icons/snowflake.mjs:
2623
+ lucide-react/dist/esm/icons/sprout.mjs:
2624
+ lucide-react/dist/esm/icons/star.mjs:
2625
+ lucide-react/dist/esm/icons/target.mjs:
2626
+ lucide-react/dist/esm/icons/trash.mjs:
2627
+ lucide-react/dist/esm/icons/trending-up.mjs:
2628
+ lucide-react/dist/esm/icons/wrench.mjs:
2629
+ lucide-react/dist/esm/icons/zap.mjs:
2630
+ lucide-react/dist/esm/lucide-react.mjs:
2631
+ (**
2632
+ * @license lucide-react v1.41.0 - ISC
2633
+ *
2634
+ * This source code is licensed under the ISC license.
2635
+ * See the LICENSE file in the root directory of this source tree.
2636
+ *)
2637
+ */
2638
+
2639
+ return module.exports;
2640
+ }
2641
+ });
2642
+