@myrialabs/clopen 0.1.7 → 0.1.8

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.
@@ -67,9 +67,6 @@
67
67
  let newTagName = $state('');
68
68
  let newTagMessage = $state('');
69
69
 
70
- // More menu state (for Stash/Tags)
71
- let showMoreMenu = $state(false);
72
-
73
70
  // Tab system (like Files panel)
74
71
  interface DiffTab {
75
72
  id: string;
@@ -1053,12 +1050,21 @@
1053
1050
  gitStatus.staged.length + allChanges.length + gitStatus.conflicted.length
1054
1051
  );
1055
1052
 
1053
+ // View tabs config for tab bar
1054
+ const viewTabs = $derived([
1055
+ { id: 'changes' as const, label: 'Changes', icon: 'lucide:file-pen' as IconName, badge: totalChanges > 0 ? totalChanges : null },
1056
+ { id: 'log' as const, label: 'History', icon: 'lucide:history' as IconName, badge: null },
1057
+ { id: 'stash' as const, label: 'Stash', icon: 'lucide:archive' as IconName, badge: stashEntries.length > 0 ? stashEntries.length : null },
1058
+ { id: 'tags' as const, label: 'Tags', icon: 'lucide:tag' as IconName, badge: tags.length > 0 ? tags.length : null }
1059
+ ]);
1060
+
1056
1061
  // Exported panel actions for PanelHeader
