@industry-theme/github-panels 0.1.8 → 0.1.10

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.
@@ -1,4 +1,4 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import React2, { createContext, useState, useEffect, useContext, forwardRef, createElement, useRef, useCallback, useMemo } from "react";
3
3
  var terminalTheme = {
4
4
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
@@ -320,7 +320,48 @@ const createLucideIcon = (iconName, iconNode) => {
320
320
  * This source code is licensed under the ISC license.
321
321
  * See the LICENSE file in the root directory of this source tree.
322
322
  */
323
- const __iconNode$a = [
323
+ const __iconNode$o = [
324
+ ["path", { d: "M5 12h14", key: "1ays0h" }],
325
+ ["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
326
+ ];
327
+ const ArrowRight = createLucideIcon("arrow-right", __iconNode$o);
328
+ /**
329
+ * @license lucide-react v0.552.0 - ISC
330
+ *
331
+ * This source code is licensed under the ISC license.
332
+ * See the LICENSE file in the root directory of this source tree.
333
+ */
334
+ const __iconNode$n = [
335
+ ["path", { d: "m21 16-4 4-4-4", key: "f6ql7i" }],
336
+ ["path", { d: "M17 20V4", key: "1ejh1v" }],
337
+ ["path", { d: "m3 8 4-4 4 4", key: "11wl7u" }],
338
+ ["path", { d: "M7 4v16", key: "1glfcx" }]
339
+ ];
340
+ const ArrowUpDown = createLucideIcon("arrow-up-down", __iconNode$n);
341
+ /**
342
+ * @license lucide-react v0.552.0 - ISC
343
+ *
344
+ * This source code is licensed under the ISC license.
345
+ * See the LICENSE file in the root directory of this source tree.
346
+ */
347
+ const __iconNode$m = [
348
+ ["path", { d: "M12 7v14", key: "1akyts" }],
349
+ [
350
+ "path",
351
+ {
352
+ d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",
353
+ key: "ruj8y"
354
+ }
355
+ ]
356
+ ];
357
+ const BookOpen = createLucideIcon("book-open", __iconNode$m);
358
+ /**
359
+ * @license lucide-react v0.552.0 - ISC
360
+ *
361
+ * This source code is licensed under the ISC license.
362
+ * See the LICENSE file in the root directory of this source tree.
363
+ */
364
+ const __iconNode$l = [
324
365
  ["path", { d: "M10 12h4", key: "a56b0p" }],
325
366
  ["path", { d: "M10 8h4", key: "1sr2af" }],
326
367
  ["path", { d: "M14 21v-3a2 2 0 0 0-4 0v3", key: "1rgiei" }],
@@ -333,42 +374,55 @@ const __iconNode$a = [
333
374
  ],
334
375
  ["path", { d: "M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16", key: "16ra0t" }]
335
376
  ];
336
- const Building2 = createLucideIcon("building-2", __iconNode$a);
377
+ const Building2 = createLucideIcon("building-2", __iconNode$l);
337
378
  /**
338
379
  * @license lucide-react v0.552.0 - ISC
339
380
  *
340
381
  * This source code is licensed under the ISC license.
341
382
  * See the LICENSE file in the root directory of this source tree.
342
383
  */
343
- const __iconNode$9 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
344
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$9);
384
+ const __iconNode$k = [
385
+ ["path", { d: "M8 2v4", key: "1cmpym" }],
386
+ ["path", { d: "M16 2v4", key: "4m81vk" }],
387
+ ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
388
+ ["path", { d: "M3 10h18", key: "8toen8" }]
389
+ ];
390
+ const Calendar = createLucideIcon("calendar", __iconNode$k);
345
391
  /**
346
392
  * @license lucide-react v0.552.0 - ISC
347
393
  *
348
394
  * This source code is licensed under the ISC license.
349
395
  * See the LICENSE file in the root directory of this source tree.
350
396
  */
351
- const __iconNode$8 = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
352
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$8);
397
+ const __iconNode$j = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
398
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$j);
353
399
  /**
354
400
  * @license lucide-react v0.552.0 - ISC
355
401
  *
356
402
  * This source code is licensed under the ISC license.
357
403
  * See the LICENSE file in the root directory of this source tree.
358
404
  */
359
- const __iconNode$7 = [
405
+ const __iconNode$i = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
406
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$i);
407
+ /**
408
+ * @license lucide-react v0.552.0 - ISC
409
+ *
410
+ * This source code is licensed under the ISC license.
411
+ * See the LICENSE file in the root directory of this source tree.
412
+ */
413
+ const __iconNode$h = [
360
414
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
361
415
  ["path", { d: "M10 14 21 3", key: "gplh6r" }],
362
416
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
363
417
  ];
364
- const ExternalLink = createLucideIcon("external-link", __iconNode$7);
418
+ const ExternalLink = createLucideIcon("external-link", __iconNode$h);
365
419
  /**
366
420
  * @license lucide-react v0.552.0 - ISC
367
421
  *
368
422
  * This source code is licensed under the ISC license.
369
423
  * See the LICENSE file in the root directory of this source tree.
370
424
  */
371
- const __iconNode$6 = [
425
+ const __iconNode$g = [
372
426
  [
373
427
  "path",
374
428
  {
@@ -377,28 +431,57 @@ const __iconNode$6 = [
377
431
  }
378
432
  ]
379
433
  ];
380
- const Folder = createLucideIcon("folder", __iconNode$6);
434
+ const Folder = createLucideIcon("folder", __iconNode$g);
381
435
  /**
382
436
  * @license lucide-react v0.552.0 - ISC
383
437
  *
384
438
  * This source code is licensed under the ISC license.
385
439
  * See the LICENSE file in the root directory of this source tree.
386
440
  */
387
- const __iconNode$5 = [
441
+ const __iconNode$f = [
442
+ [
443
+ "path",
444
+ {
445
+ d: "M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z",
446
+ key: "sc7q7i"
447
+ }
448
+ ]
449
+ ];
450
+ const Funnel = createLucideIcon("funnel", __iconNode$f);
451
+ /**
452
+ * @license lucide-react v0.552.0 - ISC
453
+ *
454
+ * This source code is licensed under the ISC license.
455
+ * See the LICENSE file in the root directory of this source tree.
456
+ */
457
+ const __iconNode$e = [
458
+ ["line", { x1: "6", x2: "6", y1: "3", y2: "15", key: "17qcm7" }],
459
+ ["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
460
+ ["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
461
+ ["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
462
+ ];
463
+ const GitBranch = createLucideIcon("git-branch", __iconNode$e);
464
+ /**
465
+ * @license lucide-react v0.552.0 - ISC
466
+ *
467
+ * This source code is licensed under the ISC license.
468
+ * See the LICENSE file in the root directory of this source tree.
469
+ */
470
+ const __iconNode$d = [
388
471
  ["circle", { cx: "12", cy: "18", r: "3", key: "1mpf1b" }],
389
472
  ["circle", { cx: "6", cy: "6", r: "3", key: "1lh9wr" }],
390
473
  ["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
391
474
  ["path", { d: "M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9", key: "1uq4wg" }],
392
475
  ["path", { d: "M12 12v3", key: "158kv8" }]
393
476
  ];
394
- const GitFork = createLucideIcon("git-fork", __iconNode$5);
477
+ const GitFork = createLucideIcon("git-fork", __iconNode$d);
395
478
  /**
396
479
  * @license lucide-react v0.552.0 - ISC
397
480
  *
398
481
  * This source code is licensed under the ISC license.
399
482
  * See the LICENSE file in the root directory of this source tree.
400
483
  */
401
- const __iconNode$4 = [
484
+ const __iconNode$c = [
402
485
  [
403
486
  "path",
404
487
  {
@@ -408,48 +491,122 @@ const __iconNode$4 = [
408
491
  ],
409
492
  ["path", { d: "M9 18c-4.51 2-5-2-7-2", key: "9comsn" }]
410
493
  ];
411
- const Github = createLucideIcon("github", __iconNode$4);
494
+ const Github = createLucideIcon("github", __iconNode$c);
412
495
  /**
413
496
  * @license lucide-react v0.552.0 - ISC
414
497
  *
415
498
  * This source code is licensed under the ISC license.
416
499
  * See the LICENSE file in the root directory of this source tree.
417
500
  */
418
- const __iconNode$3 = [
501
+ const __iconNode$b = [
502
+ ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
503
+ ["path", { d: "M3 3v5h5", key: "1xhq8a" }],
504
+ ["path", { d: "M12 7v5l4 2", key: "1fdv2h" }]
505
+ ];
506
+ const History = createLucideIcon("history", __iconNode$b);
507
+ /**
508
+ * @license lucide-react v0.552.0 - ISC
509
+ *
510
+ * This source code is licensed under the ISC license.
511
+ * See the LICENSE file in the root directory of this source tree.
512
+ */
513
+ const __iconNode$a = [
419
514
  ["rect", { width: "18", height: "11", x: "3", y: "11", rx: "2", ry: "2", key: "1w4ew1" }],
420
515
  ["path", { d: "M7 11V7a5 5 0 0 1 10 0v4", key: "fwvmzm" }]
421
516
  ];
422
- const Lock = createLucideIcon("lock", __iconNode$3);
517
+ const Lock = createLucideIcon("lock", __iconNode$a);
423
518
  /**
424
519
  * @license lucide-react v0.552.0 - ISC
425
520
  *
426
521
  * This source code is licensed under the ISC license.
427
522
  * See the LICENSE file in the root directory of this source tree.
428
523
  */
429
- const __iconNode$2 = [
524
+ const __iconNode$9 = [
430
525
  ["path", { d: "m10 17 5-5-5-5", key: "1bsop3" }],
431
526
  ["path", { d: "M15 12H3", key: "6jk70r" }],
432
527
  ["path", { d: "M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4", key: "u53s6r" }]
433
528
  ];
434
- const LogIn = createLucideIcon("log-in", __iconNode$2);
529
+ const LogIn = createLucideIcon("log-in", __iconNode$9);
435
530
  /**
436
531
  * @license lucide-react v0.552.0 - ISC
437
532
  *
438
533
  * This source code is licensed under the ISC license.
439
534
  * See the LICENSE file in the root directory of this source tree.
440
535
  */
441
- const __iconNode$1 = [
536
+ const __iconNode$8 = [
537
+ [
538
+ "path",
539
+ {
540
+ d: "M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",
541
+ key: "18887p"
542
+ }
543
+ ]
544
+ ];
545
+ const MessageSquare = createLucideIcon("message-square", __iconNode$8);
546
+ /**
547
+ * @license lucide-react v0.552.0 - ISC
548
+ *
549
+ * This source code is licensed under the ISC license.
550
+ * See the LICENSE file in the root directory of this source tree.
551
+ */
552
+ const __iconNode$7 = [
553
+ ["rect", { x: "16", y: "16", width: "6", height: "6", rx: "1", key: "4q2zg0" }],
554
+ ["rect", { x: "2", y: "16", width: "6", height: "6", rx: "1", key: "8cvhb9" }],
555
+ ["rect", { x: "9", y: "2", width: "6", height: "6", rx: "1", key: "1egb70" }],
556
+ ["path", { d: "M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3", key: "1jsf9p" }],
557
+ ["path", { d: "M12 12V8", key: "2874zd" }]
558
+ ];
559
+ const Network = createLucideIcon("network", __iconNode$7);
560
+ /**
561
+ * @license lucide-react v0.552.0 - ISC
562
+ *
563
+ * This source code is licensed under the ISC license.
564
+ * See the LICENSE file in the root directory of this source tree.
565
+ */
566
+ const __iconNode$6 = [
567
+ ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
568
+ ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
569
+ ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
570
+ ["path", { d: "M8 16H3v5", key: "1cv678" }]
571
+ ];
572
+ const RefreshCw = createLucideIcon("refresh-cw", __iconNode$6);
573
+ /**
574
+ * @license lucide-react v0.552.0 - ISC
575
+ *
576
+ * This source code is licensed under the ISC license.
577
+ * See the LICENSE file in the root directory of this source tree.
578
+ */
579
+ const __iconNode$5 = [
442
580
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
443
581
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
444
582
  ];
445
- const Search = createLucideIcon("search", __iconNode$1);
583
+ const Search = createLucideIcon("search", __iconNode$5);
446
584
  /**
447
585
  * @license lucide-react v0.552.0 - ISC
448
586
  *
449
587
  * This source code is licensed under the ISC license.
450
588
  * See the LICENSE file in the root directory of this source tree.
451
589
  */
452
- const __iconNode = [
590
+ const __iconNode$4 = [
591
+ [
592
+ "path",
593
+ {
594
+ d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",
595
+ key: "1s2grr"
596
+ }
597
+ ],
598
+ ["path", { d: "M20 2v4", key: "1rf3ol" }],
599
+ ["path", { d: "M22 4h-4", key: "gwowj6" }],
600
+ ["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
601
+ ];
602
+ const Sparkles = createLucideIcon("sparkles", __iconNode$4);
603
+ /**
604
+ * @license lucide-react v0.552.0 - ISC
605
+ *
606
+ * This source code is licensed under the ISC license.
607
+ * See the LICENSE file in the root directory of this source tree.
608
+ */
609
+ const __iconNode$3 = [
453
610
  [
454
611
  "path",
455
612
  {
@@ -458,7 +615,43 @@ const __iconNode = [
458
615
  }
459
616
  ]
460
617
  ];
461
- const Star = createLucideIcon("star", __iconNode);
618
+ const Star = createLucideIcon("star", __iconNode$3);
619
+ /**
620
+ * @license lucide-react v0.552.0 - ISC
621
+ *
622
+ * This source code is licensed under the ISC license.
623
+ * See the LICENSE file in the root directory of this source tree.
624
+ */
625
+ const __iconNode$2 = [
626
+ ["path", { d: "M10 11v6", key: "nco0om" }],
627
+ ["path", { d: "M14 11v6", key: "outv1u" }],
628
+ ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
629
+ ["path", { d: "M3 6h18", key: "d0wm0j" }],
630
+ ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
631
+ ];
632
+ const Trash2 = createLucideIcon("trash-2", __iconNode$2);
633
+ /**
634
+ * @license lucide-react v0.552.0 - ISC
635
+ *
636
+ * This source code is licensed under the ISC license.
637
+ * See the LICENSE file in the root directory of this source tree.
638
+ */
639
+ const __iconNode$1 = [
640
+ ["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
641
+ ["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
642
+ ];
643
+ const User = createLucideIcon("user", __iconNode$1);
644
+ /**
645
+ * @license lucide-react v0.552.0 - ISC
646
+ *
647
+ * This source code is licensed under the ISC license.
648
+ * See the LICENSE file in the root directory of this source tree.
649
+ */
650
+ const __iconNode = [
651
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
652
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
653
+ ];
654
+ const X = createLucideIcon("x", __iconNode);
462
655
  function getLanguageColor(language) {
463
656
  const colors = {
464
657
  TypeScript: "#3178c6",
@@ -1545,114 +1738,1896 @@ const GitHubSearchPanelMetadata = {
1545
1738
  slices: [],
1546
1739
  surfaces: ["panel"]
1547
1740
  };
1548
- const listRepositoriesTool = {
1549
- name: "list_repositories",
1550
- description: "Get a list of GitHub repositories the user has access to, including owned repos, starred repos, and organization repos.",
1551
- inputs: {
1552
- type: "object",
1553
- properties: {},
1554
- required: []
1555
- },
1556
- outputs: {
1557
- type: "object",
1558
- properties: {
1559
- success: { type: "boolean" }
1741
+ const OwnerRepositoriesPanelContent = ({
1742
+ events,
1743
+ context,
1744
+ owner: propOwner
1745
+ }) => {
1746
+ var _a, _b;
1747
+ const { theme: theme2 } = useTheme();
1748
+ const [repositories, setRepositories] = useState([]);
1749
+ const [ownerInfo, setOwnerInfo] = useState(null);
1750
+ const [isLoading, setIsLoading] = useState(true);
1751
+ const [error, setError] = useState(null);
1752
+ const [selectedRepoId, setSelectedRepoId] = useState(null);
1753
+ const [sortField, setSortField] = useState("updated");
1754
+ const [sortOrder, setSortOrder] = useState("desc");
1755
+ const [languageFilter, setLanguageFilter] = useState(null);
1756
+ const [languages, setLanguages] = useState([]);
1757
+ const owner = propOwner || ((_b = (_a = context == null ? void 0 : context.currentScope) == null ? void 0 : _a.repository) == null ? void 0 : _b.name);
1758
+ const fetchOwnerData = useCallback(async () => {
1759
+ if (!owner) {
1760
+ setError("No owner specified");
1761
+ setIsLoading(false);
1762
+ return;
1560
1763
  }
1561
- },
1562
- tags: ["github", "repository", "list", "browse"],
1563
- tool_call_template: {
1564
- call_template_type: "panel_event",
1565
- event_type: "github:list-repositories"
1566
- }
1567
- };
1568
- const selectRepositoryTool = {
1569
- name: "select_repository",
1570
- description: 'Select a GitHub repository to view its details, README, and files. Use the full repository name in "owner/repo" format.',
1571
- inputs: {
1572
- type: "object",
1573
- properties: {
1574
- repository: {
1575
- type: "string",
1576
- description: 'The full repository name in "owner/repo" format (e.g., "facebook/react")'
1764
+ setIsLoading(true);
1765
+ setError(null);
1766
+ try {
1767
+ const userResponse = await fetch(`https://api.github.com/users/${owner}`);
1768
+ if (!userResponse.ok) {
1769
+ if (userResponse.status === 404) {
1770
+ throw new Error(`User or organization "${owner}" not found`);
1771
+ }
1772
+ throw new Error("Failed to fetch owner info");
1577
1773
  }
1578
- },
1579
- required: ["repository"]
1580
- },
1581
- outputs: {
1582
- type: "object",
1583
- properties: {
1584
- success: { type: "boolean" },
1585
- repository: { type: "string" }
1586
- }
1587
- },
1588
- tags: ["github", "repository", "select", "navigate"],
1589
- tool_call_template: {
1590
- call_template_type: "panel_event",
1591
- event_type: "repository:selected"
1592
- }
1593
- };
1594
- const previewRepositoryTool = {
1595
- name: "preview_repository",
1596
- description: "Preview a GitHub repository's README in the viewer without navigating to it.",
1597
- inputs: {
1598
- type: "object",
1599
- properties: {
1600
- repository: {
1601
- type: "string",
1602
- description: 'The full repository name in "owner/repo" format (e.g., "facebook/react")'
1774
+ const userData = await userResponse.json();
1775
+ setOwnerInfo({
1776
+ login: userData.login,
1777
+ avatar_url: userData.avatar_url,
1778
+ name: userData.name,
1779
+ bio: userData.bio,
1780
+ type: userData.type,
1781
+ public_repos: userData.public_repos,
1782
+ followers: userData.followers,
1783
+ following: userData.following
1784
+ });
1785
+ const reposResponse = await fetch(
1786
+ `https://api.github.com/users/${owner}/repos?per_page=100&sort=updated`
1787
+ );
1788
+ if (!reposResponse.ok) {
1789
+ throw new Error("Failed to fetch repositories");
1603
1790
  }
1604
- },
1605
- required: ["repository"]
1606
- },
1607
- outputs: {
1608
- type: "object",
1609
- properties: {
1610
- success: { type: "boolean" }
1791
+ const reposData = await reposResponse.json();
1792
+ setRepositories(reposData);
1793
+ const uniqueLanguages = [...new Set(
1794
+ reposData.map((r) => r.language).filter((lang) => lang !== null)
1795
+ )].sort();
1796
+ setLanguages(uniqueLanguages);
1797
+ } catch (err) {
1798
+ setError(err instanceof Error ? err.message : "Failed to load data");
1799
+ } finally {
1800
+ setIsLoading(false);
1611
1801
  }
1612
- },
1613
- tags: ["github", "repository", "preview", "readme"],
1614
- tool_call_template: {
1615
- call_template_type: "panel_event",
1616
- event_type: "repository:preview"
1617
- }
1618
- };
1619
- const searchRepositoriesTool = {
1620
- name: "search_repositories",
1621
- description: "Search through the user's GitHub repositories by name, description, or language.",
1622
- inputs: {
1623
- type: "object",
1624
- properties: {
1625
- query: {
1626
- type: "string",
1627
- description: "The search query to filter repositories"
1628
- }
1629
- },
1630
- required: ["query"]
1631
- },
1632
- outputs: {
1633
- type: "object",
1634
- properties: {
1635
- success: { type: "boolean" }
1802
+ }, [owner]);
1803
+ useEffect(() => {
1804
+ fetchOwnerData();
1805
+ }, [fetchOwnerData]);
1806
+ const sortedAndFilteredRepos = React2.useMemo(() => {
1807
+ let filtered = repositories;
1808
+ if (languageFilter) {
1809
+ filtered = filtered.filter((r) => r.language === languageFilter);
1636
1810
  }
1637
- },
1638
- tags: ["github", "repository", "search", "filter"],
1639
- tool_call_template: {
1640
- call_template_type: "panel_event",
1641
- event_type: "github:search-repositories"
1642
- }
1643
- };
1644
- const openRepositorySwitcherTool = {
1645
- name: "open_repository_switcher",
1646
- description: "Open the repository switcher modal to browse and select a different repository.",
1647
- inputs: {
1648
- type: "object",
1649
- properties: {},
1650
- required: []
1651
- },
1652
- outputs: {
1653
- type: "object",
1654
- properties: {
1655
- success: { type: "boolean" }
1811
+ return [...filtered].sort((a, b) => {
1812
+ let comparison = 0;
1813
+ switch (sortField) {
1814
+ case "updated":
1815
+ comparison = new Date(b.updated_at || 0).getTime() - new Date(a.updated_at || 0).getTime();
1816
+ break;
1817
+ case "stars":
1818
+ comparison = (b.stargazers_count || 0) - (a.stargazers_count || 0);
1819
+ break;
1820
+ case "name":
1821
+ comparison = a.name.localeCompare(b.name);
1822
+ break;
1823
+ case "created":
1824
+ comparison = new Date(b.created_at || 0).getTime() - new Date(a.created_at || 0).getTime();
1825
+ break;
1826
+ }
1827
+ return sortOrder === "desc" ? comparison : -comparison;
1828
+ });
1829
+ }, [repositories, sortField, sortOrder, languageFilter]);
1830
+ const handleSelectRepository = (repo) => {
1831
+ setSelectedRepoId(repo.id);
1832
+ events.emit({
1833
+ type: "repository:preview",
1834
+ source: "owner-repositories-panel",
1835
+ timestamp: Date.now(),
1836
+ payload: {
1837
+ repository: repo,
1838
+ source: "click"
1839
+ }
1840
+ });
1841
+ };
1842
+ const handleOpenRepository = (repo) => {
1843
+ events.emit({
1844
+ type: "repository:selected",
1845
+ source: "owner-repositories-panel",
1846
+ timestamp: Date.now(),
1847
+ payload: {
1848
+ repository: repo,
1849
+ source: "click"
1850
+ }
1851
+ });
1852
+ };
1853
+ const formatNumber = (num) => {
1854
+ if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
1855
+ if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
1856
+ return num.toString();
1857
+ };
1858
+ const formatRelativeTime = (dateString) => {
1859
+ const date = new Date(dateString);
1860
+ const now = /* @__PURE__ */ new Date();
1861
+ const diffMs = now.getTime() - date.getTime();
1862
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
1863
+ if (diffDays === 0) return "today";
1864
+ if (diffDays === 1) return "yesterday";
1865
+ if (diffDays < 7) return `${diffDays} days ago`;
1866
+ if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;
1867
+ if (diffDays < 365) return `${Math.floor(diffDays / 30)} months ago`;
1868
+ return `${Math.floor(diffDays / 365)} years ago`;
1869
+ };
1870
+ const handleSort = (field) => {
1871
+ if (sortField === field) {
1872
+ setSortOrder((prev) => prev === "desc" ? "asc" : "desc");
1873
+ } else {
1874
+ setSortField(field);
1875
+ setSortOrder("desc");
1876
+ }
1877
+ };
1878
+ return /* @__PURE__ */ jsxs(
1879
+ "div",
1880
+ {
1881
+ style: {
1882
+ height: "100%",
1883
+ display: "flex",
1884
+ flexDirection: "column",
1885
+ backgroundColor: theme2.colors.background,
1886
+ color: theme2.colors.text,
1887
+ fontFamily: theme2.fonts.body
1888
+ },
1889
+ children: [
1890
+ /* @__PURE__ */ jsx(
1891
+ "div",
1892
+ {
1893
+ style: {
1894
+ padding: "16px",
1895
+ borderBottom: `1px solid ${theme2.colors.border}`,
1896
+ display: "flex",
1897
+ alignItems: "center",
1898
+ gap: "12px"
1899
+ },
1900
+ children: ownerInfo ? /* @__PURE__ */ jsxs(Fragment, { children: [
1901
+ /* @__PURE__ */ jsx(
1902
+ "img",
1903
+ {
1904
+ src: ownerInfo.avatar_url,
1905
+ alt: ownerInfo.login,
1906
+ style: {
1907
+ width: 48,
1908
+ height: 48,
1909
+ borderRadius: ownerInfo.type === "Organization" ? 8 : "50%",
1910
+ border: `2px solid ${theme2.colors.border}`
1911
+ }
1912
+ }
1913
+ ),
1914
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
1915
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
1916
+ /* @__PURE__ */ jsx(
1917
+ "h2",
1918
+ {
1919
+ style: {
1920
+ margin: 0,
1921
+ fontSize: `${theme2.fontSizes[4]}px`,
1922
+ fontWeight: theme2.fontWeights.bold
1923
+ },
1924
+ children: ownerInfo.name || ownerInfo.login
1925
+ }
1926
+ ),
1927
+ ownerInfo.type === "Organization" ? /* @__PURE__ */ jsx(Building2, { size: 16, color: theme2.colors.textSecondary }) : /* @__PURE__ */ jsx(User, { size: 16, color: theme2.colors.textSecondary })
1928
+ ] }),
1929
+ ownerInfo.bio && /* @__PURE__ */ jsx(
1930
+ "p",
1931
+ {
1932
+ style: {
1933
+ margin: "4px 0 0",
1934
+ fontSize: `${theme2.fontSizes[1]}px`,
1935
+ color: theme2.colors.textSecondary
1936
+ },
1937
+ children: ownerInfo.bio
1938
+ }
1939
+ ),
1940
+ /* @__PURE__ */ jsxs(
1941
+ "div",
1942
+ {
1943
+ style: {
1944
+ display: "flex",
1945
+ gap: "12px",
1946
+ marginTop: "4px",
1947
+ fontSize: `${theme2.fontSizes[1]}px`,
1948
+ color: theme2.colors.textSecondary
1949
+ },
1950
+ children: [
1951
+ /* @__PURE__ */ jsxs("span", { children: [
1952
+ ownerInfo.public_repos,
1953
+ " repositories"
1954
+ ] }),
1955
+ ownerInfo.followers !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
1956
+ formatNumber(ownerInfo.followers),
1957
+ " followers"
1958
+ ] })
1959
+ ]
1960
+ }
1961
+ )
1962
+ ] }),
1963
+ /* @__PURE__ */ jsx(
1964
+ "button",
1965
+ {
1966
+ onClick: fetchOwnerData,
1967
+ style: {
1968
+ padding: "8px",
1969
+ borderRadius: "6px",
1970
+ border: `1px solid ${theme2.colors.border}`,
1971
+ background: "transparent",
1972
+ cursor: "pointer",
1973
+ color: theme2.colors.textSecondary
1974
+ },
1975
+ title: "Refresh",
1976
+ children: /* @__PURE__ */ jsx(RefreshCw, { size: 16 })
1977
+ }
1978
+ )
1979
+ ] }) : /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
1980
+ /* @__PURE__ */ jsx(Github, { size: 24, color: theme2.colors.primary }),
1981
+ /* @__PURE__ */ jsx(
1982
+ "h2",
1983
+ {
1984
+ style: {
1985
+ margin: 0,
1986
+ fontSize: `${theme2.fontSizes[3]}px`,
1987
+ fontWeight: theme2.fontWeights.semibold
1988
+ },
1989
+ children: owner || "Repositories"
1990
+ }
1991
+ )
1992
+ ] })
1993
+ }
1994
+ ),
1995
+ !isLoading && !error && repositories.length > 0 && /* @__PURE__ */ jsxs(
1996
+ "div",
1997
+ {
1998
+ style: {
1999
+ padding: "8px 16px",
2000
+ borderBottom: `1px solid ${theme2.colors.border}`,
2001
+ display: "flex",
2002
+ alignItems: "center",
2003
+ gap: "8px",
2004
+ flexWrap: "wrap"
2005
+ },
2006
+ children: [
2007
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2008
+ /* @__PURE__ */ jsx(ArrowUpDown, { size: 14, color: theme2.colors.textSecondary }),
2009
+ ["updated", "stars", "name"].map((field) => /* @__PURE__ */ jsxs(
2010
+ "button",
2011
+ {
2012
+ onClick: () => handleSort(field),
2013
+ style: {
2014
+ padding: "4px 8px",
2015
+ borderRadius: "4px",
2016
+ border: "none",
2017
+ background: sortField === field ? theme2.colors.primary : theme2.colors.backgroundSecondary,
2018
+ color: sortField === field ? theme2.colors.background : theme2.colors.text,
2019
+ fontSize: `${theme2.fontSizes[1]}px`,
2020
+ cursor: "pointer",
2021
+ textTransform: "capitalize"
2022
+ },
2023
+ children: [
2024
+ field,
2025
+ sortField === field && (sortOrder === "desc" ? " ↓" : " ↑")
2026
+ ]
2027
+ },
2028
+ field
2029
+ ))
2030
+ ] }),
2031
+ languages.length > 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px", marginLeft: "auto" }, children: [
2032
+ /* @__PURE__ */ jsx(Funnel, { size: 14, color: theme2.colors.textSecondary }),
2033
+ /* @__PURE__ */ jsxs(
2034
+ "select",
2035
+ {
2036
+ value: languageFilter || "",
2037
+ onChange: (e) => setLanguageFilter(e.target.value || null),
2038
+ style: {
2039
+ padding: "4px 8px",
2040
+ borderRadius: "4px",
2041
+ border: `1px solid ${theme2.colors.border}`,
2042
+ background: theme2.colors.backgroundSecondary,
2043
+ color: theme2.colors.text,
2044
+ fontSize: `${theme2.fontSizes[1]}px`,
2045
+ cursor: "pointer"
2046
+ },
2047
+ children: [
2048
+ /* @__PURE__ */ jsx("option", { value: "", children: "All languages" }),
2049
+ languages.map((lang) => /* @__PURE__ */ jsx("option", { value: lang, children: lang }, lang))
2050
+ ]
2051
+ }
2052
+ )
2053
+ ] })
2054
+ ]
2055
+ }
2056
+ ),
2057
+ isLoading && /* @__PURE__ */ jsxs(
2058
+ "div",
2059
+ {
2060
+ style: {
2061
+ flex: 1,
2062
+ display: "flex",
2063
+ flexDirection: "column",
2064
+ alignItems: "center",
2065
+ justifyContent: "center",
2066
+ gap: "16px",
2067
+ color: theme2.colors.textSecondary
2068
+ },
2069
+ children: [
2070
+ /* @__PURE__ */ jsx(
2071
+ "div",
2072
+ {
2073
+ style: {
2074
+ width: 32,
2075
+ height: 32,
2076
+ border: `3px solid ${theme2.colors.border}`,
2077
+ borderTopColor: theme2.colors.primary,
2078
+ borderRadius: "50%",
2079
+ animation: "spin 1s linear infinite"
2080
+ }
2081
+ }
2082
+ ),
2083
+ /* @__PURE__ */ jsx("span", { children: "Loading repositories..." })
2084
+ ]
2085
+ }
2086
+ ),
2087
+ error && /* @__PURE__ */ jsxs(
2088
+ "div",
2089
+ {
2090
+ style: {
2091
+ flex: 1,
2092
+ display: "flex",
2093
+ flexDirection: "column",
2094
+ alignItems: "center",
2095
+ justifyContent: "center",
2096
+ padding: "32px",
2097
+ textAlign: "center"
2098
+ },
2099
+ children: [
2100
+ /* @__PURE__ */ jsx(
2101
+ "div",
2102
+ {
2103
+ style: {
2104
+ padding: "16px 24px",
2105
+ borderRadius: "8px",
2106
+ backgroundColor: `${theme2.colors.error}15`,
2107
+ color: theme2.colors.error,
2108
+ marginBottom: "16px"
2109
+ },
2110
+ children: error
2111
+ }
2112
+ ),
2113
+ /* @__PURE__ */ jsx(
2114
+ "button",
2115
+ {
2116
+ onClick: fetchOwnerData,
2117
+ style: {
2118
+ padding: "8px 16px",
2119
+ borderRadius: "6px",
2120
+ border: "none",
2121
+ background: theme2.colors.primary,
2122
+ color: theme2.colors.background,
2123
+ cursor: "pointer",
2124
+ fontWeight: theme2.fontWeights.medium
2125
+ },
2126
+ children: "Try Again"
2127
+ }
2128
+ )
2129
+ ]
2130
+ }
2131
+ ),
2132
+ !isLoading && !error && repositories.length === 0 && /* @__PURE__ */ jsxs(
2133
+ "div",
2134
+ {
2135
+ style: {
2136
+ flex: 1,
2137
+ display: "flex",
2138
+ flexDirection: "column",
2139
+ alignItems: "center",
2140
+ justifyContent: "center",
2141
+ padding: "32px",
2142
+ color: theme2.colors.textSecondary
2143
+ },
2144
+ children: [
2145
+ /* @__PURE__ */ jsx(Github, { size: 48, color: theme2.colors.border, style: { marginBottom: 16 } }),
2146
+ /* @__PURE__ */ jsx("p", { style: { margin: 0 }, children: "No public repositories found" })
2147
+ ]
2148
+ }
2149
+ ),
2150
+ !isLoading && !error && sortedAndFilteredRepos.length > 0 && /* @__PURE__ */ jsx(
2151
+ "div",
2152
+ {
2153
+ style: {
2154
+ flex: 1,
2155
+ overflowY: "auto",
2156
+ padding: "8px"
2157
+ },
2158
+ children: sortedAndFilteredRepos.map((repo) => /* @__PURE__ */ jsxs(
2159
+ "button",
2160
+ {
2161
+ type: "button",
2162
+ onClick: () => handleSelectRepository(repo),
2163
+ onDoubleClick: () => handleOpenRepository(repo),
2164
+ style: {
2165
+ width: "100%",
2166
+ padding: "12px",
2167
+ margin: "4px 0",
2168
+ borderRadius: "8px",
2169
+ border: selectedRepoId === repo.id ? `2px solid ${theme2.colors.primary}` : `1px solid ${theme2.colors.border}`,
2170
+ backgroundColor: selectedRepoId === repo.id ? `${theme2.colors.primary}10` : theme2.colors.surface,
2171
+ cursor: "pointer",
2172
+ textAlign: "left",
2173
+ display: "flex",
2174
+ flexDirection: "column",
2175
+ gap: "8px",
2176
+ transition: "all 0.15s ease"
2177
+ },
2178
+ children: [
2179
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
2180
+ /* @__PURE__ */ jsx(
2181
+ "span",
2182
+ {
2183
+ style: {
2184
+ fontSize: `${theme2.fontSizes[2]}px`,
2185
+ fontWeight: theme2.fontWeights.semibold,
2186
+ color: theme2.colors.primary
2187
+ },
2188
+ children: repo.name
2189
+ }
2190
+ ),
2191
+ repo.archived && /* @__PURE__ */ jsx(
2192
+ "span",
2193
+ {
2194
+ style: {
2195
+ fontSize: `${theme2.fontSizes[0]}px`,
2196
+ padding: "2px 6px",
2197
+ borderRadius: "4px",
2198
+ backgroundColor: theme2.colors.warning + "20",
2199
+ color: theme2.colors.warning
2200
+ },
2201
+ children: "Archived"
2202
+ }
2203
+ ),
2204
+ repo.fork && /* @__PURE__ */ jsx(
2205
+ "span",
2206
+ {
2207
+ style: {
2208
+ fontSize: `${theme2.fontSizes[0]}px`,
2209
+ padding: "2px 6px",
2210
+ borderRadius: "4px",
2211
+ backgroundColor: theme2.colors.backgroundTertiary,
2212
+ color: theme2.colors.textSecondary
2213
+ },
2214
+ children: "Fork"
2215
+ }
2216
+ )
2217
+ ] }),
2218
+ repo.description && /* @__PURE__ */ jsx(
2219
+ "p",
2220
+ {
2221
+ style: {
2222
+ margin: 0,
2223
+ fontSize: `${theme2.fontSizes[1]}px`,
2224
+ color: theme2.colors.textSecondary,
2225
+ overflow: "hidden",
2226
+ textOverflow: "ellipsis",
2227
+ display: "-webkit-box",
2228
+ WebkitLineClamp: 2,
2229
+ WebkitBoxOrient: "vertical"
2230
+ },
2231
+ children: repo.description
2232
+ }
2233
+ ),
2234
+ /* @__PURE__ */ jsxs(
2235
+ "div",
2236
+ {
2237
+ style: {
2238
+ display: "flex",
2239
+ alignItems: "center",
2240
+ gap: "16px",
2241
+ fontSize: `${theme2.fontSizes[1]}px`,
2242
+ color: theme2.colors.textSecondary
2243
+ },
2244
+ children: [
2245
+ repo.language && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2246
+ /* @__PURE__ */ jsx(
2247
+ "span",
2248
+ {
2249
+ style: {
2250
+ width: 10,
2251
+ height: 10,
2252
+ borderRadius: "50%",
2253
+ backgroundColor: theme2.colors.info
2254
+ }
2255
+ }
2256
+ ),
2257
+ repo.language
2258
+ ] }),
2259
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2260
+ /* @__PURE__ */ jsx(Star, { size: 14 }),
2261
+ formatNumber(repo.stargazers_count || 0)
2262
+ ] }),
2263
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2264
+ /* @__PURE__ */ jsx(GitFork, { size: 14 }),
2265
+ formatNumber(repo.forks_count || 0)
2266
+ ] }),
2267
+ repo.updated_at && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2268
+ /* @__PURE__ */ jsx(Calendar, { size: 14 }),
2269
+ formatRelativeTime(repo.updated_at)
2270
+ ] }),
2271
+ /* @__PURE__ */ jsx(
2272
+ "a",
2273
+ {
2274
+ href: repo.html_url,
2275
+ target: "_blank",
2276
+ rel: "noopener noreferrer",
2277
+ onClick: (e) => e.stopPropagation(),
2278
+ style: {
2279
+ marginLeft: "auto",
2280
+ color: theme2.colors.textSecondary,
2281
+ display: "flex",
2282
+ alignItems: "center"
2283
+ },
2284
+ children: /* @__PURE__ */ jsx(ExternalLink, { size: 14 })
2285
+ }
2286
+ )
2287
+ ]
2288
+ }
2289
+ )
2290
+ ]
2291
+ },
2292
+ repo.id
2293
+ ))
2294
+ }
2295
+ ),
2296
+ !isLoading && !error && repositories.length > 0 && sortedAndFilteredRepos.length === 0 && /* @__PURE__ */ jsxs(
2297
+ "div",
2298
+ {
2299
+ style: {
2300
+ flex: 1,
2301
+ display: "flex",
2302
+ flexDirection: "column",
2303
+ alignItems: "center",
2304
+ justifyContent: "center",
2305
+ padding: "32px",
2306
+ color: theme2.colors.textSecondary
2307
+ },
2308
+ children: [
2309
+ /* @__PURE__ */ jsx(Funnel, { size: 48, color: theme2.colors.border, style: { marginBottom: 16 } }),
2310
+ /* @__PURE__ */ jsx("p", { style: { margin: 0 }, children: "No repositories match the current filter" }),
2311
+ /* @__PURE__ */ jsx(
2312
+ "button",
2313
+ {
2314
+ onClick: () => setLanguageFilter(null),
2315
+ style: {
2316
+ marginTop: "12px",
2317
+ padding: "8px 16px",
2318
+ borderRadius: "6px",
2319
+ border: `1px solid ${theme2.colors.border}`,
2320
+ background: "transparent",
2321
+ color: theme2.colors.text,
2322
+ cursor: "pointer"
2323
+ },
2324
+ children: "Clear filter"
2325
+ }
2326
+ )
2327
+ ]
2328
+ }
2329
+ ),
2330
+ /* @__PURE__ */ jsx("style", { children: `
2331
+ @keyframes spin {
2332
+ to { transform: rotate(360deg); }
2333
+ }
2334
+ ` })
2335
+ ]
2336
+ }
2337
+ );
2338
+ };
2339
+ const OwnerRepositoriesPanel = (props) => {
2340
+ return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(OwnerRepositoriesPanelContent, { ...props }) });
2341
+ };
2342
+ const OwnerRepositoriesPanelMetadata = {
2343
+ id: "owner-repositories",
2344
+ name: "Owner Repositories",
2345
+ description: "Browse repositories for a GitHub user or organization",
2346
+ icon: "github",
2347
+ version: "0.1.0",
2348
+ slices: [],
2349
+ surfaces: ["panel"]
2350
+ };
2351
+ const STORAGE_KEY = "recent-repositories";
2352
+ const OWNERS_STORAGE_KEY = "recent-owners";
2353
+ const MAX_RECENT_ITEMS = 50;
2354
+ function loadRecentRepositories() {
2355
+ try {
2356
+ const stored = localStorage.getItem(STORAGE_KEY);
2357
+ if (stored) {
2358
+ const items = JSON.parse(stored);
2359
+ return items.map((item) => ({ ...item, type: "repository" }));
2360
+ }
2361
+ } catch (err) {
2362
+ console.error("Failed to load recent repositories:", err);
2363
+ }
2364
+ return [];
2365
+ }
2366
+ function loadRecentOwners() {
2367
+ try {
2368
+ const stored = localStorage.getItem(OWNERS_STORAGE_KEY);
2369
+ if (stored) {
2370
+ return JSON.parse(stored);
2371
+ }
2372
+ } catch (err) {
2373
+ console.error("Failed to load recent owners:", err);
2374
+ }
2375
+ return [];
2376
+ }
2377
+ function saveRecentRepositories(repos) {
2378
+ try {
2379
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(repos));
2380
+ } catch (err) {
2381
+ console.error("Failed to save recent repositories:", err);
2382
+ }
2383
+ }
2384
+ function saveRecentOwners(owners) {
2385
+ try {
2386
+ localStorage.setItem(OWNERS_STORAGE_KEY, JSON.stringify(owners));
2387
+ } catch (err) {
2388
+ console.error("Failed to save recent owners:", err);
2389
+ }
2390
+ }
2391
+ function addRecentRepository(repo) {
2392
+ const recent = loadRecentRepositories();
2393
+ const filtered = recent.filter((r) => r.id !== repo.id);
2394
+ const newEntry = {
2395
+ type: "repository",
2396
+ id: repo.id,
2397
+ name: repo.name,
2398
+ full_name: repo.full_name,
2399
+ owner: {
2400
+ login: repo.owner.login,
2401
+ avatar_url: repo.owner.avatar_url
2402
+ },
2403
+ description: repo.description,
2404
+ language: repo.language,
2405
+ html_url: repo.html_url,
2406
+ stargazers_count: repo.stargazers_count,
2407
+ forks_count: repo.forks_count,
2408
+ visitedAt: Date.now()
2409
+ };
2410
+ const updated = [newEntry, ...filtered].slice(0, MAX_RECENT_ITEMS);
2411
+ saveRecentRepositories(updated);
2412
+ window.dispatchEvent(new CustomEvent("recent-items-updated"));
2413
+ }
2414
+ function addRecentOwner(owner) {
2415
+ const recent = loadRecentOwners();
2416
+ const filtered = recent.filter((o) => o.id !== owner.id);
2417
+ const newEntry = {
2418
+ type: "owner",
2419
+ id: owner.id,
2420
+ login: owner.login,
2421
+ avatar_url: owner.avatar_url,
2422
+ name: owner.name,
2423
+ bio: owner.bio,
2424
+ ownerType: owner.type,
2425
+ public_repos: owner.public_repos,
2426
+ followers: owner.followers,
2427
+ visitedAt: Date.now()
2428
+ };
2429
+ const updated = [newEntry, ...filtered].slice(0, MAX_RECENT_ITEMS);
2430
+ saveRecentOwners(updated);
2431
+ window.dispatchEvent(new CustomEvent("recent-items-updated"));
2432
+ }
2433
+ const RecentRepositoriesPanelContent = ({
2434
+ events,
2435
+ onNavigate
2436
+ }) => {
2437
+ const { theme: theme2 } = useTheme();
2438
+ const [items, setItems] = useState([]);
2439
+ const [selectedId, setSelectedId] = useState(null);
2440
+ const [hoveredId, setHoveredId] = useState(null);
2441
+ const [filter, setFilter] = useState("all");
2442
+ const getItemId = (item) => {
2443
+ return item.type === "repository" ? `repo-${item.id}` : `owner-${item.id}`;
2444
+ };
2445
+ useEffect(() => {
2446
+ const loadItems = () => {
2447
+ const repos = loadRecentRepositories();
2448
+ const owners = loadRecentOwners();
2449
+ const merged = [...repos, ...owners].sort(
2450
+ (a, b) => b.visitedAt - a.visitedAt
2451
+ );
2452
+ setItems(merged);
2453
+ };
2454
+ loadItems();
2455
+ const handleUpdate = () => loadItems();
2456
+ window.addEventListener("recent-items-updated", handleUpdate);
2457
+ window.addEventListener("recent-repositories-updated", handleUpdate);
2458
+ return () => {
2459
+ window.removeEventListener("recent-items-updated", handleUpdate);
2460
+ window.removeEventListener("recent-repositories-updated", handleUpdate);
2461
+ };
2462
+ }, []);
2463
+ const filteredItems = items.filter((item) => {
2464
+ if (filter === "all") return true;
2465
+ if (filter === "repos") return item.type === "repository";
2466
+ if (filter === "owners") return item.type === "owner";
2467
+ return true;
2468
+ });
2469
+ const formatRelativeTime = (timestamp) => {
2470
+ const now = Date.now();
2471
+ const diffMs = now - timestamp;
2472
+ const diffMins = Math.floor(diffMs / (1e3 * 60));
2473
+ const diffHours = Math.floor(diffMs / (1e3 * 60 * 60));
2474
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
2475
+ if (diffMins < 1) return "just now";
2476
+ if (diffMins < 60) return `${diffMins}m ago`;
2477
+ if (diffHours < 24) return `${diffHours}h ago`;
2478
+ if (diffDays === 1) return "yesterday";
2479
+ if (diffDays < 7) return `${diffDays}d ago`;
2480
+ if (diffDays < 30) return `${Math.floor(diffDays / 7)}w ago`;
2481
+ return `${Math.floor(diffDays / 30)}mo ago`;
2482
+ };
2483
+ const formatNumber = (num) => {
2484
+ if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
2485
+ if (num >= 1e3) return `${(num / 1e3).toFixed(1)}K`;
2486
+ return num.toString();
2487
+ };
2488
+ const handleSelectRepository = useCallback((repo) => {
2489
+ setSelectedId(getItemId(repo));
2490
+ const githubRepo = {
2491
+ id: repo.id,
2492
+ name: repo.name,
2493
+ full_name: repo.full_name,
2494
+ owner: {
2495
+ login: repo.owner.login,
2496
+ avatar_url: repo.owner.avatar_url
2497
+ },
2498
+ private: false,
2499
+ html_url: repo.html_url,
2500
+ description: repo.description,
2501
+ fork: false,
2502
+ clone_url: `https://github.com/${repo.full_name}.git`,
2503
+ language: repo.language,
2504
+ default_branch: "main",
2505
+ stargazers_count: repo.stargazers_count,
2506
+ forks_count: repo.forks_count
2507
+ };
2508
+ events.emit({
2509
+ type: "repository:preview",
2510
+ source: "recent-repositories-panel",
2511
+ timestamp: Date.now(),
2512
+ payload: {
2513
+ repository: githubRepo,
2514
+ source: "click"
2515
+ }
2516
+ });
2517
+ }, [events]);
2518
+ const handleOpenRepository = useCallback((repo) => {
2519
+ if (onNavigate) {
2520
+ onNavigate(`/${repo.full_name}`);
2521
+ } else {
2522
+ const githubRepo = {
2523
+ id: repo.id,
2524
+ name: repo.name,
2525
+ full_name: repo.full_name,
2526
+ owner: {
2527
+ login: repo.owner.login,
2528
+ avatar_url: repo.owner.avatar_url
2529
+ },
2530
+ private: false,
2531
+ html_url: repo.html_url,
2532
+ description: repo.description,
2533
+ fork: false,
2534
+ clone_url: `https://github.com/${repo.full_name}.git`,
2535
+ language: repo.language,
2536
+ default_branch: "main",
2537
+ stargazers_count: repo.stargazers_count,
2538
+ forks_count: repo.forks_count
2539
+ };
2540
+ events.emit({
2541
+ type: "repository:selected",
2542
+ source: "recent-repositories-panel",
2543
+ timestamp: Date.now(),
2544
+ payload: {
2545
+ repository: githubRepo,
2546
+ source: "click"
2547
+ }
2548
+ });
2549
+ }
2550
+ }, [events, onNavigate]);
2551
+ const handleSelectOwner = useCallback((owner) => {
2552
+ setSelectedId(getItemId(owner));
2553
+ events.emit({
2554
+ type: "owner:preview",
2555
+ source: "recent-repositories-panel",
2556
+ timestamp: Date.now(),
2557
+ payload: { owner }
2558
+ });
2559
+ }, [events]);
2560
+ const handleOpenOwner = useCallback((owner) => {
2561
+ if (onNavigate) {
2562
+ onNavigate(`/${owner.login}`);
2563
+ } else {
2564
+ events.emit({
2565
+ type: "owner:selected",
2566
+ source: "recent-repositories-panel",
2567
+ timestamp: Date.now(),
2568
+ payload: { owner }
2569
+ });
2570
+ }
2571
+ }, [events, onNavigate]);
2572
+ const handleRemoveItem = useCallback((item, e) => {
2573
+ e.stopPropagation();
2574
+ if (item.type === "repository") {
2575
+ const repos = loadRecentRepositories().filter((r) => r.id !== item.id);
2576
+ saveRecentRepositories(repos);
2577
+ } else {
2578
+ const owners = loadRecentOwners().filter((o) => o.id !== item.id);
2579
+ saveRecentOwners(owners);
2580
+ }
2581
+ setItems((prev) => prev.filter((i) => getItemId(i) !== getItemId(item)));
2582
+ if (selectedId === getItemId(item)) {
2583
+ setSelectedId(null);
2584
+ }
2585
+ }, [selectedId]);
2586
+ const handleClearAll = useCallback(() => {
2587
+ if (filter === "all" || filter === "repos") {
2588
+ saveRecentRepositories([]);
2589
+ }
2590
+ if (filter === "all" || filter === "owners") {
2591
+ saveRecentOwners([]);
2592
+ }
2593
+ if (filter === "all") {
2594
+ setItems([]);
2595
+ } else {
2596
+ setItems((prev) => prev.filter(
2597
+ (item) => filter === "repos" ? item.type !== "repository" : item.type !== "owner"
2598
+ ));
2599
+ }
2600
+ setSelectedId(null);
2601
+ }, [filter]);
2602
+ return /* @__PURE__ */ jsxs(
2603
+ "div",
2604
+ {
2605
+ style: {
2606
+ height: "100%",
2607
+ display: "flex",
2608
+ flexDirection: "column",
2609
+ backgroundColor: theme2.colors.background,
2610
+ color: theme2.colors.text,
2611
+ fontFamily: theme2.fonts.body
2612
+ },
2613
+ children: [
2614
+ /* @__PURE__ */ jsxs(
2615
+ "div",
2616
+ {
2617
+ style: {
2618
+ padding: "16px",
2619
+ borderBottom: `1px solid ${theme2.colors.border}`,
2620
+ display: "flex",
2621
+ alignItems: "center",
2622
+ justifyContent: "space-between"
2623
+ },
2624
+ children: [
2625
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
2626
+ /* @__PURE__ */ jsx(History, { size: 24, color: theme2.colors.primary }),
2627
+ /* @__PURE__ */ jsx(
2628
+ "h2",
2629
+ {
2630
+ style: {
2631
+ margin: 0,
2632
+ fontSize: `${theme2.fontSizes[3]}px`,
2633
+ fontWeight: theme2.fontWeights.semibold
2634
+ },
2635
+ children: "Recent"
2636
+ }
2637
+ )
2638
+ ] }),
2639
+ items.length > 0 && /* @__PURE__ */ jsxs(
2640
+ "button",
2641
+ {
2642
+ onClick: handleClearAll,
2643
+ style: {
2644
+ padding: "6px 12px",
2645
+ borderRadius: "6px",
2646
+ border: `1px solid ${theme2.colors.border}`,
2647
+ background: "transparent",
2648
+ cursor: "pointer",
2649
+ color: theme2.colors.textSecondary,
2650
+ fontSize: `${theme2.fontSizes[1]}px`,
2651
+ display: "flex",
2652
+ alignItems: "center",
2653
+ gap: "6px"
2654
+ },
2655
+ title: "Clear history",
2656
+ children: [
2657
+ /* @__PURE__ */ jsx(Trash2, { size: 14 }),
2658
+ "Clear"
2659
+ ]
2660
+ }
2661
+ )
2662
+ ]
2663
+ }
2664
+ ),
2665
+ items.length > 0 && /* @__PURE__ */ jsx(
2666
+ "div",
2667
+ {
2668
+ style: {
2669
+ padding: "8px 16px",
2670
+ borderBottom: `1px solid ${theme2.colors.border}`,
2671
+ display: "flex",
2672
+ gap: "4px"
2673
+ },
2674
+ children: [
2675
+ { key: "all", label: "All" },
2676
+ { key: "repos", label: "Repositories" },
2677
+ { key: "owners", label: "Owners" }
2678
+ ].map(({ key, label }) => /* @__PURE__ */ jsx(
2679
+ "button",
2680
+ {
2681
+ onClick: () => setFilter(key),
2682
+ style: {
2683
+ padding: "6px 12px",
2684
+ borderRadius: "6px",
2685
+ border: "none",
2686
+ background: filter === key ? theme2.colors.primary : theme2.colors.backgroundSecondary,
2687
+ color: filter === key ? "#fff" : theme2.colors.text,
2688
+ fontSize: `${theme2.fontSizes[1]}px`,
2689
+ cursor: "pointer",
2690
+ fontWeight: filter === key ? theme2.fontWeights.semibold : theme2.fontWeights.body
2691
+ },
2692
+ children: label
2693
+ },
2694
+ key
2695
+ ))
2696
+ }
2697
+ ),
2698
+ filteredItems.length === 0 && /* @__PURE__ */ jsxs(
2699
+ "div",
2700
+ {
2701
+ style: {
2702
+ flex: 1,
2703
+ display: "flex",
2704
+ flexDirection: "column",
2705
+ alignItems: "center",
2706
+ justifyContent: "center",
2707
+ padding: "32px",
2708
+ color: theme2.colors.textSecondary
2709
+ },
2710
+ children: [
2711
+ /* @__PURE__ */ jsx(Github, { size: 48, color: theme2.colors.border, style: { marginBottom: 16 } }),
2712
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: `${theme2.fontSizes[2]}px` }, children: items.length === 0 ? "No recent activity" : "No items match filter" }),
2713
+ /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0", fontSize: `${theme2.fontSizes[1]}px` }, children: items.length === 0 ? "Repositories and owners you visit will appear here" : "Try a different filter" })
2714
+ ]
2715
+ }
2716
+ ),
2717
+ filteredItems.length > 0 && /* @__PURE__ */ jsx(
2718
+ "div",
2719
+ {
2720
+ style: {
2721
+ flex: 1,
2722
+ overflowY: "auto",
2723
+ padding: "8px"
2724
+ },
2725
+ children: filteredItems.map((item) => {
2726
+ const itemId = getItemId(item);
2727
+ const isSelected = selectedId === itemId;
2728
+ const isHovered = hoveredId === itemId;
2729
+ if (item.type === "repository") {
2730
+ return /* @__PURE__ */ jsxs(
2731
+ "button",
2732
+ {
2733
+ type: "button",
2734
+ onClick: () => handleSelectRepository(item),
2735
+ onDoubleClick: () => handleOpenRepository(item),
2736
+ onMouseEnter: () => setHoveredId(itemId),
2737
+ onMouseLeave: () => setHoveredId(null),
2738
+ style: {
2739
+ width: "100%",
2740
+ padding: "12px",
2741
+ margin: "4px 0",
2742
+ borderRadius: "8px",
2743
+ border: isSelected ? `2px solid ${theme2.colors.primary}` : `1px solid ${theme2.colors.border}`,
2744
+ backgroundColor: isSelected ? `${theme2.colors.primary}10` : theme2.colors.surface,
2745
+ cursor: "pointer",
2746
+ textAlign: "left",
2747
+ display: "flex",
2748
+ flexDirection: "column",
2749
+ gap: "8px",
2750
+ transition: "all 0.15s ease",
2751
+ position: "relative"
2752
+ },
2753
+ children: [
2754
+ isHovered && /* @__PURE__ */ jsx(
2755
+ "button",
2756
+ {
2757
+ onClick: (e) => handleRemoveItem(item, e),
2758
+ style: {
2759
+ position: "absolute",
2760
+ top: "8px",
2761
+ right: "8px",
2762
+ padding: "4px",
2763
+ borderRadius: "4px",
2764
+ border: "none",
2765
+ background: theme2.colors.backgroundSecondary,
2766
+ cursor: "pointer",
2767
+ color: theme2.colors.textSecondary,
2768
+ display: "flex",
2769
+ alignItems: "center",
2770
+ justifyContent: "center"
2771
+ },
2772
+ title: "Remove from history",
2773
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
2774
+ }
2775
+ ),
2776
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
2777
+ /* @__PURE__ */ jsx(BookOpen, { size: 16, color: theme2.colors.textSecondary }),
2778
+ item.owner.avatar_url && /* @__PURE__ */ jsx(
2779
+ "img",
2780
+ {
2781
+ src: item.owner.avatar_url,
2782
+ alt: item.owner.login,
2783
+ style: {
2784
+ width: 24,
2785
+ height: 24,
2786
+ borderRadius: "50%",
2787
+ border: `1px solid ${theme2.colors.border}`
2788
+ }
2789
+ }
2790
+ ),
2791
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
2792
+ /* @__PURE__ */ jsx(
2793
+ "span",
2794
+ {
2795
+ style: {
2796
+ fontSize: `${theme2.fontSizes[1]}px`,
2797
+ color: theme2.colors.textSecondary
2798
+ },
2799
+ children: item.owner.login
2800
+ }
2801
+ ),
2802
+ /* @__PURE__ */ jsx(
2803
+ "span",
2804
+ {
2805
+ style: {
2806
+ fontSize: `${theme2.fontSizes[2]}px`,
2807
+ fontWeight: theme2.fontWeights.semibold,
2808
+ color: theme2.colors.primary
2809
+ },
2810
+ children: item.name
2811
+ }
2812
+ )
2813
+ ] })
2814
+ ] }),
2815
+ item.description && /* @__PURE__ */ jsx(
2816
+ "p",
2817
+ {
2818
+ style: {
2819
+ margin: 0,
2820
+ fontSize: `${theme2.fontSizes[1]}px`,
2821
+ color: theme2.colors.textSecondary,
2822
+ overflow: "hidden",
2823
+ textOverflow: "ellipsis",
2824
+ display: "-webkit-box",
2825
+ WebkitLineClamp: 2,
2826
+ WebkitBoxOrient: "vertical"
2827
+ },
2828
+ children: item.description
2829
+ }
2830
+ ),
2831
+ /* @__PURE__ */ jsxs(
2832
+ "div",
2833
+ {
2834
+ style: {
2835
+ display: "flex",
2836
+ alignItems: "center",
2837
+ gap: "16px",
2838
+ fontSize: `${theme2.fontSizes[1]}px`,
2839
+ color: theme2.colors.textSecondary
2840
+ },
2841
+ children: [
2842
+ item.language && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2843
+ /* @__PURE__ */ jsx(
2844
+ "span",
2845
+ {
2846
+ style: {
2847
+ width: 10,
2848
+ height: 10,
2849
+ borderRadius: "50%",
2850
+ backgroundColor: theme2.colors.info
2851
+ }
2852
+ }
2853
+ ),
2854
+ item.language
2855
+ ] }),
2856
+ item.stargazers_count !== void 0 && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2857
+ /* @__PURE__ */ jsx(Star, { size: 14 }),
2858
+ formatNumber(item.stargazers_count)
2859
+ ] }),
2860
+ item.forks_count !== void 0 && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2861
+ /* @__PURE__ */ jsx(GitFork, { size: 14 }),
2862
+ formatNumber(item.forks_count)
2863
+ ] }),
2864
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2865
+ /* @__PURE__ */ jsx(Calendar, { size: 14 }),
2866
+ formatRelativeTime(item.visitedAt)
2867
+ ] }),
2868
+ /* @__PURE__ */ jsx(
2869
+ "a",
2870
+ {
2871
+ href: item.html_url,
2872
+ target: "_blank",
2873
+ rel: "noopener noreferrer",
2874
+ onClick: (e) => e.stopPropagation(),
2875
+ style: {
2876
+ marginLeft: "auto",
2877
+ color: theme2.colors.textSecondary,
2878
+ display: "flex",
2879
+ alignItems: "center"
2880
+ },
2881
+ children: /* @__PURE__ */ jsx(ExternalLink, { size: 14 })
2882
+ }
2883
+ )
2884
+ ]
2885
+ }
2886
+ )
2887
+ ]
2888
+ },
2889
+ itemId
2890
+ );
2891
+ }
2892
+ return /* @__PURE__ */ jsxs(
2893
+ "button",
2894
+ {
2895
+ type: "button",
2896
+ onClick: () => handleSelectOwner(item),
2897
+ onDoubleClick: () => handleOpenOwner(item),
2898
+ onMouseEnter: () => setHoveredId(itemId),
2899
+ onMouseLeave: () => setHoveredId(null),
2900
+ style: {
2901
+ width: "100%",
2902
+ padding: "12px",
2903
+ margin: "4px 0",
2904
+ borderRadius: "8px",
2905
+ border: isSelected ? `2px solid ${theme2.colors.primary}` : `1px solid ${theme2.colors.border}`,
2906
+ backgroundColor: isSelected ? `${theme2.colors.primary}10` : theme2.colors.surface,
2907
+ cursor: "pointer",
2908
+ textAlign: "left",
2909
+ display: "flex",
2910
+ flexDirection: "column",
2911
+ gap: "8px",
2912
+ transition: "all 0.15s ease",
2913
+ position: "relative"
2914
+ },
2915
+ children: [
2916
+ isHovered && /* @__PURE__ */ jsx(
2917
+ "button",
2918
+ {
2919
+ onClick: (e) => handleRemoveItem(item, e),
2920
+ style: {
2921
+ position: "absolute",
2922
+ top: "8px",
2923
+ right: "8px",
2924
+ padding: "4px",
2925
+ borderRadius: "4px",
2926
+ border: "none",
2927
+ background: theme2.colors.backgroundSecondary,
2928
+ cursor: "pointer",
2929
+ color: theme2.colors.textSecondary,
2930
+ display: "flex",
2931
+ alignItems: "center",
2932
+ justifyContent: "center"
2933
+ },
2934
+ title: "Remove from history",
2935
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
2936
+ }
2937
+ ),
2938
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
2939
+ item.ownerType === "Organization" ? /* @__PURE__ */ jsx(Building2, { size: 16, color: theme2.colors.textSecondary }) : /* @__PURE__ */ jsx(User, { size: 16, color: theme2.colors.textSecondary }),
2940
+ item.avatar_url && /* @__PURE__ */ jsx(
2941
+ "img",
2942
+ {
2943
+ src: item.avatar_url,
2944
+ alt: item.login,
2945
+ style: {
2946
+ width: 32,
2947
+ height: 32,
2948
+ borderRadius: item.ownerType === "Organization" ? 8 : "50%",
2949
+ border: `1px solid ${theme2.colors.border}`
2950
+ }
2951
+ }
2952
+ ),
2953
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
2954
+ /* @__PURE__ */ jsx(
2955
+ "span",
2956
+ {
2957
+ style: {
2958
+ fontSize: `${theme2.fontSizes[2]}px`,
2959
+ fontWeight: theme2.fontWeights.semibold,
2960
+ color: theme2.colors.primary
2961
+ },
2962
+ children: item.name || item.login
2963
+ }
2964
+ ),
2965
+ item.name && /* @__PURE__ */ jsxs(
2966
+ "span",
2967
+ {
2968
+ style: {
2969
+ fontSize: `${theme2.fontSizes[1]}px`,
2970
+ color: theme2.colors.textSecondary
2971
+ },
2972
+ children: [
2973
+ "@",
2974
+ item.login
2975
+ ]
2976
+ }
2977
+ )
2978
+ ] })
2979
+ ] }),
2980
+ item.bio && /* @__PURE__ */ jsx(
2981
+ "p",
2982
+ {
2983
+ style: {
2984
+ margin: 0,
2985
+ fontSize: `${theme2.fontSizes[1]}px`,
2986
+ color: theme2.colors.textSecondary,
2987
+ overflow: "hidden",
2988
+ textOverflow: "ellipsis",
2989
+ display: "-webkit-box",
2990
+ WebkitLineClamp: 2,
2991
+ WebkitBoxOrient: "vertical"
2992
+ },
2993
+ children: item.bio
2994
+ }
2995
+ ),
2996
+ /* @__PURE__ */ jsxs(
2997
+ "div",
2998
+ {
2999
+ style: {
3000
+ display: "flex",
3001
+ alignItems: "center",
3002
+ gap: "16px",
3003
+ fontSize: `${theme2.fontSizes[1]}px`,
3004
+ color: theme2.colors.textSecondary
3005
+ },
3006
+ children: [
3007
+ item.public_repos !== void 0 && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
3008
+ /* @__PURE__ */ jsx(BookOpen, { size: 14 }),
3009
+ formatNumber(item.public_repos),
3010
+ " repos"
3011
+ ] }),
3012
+ item.followers !== void 0 && /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
3013
+ /* @__PURE__ */ jsx(User, { size: 14 }),
3014
+ formatNumber(item.followers),
3015
+ " followers"
3016
+ ] }),
3017
+ /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
3018
+ /* @__PURE__ */ jsx(Calendar, { size: 14 }),
3019
+ formatRelativeTime(item.visitedAt)
3020
+ ] }),
3021
+ /* @__PURE__ */ jsx(
3022
+ "a",
3023
+ {
3024
+ href: `https://github.com/${item.login}`,
3025
+ target: "_blank",
3026
+ rel: "noopener noreferrer",
3027
+ onClick: (e) => e.stopPropagation(),
3028
+ style: {
3029
+ marginLeft: "auto",
3030
+ color: theme2.colors.textSecondary,
3031
+ display: "flex",
3032
+ alignItems: "center"
3033
+ },
3034
+ children: /* @__PURE__ */ jsx(ExternalLink, { size: 14 })
3035
+ }
3036
+ )
3037
+ ]
3038
+ }
3039
+ )
3040
+ ]
3041
+ },
3042
+ itemId
3043
+ );
3044
+ })
3045
+ }
3046
+ )
3047
+ ]
3048
+ }
3049
+ );
3050
+ };
3051
+ const RecentRepositoriesPanel = (props) => {
3052
+ return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(RecentRepositoriesPanelContent, { ...props }) });
3053
+ };
3054
+ const RecentRepositoriesPanelMetadata = {
3055
+ id: "recent-repositories",
3056
+ name: "Recent",
3057
+ description: "View and navigate to recently visited repositories and owners",
3058
+ icon: "history",
3059
+ version: "0.1.0",
3060
+ slices: [],
3061
+ surfaces: ["panel"]
3062
+ };
3063
+ function parseGitHubInput(input) {
3064
+ const trimmed = input.trim();
3065
+ const urlMatch = trimmed.match(/github\.com\/([^/]+)\/([^/]+)/);
3066
+ if (urlMatch) {
3067
+ return { owner: urlMatch[1], repo: urlMatch[2].replace(/\.git$/, "") };
3068
+ }
3069
+ const shortMatch = trimmed.match(/^([^/]+)\/([^/]+)$/);
3070
+ if (shortMatch) {
3071
+ return { owner: shortMatch[1], repo: shortMatch[2] };
3072
+ }
3073
+ return null;
3074
+ }
3075
+ const FeatureCard = ({ icon, title, description, theme: theme2 }) => /* @__PURE__ */ jsxs(
3076
+ "div",
3077
+ {
3078
+ style: {
3079
+ padding: "24px",
3080
+ borderRadius: "12px",
3081
+ backgroundColor: theme2.colors.surface,
3082
+ border: `1px solid ${theme2.colors.border}`,
3083
+ display: "flex",
3084
+ flexDirection: "column",
3085
+ gap: "12px",
3086
+ flex: 1,
3087
+ minWidth: "200px"
3088
+ },
3089
+ children: [
3090
+ /* @__PURE__ */ jsx(
3091
+ "div",
3092
+ {
3093
+ style: {
3094
+ width: 48,
3095
+ height: 48,
3096
+ borderRadius: "10px",
3097
+ backgroundColor: `${theme2.colors.primary}15`,
3098
+ display: "flex",
3099
+ alignItems: "center",
3100
+ justifyContent: "center",
3101
+ color: theme2.colors.primary
3102
+ },
3103
+ children: icon
3104
+ }
3105
+ ),
3106
+ /* @__PURE__ */ jsx(
3107
+ "h3",
3108
+ {
3109
+ style: {
3110
+ margin: 0,
3111
+ fontSize: `${theme2.fontSizes[3]}px`,
3112
+ fontWeight: theme2.fontWeights.semibold,
3113
+ color: theme2.colors.text
3114
+ },
3115
+ children: title
3116
+ }
3117
+ ),
3118
+ /* @__PURE__ */ jsx(
3119
+ "p",
3120
+ {
3121
+ style: {
3122
+ margin: 0,
3123
+ fontSize: `${theme2.fontSizes[2]}px`,
3124
+ color: theme2.colors.textSecondary,
3125
+ lineHeight: 1.5
3126
+ },
3127
+ children: description
3128
+ }
3129
+ )
3130
+ ]
3131
+ }
3132
+ );
3133
+ const WelcomePanelContent = ({
3134
+ onNavigate
3135
+ }) => {
3136
+ const { theme: theme2 } = useTheme();
3137
+ const [repoInput, setRepoInput] = useState("");
3138
+ const [error, setError] = useState(null);
3139
+ const handleSubmit = useCallback((e) => {
3140
+ e.preventDefault();
3141
+ setError(null);
3142
+ const parsed = parseGitHubInput(repoInput);
3143
+ if (!parsed) {
3144
+ setError("Enter a valid format: owner/repo or GitHub URL");
3145
+ return;
3146
+ }
3147
+ if (onNavigate) {
3148
+ onNavigate(parsed.owner, parsed.repo);
3149
+ } else {
3150
+ window.location.href = `/${parsed.owner}/${parsed.repo}`;
3151
+ }
3152
+ }, [repoInput, onNavigate]);
3153
+ return /* @__PURE__ */ jsxs(
3154
+ "div",
3155
+ {
3156
+ style: {
3157
+ height: "100%",
3158
+ display: "flex",
3159
+ flexDirection: "column",
3160
+ backgroundColor: theme2.colors.background,
3161
+ color: theme2.colors.text,
3162
+ fontFamily: theme2.fonts.body,
3163
+ overflowY: "auto"
3164
+ },
3165
+ children: [
3166
+ /* @__PURE__ */ jsxs(
3167
+ "div",
3168
+ {
3169
+ style: {
3170
+ padding: "48px 32px",
3171
+ display: "flex",
3172
+ flexDirection: "column",
3173
+ alignItems: "center",
3174
+ textAlign: "center",
3175
+ borderBottom: `1px solid ${theme2.colors.border}`
3176
+ },
3177
+ children: [
3178
+ /* @__PURE__ */ jsxs(
3179
+ "div",
3180
+ {
3181
+ style: {
3182
+ display: "flex",
3183
+ alignItems: "center",
3184
+ gap: "12px",
3185
+ marginBottom: "24px"
3186
+ },
3187
+ children: [
3188
+ /* @__PURE__ */ jsx(
3189
+ "div",
3190
+ {
3191
+ style: {
3192
+ width: 56,
3193
+ height: 56,
3194
+ borderRadius: "14px",
3195
+ background: `linear-gradient(135deg, ${theme2.colors.primary}, ${theme2.colors.secondary || theme2.colors.primary})`,
3196
+ display: "flex",
3197
+ alignItems: "center",
3198
+ justifyContent: "center"
3199
+ },
3200
+ children: /* @__PURE__ */ jsx(GitBranch, { size: 32, color: "#fff" })
3201
+ }
3202
+ ),
3203
+ /* @__PURE__ */ jsx(
3204
+ "span",
3205
+ {
3206
+ style: {
3207
+ fontSize: `${theme2.fontSizes[5]}px`,
3208
+ fontWeight: theme2.fontWeights.bold,
3209
+ color: theme2.colors.text
3210
+ },
3211
+ children: "Principal"
3212
+ }
3213
+ )
3214
+ ]
3215
+ }
3216
+ ),
3217
+ /* @__PURE__ */ jsx(
3218
+ "h1",
3219
+ {
3220
+ style: {
3221
+ margin: "0 0 16px",
3222
+ fontSize: `${theme2.fontSizes[6] || 32}px`,
3223
+ fontWeight: theme2.fontWeights.bold,
3224
+ color: theme2.colors.text,
3225
+ maxWidth: "600px"
3226
+ },
3227
+ children: "Explore repositories like never before"
3228
+ }
3229
+ ),
3230
+ /* @__PURE__ */ jsx(
3231
+ "p",
3232
+ {
3233
+ style: {
3234
+ margin: "0 0 32px",
3235
+ fontSize: `${theme2.fontSizes[3]}px`,
3236
+ color: theme2.colors.textSecondary,
3237
+ maxWidth: "500px",
3238
+ lineHeight: 1.6
3239
+ },
3240
+ children: "Interactive diagrams, intelligent chat, and visual exploration to understand any codebase in minutes."
3241
+ }
3242
+ ),
3243
+ /* @__PURE__ */ jsxs(
3244
+ "form",
3245
+ {
3246
+ onSubmit: handleSubmit,
3247
+ style: {
3248
+ width: "100%",
3249
+ maxWidth: "500px"
3250
+ },
3251
+ children: [
3252
+ /* @__PURE__ */ jsxs(
3253
+ "div",
3254
+ {
3255
+ style: {
3256
+ display: "flex",
3257
+ gap: "8px",
3258
+ padding: "6px",
3259
+ borderRadius: "12px",
3260
+ backgroundColor: theme2.colors.surface,
3261
+ border: `2px solid ${error ? theme2.colors.error : theme2.colors.border}`
3262
+ },
3263
+ children: [
3264
+ /* @__PURE__ */ jsx(
3265
+ "div",
3266
+ {
3267
+ style: {
3268
+ display: "flex",
3269
+ alignItems: "center",
3270
+ paddingLeft: "12px",
3271
+ color: theme2.colors.textSecondary
3272
+ },
3273
+ children: /* @__PURE__ */ jsx(Github, { size: 20 })
3274
+ }
3275
+ ),
3276
+ /* @__PURE__ */ jsx(
3277
+ "input",
3278
+ {
3279
+ type: "text",
3280
+ value: repoInput,
3281
+ onChange: (e) => {
3282
+ setRepoInput(e.target.value);
3283
+ setError(null);
3284
+ },
3285
+ placeholder: "owner/repo or paste GitHub URL",
3286
+ style: {
3287
+ flex: 1,
3288
+ padding: "12px 8px",
3289
+ border: "none",
3290
+ background: "transparent",
3291
+ color: theme2.colors.text,
3292
+ fontSize: `${theme2.fontSizes[2]}px`,
3293
+ outline: "none"
3294
+ }
3295
+ }
3296
+ ),
3297
+ /* @__PURE__ */ jsxs(
3298
+ "button",
3299
+ {
3300
+ type: "submit",
3301
+ style: {
3302
+ padding: "12px 20px",
3303
+ borderRadius: "8px",
3304
+ border: "none",
3305
+ backgroundColor: theme2.colors.primary,
3306
+ color: "#fff",
3307
+ fontSize: `${theme2.fontSizes[2]}px`,
3308
+ fontWeight: theme2.fontWeights.semibold,
3309
+ cursor: "pointer",
3310
+ display: "flex",
3311
+ alignItems: "center",
3312
+ gap: "8px"
3313
+ },
3314
+ children: [
3315
+ "Explore",
3316
+ /* @__PURE__ */ jsx(ArrowRight, { size: 18 })
3317
+ ]
3318
+ }
3319
+ )
3320
+ ]
3321
+ }
3322
+ ),
3323
+ error && /* @__PURE__ */ jsx(
3324
+ "p",
3325
+ {
3326
+ style: {
3327
+ margin: "8px 0 0",
3328
+ fontSize: `${theme2.fontSizes[1]}px`,
3329
+ color: theme2.colors.error
3330
+ },
3331
+ children: error
3332
+ }
3333
+ )
3334
+ ]
3335
+ }
3336
+ )
3337
+ ]
3338
+ }
3339
+ ),
3340
+ /* @__PURE__ */ jsxs(
3341
+ "div",
3342
+ {
3343
+ style: {
3344
+ padding: "48px 32px",
3345
+ display: "flex",
3346
+ flexDirection: "column",
3347
+ alignItems: "center"
3348
+ },
3349
+ children: [
3350
+ /* @__PURE__ */ jsxs(
3351
+ "div",
3352
+ {
3353
+ style: {
3354
+ display: "flex",
3355
+ alignItems: "center",
3356
+ gap: "8px",
3357
+ marginBottom: "12px"
3358
+ },
3359
+ children: [
3360
+ /* @__PURE__ */ jsx(Sparkles, { size: 20, color: theme2.colors.primary }),
3361
+ /* @__PURE__ */ jsx(
3362
+ "span",
3363
+ {
3364
+ style: {
3365
+ fontSize: `${theme2.fontSizes[1]}px`,
3366
+ fontWeight: theme2.fontWeights.semibold,
3367
+ color: theme2.colors.primary,
3368
+ textTransform: "uppercase",
3369
+ letterSpacing: "0.05em"
3370
+ },
3371
+ children: "Features"
3372
+ }
3373
+ )
3374
+ ]
3375
+ }
3376
+ ),
3377
+ /* @__PURE__ */ jsx(
3378
+ "h2",
3379
+ {
3380
+ style: {
3381
+ margin: "0 0 32px",
3382
+ fontSize: `${theme2.fontSizes[4]}px`,
3383
+ fontWeight: theme2.fontWeights.semibold,
3384
+ color: theme2.colors.text,
3385
+ textAlign: "center"
3386
+ },
3387
+ children: "Understand code faster"
3388
+ }
3389
+ ),
3390
+ /* @__PURE__ */ jsxs(
3391
+ "div",
3392
+ {
3393
+ style: {
3394
+ display: "flex",
3395
+ gap: "20px",
3396
+ flexWrap: "wrap",
3397
+ justifyContent: "center",
3398
+ maxWidth: "900px"
3399
+ },
3400
+ children: [
3401
+ /* @__PURE__ */ jsx(
3402
+ FeatureCard,
3403
+ {
3404
+ icon: /* @__PURE__ */ jsx(Network, { size: 24 }),
3405
+ title: "Interactive Diagrams",
3406
+ description: "Visualize repository structure, dependencies, and architecture with auto-generated diagrams you can explore.",
3407
+ theme: theme2
3408
+ }
3409
+ ),
3410
+ /* @__PURE__ */ jsx(
3411
+ FeatureCard,
3412
+ {
3413
+ icon: /* @__PURE__ */ jsx(MessageSquare, { size: 24 }),
3414
+ title: "Chat with Code",
3415
+ description: "Ask questions about any repository and get instant, context-aware answers powered by AI.",
3416
+ theme: theme2
3417
+ }
3418
+ ),
3419
+ /* @__PURE__ */ jsx(
3420
+ FeatureCard,
3421
+ {
3422
+ icon: /* @__PURE__ */ jsx(GitBranch, { size: 24 }),
3423
+ title: "Deep Git Insights",
3424
+ description: "Explore commits, branches, and history with visual timelines and contributor analytics.",
3425
+ theme: theme2
3426
+ }
3427
+ )
3428
+ ]
3429
+ }
3430
+ )
3431
+ ]
3432
+ }
3433
+ ),
3434
+ /* @__PURE__ */ jsx(
3435
+ "div",
3436
+ {
3437
+ style: {
3438
+ padding: "24px 32px 48px",
3439
+ display: "flex",
3440
+ justifyContent: "center"
3441
+ },
3442
+ children: /* @__PURE__ */ jsxs(
3443
+ "p",
3444
+ {
3445
+ style: {
3446
+ margin: 0,
3447
+ fontSize: `${theme2.fontSizes[1]}px`,
3448
+ color: theme2.colors.textSecondary
3449
+ },
3450
+ children: [
3451
+ "Try it with",
3452
+ " ",
3453
+ /* @__PURE__ */ jsx(
3454
+ "button",
3455
+ {
3456
+ onClick: () => {
3457
+ if (onNavigate) {
3458
+ onNavigate("facebook", "react");
3459
+ } else {
3460
+ window.location.href = "/facebook/react";
3461
+ }
3462
+ },
3463
+ style: {
3464
+ background: "none",
3465
+ border: "none",
3466
+ color: theme2.colors.primary,
3467
+ cursor: "pointer",
3468
+ padding: 0,
3469
+ fontSize: "inherit",
3470
+ fontWeight: theme2.fontWeights.medium,
3471
+ textDecoration: "underline"
3472
+ },
3473
+ children: "facebook/react"
3474
+ }
3475
+ ),
3476
+ " ",
3477
+ "or",
3478
+ " ",
3479
+ /* @__PURE__ */ jsx(
3480
+ "button",
3481
+ {
3482
+ onClick: () => {
3483
+ if (onNavigate) {
3484
+ onNavigate("vercel", "next.js");
3485
+ } else {
3486
+ window.location.href = "/vercel/next.js";
3487
+ }
3488
+ },
3489
+ style: {
3490
+ background: "none",
3491
+ border: "none",
3492
+ color: theme2.colors.primary,
3493
+ cursor: "pointer",
3494
+ padding: 0,
3495
+ fontSize: "inherit",
3496
+ fontWeight: theme2.fontWeights.medium,
3497
+ textDecoration: "underline"
3498
+ },
3499
+ children: "vercel/next.js"
3500
+ }
3501
+ )
3502
+ ]
3503
+ }
3504
+ )
3505
+ }
3506
+ )
3507
+ ]
3508
+ }
3509
+ );
3510
+ };
3511
+ const WelcomePanel = (props) => {
3512
+ return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(WelcomePanelContent, { ...props }) });
3513
+ };
3514
+ const WelcomePanelMetadata = {
3515
+ id: "welcome",
3516
+ name: "Welcome",
3517
+ description: "Landing page with branding and repository search",
3518
+ icon: "home",
3519
+ version: "0.1.0",
3520
+ slices: [],
3521
+ surfaces: ["panel"]
3522
+ };
3523
+ const listRepositoriesTool = {
3524
+ name: "list_repositories",
3525
+ description: "Get a list of GitHub repositories the user has access to, including owned repos, starred repos, and organization repos.",
3526
+ inputs: {
3527
+ type: "object",
3528
+ properties: {},
3529
+ required: []
3530
+ },
3531
+ outputs: {
3532
+ type: "object",
3533
+ properties: {
3534
+ success: { type: "boolean" }
3535
+ }
3536
+ },
3537
+ tags: ["github", "repository", "list", "browse"],
3538
+ tool_call_template: {
3539
+ call_template_type: "panel_event",
3540
+ event_type: "github:list-repositories"
3541
+ }
3542
+ };
3543
+ const selectRepositoryTool = {
3544
+ name: "select_repository",
3545
+ description: 'Select a GitHub repository to view its details, README, and files. Use the full repository name in "owner/repo" format.',
3546
+ inputs: {
3547
+ type: "object",
3548
+ properties: {
3549
+ repository: {
3550
+ type: "string",
3551
+ description: 'The full repository name in "owner/repo" format (e.g., "facebook/react")'
3552
+ }
3553
+ },
3554
+ required: ["repository"]
3555
+ },
3556
+ outputs: {
3557
+ type: "object",
3558
+ properties: {
3559
+ success: { type: "boolean" },
3560
+ repository: { type: "string" }
3561
+ }
3562
+ },
3563
+ tags: ["github", "repository", "select", "navigate"],
3564
+ tool_call_template: {
3565
+ call_template_type: "panel_event",
3566
+ event_type: "repository:selected"
3567
+ }
3568
+ };
3569
+ const previewRepositoryTool = {
3570
+ name: "preview_repository",
3571
+ description: "Preview a GitHub repository's README in the viewer without navigating to it.",
3572
+ inputs: {
3573
+ type: "object",
3574
+ properties: {
3575
+ repository: {
3576
+ type: "string",
3577
+ description: 'The full repository name in "owner/repo" format (e.g., "facebook/react")'
3578
+ }
3579
+ },
3580
+ required: ["repository"]
3581
+ },
3582
+ outputs: {
3583
+ type: "object",
3584
+ properties: {
3585
+ success: { type: "boolean" }
3586
+ }
3587
+ },
3588
+ tags: ["github", "repository", "preview", "readme"],
3589
+ tool_call_template: {
3590
+ call_template_type: "panel_event",
3591
+ event_type: "repository:preview"
3592
+ }
3593
+ };
3594
+ const searchRepositoriesTool = {
3595
+ name: "search_repositories",
3596
+ description: "Search through the user's GitHub repositories by name, description, or language.",
3597
+ inputs: {
3598
+ type: "object",
3599
+ properties: {
3600
+ query: {
3601
+ type: "string",
3602
+ description: "The search query to filter repositories"
3603
+ }
3604
+ },
3605
+ required: ["query"]
3606
+ },
3607
+ outputs: {
3608
+ type: "object",
3609
+ properties: {
3610
+ success: { type: "boolean" }
3611
+ }
3612
+ },
3613
+ tags: ["github", "repository", "search", "filter"],
3614
+ tool_call_template: {
3615
+ call_template_type: "panel_event",
3616
+ event_type: "github:search-repositories"
3617
+ }
3618
+ };
3619
+ const openRepositorySwitcherTool = {
3620
+ name: "open_repository_switcher",
3621
+ description: "Open the repository switcher modal to browse and select a different repository.",
3622
+ inputs: {
3623
+ type: "object",
3624
+ properties: {},
3625
+ required: []
3626
+ },
3627
+ outputs: {
3628
+ type: "object",
3629
+ properties: {
3630
+ success: { type: "boolean" }
1656
3631
  }
1657
3632
  },
1658
3633
  tags: ["github", "repository", "switch", "modal"],
@@ -1723,6 +3698,36 @@ const panels = [
1723
3698
  onUnmount: async (_context) => {
1724
3699
  console.log("GitHub Search Panel unmounting");
1725
3700
  }
3701
+ },
3702
+ {
3703
+ metadata: OwnerRepositoriesPanelMetadata,
3704
+ component: OwnerRepositoriesPanel,
3705
+ onMount: async (_context) => {
3706
+ console.log("Owner Repositories Panel mounted");
3707
+ },
3708
+ onUnmount: async (_context) => {
3709
+ console.log("Owner Repositories Panel unmounting");
3710
+ }
3711
+ },
3712
+ {
3713
+ metadata: RecentRepositoriesPanelMetadata,
3714
+ component: RecentRepositoriesPanel,
3715
+ onMount: async (_context) => {
3716
+ console.log("Recent Repositories Panel mounted");
3717
+ },
3718
+ onUnmount: async (_context) => {
3719
+ console.log("Recent Repositories Panel unmounting");
3720
+ }
3721
+ },
3722
+ {
3723
+ metadata: WelcomePanelMetadata,
3724
+ component: WelcomePanel,
3725
+ onMount: async (_context) => {
3726
+ console.log("Welcome Panel mounted");
3727
+ },
3728
+ onUnmount: async (_context) => {
3729
+ console.log("Welcome Panel unmounting");
3730
+ }
1726
3731
  }
1727
3732
  ];
1728
3733
  const onPackageLoad = async () => {
@@ -1735,6 +3740,11 @@ export {
1735
3740
  GitHubProjectCard,
1736
3741
  GitHubProjectsPanel,
1737
3742
  GitHubSearchPanel,
3743
+ OwnerRepositoriesPanel,
3744
+ RecentRepositoriesPanel,
3745
+ WelcomePanel,
3746
+ addRecentOwner,
3747
+ addRecentRepository,
1738
3748
  githubTools,
1739
3749
  githubToolsMetadata,
1740
3750
  listRepositoriesTool,