@industry-theme/alexandria-panels 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.
@@ -0,0 +1,1282 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import React2, { createContext, useState, useEffect, useContext, forwardRef, createElement, useMemo, useCallback } from "react";
3
+ var terminalTheme = {
4
+ space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
5
+ fonts: {
6
+ body: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace',
7
+ heading: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace',
8
+ monospace: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace'
9
+ },
10
+ fontSizes: [12, 14, 16, 18, 20, 24, 32, 48, 64, 96],
11
+ fontScale: 1,
12
+ fontWeights: {
13
+ body: 400,
14
+ heading: 500,
15
+ bold: 600,
16
+ light: 300,
17
+ medium: 500,
18
+ semibold: 600
19
+ },
20
+ lineHeights: {
21
+ body: 1.6,
22
+ heading: 1.3,
23
+ tight: 1.4,
24
+ relaxed: 1.8
25
+ },
26
+ breakpoints: ["640px", "768px", "1024px", "1280px"],
27
+ sizes: [16, 32, 64, 128, 256, 512, 768, 1024, 1536],
28
+ radii: [0, 2, 4, 6, 8, 12, 16, 24],
29
+ shadows: [
30
+ "none",
31
+ "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
32
+ "0 2px 4px 0 rgba(0, 0, 0, 0.06)",
33
+ "0 4px 6px 0 rgba(0, 0, 0, 0.07)",
34
+ "0 8px 12px 0 rgba(0, 0, 0, 0.08)",
35
+ "0 16px 24px 0 rgba(0, 0, 0, 0.10)"
36
+ ],
37
+ zIndices: [0, 1, 10, 20, 30, 40, 50],
38
+ colors: {
39
+ text: "#e4e4e4",
40
+ background: "rgba(10, 10, 10, 0.85)",
41
+ primary: "#66b3ff",
42
+ secondary: "#80c4ff",
43
+ accent: "#66ff99",
44
+ highlight: "rgba(102, 179, 255, 0.15)",
45
+ muted: "rgba(26, 26, 26, 0.8)",
46
+ success: "#66ff99",
47
+ warning: "#ffcc66",
48
+ error: "#ff6666",
49
+ info: "#66b3ff",
50
+ border: "rgba(255, 255, 255, 0.1)",
51
+ backgroundSecondary: "rgba(15, 15, 15, 0.9)",
52
+ backgroundTertiary: "rgba(20, 20, 20, 0.9)",
53
+ backgroundLight: "rgba(255, 255, 255, 0.05)",
54
+ backgroundHover: "rgba(102, 179, 255, 0.08)",
55
+ surface: "rgba(15, 15, 15, 0.95)",
56
+ textSecondary: "rgba(255, 255, 255, 0.7)",
57
+ textTertiary: "rgba(255, 255, 255, 0.5)",
58
+ textMuted: "rgba(255, 255, 255, 0.4)",
59
+ highlightBg: "rgba(255, 235, 59, 0.25)",
60
+ highlightBorder: "rgba(255, 235, 59, 0.5)"
61
+ },
62
+ modes: {
63
+ light: {
64
+ text: "#1a1a1a",
65
+ background: "rgba(255, 255, 255, 0.9)",
66
+ primary: "#0066cc",
67
+ secondary: "#0052a3",
68
+ accent: "#00cc88",
69
+ highlight: "rgba(0, 102, 204, 0.08)",
70
+ muted: "rgba(245, 245, 245, 0.8)",
71
+ success: "#00cc88",
72
+ warning: "#ffaa00",
73
+ error: "#ff3333",
74
+ info: "#0066cc",
75
+ border: "rgba(0, 0, 0, 0.1)",
76
+ backgroundSecondary: "rgba(250, 250, 250, 0.9)",
77
+ backgroundTertiary: "rgba(245, 245, 245, 0.9)",
78
+ backgroundLight: "rgba(0, 0, 0, 0.02)",
79
+ backgroundHover: "rgba(0, 102, 204, 0.04)",
80
+ surface: "rgba(255, 255, 255, 0.95)",
81
+ textSecondary: "rgba(0, 0, 0, 0.6)",
82
+ textTertiary: "rgba(0, 0, 0, 0.4)",
83
+ textMuted: "rgba(0, 0, 0, 0.3)",
84
+ highlightBg: "rgba(255, 235, 59, 0.3)",
85
+ highlightBorder: "rgba(255, 235, 59, 0.6)"
86
+ }
87
+ },
88
+ buttons: {
89
+ primary: {
90
+ color: "white",
91
+ bg: "primary",
92
+ borderWidth: 0,
93
+ "&:hover": {
94
+ bg: "secondary"
95
+ }
96
+ },
97
+ secondary: {
98
+ color: "primary",
99
+ bg: "transparent",
100
+ borderWidth: 1,
101
+ borderStyle: "solid",
102
+ borderColor: "primary",
103
+ "&:hover": {
104
+ bg: "highlight"
105
+ }
106
+ },
107
+ ghost: {
108
+ color: "text",
109
+ bg: "transparent",
110
+ "&:hover": {
111
+ bg: "backgroundHover"
112
+ }
113
+ }
114
+ },
115
+ text: {
116
+ heading: {
117
+ fontFamily: "heading",
118
+ fontWeight: "heading",
119
+ lineHeight: "heading"
120
+ },
121
+ body: {
122
+ fontFamily: "body",
123
+ fontWeight: "body",
124
+ lineHeight: "body"
125
+ },
126
+ caption: {
127
+ fontSize: 1,
128
+ color: "textSecondary"
129
+ }
130
+ },
131
+ cards: {
132
+ primary: {
133
+ bg: "surface",
134
+ border: "1px solid",
135
+ borderColor: "border",
136
+ borderRadius: 1
137
+ },
138
+ secondary: {
139
+ bg: "backgroundSecondary",
140
+ border: "1px solid",
141
+ borderColor: "border",
142
+ borderRadius: 1
143
+ }
144
+ }
145
+ };
146
+ function getMode(theme2, mode) {
147
+ if (!mode || !theme2.modes || !theme2.modes[mode]) {
148
+ return theme2.colors;
149
+ }
150
+ return {
151
+ ...theme2.colors,
152
+ ...theme2.modes[mode]
153
+ };
154
+ }
155
+ var ThemeContext;
156
+ var getThemeContext = () => {
157
+ if (typeof window !== "undefined") {
158
+ const globalWindow = window;
159
+ if (!globalWindow.__principlemd_theme_context__) {
160
+ globalWindow.__principlemd_theme_context__ = createContext(void 0);
161
+ }
162
+ return globalWindow.__principlemd_theme_context__;
163
+ } else {
164
+ if (!ThemeContext) {
165
+ ThemeContext = createContext(void 0);
166
+ }
167
+ return ThemeContext;
168
+ }
169
+ };
170
+ var ThemeContextSingleton = getThemeContext();
171
+ var useTheme = () => {
172
+ const context = useContext(ThemeContextSingleton);
173
+ if (!context) {
174
+ throw new Error("useTheme must be used within a ThemeProvider");
175
+ }
176
+ return context;
177
+ };
178
+ var ThemeProvider = ({
179
+ children,
180
+ theme: customTheme = theme,
181
+ initialMode
182
+ }) => {
183
+ const [mode, setMode] = useState(initialMode);
184
+ const activeTheme = React2.useMemo(() => {
185
+ if (!mode || !customTheme.modes || !customTheme.modes[mode]) {
186
+ return customTheme;
187
+ }
188
+ return {
189
+ ...customTheme,
190
+ colors: getMode(customTheme, mode)
191
+ };
192
+ }, [customTheme, mode]);
193
+ useEffect(() => {
194
+ if (!initialMode) {
195
+ const savedMode = localStorage.getItem("principlemd-theme-mode");
196
+ if (savedMode) {
197
+ setMode(savedMode);
198
+ }
199
+ }
200
+ }, [initialMode]);
201
+ useEffect(() => {
202
+ if (mode) {
203
+ localStorage.setItem("principlemd-theme-mode", mode);
204
+ } else {
205
+ localStorage.removeItem("principlemd-theme-mode");
206
+ }
207
+ }, [mode]);
208
+ const value = {
209
+ theme: activeTheme,
210
+ mode,
211
+ setMode
212
+ };
213
+ return /* @__PURE__ */ React2.createElement(ThemeContextSingleton.Provider, {
214
+ value
215
+ }, children);
216
+ };
217
+ var theme = terminalTheme;
218
+ /**
219
+ * @license lucide-react v0.552.0 - ISC
220
+ *
221
+ * This source code is licensed under the ISC license.
222
+ * See the LICENSE file in the root directory of this source tree.
223
+ */
224
+ const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
225
+ const toCamelCase = (string) => string.replace(
226
+ /^([A-Z])|[\s-_]+(\w)/g,
227
+ (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()
228
+ );
229
+ const toPascalCase = (string) => {
230
+ const camelCase = toCamelCase(string);
231
+ return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
232
+ };
233
+ const mergeClasses = (...classes) => classes.filter((className, index, array) => {
234
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
235
+ }).join(" ").trim();
236
+ const hasA11yProp = (props) => {
237
+ for (const prop in props) {
238
+ if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
239
+ return true;
240
+ }
241
+ }
242
+ };
243
+ /**
244
+ * @license lucide-react v0.552.0 - ISC
245
+ *
246
+ * This source code is licensed under the ISC license.
247
+ * See the LICENSE file in the root directory of this source tree.
248
+ */
249
+ var defaultAttributes = {
250
+ xmlns: "http://www.w3.org/2000/svg",
251
+ width: 24,
252
+ height: 24,
253
+ viewBox: "0 0 24 24",
254
+ fill: "none",
255
+ stroke: "currentColor",
256
+ strokeWidth: 2,
257
+ strokeLinecap: "round",
258
+ strokeLinejoin: "round"
259
+ };
260
+ /**
261
+ * @license lucide-react v0.552.0 - ISC
262
+ *
263
+ * This source code is licensed under the ISC license.
264
+ * See the LICENSE file in the root directory of this source tree.
265
+ */
266
+ const Icon = forwardRef(
267
+ ({
268
+ color = "currentColor",
269
+ size = 24,
270
+ strokeWidth = 2,
271
+ absoluteStrokeWidth,
272
+ className = "",
273
+ children,
274
+ iconNode,
275
+ ...rest
276
+ }, ref) => createElement(
277
+ "svg",
278
+ {
279
+ ref,
280
+ ...defaultAttributes,
281
+ width: size,
282
+ height: size,
283
+ stroke: color,
284
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
285
+ className: mergeClasses("lucide", className),
286
+ ...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
287
+ ...rest
288
+ },
289
+ [
290
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
291
+ ...Array.isArray(children) ? children : [children]
292
+ ]
293
+ )
294
+ );
295
+ /**
296
+ * @license lucide-react v0.552.0 - ISC
297
+ *
298
+ * This source code is licensed under the ISC license.
299
+ * See the LICENSE file in the root directory of this source tree.
300
+ */
301
+ const createLucideIcon = (iconName, iconNode) => {
302
+ const Component = forwardRef(
303
+ ({ className, ...props }, ref) => createElement(Icon, {
304
+ ref,
305
+ iconNode,
306
+ className: mergeClasses(
307
+ `lucide-${toKebabCase(toPascalCase(iconName))}`,
308
+ `lucide-${iconName}`,
309
+ className
310
+ ),
311
+ ...props
312
+ })
313
+ );
314
+ Component.displayName = toPascalCase(iconName);
315
+ return Component;
316
+ };
317
+ /**
318
+ * @license lucide-react v0.552.0 - ISC
319
+ *
320
+ * This source code is licensed under the ISC license.
321
+ * See the LICENSE file in the root directory of this source tree.
322
+ */
323
+ const __iconNode$9 = [
324
+ ["path", { d: "M10 12h4", key: "a56b0p" }],
325
+ ["path", { d: "M10 8h4", key: "1sr2af" }],
326
+ ["path", { d: "M14 21v-3a2 2 0 0 0-4 0v3", key: "1rgiei" }],
327
+ [
328
+ "path",
329
+ {
330
+ d: "M6 10H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-2",
331
+ key: "secmi2"
332
+ }
333
+ ],
334
+ ["path", { d: "M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16", key: "16ra0t" }]
335
+ ];
336
+ const Building2 = createLucideIcon("building-2", __iconNode$9);
337
+ /**
338
+ * @license lucide-react v0.552.0 - ISC
339
+ *
340
+ * This source code is licensed under the ISC license.
341
+ * See the LICENSE file in the root directory of this source tree.
342
+ */
343
+ const __iconNode$8 = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
344
+ const Check = createLucideIcon("check", __iconNode$8);
345
+ /**
346
+ * @license lucide-react v0.552.0 - ISC
347
+ *
348
+ * This source code is licensed under the ISC license.
349
+ * See the LICENSE file in the root directory of this source tree.
350
+ */
351
+ const __iconNode$7 = [
352
+ ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
353
+ ["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" }]
354
+ ];
355
+ const Copy = createLucideIcon("copy", __iconNode$7);
356
+ /**
357
+ * @license lucide-react v0.552.0 - ISC
358
+ *
359
+ * This source code is licensed under the ISC license.
360
+ * See the LICENSE file in the root directory of this source tree.
361
+ */
362
+ const __iconNode$6 = [
363
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }],
364
+ ["path", { d: "M3 7V5a2 2 0 0 1 2-2h2", key: "aa7l1z" }],
365
+ ["path", { d: "M17 3h2a2 2 0 0 1 2 2v2", key: "4qcy5o" }],
366
+ ["path", { d: "M21 17v2a2 2 0 0 1-2 2h-2", key: "6vwrx8" }],
367
+ ["path", { d: "M7 21H5a2 2 0 0 1-2-2v-2", key: "ioqczr" }]
368
+ ];
369
+ const Focus = createLucideIcon("focus", __iconNode$6);
370
+ /**
371
+ * @license lucide-react v0.552.0 - ISC
372
+ *
373
+ * This source code is licensed under the ISC license.
374
+ * See the LICENSE file in the root directory of this source tree.
375
+ */
376
+ const __iconNode$5 = [
377
+ [
378
+ "path",
379
+ {
380
+ d: "M9 20H4a2 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.9H20a2 2 0 0 1 2 2v5",
381
+ key: "1w6njk"
382
+ }
383
+ ],
384
+ ["circle", { cx: "13", cy: "12", r: "2", key: "1j92g6" }],
385
+ ["path", { d: "M18 19c-2.8 0-5-2.2-5-5v8", key: "pkpw2h" }],
386
+ ["circle", { cx: "20", cy: "19", r: "2", key: "1obnsp" }]
387
+ ];
388
+ const FolderGit2 = createLucideIcon("folder-git-2", __iconNode$5);
389
+ /**
390
+ * @license lucide-react v0.552.0 - ISC
391
+ *
392
+ * This source code is licensed under the ISC license.
393
+ * See the LICENSE file in the root directory of this source tree.
394
+ */
395
+ const __iconNode$4 = [
396
+ [
397
+ "path",
398
+ {
399
+ 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",
400
+ key: "usdka0"
401
+ }
402
+ ]
403
+ ];
404
+ const FolderOpen = createLucideIcon("folder-open", __iconNode$4);
405
+ /**
406
+ * @license lucide-react v0.552.0 - ISC
407
+ *
408
+ * This source code is licensed under the ISC license.
409
+ * See the LICENSE file in the root directory of this source tree.
410
+ */
411
+ const __iconNode$3 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
412
+ const LoaderCircle = createLucideIcon("loader-circle", __iconNode$3);
413
+ /**
414
+ * @license lucide-react v0.552.0 - ISC
415
+ *
416
+ * This source code is licensed under the ISC license.
417
+ * See the LICENSE file in the root directory of this source tree.
418
+ */
419
+ const __iconNode$2 = [
420
+ ["path", { d: "M5 12h14", key: "1ays0h" }],
421
+ ["path", { d: "M12 5v14", key: "s699le" }]
422
+ ];
423
+ const Plus = createLucideIcon("plus", __iconNode$2);
424
+ /**
425
+ * @license lucide-react v0.552.0 - ISC
426
+ *
427
+ * This source code is licensed under the ISC license.
428
+ * See the LICENSE file in the root directory of this source tree.
429
+ */
430
+ const __iconNode$1 = [
431
+ ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
432
+ ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
433
+ ];
434
+ const Search = createLucideIcon("search", __iconNode$1);
435
+ /**
436
+ * @license lucide-react v0.552.0 - ISC
437
+ *
438
+ * This source code is licensed under the ISC license.
439
+ * See the LICENSE file in the root directory of this source tree.
440
+ */
441
+ const __iconNode = [
442
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
443
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
444
+ ];
445
+ const X = createLucideIcon("x", __iconNode);
446
+ const RepositoryAvatar = ({
447
+ owner,
448
+ customAvatarUrl,
449
+ size = 32,
450
+ fallbackIcon
451
+ }) => {
452
+ const { theme: theme2 } = useTheme();
453
+ const borderRadius = `${Math.min(8, size / 4)}px`;
454
+ const avatarUrl = customAvatarUrl || (owner ? `https://github.com/${owner}.png` : null);
455
+ const getContent = () => {
456
+ if (avatarUrl) {
457
+ return /* @__PURE__ */ jsx(
458
+ "img",
459
+ {
460
+ src: avatarUrl,
461
+ alt: owner || "Repository",
462
+ style: {
463
+ width: "100%",
464
+ height: "100%",
465
+ objectFit: "cover"
466
+ },
467
+ onError: (e) => {
468
+ e.currentTarget.style.display = "none";
469
+ }
470
+ }
471
+ );
472
+ }
473
+ if (fallbackIcon) {
474
+ return fallbackIcon;
475
+ }
476
+ return null;
477
+ };
478
+ return /* @__PURE__ */ jsx(
479
+ "div",
480
+ {
481
+ style: {
482
+ width: `${size}px`,
483
+ height: `${size}px`,
484
+ borderRadius,
485
+ backgroundColor: theme2.colors.backgroundTertiary,
486
+ display: "flex",
487
+ alignItems: "center",
488
+ justifyContent: "center",
489
+ overflow: "hidden",
490
+ flexShrink: 0
491
+ },
492
+ children: getContent()
493
+ }
494
+ );
495
+ };
496
+ const LANGUAGE_COLORS = {
497
+ TypeScript: "#3178c6",
498
+ JavaScript: "#f7df1e",
499
+ Python: "#3776ab",
500
+ Java: "#b07219",
501
+ Go: "#00add8",
502
+ Rust: "#dea584",
503
+ Ruby: "#cc342d",
504
+ PHP: "#777bb4",
505
+ "C++": "#00599c",
506
+ C: "#555555",
507
+ "C#": "#239120",
508
+ Swift: "#fa7343",
509
+ Kotlin: "#7f52ff",
510
+ Dart: "#0175c2",
511
+ Vue: "#4fc08d",
512
+ HTML: "#e34c26",
513
+ CSS: "#1572b6",
514
+ Shell: "#89e051",
515
+ PowerShell: "#012456"
516
+ };
517
+ const getLanguageColor = (language) => {
518
+ return LANGUAGE_COLORS[language] || "#6e7681";
519
+ };
520
+ const LocalProjectCard = ({
521
+ entry,
522
+ actionMode = "default",
523
+ isSelected = false,
524
+ onSelect,
525
+ onOpen,
526
+ onRemove,
527
+ onAddToWorkspace,
528
+ isLoading = false,
529
+ windowState = "closed",
530
+ compact: _compact = false
531
+ }) => {
532
+ var _a, _b, _c, _d;
533
+ const { theme: theme2 } = useTheme();
534
+ const [copiedPath, setCopiedPath] = useState(false);
535
+ const highlightColor = theme2.colors.primary;
536
+ const avatarUrl = ((_a = entry.github) == null ? void 0 : _a.owner) ? `https://github.com/${entry.github.owner}.png` : null;
537
+ const handleCardClick = () => {
538
+ onSelect == null ? void 0 : onSelect(entry);
539
+ };
540
+ const handleOpenClick = (e) => {
541
+ e.stopPropagation();
542
+ onOpen == null ? void 0 : onOpen(entry);
543
+ };
544
+ const handleRemoveClick = (e) => {
545
+ e.stopPropagation();
546
+ onRemove == null ? void 0 : onRemove(entry);
547
+ };
548
+ const handleAddToWorkspaceClick = (e) => {
549
+ e.stopPropagation();
550
+ onAddToWorkspace == null ? void 0 : onAddToWorkspace(entry);
551
+ };
552
+ const handleCopyPath = async (e) => {
553
+ e.stopPropagation();
554
+ try {
555
+ await navigator.clipboard.writeText(entry.path);
556
+ setCopiedPath(true);
557
+ setTimeout(() => setCopiedPath(false), 2e3);
558
+ } catch (err) {
559
+ console.error("Failed to copy path:", err);
560
+ }
561
+ };
562
+ const renderActionButtons = (isCompact = false) => {
563
+ const buttonFlex = isCompact ? 1 : void 0;
564
+ if (actionMode === "add-to-workspace") {
565
+ return /* @__PURE__ */ jsxs(
566
+ "button",
567
+ {
568
+ type: "button",
569
+ onClick: handleAddToWorkspaceClick,
570
+ disabled: isLoading,
571
+ title: "Add to workspace",
572
+ style: {
573
+ flex: buttonFlex,
574
+ display: "inline-flex",
575
+ alignItems: "center",
576
+ justifyContent: "center",
577
+ padding: "6px 10px",
578
+ gap: "4px",
579
+ borderRadius: "4px",
580
+ border: `1px solid ${theme2.colors.primary || "#3b82f6"}`,
581
+ backgroundColor: `${theme2.colors.primary || "#3b82f6"}15`,
582
+ color: theme2.colors.primary || "#3b82f6",
583
+ fontSize: `${theme2.fontSizes[0]}px`,
584
+ fontWeight: theme2.fontWeights.medium,
585
+ cursor: isLoading ? "wait" : "pointer",
586
+ opacity: isLoading ? 0.6 : 1,
587
+ transition: "all 0.15s ease"
588
+ },
589
+ children: [
590
+ isLoading ? /* @__PURE__ */ jsx(LoaderCircle, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(Plus, { size: 12 }),
591
+ isLoading ? "Adding..." : "Add"
592
+ ]
593
+ }
594
+ );
595
+ }
596
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
597
+ /* @__PURE__ */ jsxs(
598
+ "button",
599
+ {
600
+ type: "button",
601
+ onClick: handleOpenClick,
602
+ title: windowState === "ready" ? "Focus window" : windowState === "opening" ? "Window is opening..." : "Open locally",
603
+ disabled: windowState === "opening",
604
+ style: {
605
+ flex: buttonFlex,
606
+ display: "inline-flex",
607
+ alignItems: "center",
608
+ justifyContent: "center",
609
+ padding: "6px 10px",
610
+ gap: "4px",
611
+ borderRadius: "4px",
612
+ border: `1px solid ${theme2.colors.success || "#10b981"}`,
613
+ backgroundColor: `${theme2.colors.success || "#10b981"}15`,
614
+ color: theme2.colors.success || "#10b981",
615
+ fontSize: `${theme2.fontSizes[0]}px`,
616
+ fontWeight: theme2.fontWeights.medium,
617
+ cursor: windowState === "opening" ? "wait" : "pointer",
618
+ opacity: windowState === "opening" ? 0.6 : 1,
619
+ transition: "all 0.15s ease"
620
+ },
621
+ children: [
622
+ windowState === "ready" ? /* @__PURE__ */ jsx(Focus, { size: 12 }) : windowState === "opening" ? /* @__PURE__ */ jsx(LoaderCircle, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx(FolderOpen, { size: 12 }),
623
+ windowState === "ready" ? "Focus" : windowState === "opening" ? "Opening..." : "Open"
624
+ ]
625
+ }
626
+ ),
627
+ actionMode === "default" && onRemove && /* @__PURE__ */ jsxs(
628
+ "button",
629
+ {
630
+ type: "button",
631
+ onClick: handleRemoveClick,
632
+ disabled: isLoading,
633
+ title: "Remove from local projects",
634
+ style: {
635
+ flex: buttonFlex,
636
+ display: "inline-flex",
637
+ alignItems: "center",
638
+ justifyContent: "center",
639
+ minWidth: isCompact ? void 0 : "28px",
640
+ height: "28px",
641
+ padding: isCompact ? "6px 10px" : 0,
642
+ gap: "4px",
643
+ borderRadius: "4px",
644
+ border: isCompact ? `1px solid ${theme2.colors.error || "#ef4444"}` : "none",
645
+ backgroundColor: isCompact ? `${theme2.colors.error || "#ef4444"}15` : "transparent",
646
+ color: isCompact ? theme2.colors.error || "#ef4444" : theme2.colors.textSecondary,
647
+ fontSize: `${theme2.fontSizes[0]}px`,
648
+ fontWeight: theme2.fontWeights.medium,
649
+ cursor: isLoading ? "wait" : "pointer",
650
+ opacity: isLoading ? 0.6 : 1,
651
+ transition: "all 0.15s ease"
652
+ },
653
+ children: [
654
+ isLoading ? /* @__PURE__ */ jsx(LoaderCircle, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsx(X, { size: 14 }),
655
+ isCompact && (isLoading ? "Removing..." : "Remove")
656
+ ]
657
+ }
658
+ )
659
+ ] });
660
+ };
661
+ return /* @__PURE__ */ jsxs(
662
+ "div",
663
+ {
664
+ className: "local-project-card",
665
+ style: {
666
+ padding: "8px 12px",
667
+ borderRadius: "4px",
668
+ backgroundColor: isSelected ? `${highlightColor}15` : "transparent",
669
+ border: isSelected ? `1px solid ${highlightColor}40` : "1px solid transparent",
670
+ cursor: "pointer",
671
+ transition: "background-color 0.15s",
672
+ fontFamily: theme2.fonts.body
673
+ },
674
+ onClick: handleCardClick,
675
+ children: [
676
+ /* @__PURE__ */ jsxs("div", { className: "local-project-card__content", children: [
677
+ /* @__PURE__ */ jsx(
678
+ RepositoryAvatar,
679
+ {
680
+ customAvatarUrl: avatarUrl,
681
+ size: 32,
682
+ fallbackIcon: /* @__PURE__ */ jsx(
683
+ "div",
684
+ {
685
+ style: {
686
+ color: theme2.colors.textSecondary,
687
+ fontSize: `${theme2.fontSizes[0]}px`,
688
+ fontWeight: theme2.fontWeights.semibold
689
+ },
690
+ children: ((_b = entry.name[0]) == null ? void 0 : _b.toUpperCase()) || "?"
691
+ }
692
+ )
693
+ }
694
+ ),
695
+ /* @__PURE__ */ jsxs("div", { className: "local-project-card__info", children: [
696
+ /* @__PURE__ */ jsx(
697
+ "span",
698
+ {
699
+ style: {
700
+ fontSize: `${theme2.fontSizes[2]}px`,
701
+ fontWeight: theme2.fontWeights.medium,
702
+ color: theme2.colors.text,
703
+ overflow: "hidden",
704
+ textOverflow: "ellipsis",
705
+ whiteSpace: "nowrap",
706
+ textDecoration: "underline",
707
+ textDecorationColor: ((_c = entry.github) == null ? void 0 : _c.primaryLanguage) ? getLanguageColor(entry.github.primaryLanguage) : theme2.colors.textSecondary,
708
+ textUnderlineOffset: "3px"
709
+ },
710
+ children: entry.name
711
+ }
712
+ ),
713
+ /* @__PURE__ */ jsxs(
714
+ "div",
715
+ {
716
+ className: "local-project-card__path",
717
+ onClick: handleCopyPath,
718
+ style: {
719
+ fontSize: `${theme2.fontSizes[0]}px`,
720
+ fontFamily: theme2.fonts.monospace,
721
+ color: copiedPath ? theme2.colors.success || "#10b981" : theme2.colors.textTertiary || theme2.colors.textSecondary,
722
+ overflow: "hidden",
723
+ textOverflow: "ellipsis",
724
+ whiteSpace: "nowrap",
725
+ cursor: "pointer",
726
+ alignItems: "center",
727
+ gap: "4px",
728
+ transition: "color 0.15s ease"
729
+ },
730
+ title: copiedPath ? "Copied!" : `Click to copy: ${entry.path}`,
731
+ children: [
732
+ copiedPath ? /* @__PURE__ */ jsx(Check, { size: 12 }) : /* @__PURE__ */ jsx(Copy, { size: 12 }),
733
+ entry.path
734
+ ]
735
+ }
736
+ ),
737
+ ((_d = entry.github) == null ? void 0 : _d.description) && /* @__PURE__ */ jsx(
738
+ "div",
739
+ {
740
+ className: "local-project-card__meta",
741
+ style: {
742
+ alignItems: "center",
743
+ gap: "12px",
744
+ fontSize: `${theme2.fontSizes[0]}px`,
745
+ color: theme2.colors.textSecondary
746
+ },
747
+ children: /* @__PURE__ */ jsx(
748
+ "span",
749
+ {
750
+ style: {
751
+ overflow: "hidden",
752
+ textOverflow: "ellipsis",
753
+ whiteSpace: "nowrap"
754
+ },
755
+ children: entry.github.description
756
+ }
757
+ )
758
+ }
759
+ )
760
+ ] }),
761
+ /* @__PURE__ */ jsx("div", { className: "local-project-card__actions", children: renderActionButtons(false) })
762
+ ] }),
763
+ /* @__PURE__ */ jsx("div", { className: "local-project-card__actions--stacked", children: renderActionButtons(true) })
764
+ ]
765
+ }
766
+ );
767
+ };
768
+ const PANEL_ID$1 = "industry-theme.local-projects";
769
+ const createPanelEvent = (type, payload) => ({
770
+ type,
771
+ source: PANEL_ID$1,
772
+ timestamp: Date.now(),
773
+ payload
774
+ });
775
+ const LocalProjectsPanelContent = ({
776
+ context,
777
+ actions,
778
+ events
779
+ }) => {
780
+ var _a;
781
+ const { theme: theme2 } = useTheme();
782
+ const [filter, setFilter] = useState("");
783
+ const [isAdding, setIsAdding] = useState(false);
784
+ const [selectedEntry, setSelectedEntry] = useState(null);
785
+ const [windowStates, setWindowStates] = useState(/* @__PURE__ */ new Map());
786
+ const [sortByOrg, setSortByOrg] = useState(false);
787
+ const panelActions = actions;
788
+ const repoSlice = context.getSlice("alexandriaRepositories");
789
+ const repositories = useMemo(
790
+ () => {
791
+ var _a2;
792
+ return ((_a2 = repoSlice == null ? void 0 : repoSlice.data) == null ? void 0 : _a2.repositories) || [];
793
+ },
794
+ [(_a = repoSlice == null ? void 0 : repoSlice.data) == null ? void 0 : _a.repositories]
795
+ );
796
+ const loading = (repoSlice == null ? void 0 : repoSlice.loading) ?? false;
797
+ const handleOpenRepository = useCallback(
798
+ async (entry) => {
799
+ if (!panelActions.openRepository) {
800
+ console.warn("Open repository action not available");
801
+ return;
802
+ }
803
+ setWindowStates((prev) => new Map(prev).set(entry.path, "opening"));
804
+ try {
805
+ await panelActions.openRepository(entry);
806
+ setWindowStates((prev) => new Map(prev).set(entry.path, "ready"));
807
+ events.emit(createPanelEvent(`${PANEL_ID$1}:repository-opened`, { entry }));
808
+ } catch (error) {
809
+ console.error("Error opening repository:", error);
810
+ setWindowStates((prev) => new Map(prev).set(entry.path, "closed"));
811
+ }
812
+ },
813
+ [panelActions, events]
814
+ );
815
+ useEffect(() => {
816
+ const unsubscribers = [
817
+ // Filter event from tools
818
+ events.on(`${PANEL_ID$1}:filter`, (event) => {
819
+ var _a2;
820
+ if (((_a2 = event.payload) == null ? void 0 : _a2.filter) !== void 0) {
821
+ setFilter(event.payload.filter);
822
+ }
823
+ }),
824
+ // Select repository event from tools
825
+ events.on(`${PANEL_ID$1}:select-repository`, (event) => {
826
+ var _a2;
827
+ const identifier = (_a2 = event.payload) == null ? void 0 : _a2.identifier;
828
+ if (identifier) {
829
+ const entry = repositories.find(
830
+ (r) => r.name === identifier || r.path === identifier
831
+ );
832
+ if (entry) {
833
+ setSelectedEntry(entry);
834
+ events.emit(createPanelEvent(`${PANEL_ID$1}:repository-selected`, { entry }));
835
+ }
836
+ }
837
+ }),
838
+ // Open repository event from tools
839
+ events.on(`${PANEL_ID$1}:open-repository`, (event) => {
840
+ var _a2;
841
+ const identifier = (_a2 = event.payload) == null ? void 0 : _a2.identifier;
842
+ if (identifier) {
843
+ const entry = repositories.find(
844
+ (r) => r.name === identifier || r.path === identifier
845
+ );
846
+ if (entry) {
847
+ handleOpenRepository(entry);
848
+ }
849
+ }
850
+ })
851
+ ];
852
+ return () => unsubscribers.forEach((unsub) => unsub());
853
+ }, [events, repositories, handleOpenRepository]);
854
+ const handleAddProject = async () => {
855
+ if (!panelActions.selectDirectory || !panelActions.registerRepository) {
856
+ console.warn("Add project actions not available");
857
+ return;
858
+ }
859
+ try {
860
+ setIsAdding(true);
861
+ const result = await panelActions.selectDirectory();
862
+ if (!result) {
863
+ return;
864
+ }
865
+ await panelActions.registerRepository(result.name, result.path);
866
+ await context.refresh("repository", "alexandriaRepositories");
867
+ } catch (error) {
868
+ console.error("Failed to add project:", error);
869
+ } finally {
870
+ setIsAdding(false);
871
+ }
872
+ };
873
+ const handleRemoveRepository = async (entry) => {
874
+ if (!panelActions.removeRepository) {
875
+ console.warn("Remove repository action not available");
876
+ return;
877
+ }
878
+ try {
879
+ await panelActions.removeRepository(entry.name, false);
880
+ await context.refresh("repository", "alexandriaRepositories");
881
+ } catch (error) {
882
+ console.error("Failed to remove repository:", error);
883
+ }
884
+ };
885
+ const handleSelectRepository = (entry) => {
886
+ setSelectedEntry(entry);
887
+ events.emit(createPanelEvent(`${PANEL_ID$1}:repository-selected`, { entry }));
888
+ };
889
+ const normalizedFilter = filter.trim().toLowerCase();
890
+ const filteredAndSortedRepositories = useMemo(() => {
891
+ const filtered = repositories.filter((entry) => {
892
+ var _a2, _b;
893
+ if (!normalizedFilter) return true;
894
+ const haystack = [
895
+ entry.name,
896
+ ((_a2 = entry.github) == null ? void 0 : _a2.name) ?? "",
897
+ ((_b = entry.github) == null ? void 0 : _b.owner) ?? "",
898
+ entry.remoteUrl ?? ""
899
+ ].join(" ").toLowerCase();
900
+ return haystack.includes(normalizedFilter);
901
+ });
902
+ return filtered.sort((a, b) => {
903
+ var _a2, _b;
904
+ if (sortByOrg) {
905
+ const aOrg = (((_a2 = a.github) == null ? void 0 : _a2.owner) ?? "").toLowerCase();
906
+ const bOrg = (((_b = b.github) == null ? void 0 : _b.owner) ?? "").toLowerCase();
907
+ const orgCompare = aOrg.localeCompare(bOrg);
908
+ if (orgCompare !== 0) return orgCompare;
909
+ }
910
+ return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
911
+ });
912
+ }, [repositories, normalizedFilter, sortByOrg]);
913
+ const baseContainerStyle = {
914
+ display: "flex",
915
+ flexDirection: "column",
916
+ height: "100%",
917
+ backgroundColor: theme2.colors.backgroundSecondary
918
+ };
919
+ const contentContainerStyle = {
920
+ ...baseContainerStyle,
921
+ padding: "16px",
922
+ gap: "12px"
923
+ };
924
+ if (loading) {
925
+ return /* @__PURE__ */ jsx("div", { style: baseContainerStyle, children: /* @__PURE__ */ jsx(
926
+ "div",
927
+ {
928
+ style: {
929
+ flex: 1,
930
+ display: "flex",
931
+ alignItems: "center",
932
+ justifyContent: "center",
933
+ padding: "32px",
934
+ textAlign: "center"
935
+ },
936
+ children: /* @__PURE__ */ jsx(
937
+ "div",
938
+ {
939
+ style: {
940
+ display: "flex",
941
+ flexDirection: "column",
942
+ alignItems: "center",
943
+ gap: "16px",
944
+ maxWidth: "360px"
945
+ },
946
+ children: /* @__PURE__ */ jsx(
947
+ "h3",
948
+ {
949
+ style: {
950
+ margin: 0,
951
+ color: theme2.colors.text,
952
+ fontSize: `${theme2.fontSizes[3]}px`,
953
+ fontWeight: theme2.fontWeights.semibold,
954
+ fontFamily: theme2.fonts.body
955
+ },
956
+ children: "Loading local projects..."
957
+ }
958
+ )
959
+ }
960
+ )
961
+ }
962
+ ) });
963
+ }
964
+ return /* @__PURE__ */ jsxs("div", { className: "local-projects-panel", style: contentContainerStyle, children: [
965
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center" }, children: [
966
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative", flex: 1, minWidth: 0 }, children: [
967
+ /* @__PURE__ */ jsx(
968
+ Search,
969
+ {
970
+ size: 16,
971
+ style: {
972
+ position: "absolute",
973
+ top: "50%",
974
+ left: "12px",
975
+ transform: "translateY(-50%)",
976
+ color: theme2.colors.textSecondary,
977
+ pointerEvents: "none",
978
+ zIndex: 1
979
+ }
980
+ }
981
+ ),
982
+ /* @__PURE__ */ jsx(
983
+ "input",
984
+ {
985
+ type: "text",
986
+ value: filter,
987
+ placeholder: "Filter local projects...",
988
+ onChange: (event) => setFilter(event.target.value),
989
+ style: {
990
+ width: "100%",
991
+ boxSizing: "border-box",
992
+ padding: "8px 12px 8px 36px",
993
+ borderRadius: "6px",
994
+ border: `1px solid ${theme2.colors.border}`,
995
+ backgroundColor: theme2.colors.background,
996
+ color: theme2.colors.text,
997
+ fontSize: `${theme2.fontSizes[1]}px`,
998
+ fontFamily: theme2.fonts.body,
999
+ outline: "none"
1000
+ }
1001
+ }
1002
+ )
1003
+ ] }),
1004
+ /* @__PURE__ */ jsx(
1005
+ "button",
1006
+ {
1007
+ onClick: () => setSortByOrg(!sortByOrg),
1008
+ title: sortByOrg ? "Sorting by organization" : "Sorting by repo name",
1009
+ style: {
1010
+ padding: "8px",
1011
+ borderRadius: "6px",
1012
+ border: `1px solid ${theme2.colors.border}`,
1013
+ backgroundColor: sortByOrg ? `${theme2.colors.primary}20` : theme2.colors.background,
1014
+ color: sortByOrg ? theme2.colors.primary : theme2.colors.textSecondary,
1015
+ cursor: "pointer",
1016
+ display: "flex",
1017
+ alignItems: "center",
1018
+ justifyContent: "center",
1019
+ transition: "all 0.15s",
1020
+ flexShrink: 0
1021
+ },
1022
+ children: sortByOrg ? /* @__PURE__ */ jsx(Building2, { size: 16 }) : /* @__PURE__ */ jsx(FolderGit2, { size: 16 })
1023
+ }
1024
+ ),
1025
+ panelActions.selectDirectory && /* @__PURE__ */ jsx(
1026
+ "button",
1027
+ {
1028
+ onClick: handleAddProject,
1029
+ disabled: isAdding,
1030
+ title: "Add existing project",
1031
+ style: {
1032
+ padding: "8px",
1033
+ borderRadius: "6px",
1034
+ border: `1px solid ${theme2.colors.border}`,
1035
+ backgroundColor: theme2.colors.primary,
1036
+ color: theme2.colors.background,
1037
+ cursor: isAdding ? "default" : "pointer",
1038
+ display: "flex",
1039
+ alignItems: "center",
1040
+ justifyContent: "center",
1041
+ opacity: isAdding ? 0.6 : 1,
1042
+ transition: "opacity 0.2s",
1043
+ flexShrink: 0
1044
+ },
1045
+ children: /* @__PURE__ */ jsx(Plus, { size: 16 })
1046
+ }
1047
+ )
1048
+ ] }),
1049
+ /* @__PURE__ */ jsxs(
1050
+ "div",
1051
+ {
1052
+ className: "local-projects-list",
1053
+ style: {
1054
+ flex: 1,
1055
+ overflowY: "auto",
1056
+ display: "flex",
1057
+ flexDirection: "column",
1058
+ gap: "4px"
1059
+ },
1060
+ children: [
1061
+ filteredAndSortedRepositories.map((entry) => /* @__PURE__ */ jsx(
1062
+ LocalProjectCard,
1063
+ {
1064
+ entry,
1065
+ isSelected: (selectedEntry == null ? void 0 : selectedEntry.path) === entry.path,
1066
+ onSelect: handleSelectRepository,
1067
+ onOpen: handleOpenRepository,
1068
+ onRemove: handleRemoveRepository,
1069
+ windowState: windowStates.get(entry.path) || "closed"
1070
+ },
1071
+ entry.path
1072
+ )),
1073
+ filteredAndSortedRepositories.length === 0 && !loading && /* @__PURE__ */ jsx(
1074
+ "div",
1075
+ {
1076
+ style: {
1077
+ padding: "32px",
1078
+ textAlign: "center",
1079
+ color: theme2.colors.textSecondary
1080
+ },
1081
+ children: /* @__PURE__ */ jsx("p", { style: { margin: 0 }, children: normalizedFilter ? "No local projects match your filter." : "No local projects found." })
1082
+ }
1083
+ )
1084
+ ]
1085
+ }
1086
+ )
1087
+ ] });
1088
+ };
1089
+ const LocalProjectsPanel = (props) => {
1090
+ return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(LocalProjectsPanelContent, { ...props }) });
1091
+ };
1092
+ const LocalProjectsPanelPreview = () => {
1093
+ const { theme: theme2 } = useTheme();
1094
+ return /* @__PURE__ */ jsxs(
1095
+ "div",
1096
+ {
1097
+ style: {
1098
+ padding: "12px",
1099
+ fontSize: `${theme2.fontSizes[0]}px`,
1100
+ fontFamily: theme2.fonts.body,
1101
+ color: theme2.colors.text,
1102
+ display: "flex",
1103
+ flexDirection: "column",
1104
+ gap: "8px"
1105
+ },
1106
+ children: [
1107
+ /* @__PURE__ */ jsxs(
1108
+ "div",
1109
+ {
1110
+ style: {
1111
+ display: "flex",
1112
+ alignItems: "center",
1113
+ gap: "6px",
1114
+ fontWeight: theme2.fontWeights.semibold
1115
+ },
1116
+ children: [
1117
+ /* @__PURE__ */ jsx(
1118
+ "div",
1119
+ {
1120
+ style: {
1121
+ width: "16px",
1122
+ height: "16px",
1123
+ borderRadius: "2px",
1124
+ backgroundColor: `${theme2.colors.success || "#10b981"}40`
1125
+ }
1126
+ }
1127
+ ),
1128
+ /* @__PURE__ */ jsx("span", { children: "Local Projects" })
1129
+ ]
1130
+ }
1131
+ ),
1132
+ /* @__PURE__ */ jsx(
1133
+ "div",
1134
+ {
1135
+ style: {
1136
+ fontSize: `${theme2.fontSizes[0]}px`,
1137
+ fontFamily: theme2.fonts.body,
1138
+ color: theme2.colors.textSecondary,
1139
+ marginTop: "4px"
1140
+ },
1141
+ children: "Browse your cloned repositories sorted by recent activity"
1142
+ }
1143
+ )
1144
+ ]
1145
+ }
1146
+ );
1147
+ };
1148
+ const PANEL_ID = "industry-theme.local-projects";
1149
+ const filterProjectsTool = {
1150
+ name: "filter_projects",
1151
+ description: "Filter the local projects list by name, owner, or path",
1152
+ inputs: {
1153
+ type: "object",
1154
+ properties: {
1155
+ filter: {
1156
+ type: "string",
1157
+ description: "Search term to filter projects (matches name, owner, or path)"
1158
+ }
1159
+ },
1160
+ required: ["filter"]
1161
+ },
1162
+ outputs: {
1163
+ type: "object",
1164
+ properties: {
1165
+ success: { type: "boolean" },
1166
+ message: { type: "string" }
1167
+ }
1168
+ },
1169
+ tags: ["filter", "search", "projects"],
1170
+ tool_call_template: {
1171
+ call_template_type: "panel_event",
1172
+ event_type: `${PANEL_ID}:filter`
1173
+ }
1174
+ };
1175
+ const selectProjectTool = {
1176
+ name: "select_project",
1177
+ description: "Select a project by name or path to view its details",
1178
+ inputs: {
1179
+ type: "object",
1180
+ properties: {
1181
+ identifier: {
1182
+ type: "string",
1183
+ description: "Project name or full path to select"
1184
+ }
1185
+ },
1186
+ required: ["identifier"]
1187
+ },
1188
+ outputs: {
1189
+ type: "object",
1190
+ properties: {
1191
+ success: { type: "boolean" },
1192
+ selectedProject: { type: "string" }
1193
+ }
1194
+ },
1195
+ tags: ["select", "project", "navigation"],
1196
+ tool_call_template: {
1197
+ call_template_type: "panel_event",
1198
+ event_type: `${PANEL_ID}:select-repository`
1199
+ }
1200
+ };
1201
+ const openProjectTool = {
1202
+ name: "open_project",
1203
+ description: "Open a local project in the development workspace",
1204
+ inputs: {
1205
+ type: "object",
1206
+ properties: {
1207
+ identifier: {
1208
+ type: "string",
1209
+ description: "Project name or full path to open"
1210
+ }
1211
+ },
1212
+ required: ["identifier"]
1213
+ },
1214
+ outputs: {
1215
+ type: "object",
1216
+ properties: {
1217
+ success: { type: "boolean" },
1218
+ message: { type: "string" }
1219
+ }
1220
+ },
1221
+ tags: ["open", "project", "workspace"],
1222
+ tool_call_template: {
1223
+ call_template_type: "panel_event",
1224
+ event_type: `${PANEL_ID}:open-repository`
1225
+ }
1226
+ };
1227
+ const localProjectsPanelTools = [
1228
+ filterProjectsTool,
1229
+ selectProjectTool,
1230
+ openProjectTool
1231
+ ];
1232
+ const localProjectsPanelToolsMetadata = {
1233
+ id: PANEL_ID,
1234
+ name: "Local Projects Panel",
1235
+ description: "Tools for browsing and managing local Alexandria repositories",
1236
+ tools: localProjectsPanelTools
1237
+ };
1238
+ const panels = [
1239
+ {
1240
+ metadata: {
1241
+ id: "industry-theme.local-projects",
1242
+ name: "Local Projects",
1243
+ icon: "Folder",
1244
+ version: "0.1.0",
1245
+ author: "Industry Theme",
1246
+ description: "Browse and manage local Alexandria repositories",
1247
+ slices: ["alexandriaRepositories"],
1248
+ tools: localProjectsPanelTools
1249
+ },
1250
+ component: LocalProjectsPanel,
1251
+ onMount: async (context) => {
1252
+ console.log("Local Projects Panel mounted");
1253
+ if (context.hasSlice("alexandriaRepositories") && !context.isSliceLoading("alexandriaRepositories")) {
1254
+ await context.refresh("repository", "alexandriaRepositories");
1255
+ }
1256
+ },
1257
+ onUnmount: async (_context) => {
1258
+ console.log("Local Projects Panel unmounting");
1259
+ }
1260
+ }
1261
+ ];
1262
+ const onPackageLoad = async () => {
1263
+ console.log("Alexandria Panels package loaded");
1264
+ };
1265
+ const onPackageUnload = async () => {
1266
+ console.log("Alexandria Panels package unloading");
1267
+ };
1268
+ export {
1269
+ LocalProjectCard,
1270
+ LocalProjectsPanel,
1271
+ LocalProjectsPanelPreview,
1272
+ RepositoryAvatar,
1273
+ filterProjectsTool,
1274
+ localProjectsPanelTools,
1275
+ localProjectsPanelToolsMetadata,
1276
+ onPackageLoad,
1277
+ onPackageUnload,
1278
+ openProjectTool,
1279
+ panels,
1280
+ selectProjectTool
1281
+ };
1282
+ //# sourceMappingURL=panels.bundle.js.map