1057
1062
  export const panelActions = {
1058
1063
  push: handlePush,
1059
1064
  pull: handlePull,
1060
1065
  fetch: handleFetch,
1061
1066
  init: handleInit,
1067
+ openBranchManager: () => { showBranchManager = true; },
1062
1068
  getBranchInfo: () => branchInfo,
1063
1069
  getIsRepo: () => isRepo,
1064
1070
  getIsFetching: () => isFetching,
@@ -1102,97 +1108,32 @@
1102
1108
  {/if}
1103
1109
  {/snippet}
1104
1110
 
1105
- <!-- Changes list snippet -->
1106
- {#snippet changesList()}
1107
- <!-- View tabs with branch switch -->
1108
- <div class="flex items-center gap-1 px-2 py-1.5 border-b border-slate-100 dark:border-slate-800">
1109
- <button
1110
- type="button"
1111
- class="flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded-md bg-slate-100 dark:bg-slate-800/60 text-slate-700 dark:text-slate-300 hover:bg-violet-500/10 hover:text-violet-600 transition-colors cursor-pointer border-none min-w-0"
1112
- onclick={() => showBranchManager = true}
1113
- title="Switch Branch"
1114
- >
1115
- <Icon name="lucide:git-branch" class="w-3.5 h-3.5 shrink-0" />
1116
- <span class="truncate max-w-24">{branchInfo?.current || '...'}</span>
1117
- </button>
1118
-
1119
- <div class="flex-1"></div>
1120
-
1121
- <!-- Primary tabs: Changes & History -->
1122
- <button
1123
- type="button"
1124
- class="px-2 py-1 text-xs font-medium rounded-md transition-colors cursor-pointer border-none
1125
- {activeView === 'changes'
1126
- ? 'bg-violet-500/10 text-violet-600'
1127
- : 'bg-transparent text-slate-500 hover:text-slate-700 dark:hover:text-slate-300'}"
1128
- onclick={() => { switchToView('changes'); showMoreMenu = false; }}
1129
- >
1130
- Changes{totalChanges > 0 ? ` (${totalChanges})` : ''}
1131
- </button>
1132
- <button
1133
- type="button"
1134
- class="px-2 py-1 text-xs font-medium rounded-md transition-colors cursor-pointer border-none
1135
- {activeView === 'log'
1136
- ? 'bg-violet-500/10 text-violet-600'
1137
- : 'bg-transparent text-slate-500 hover:text-slate-700 dark:hover:text-slate-300'}"
1138
- onclick={() => { switchToView('log'); showMoreMenu = false; }}
1139
- >
1140
- History
1141
- </button>
1142
-
1143
- <!-- More menu (Stash, Tags) -->
1144
- <div class="relative">
1111
+ <!-- View tabs snippet (always visible, even in single-column diff mode) -->
1112
+ {#snippet viewTabBar()}
1113
+ <div class="relative flex border-b border-slate-200 dark:border-slate-700">
1114
+ {#each viewTabs as tab (tab.id)}
1115
+ {@const isActive = activeView === tab.id}
1145
1116
  <button
1146
1117
  type="button"
1147
- class="flex items-center justify-center w-7 h-7 rounded-md transition-colors cursor-pointer border-none
1148
- {activeView === 'stash' || activeView === 'tags'
1149
- ? 'bg-violet-500/10 text-violet-600'
1150
- : 'bg-transparent text-slate-400 hover:text-slate-700 dark:hover:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-800'}"
1151
- onclick={() => showMoreMenu = !showMoreMenu}
1152
- title="More views"
1118
+ class="relative flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-xs font-medium transition-colors {isActive
1119
+ ? 'text-violet-600 dark:text-violet-400'
1120
+ : 'text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-slate-300'}"
1121
+ onclick={() => switchToView(tab.id)}
1153
1122
  >
1154
- <Icon name="lucide:ellipsis" class="w-4 h-4" />
1123
+ {tab.label}
1124
+ {#if tab.badge}
1125
+ <span class="min-w-4 h-4 px-1 rounded-full bg-violet-500/15 dark:bg-violet-500/25 text-3xs font-semibold flex items-center justify-center">{tab.badge}</span>
1126
+ {/if}
1127
+ {#if isActive}
1128
+ <span class="absolute bottom-0 inset-x-0 h-px bg-violet-600 dark:bg-violet-400"></span>
1129
+ {/if}
1155
1130
  </button>
1156
-
1157
- {#if showMoreMenu}
1158
- <div
1159
- class="fixed inset-0 z-40"
1160
- onclick={() => showMoreMenu = false}
1161
- ></div>
1162
- <div class="absolute right-0 top-full mt-1 z-50 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg shadow-lg py-1 min-w-32">
1163
- <button
1164
- type="button"
1165
- class="flex items-center gap-2 w-full px-3 py-1.5 text-xs font-medium text-left transition-colors cursor-pointer border-none
1166
- {activeView === 'stash'
1167
- ? 'bg-violet-500/10 text-violet-600'
1168
- : 'bg-transparent text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700'}"
1169
- onclick={() => { switchToView('stash'); showMoreMenu = false; }}
1170
- >
1171
- <Icon name="lucide:archive" class="w-3.5 h-3.5" />
1172
- Stash
1173
- {#if stashEntries.length > 0}
1174
- <span class="ml-auto text-3xs font-semibold text-slate-400">{stashEntries.length}</span>
1175
- {/if}
1176
- </button>
1177
- <button
1178
- type="button"
1179
- class="flex items-center gap-2 w-full px-3 py-1.5 text-xs font-medium text-left transition-colors cursor-pointer border-none
1180
- {activeView === 'tags'
1181
- ? 'bg-violet-500/10 text-violet-600'
1182
- : 'bg-transparent text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700'}"
1183
- onclick={() => { switchToView('tags'); showMoreMenu = false; }}
1184
- >
1185
- <Icon name="lucide:tag" class="w-3.5 h-3.5" />
1186
- Tags
1187
- {#if tags.length > 0}
1188
- <span class="ml-auto text-3xs font-semibold text-slate-400">{tags.length}</span>
1189
- {/if}
1190
- </button>
1191
- </div>
1192
- {/if}
1193
- </div>
1131
+ {/each}
1194
1132
  </div>
1133
+ {/snippet}
1195
1134
 
1135
+ <!-- Changes list snippet -->
1136
+ {#snippet changesList()}
1196
1137
  {#if activeView === 'changes'}
1197
1138
  <!-- Commit form -->
1198
1139
  <CommitForm
@@ -1253,7 +1194,7 @@
1253
1194
  />
1254
1195
  {:else if activeView === 'stash'}
1255
1196
  <!-- Stash View -->
1256
- <div class="flex-1 overflow-y-auto">
1197
+ <div class="flex-1 overflow-y-auto pt-2">
1257
1198
  <!-- Stash save button/form -->
1258
1199
  <div class="px-2 pb-2">
1259
1200
  {#if showStashSaveForm}
@@ -1337,7 +1278,7 @@
1337
1278
  </div>
1338
1279
  {:else if activeView === 'tags'}
1339
1280
  <!-- Tags View -->
1340
- <div class="flex-1 overflow-y-auto">
1281
+ <div class="flex-1 overflow-y-auto pt-2">
1341
1282
  <!-- Create tag button/form -->
1342
1283
  <div class="px-2 pb-2">
1343
1284
  {#if showCreateTagForm}
@@ -1502,16 +1443,17 @@
1502
1443
  <div class="flex-1 overflow-hidden">
1503
1444
  <!-- Unified layout: always render both panels to preserve state (like Files panel) -->
1504
1445
  <div class="h-full flex">
1505
- <!-- Left panel: Changes list (w-80 like Files panel tree) -->
1446
+ <!-- Left panel: Changes list -->
1506
1447
  <div
1507
1448
  class={isTwoColumnMode
1508
1449
  ? 'w-72 flex-shrink-0 h-full overflow-hidden border-r border-slate-200 dark:border-slate-700 flex flex-col'
1509
1450
  : (viewMode === 'list' ? 'w-full h-full overflow-hidden flex flex-col' : 'hidden')}
1510
1451
  >
1452
+ {@render viewTabBar()}
1511
1453
  {@render changesList()}
1512
1454
  </div>
1513
1455
 
1514
- <!-- Right panel: Diff viewer (like Files panel editor) -->
1456
+ <!-- Right panel: Diff viewer -->
1515
1457
  <div
1516
1458
  class={isTwoColumnMode
1517
1459
  ? 'flex-1 h-full overflow-hidden flex flex-col'
@@ -459,20 +459,20 @@ const defaultPanels: Record<PanelId, PanelConfig> = {
459
459
  minimized: false,
460
460
  order: 0
461
461
  },
462
- preview: {
463
- id: 'preview',
464
- title: 'Preview',
465
- icon: 'lucide:globe',
466
- visible: true,
467
- minimized: false,
468
- order: 1
469
- },
470
462
  files: {
471
463
  id: 'files',
472
464
  title: 'Files',
473
465
  icon: 'lucide:folder',
474
466
  visible: true,
475
467
  minimized: false,
468
+ order: 1
469
+ },
470
+ git: {
471
+ id: 'git',
472
+ title: 'Source Control',
473
+ icon: 'lucide:git-branch',
474
+ visible: true,
475
+ minimized: false,
476
476
  order: 2
477
477
  },
478
478
  terminal: {
@@ -483,10 +483,10 @@ const defaultPanels: Record<PanelId, PanelConfig> = {
483
483
  minimized: false,
484
484
  order: 3
485
485
  },
486
- git: {
487
- id: 'git',
488
- title: 'Source Control',
489
- icon: 'lucide:git-branch',
486
+ preview: {
487
+ id: 'preview',
488
+ title: 'Preview',
489
+ icon: 'lucide:globe',
490
490
  visible: true,
491
491
  minimized: false,
492
492
  order: 4
@@ -496,9 +496,9 @@ const defaultPanels: Record<PanelId, PanelConfig> = {
496
496
  export const PANEL_OPTIONS: { id: PanelId; title: string; icon: IconName }[] = [
497
497
  { id: 'chat', title: 'AI Assistant', icon: 'lucide:bot' },
498
498
  { id: 'files', title: 'Files', icon: 'lucide:folder' },
499
- { id: 'preview', title: 'Preview', icon: 'lucide:globe' },
499
+ { id: 'git', title: 'Source Control', icon: 'lucide:git-branch' },
500
500
  { id: 'terminal', title: 'Terminal', icon: 'lucide:terminal' },
501
- { id: 'git', title: 'Source Control', icon: 'lucide:git-branch' }
501
+ { id: 'preview', title: 'Preview', icon: 'lucide:globe' }
502
502
  ];
503
503
 
504
504
  // Default: Main + Stack layout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myrialabs/clopen",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "All-in-one web workspace for Claude Code & OpenCode — chat, terminal, git, browser preview, checkpoints, and real-time collaboration",
5
5
  "author": "Myria Labs",
6
6
  "license": "MIT",
@@ -62,7 +62,6 @@
62
62
  "@types/bun": "^1.2.18",
63
63
  "@types/node": "^24.0.14",
64
64
  "@types/qrcode": "^1.5.6",
65
- "@types/xterm": "^3.0.0",
66
65
  "concurrently": "^9.2.1",
67
66
  "eslint": "^9.31.0",
68
67
  "eslint-plugin-svelte": "^3.10.1",
@@ -83,8 +82,12 @@
83
82
  "@modelcontextprotocol/sdk": "^1.26.0",
84
83
  "@monaco-editor/loader": "^1.5.0",
85
84
  "@opencode-ai/sdk": "^1.2.15",
86
- "@xterm/addon-fit": "^0.10.0",
87
- "@xterm/addon-web-links": "^0.11.0",
85
+ "@xterm/addon-clipboard": "^0.2.0",
86
+ "@xterm/addon-fit": "^0.11.0",
87
+ "@xterm/addon-ligatures": "^0.10.0",
88
+ "@xterm/addon-unicode11": "^0.9.0",
89
+ "@xterm/addon-web-links": "^0.12.0",
90
+ "@xterm/xterm": "^6.0.0",
88
91
  "bun-pty": "^0.4.2",
89
92
  "cloudflared": "^0.7.1",
90
93
  "elysia": "^1.4.19",
@@ -95,8 +98,7 @@
95
98
  "nanoid": "^5.1.6",
96
99
  "puppeteer": "^24.33.0",
97
100
  "puppeteer-cluster": "^0.25.0",
98
- "qrcode": "^1.5.4",
99
- "xterm": "^5.3.0"
101
+ "qrcode": "^1.5.4"
100
102
  },
101
103
  "trustedDependencies": [
102
104
  "cloudflared",