clay-server 5.3.0-beta.5 → 5.3.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/clay-product-control-tools.js +2 -2
- package/lib/clay-product-control.js +1 -1
- package/lib/clay-screen-controls.js +1 -0
- package/lib/clay-split-view-awareness.js +5 -2
- package/lib/clay-split-view-controls.js +14 -7
- package/lib/clay-split-view-input.js +5 -4
- package/lib/clay-split-view-render-proof.js +14 -4
- package/lib/clay-view-workspace-input.js +71 -0
- package/lib/project-admin-overview.js +22 -11
- package/lib/project-background-tasks.js +76 -0
- package/lib/project-connection.js +1 -1
- package/lib/project-file-history.js +11 -9
- package/lib/project-file-watch.js +26 -7
- package/lib/project-filesystem.js +5 -4
- package/lib/project-sessions.js +12 -5
- package/lib/project-shared-browser.js +7 -3
- package/lib/project-split-view-document.js +16 -2
- package/lib/project-split-views.js +27 -297
- package/lib/project-user-message.js +4 -3
- package/lib/project-vendor-login.js +2 -2
- package/lib/project-view-input.js +11 -0
- package/lib/project-view-pair.js +26 -0
- package/lib/project-view-store.js +348 -0
- package/lib/project-view-terminal-binding.js +16 -0
- package/lib/project-view-workspace.js +126 -0
- package/lib/project-worker-conversation.js +5 -0
- package/lib/project.js +1 -0
- package/lib/public/app.js +9 -0
- package/lib/public/css/contextual-clay.css +2 -1
- package/lib/public/css/issues.css +3 -0
- package/lib/public/css/mate-conversation.css +1 -1
- package/lib/public/css/pane.css +5 -1
- package/lib/public/css/pending-message-queue.css +24 -19
- package/lib/public/css/project-admin-overview.css +42 -13
- package/lib/public/css/right-workbench.css +0 -1
- package/lib/public/css/scheduled-tasks.css +7 -0
- package/lib/public/css/shared-browser.css +31 -8
- package/lib/public/css/split-view-layout.css +129 -10
- package/lib/public/css/tool-pane.css +124 -0
- package/lib/public/index.html +6 -6
- package/lib/public/modules/agent-message-bubbles.js +96 -0
- package/lib/public/modules/app-header.js +6 -0
- package/lib/public/modules/app-messages.js +26 -9
- package/lib/public/modules/background-task-previews.js +8 -0
- package/lib/public/modules/background-task-viewer.js +97 -0
- package/lib/public/modules/background-tasks-ui.js +34 -125
- package/lib/public/modules/chat-bubble-renderer.js +11 -5
- package/lib/public/modules/clay-file-links.js +2 -1
- package/lib/public/modules/clay-split-view-screen.js +6 -3
- package/lib/public/modules/clay-tool-pane-screen.js +35 -0
- package/lib/public/modules/contextual-clay-geometry.js +7 -3
- package/lib/public/modules/file-history-snapshot.js +12 -0
- package/lib/public/modules/file-pane-entrypoints.js +55 -0
- package/lib/public/modules/file-pane-history.js +78 -0
- package/lib/public/modules/file-pane-instances.js +140 -0
- package/lib/public/modules/file-pane-links.js +41 -0
- package/lib/public/modules/file-pane-render.js +48 -0
- package/lib/public/modules/file-pane-review.js +26 -0
- package/lib/public/modules/file-pane-toolbar.js +54 -0
- package/lib/public/modules/file-viewer-source.js +70 -0
- package/lib/public/modules/filebrowser.js +43 -82
- package/lib/public/modules/git-panel.js +5 -0
- package/lib/public/modules/issues.js +3 -4
- package/lib/public/modules/linear-panel.js +2 -2
- package/lib/public/modules/mate-knowledge-workbench.js +10 -6
- package/lib/public/modules/notifications.js +4 -1
- package/lib/public/modules/pane-activation.js +7 -3
- package/lib/public/modules/pane-binding.js +5 -1
- package/lib/public/modules/pane-browser-bridge.js +6 -2
- package/lib/public/modules/pane-browser-transport.js +110 -0
- package/lib/public/modules/pane-header-tooltips.js +32 -0
- package/lib/public/modules/pending-message-queue-drag.js +69 -0
- package/lib/public/modules/pending-message-queue.js +3 -33
- package/lib/public/modules/permission-control.js +6 -5
- package/lib/public/modules/plantuml-preview.js +12 -12
- package/lib/public/modules/project-admin-overview.js +125 -10
- package/lib/public/modules/project-grouping.js +9 -0
- package/lib/public/modules/right-workbench.js +34 -15
- package/lib/public/modules/scheduled-tasks.js +7 -6
- package/lib/public/modules/server-settings-controls.js +33 -4
- package/lib/public/modules/session-folder-toolbar.js +1 -1
- package/lib/public/modules/session-tool-item.js +86 -0
- package/lib/public/modules/settings-select.js +2 -1
- package/lib/public/modules/shared-browser-tabs.js +37 -21
- package/lib/public/modules/shared-browser.js +69 -9
- package/lib/public/modules/sidebar-projects.js +1 -10
- package/lib/public/modules/split-pane-renderer.js +1 -0
- package/lib/public/modules/split-session-empty-pane.js +47 -0
- package/lib/public/modules/split-view-create-menu.js +74 -65
- package/lib/public/modules/split-view-drag-preview.js +90 -0
- package/lib/public/modules/split-view-layout-client.js +1 -1
- package/lib/public/modules/split-view-layout-scope.js +4 -0
- package/lib/public/modules/split-view-picker-actions.js +71 -0
- package/lib/public/modules/split-view-picker-render.js +81 -0
- package/lib/public/modules/split-view-presentation-drag.js +36 -13
- package/lib/public/modules/split-view-presentation-drop.js +21 -18
- package/lib/public/modules/split-view-presentation-renderer.js +22 -17
- package/lib/public/modules/split-view-presentations.js +25 -33
- package/lib/public/modules/split-view-worker-activity.js +2 -2
- package/lib/public/modules/split-view-worker-transcript.js +70 -33
- package/lib/public/modules/split-view-workers.js +6 -4
- package/lib/public/modules/split-view.js +9 -2
- package/lib/public/modules/sticky-notes-browser.js +2 -2
- package/lib/public/modules/terminal-viewport.js +14 -0
- package/lib/public/modules/terminal.js +49 -23
- package/lib/public/modules/theme-palette.js +177 -0
- package/lib/public/modules/theme.js +2 -180
- package/lib/public/modules/tool-pane-chrome.js +88 -0
- package/lib/public/modules/tool-pane-drag.js +134 -0
- package/lib/public/modules/tool-pane-layout.js +95 -0
- package/lib/public/modules/tool-pane-legacy.js +60 -0
- package/lib/public/modules/tool-pane-tree.js +51 -0
- package/lib/public/modules/tools.js +5 -89
- package/lib/public/modules/tooltip.js +32 -6
- package/lib/public/modules/view-legacy-coordinates.js +16 -0
- package/lib/public/modules/view-mutations.js +24 -0
- package/lib/public/modules/view-pair-presentation.js +74 -0
- package/lib/public/modules/view-pair-validation.js +12 -0
- package/lib/public/modules/view-presentation-state.js +37 -0
- package/lib/public/modules/view-workspace-controller.js +210 -0
- package/lib/public/modules/view-workspace-state.js +103 -0
- package/lib/public/modules/view-workspace-validation.js +47 -0
- package/lib/public/modules/wireframe-workbench.js +13 -2
- package/lib/public/modules/workbench-layout-preference.js +12 -5
- package/lib/public/modules/workbench-panels.js +21 -0
- package/lib/public/modules/worker-message-previews.js +39 -0
- package/lib/public/pane-assets/app-5W6KJXK5.js +1 -0
- package/lib/public/pane-assets/chunk-2IJUTAB6.js +2 -0
- package/lib/public/pane-assets/chunk-6QFLYOVY.js +1 -0
- package/lib/public/pane-assets/chunk-7OVNC5HT.js +1 -0
- package/lib/public/pane-assets/chunk-BQN7B62H.js +3 -0
- package/lib/public/pane-assets/chunk-EMLN2Y7L.js +1 -0
- package/lib/public/pane-assets/chunk-ENPAHXLB.js +1 -0
- package/lib/public/pane-assets/chunk-EPBGGZRT.js +1 -0
- package/lib/public/pane-assets/chunk-EYTE56IA.js +1 -0
- package/lib/public/pane-assets/chunk-FQTNR4ZS.js +1 -0
- package/lib/public/pane-assets/chunk-JIV7O5GN.js +1 -0
- package/lib/public/pane-assets/chunk-L6LSA5WI.js +1 -0
- package/lib/public/pane-assets/chunk-M57UIGZV.js +1 -0
- package/lib/public/pane-assets/chunk-MGTFTEJP.js +1 -0
- package/lib/public/pane-assets/chunk-MMG6MYCN.js +1 -0
- package/lib/public/pane-assets/chunk-MZLMEXMW.js +1 -0
- package/lib/public/pane-assets/chunk-OG3E5SVA.js +166 -0
- package/lib/public/pane-assets/chunk-R7QVVFUG.js +1 -0
- package/lib/public/pane-assets/chunk-RGAFZ3T2.js +1 -0
- package/lib/public/pane-assets/chunk-RNDRURMF.js +1 -0
- package/lib/public/pane-assets/chunk-SJOT74VW.js +2 -0
- package/lib/public/pane-assets/chunk-SJTGHIN5.js +1 -0
- package/lib/public/pane-assets/chunk-SLMAFKI2.js +1 -0
- package/lib/public/pane-assets/chunk-U3I5KY3B.js +1 -0
- package/lib/public/pane-assets/chunk-UPXU2IPC.js +1 -0
- package/lib/public/pane-assets/chunk-VEBYD7TL.js +1 -0
- package/lib/public/pane-assets/chunk-VZ2OKDAO.js +1 -0
- package/lib/public/pane-assets/chunk-XBHYNXXT.js +1 -0
- package/lib/public/pane-assets/manifest.json +438 -381
- package/lib/public/pane-assets/style-BSKKK54Q.css +1 -0
- package/lib/public/style.css +1 -0
- package/lib/sdk-message-processor.js +5 -2
- package/lib/server-storage.js +27 -3
- package/lib/server-workbench-layout-settings.js +3 -3
- package/lib/server.js +4 -2
- package/lib/sessions.js +1 -1
- package/lib/split-view-layout.js +11 -7
- package/lib/storage-usage.js +29 -7
- package/lib/terminal-manager.js +2 -2
- package/lib/users-workbench-layout-preferences.js +14 -4
- package/lib/workbench-window-layout.js +30 -0
- package/lib/worker-message-previews.js +50 -0
- package/lib/ws-schema.js +1 -1
- package/lib/yoke/adapters/claude-worker.js +8 -0
- package/lib/yoke/adapters/claude.js +17 -2
- package/lib/yoke/claude-task-reader.js +94 -0
- package/lib/yoke/interface.js +1 -0
- package/package.json +1 -1
- package/lib/public/pane-assets/app-6H5S2Y3Z.js +0 -1
- package/lib/public/pane-assets/chunk-3QV5SDC4.js +0 -1
- package/lib/public/pane-assets/chunk-4FM3U3DW.js +0 -1
- package/lib/public/pane-assets/chunk-7GZH3FZY.js +0 -1
- package/lib/public/pane-assets/chunk-AGJTF5WQ.js +0 -1
- package/lib/public/pane-assets/chunk-DGOFGEUK.js +0 -1
- package/lib/public/pane-assets/chunk-I57URYSL.js +0 -1
- package/lib/public/pane-assets/chunk-NPKRTUNG.js +0 -2
- package/lib/public/pane-assets/chunk-VGA2Y3D2.js +0 -2
- package/lib/public/pane-assets/chunk-WKO3T75E.js +0 -167
- package/lib/public/pane-assets/style-TSRDU54Z.css +0 -1
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { recordToolExpansion } from './view-presentation-state.js';
|
|
2
|
+
import { workspaceChanged } from './view-workspace-state.js';
|
|
1
3
|
import { store } from './store.js';
|
|
2
4
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
5
|
import { closeSidebar } from './sidebar.js';
|
|
4
6
|
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
5
7
|
import { copyToClipboard } from './utils.js';
|
|
6
|
-
import { getTerminalTheme
|
|
8
|
+
import { getTerminalTheme } from './theme.js';
|
|
7
9
|
import { getTerminalFontFamily, getTerminalFontSize, onTerminalFontChange } from './terminal-prefs.js';
|
|
8
10
|
import { createKeyToolbar } from './terminal-toolbar.js';
|
|
11
|
+
import { applyTerminalSize, hasTerminalViewport } from './terminal-viewport.js';
|
|
9
12
|
|
|
10
13
|
var ctx;
|
|
11
14
|
var tabs = new Map(); // termId -> { id, title, exited, xterm, fitAddon, bodyEl }
|
|
@@ -145,13 +148,8 @@ export function initTerminal(_ctx) {
|
|
|
145
148
|
|
|
146
149
|
// Fullscreen toggle
|
|
147
150
|
document.getElementById("terminal-fullscreen").addEventListener("click", function () {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (icon) {
|
|
151
|
-
icon.setAttribute("data-lucide", isFs ? "minimize-2" : "maximize-2");
|
|
152
|
-
refreshIcons();
|
|
153
|
-
}
|
|
154
|
-
fitTerminal();
|
|
151
|
+
setTerminalExpanded(!ctx.terminalContainerEl.classList.contains('panel-fullscreen'));
|
|
152
|
+
recordToolExpansion('terminal', ctx.terminalContainerEl.classList.contains('panel-fullscreen'));
|
|
155
153
|
});
|
|
156
154
|
|
|
157
155
|
// Header toggle button
|
|
@@ -224,6 +222,7 @@ export function openTerminal() {
|
|
|
224
222
|
|
|
225
223
|
// --- Close terminal panel (hide, detach, but keep PTYs alive) ---
|
|
226
224
|
export function closeTerminal() {
|
|
225
|
+
recordToolExpansion('terminal', false);
|
|
227
226
|
releaseRightWorkbench("terminal");
|
|
228
227
|
var container = ctx.terminalContainerEl;
|
|
229
228
|
container.classList.remove("panel-fullscreen");
|
|
@@ -279,7 +278,7 @@ function closeTab(termId) {
|
|
|
279
278
|
}
|
|
280
279
|
|
|
281
280
|
// --- Activate a tab (show xterm, attach) ---
|
|
282
|
-
function activateTab(termId) {
|
|
281
|
+
function activateTab(termId, savedBinding) {
|
|
283
282
|
var tab = tabs.get(termId);
|
|
284
283
|
if (!tab) return;
|
|
285
284
|
|
|
@@ -294,6 +293,10 @@ function activateTab(termId) {
|
|
|
294
293
|
}
|
|
295
294
|
|
|
296
295
|
activeTabId = termId;
|
|
296
|
+
var binding = (store.get("clayControlTerminalViews") || []).find(function (item) { return item.id === termId; });
|
|
297
|
+
if (binding) store.set({ savedViewTerminalResource: { id: binding.id, identity: binding.identity, runtimeId: binding.runtimeId } });
|
|
298
|
+
var unavailable = document.getElementById("terminal-saved-unavailable"); if (unavailable) unavailable.remove();
|
|
299
|
+
workspaceChanged();
|
|
297
300
|
|
|
298
301
|
// Lazy-create xterm instance
|
|
299
302
|
if (!tab.xterm) {
|
|
@@ -305,7 +308,7 @@ function activateTab(termId) {
|
|
|
305
308
|
|
|
306
309
|
// Attach to server
|
|
307
310
|
if (ctx.ws && ctx.connected) {
|
|
308
|
-
ctx.ws.send(JSON.stringify({ type: "term_attach", id: termId }));
|
|
311
|
+
ctx.ws.send(JSON.stringify({ type: "term_attach", id: termId, savedBinding: savedBinding }));
|
|
309
312
|
}
|
|
310
313
|
|
|
311
314
|
// Fit and focus
|
|
@@ -358,7 +361,7 @@ function createXtermForTab(tab) {
|
|
|
358
361
|
cursorBlink: true,
|
|
359
362
|
fontSize: getTerminalFontSize(),
|
|
360
363
|
fontFamily: getTerminalFontFamily(),
|
|
361
|
-
theme:
|
|
364
|
+
theme: getTerminalTheme(),
|
|
362
365
|
});
|
|
363
366
|
|
|
364
367
|
var fitAddon = null;
|
|
@@ -480,7 +483,7 @@ function fitTerminal() {
|
|
|
480
483
|
fitRafId = null;
|
|
481
484
|
if (!activeTabId) return;
|
|
482
485
|
var tab = tabs.get(activeTabId);
|
|
483
|
-
if (!tab || !tab.fitAddon || !tab.xterm) return;
|
|
486
|
+
if (!isOpen || !tab || !tab.fitAddon || !tab.xterm || !hasTerminalViewport(tab)) return;
|
|
484
487
|
|
|
485
488
|
try {
|
|
486
489
|
tab.fitAddon.fit();
|
|
@@ -557,11 +560,13 @@ function renderTabBar() {
|
|
|
557
560
|
|
|
558
561
|
var moreBtn = document.createElement("button");
|
|
559
562
|
moreBtn.className = "terminal-tab-more";
|
|
560
|
-
moreBtn.innerHTML = '
|
|
563
|
+
moreBtn.innerHTML = iconHtml('x');
|
|
564
|
+
moreBtn.setAttribute('aria-label', 'Close terminal tab ' + t.title);
|
|
561
565
|
moreBtn.addEventListener("click", function (e) {
|
|
562
566
|
e.stopPropagation();
|
|
563
|
-
|
|
567
|
+
closeTab(t.id);
|
|
564
568
|
});
|
|
569
|
+
el.addEventListener('contextmenu', function (event) { event.preventDefault(); showTabContextMenu(event, t, label); });
|
|
565
570
|
el.appendChild(moreBtn);
|
|
566
571
|
|
|
567
572
|
el.addEventListener("click", function () {
|
|
@@ -699,7 +704,7 @@ function updateTerminalBadge() {
|
|
|
699
704
|
// --- Handle server messages ---
|
|
700
705
|
|
|
701
706
|
export function handleTermList(msg) {
|
|
702
|
-
store.set({ clayControlTerminalViews: (msg.terminals || []).map(function (item) { return { id: item.id, identity: item.controlIdentity, revision: item.controlRevision, runtimeId: store.get('controlRuntimeId') }; }) });
|
|
707
|
+
store.set({ clayControlTerminalViews: (msg.terminals || []).map(function (item) { return { id: item.id, identity: item.controlIdentity, revision: item.controlRevision, exited: item.exited, runtimeId: store.get('controlRuntimeId') }; }) });
|
|
703
708
|
// TUI session terminals are owned by session-tui-view.js and must not
|
|
704
709
|
// appear in the bottom terminal panel. Filter them out before any tab
|
|
705
710
|
// bookkeeping so the panel never tries to render or auto-attach them.
|
|
@@ -744,6 +749,7 @@ export function handleTermList(msg) {
|
|
|
744
749
|
}
|
|
745
750
|
|
|
746
751
|
renderTabBar();
|
|
752
|
+
store.set({ savedViewTerminalListReady: true });
|
|
747
753
|
|
|
748
754
|
// If panel is open and we have tabs, re-attach
|
|
749
755
|
if (isOpen && tabs.size > 0) {
|
|
@@ -782,9 +788,7 @@ export function handleTermResized(msg) {
|
|
|
782
788
|
handleTerminalProjection(msg);
|
|
783
789
|
if (!msg.id) return;
|
|
784
790
|
var tab = tabs.get(msg.id);
|
|
785
|
-
|
|
786
|
-
tab.xterm.resize(msg.cols, msg.rows);
|
|
787
|
-
}
|
|
791
|
+
applyTerminalSize(tab, msg, isOpen && msg.id === activeTabId, fitTerminal);
|
|
788
792
|
}
|
|
789
793
|
|
|
790
794
|
export function handleTermExited(msg) {
|
|
@@ -825,6 +829,7 @@ export function handleTermClosed(msg) {
|
|
|
825
829
|
|
|
826
830
|
// --- Reset on reconnect ---
|
|
827
831
|
export function resetTerminals() {
|
|
832
|
+
store.set({ savedViewTerminalListReady: false, savedViewTerminalResource: null });
|
|
828
833
|
// Dispose all xterm instances (server state survives, client re-syncs via term_list)
|
|
829
834
|
for (var tab of tabs.values()) {
|
|
830
835
|
disposeTab(tab);
|
|
@@ -842,8 +847,8 @@ export function sendTerminalCommand(command) {
|
|
|
842
847
|
}
|
|
843
848
|
}
|
|
844
849
|
|
|
845
|
-
export function setTerminalTheme(
|
|
846
|
-
|
|
850
|
+
export function setTerminalTheme() {
|
|
851
|
+
var xtermTheme = getTerminalTheme();
|
|
847
852
|
for (var tab of tabs.values()) {
|
|
848
853
|
if (tab.xterm) {
|
|
849
854
|
tab.xterm.options.theme = xtermTheme;
|
|
@@ -851,9 +856,6 @@ export function setTerminalTheme(xtermTheme) {
|
|
|
851
856
|
}
|
|
852
857
|
}
|
|
853
858
|
|
|
854
|
-
store.subscribe(function (state, previous) {
|
|
855
|
-
if ((state.rightWorkbenchDockedOwners || []).includes('terminal') !== (previous.rightWorkbenchDockedOwners || []).includes('terminal')) setTerminalTheme(getTerminalTheme());
|
|
856
|
-
});
|
|
857
859
|
|
|
858
860
|
// Live font update: applies family/size to every open shell terminal
|
|
859
861
|
// and refits each (cell dimensions change with font size, so cols/rows
|
|
@@ -983,3 +985,27 @@ function showTermCtxMenu(e, tab) {
|
|
|
983
985
|
document.addEventListener("click", closeTermCtxMenu, { once: true });
|
|
984
986
|
}, 0);
|
|
985
987
|
}
|
|
988
|
+
|
|
989
|
+
// Restoration must never enter openTerminal's create-new branch.
|
|
990
|
+
export function restoreExistingTerminal(resource) {
|
|
991
|
+
if (!store.get('connected') || !store.get('controlRuntimeId')) return 'pending';
|
|
992
|
+
if (!store.get('savedViewTerminalListReady')) return 'pending';
|
|
993
|
+
var live = (store.get('clayControlTerminalViews') || []).find(function (item) { return item.id === resource.id && item.identity === resource.identity && item.runtimeId === resource.runtimeId && !item.exited; });
|
|
994
|
+
claimRightWorkbench('terminal');
|
|
995
|
+
var container = document.getElementById('terminal-container'); container.classList.remove('hidden');
|
|
996
|
+
if (live && tabs.has(resource.id)) { isOpen = true; activateTab(resource.id, resource); return 'restored'; }
|
|
997
|
+
isOpen = false;
|
|
998
|
+
tabs.forEach(function (tab) { if (tab.bodyEl) tab.bodyEl.style.display = 'none'; });
|
|
999
|
+
var notice = document.getElementById('terminal-saved-unavailable');
|
|
1000
|
+
if (!notice) { notice = document.createElement('p'); notice.id = 'terminal-saved-unavailable'; notice.className = 'saved-view-unavailable'; notice.setAttribute('role', 'status'); document.getElementById('terminal-body').appendChild(notice); }
|
|
1001
|
+
notice.textContent = 'This saved terminal is unavailable. Close this pane and open Terminal to choose an available shell.';
|
|
1002
|
+
return 'unavailable';
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
export function setTerminalExpanded(enabled) {
|
|
1006
|
+
var panel = document.getElementById('terminal-container'); if (!panel) return;
|
|
1007
|
+
panel.classList.toggle('panel-fullscreen', !!enabled);
|
|
1008
|
+
var icon = panel.querySelector('#terminal-fullscreen [data-lucide]');
|
|
1009
|
+
if (icon) { icon.setAttribute('data-lucide', enabled ? 'minimize-2' : 'maximize-2'); refreshIcons(); }
|
|
1010
|
+
if (!panel.classList.contains('hidden')) fitTerminal();
|
|
1011
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// --- Color utilities ---
|
|
2
|
+
|
|
3
|
+
function hexToRgb(hex) {
|
|
4
|
+
var h = hex.replace("#", "");
|
|
5
|
+
return {
|
|
6
|
+
r: parseInt(h.substring(0, 2), 16),
|
|
7
|
+
g: parseInt(h.substring(2, 4), 16),
|
|
8
|
+
b: parseInt(h.substring(4, 6), 16)
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function rgbToHex(r, g, b) {
|
|
13
|
+
return "#" + [r, g, b].map(function (v) {
|
|
14
|
+
var c = Math.max(0, Math.min(255, Math.round(v)));
|
|
15
|
+
return c.toString(16).padStart(2, "0");
|
|
16
|
+
}).join("");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function darken(hex, amount) {
|
|
20
|
+
var c = hexToRgb(hex);
|
|
21
|
+
var f = 1 - amount;
|
|
22
|
+
return rgbToHex(c.r * f, c.g * f, c.b * f);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function lighten(hex, amount) {
|
|
26
|
+
var c = hexToRgb(hex);
|
|
27
|
+
return rgbToHex(
|
|
28
|
+
c.r + (255 - c.r) * amount,
|
|
29
|
+
c.g + (255 - c.g) * amount,
|
|
30
|
+
c.b + (255 - c.b) * amount
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function mixColors(hex1, hex2, weight) {
|
|
35
|
+
var c1 = hexToRgb(hex1);
|
|
36
|
+
var c2 = hexToRgb(hex2);
|
|
37
|
+
var w = weight;
|
|
38
|
+
return rgbToHex(
|
|
39
|
+
c1.r * w + c2.r * (1 - w),
|
|
40
|
+
c1.g * w + c2.g * (1 - w),
|
|
41
|
+
c1.b * w + c2.b * (1 - w)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hexToRgba(hex, alpha) {
|
|
46
|
+
var c = hexToRgb(hex);
|
|
47
|
+
return "rgba(" + c.r + ", " + c.g + ", " + c.b + ", " + alpha + ")";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function luminance(hex) {
|
|
51
|
+
var c = hexToRgb(hex);
|
|
52
|
+
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var DEFAULT_DARK_THEME_ID = "clay-dark";
|
|
56
|
+
var DEFAULT_LIGHT_THEME_ID = "clay-light";
|
|
57
|
+
|
|
58
|
+
// Embedded defaults keep the first render branded before /api/themes loads.
|
|
59
|
+
var defaultDarkFallback = {
|
|
60
|
+
name: "Clay Studio Dark", variant: "dark",
|
|
61
|
+
base00: "171715", base01: "20201D", base02: "393934", base03: "686861",
|
|
62
|
+
base04: "A0A098", base05: "D1D1CA", base06: "E8E8E2", base07: "FAFAF5",
|
|
63
|
+
base08: "FF7479", base09: "7776FF", base0A: "E0B45B", base0B: "07E5A3",
|
|
64
|
+
base0C: "5FD2C0", base0D: "8AA7FF", base0E: "C39AF3", base0F: "D69A7D",
|
|
65
|
+
accent2: "07E5A3", link: "7F7EC8"
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
var defaultLightFallback = {
|
|
69
|
+
name: "Clay Studio Light", variant: "light",
|
|
70
|
+
base00: "F7F7F3", base01: "EEEEEA", base02: "D7D7D0", base03: "A2A29B",
|
|
71
|
+
base04: "73736C", base05: "44443F", base06: "252522", base07: "151513",
|
|
72
|
+
base08: "C84B50", base09: "5857FC", base0A: "956A19", base0B: "087B59",
|
|
73
|
+
base0C: "187A7C", base0D: "3F62B4", base0E: "7A52A8", base0F: "9A5A46",
|
|
74
|
+
accent2: "07E5A3", link: "4948B8"
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// --- Compute CSS variables from a base16 palette ---
|
|
78
|
+
function computeVars(theme) {
|
|
79
|
+
var b = {};
|
|
80
|
+
var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
81
|
+
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
82
|
+
for (var i = 0; i < keys.length; i++) {
|
|
83
|
+
b[keys[i]] = "#" + theme[keys[i]];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var isLight = theme.variant === "light";
|
|
87
|
+
var accent2 = theme.accent2 ? "#" + theme.accent2 : b.base0D;
|
|
88
|
+
var link = theme.link ? "#" + theme.link : b.base0D;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
"--bg": b.base00,
|
|
92
|
+
"--bg-alt": b.base01,
|
|
93
|
+
"--text": b.base06,
|
|
94
|
+
"--text-secondary": b.base05,
|
|
95
|
+
"--text-muted": b.base04,
|
|
96
|
+
"--text-dimmer": b.base03,
|
|
97
|
+
"--accent": b.base09,
|
|
98
|
+
"--accent-hover": isLight ? darken(b.base09, 0.12) : lighten(b.base09, 0.12),
|
|
99
|
+
"--accent-bg": hexToRgba(b.base09, 0.12),
|
|
100
|
+
"--link": link,
|
|
101
|
+
"--link-hover": isLight ? darken(link, 0.10) : lighten(link, 0.10),
|
|
102
|
+
"--code-bg": isLight ? darken(b.base00, 0.03) : darken(b.base00, 0.15),
|
|
103
|
+
"--border": b.base02,
|
|
104
|
+
"--border-subtle": mixColors(b.base00, b.base02, 0.6),
|
|
105
|
+
"--input-bg": isLight ? darken(b.base00, 0.04) : mixColors(b.base01, b.base02, 0.5),
|
|
106
|
+
"--ask-mate-bg": isLight ? mixColors("#ffffff", darken(b.base00, 0.04), 0.6) : mixColors(b.base00, mixColors(b.base01, b.base02, 0.5), 0.6),
|
|
107
|
+
"--user-bubble": isLight ? darken(b.base01, 0.03) : mixColors(b.base01, b.base02, 0.3),
|
|
108
|
+
"--error": b.base08,
|
|
109
|
+
"--success": b.base0B,
|
|
110
|
+
"--warning": b.base0A,
|
|
111
|
+
"--sidebar-bg": isLight ? darken(b.base00, 0.02) : darken(b.base00, 0.10),
|
|
112
|
+
"--sidebar-hover": isLight ? darken(b.base00, 0.06) : mixColors(b.base00, b.base01, 0.5),
|
|
113
|
+
"--sidebar-active": isLight ? darken(b.base01, 0.05) : mixColors(b.base01, b.base02, 0.5),
|
|
114
|
+
"--filebrowser-bg": isLight ? lighten(b.base00, 0.03) : lighten(b.base00, 0.04),
|
|
115
|
+
"--filebrowser-border": isLight ? darken(b.base00, 0.08) : mixColors(b.base02, b.base00, 0.5),
|
|
116
|
+
"--accent-8": hexToRgba(b.base09, 0.08),
|
|
117
|
+
"--accent-12": hexToRgba(b.base09, 0.12),
|
|
118
|
+
"--accent-15": hexToRgba(b.base09, 0.15),
|
|
119
|
+
"--accent-20": hexToRgba(b.base09, 0.20),
|
|
120
|
+
"--accent-25": hexToRgba(b.base09, 0.25),
|
|
121
|
+
"--accent-30": hexToRgba(b.base09, 0.30),
|
|
122
|
+
"--accent2": accent2,
|
|
123
|
+
"--accent2-hover": isLight ? darken(accent2, 0.12) : lighten(accent2, 0.12),
|
|
124
|
+
"--accent2-bg": hexToRgba(accent2, 0.12),
|
|
125
|
+
"--accent2-8": hexToRgba(accent2, 0.08),
|
|
126
|
+
"--accent2-12": hexToRgba(accent2, 0.12),
|
|
127
|
+
"--accent2-15": hexToRgba(accent2, 0.15),
|
|
128
|
+
"--accent2-20": hexToRgba(accent2, 0.20),
|
|
129
|
+
"--accent2-25": hexToRgba(accent2, 0.25),
|
|
130
|
+
"--accent2-30": hexToRgba(accent2, 0.30),
|
|
131
|
+
"--error-8": hexToRgba(b.base08, 0.08),
|
|
132
|
+
"--error-12": hexToRgba(b.base08, 0.12),
|
|
133
|
+
"--error-15": hexToRgba(b.base08, 0.15),
|
|
134
|
+
"--error-25": hexToRgba(b.base08, 0.25),
|
|
135
|
+
"--success-8": hexToRgba(b.base0B, 0.08),
|
|
136
|
+
"--success-12": hexToRgba(b.base0B, 0.12),
|
|
137
|
+
"--success-15": hexToRgba(b.base0B, 0.15),
|
|
138
|
+
"--success-25": hexToRgba(b.base0B, 0.25),
|
|
139
|
+
"--warning-bg": hexToRgba(b.base0A, 0.12),
|
|
140
|
+
"--overlay-rgb": isLight ? "0,0,0" : "255,255,255",
|
|
141
|
+
"--shadow-rgb": "0,0,0",
|
|
142
|
+
"--hl-comment": b.base03,
|
|
143
|
+
"--hl-keyword": b.base0E,
|
|
144
|
+
"--hl-string": b.base0B,
|
|
145
|
+
"--hl-number": b.base09,
|
|
146
|
+
"--hl-function": b.base0D,
|
|
147
|
+
"--hl-variable": b.base08,
|
|
148
|
+
"--hl-type": b.base0A,
|
|
149
|
+
"--hl-constant": b.base09,
|
|
150
|
+
"--hl-tag": b.base08,
|
|
151
|
+
"--hl-attr": b.base0D,
|
|
152
|
+
"--hl-regexp": b.base0C,
|
|
153
|
+
"--hl-meta": b.base0F,
|
|
154
|
+
"--hl-builtin": b.base09,
|
|
155
|
+
"--hl-symbol": b.base0F,
|
|
156
|
+
"--hl-addition": b.base0B,
|
|
157
|
+
"--hl-deletion": b.base08
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function validateTheme(t) {
|
|
162
|
+
if (!t || typeof t !== "object") return false;
|
|
163
|
+
if (!t.name || typeof t.name !== "string") return false;
|
|
164
|
+
var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
165
|
+
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
166
|
+
for (var i = 0; i < keys.length; i++) {
|
|
167
|
+
if (!t[keys[i]] || !/^[0-9a-fA-F]{6}$/.test(t[keys[i]])) return false;
|
|
168
|
+
}
|
|
169
|
+
if (t.variant && t.variant !== "dark" && t.variant !== "light") return false;
|
|
170
|
+
if (!t.variant) {
|
|
171
|
+
t.variant = luminance("#" + t.base00) > 0.5 ? "light" : "dark";
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
export { hexToRgb, rgbToHex, darken, lighten, mixColors, hexToRgba, luminance, computeVars, validateTheme, defaultDarkFallback, defaultLightFallback, DEFAULT_DARK_THEME_ID, DEFAULT_LIGHT_THEME_ID };
|
|
@@ -5,165 +5,7 @@ import { setTuiSessionTheme } from './session-tui-view.js';
|
|
|
5
5
|
import { setTuiAttentionTheme } from './tui-attention.js';
|
|
6
6
|
import { updateMermaidTheme } from './markdown.js';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function hexToRgb(hex) {
|
|
11
|
-
var h = hex.replace("#", "");
|
|
12
|
-
return {
|
|
13
|
-
r: parseInt(h.substring(0, 2), 16),
|
|
14
|
-
g: parseInt(h.substring(2, 4), 16),
|
|
15
|
-
b: parseInt(h.substring(4, 6), 16)
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function rgbToHex(r, g, b) {
|
|
20
|
-
return "#" + [r, g, b].map(function (v) {
|
|
21
|
-
var c = Math.max(0, Math.min(255, Math.round(v)));
|
|
22
|
-
return c.toString(16).padStart(2, "0");
|
|
23
|
-
}).join("");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function darken(hex, amount) {
|
|
27
|
-
var c = hexToRgb(hex);
|
|
28
|
-
var f = 1 - amount;
|
|
29
|
-
return rgbToHex(c.r * f, c.g * f, c.b * f);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function lighten(hex, amount) {
|
|
33
|
-
var c = hexToRgb(hex);
|
|
34
|
-
return rgbToHex(
|
|
35
|
-
c.r + (255 - c.r) * amount,
|
|
36
|
-
c.g + (255 - c.g) * amount,
|
|
37
|
-
c.b + (255 - c.b) * amount
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function mixColors(hex1, hex2, weight) {
|
|
42
|
-
var c1 = hexToRgb(hex1);
|
|
43
|
-
var c2 = hexToRgb(hex2);
|
|
44
|
-
var w = weight;
|
|
45
|
-
return rgbToHex(
|
|
46
|
-
c1.r * w + c2.r * (1 - w),
|
|
47
|
-
c1.g * w + c2.g * (1 - w),
|
|
48
|
-
c1.b * w + c2.b * (1 - w)
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function hexToRgba(hex, alpha) {
|
|
53
|
-
var c = hexToRgb(hex);
|
|
54
|
-
return "rgba(" + c.r + ", " + c.g + ", " + c.b + ", " + alpha + ")";
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function luminance(hex) {
|
|
58
|
-
var c = hexToRgb(hex);
|
|
59
|
-
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
var DEFAULT_DARK_THEME_ID = "clay-dark";
|
|
63
|
-
var DEFAULT_LIGHT_THEME_ID = "clay-light";
|
|
64
|
-
|
|
65
|
-
// Embedded defaults keep the first render branded before /api/themes loads.
|
|
66
|
-
var defaultDarkFallback = {
|
|
67
|
-
name: "Clay Studio Dark", variant: "dark",
|
|
68
|
-
base00: "171715", base01: "20201D", base02: "393934", base03: "686861",
|
|
69
|
-
base04: "A0A098", base05: "D1D1CA", base06: "E8E8E2", base07: "FAFAF5",
|
|
70
|
-
base08: "FF7479", base09: "7776FF", base0A: "E0B45B", base0B: "07E5A3",
|
|
71
|
-
base0C: "5FD2C0", base0D: "8AA7FF", base0E: "C39AF3", base0F: "D69A7D",
|
|
72
|
-
accent2: "07E5A3", link: "7F7EC8"
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
var defaultLightFallback = {
|
|
76
|
-
name: "Clay Studio Light", variant: "light",
|
|
77
|
-
base00: "F7F7F3", base01: "EEEEEA", base02: "D7D7D0", base03: "A2A29B",
|
|
78
|
-
base04: "73736C", base05: "44443F", base06: "252522", base07: "151513",
|
|
79
|
-
base08: "C84B50", base09: "5857FC", base0A: "956A19", base0B: "087B59",
|
|
80
|
-
base0C: "187A7C", base0D: "3F62B4", base0E: "7A52A8", base0F: "9A5A46",
|
|
81
|
-
accent2: "07E5A3", link: "4948B8"
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// --- Compute CSS variables from a base16 palette ---
|
|
85
|
-
function computeVars(theme) {
|
|
86
|
-
var b = {};
|
|
87
|
-
var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
88
|
-
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
89
|
-
for (var i = 0; i < keys.length; i++) {
|
|
90
|
-
b[keys[i]] = "#" + theme[keys[i]];
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
var isLight = theme.variant === "light";
|
|
94
|
-
var accent2 = theme.accent2 ? "#" + theme.accent2 : b.base0D;
|
|
95
|
-
var link = theme.link ? "#" + theme.link : b.base0D;
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
"--bg": b.base00,
|
|
99
|
-
"--bg-alt": b.base01,
|
|
100
|
-
"--text": b.base06,
|
|
101
|
-
"--text-secondary": b.base05,
|
|
102
|
-
"--text-muted": b.base04,
|
|
103
|
-
"--text-dimmer": b.base03,
|
|
104
|
-
"--accent": b.base09,
|
|
105
|
-
"--accent-hover": isLight ? darken(b.base09, 0.12) : lighten(b.base09, 0.12),
|
|
106
|
-
"--accent-bg": hexToRgba(b.base09, 0.12),
|
|
107
|
-
"--link": link,
|
|
108
|
-
"--link-hover": isLight ? darken(link, 0.10) : lighten(link, 0.10),
|
|
109
|
-
"--code-bg": isLight ? darken(b.base00, 0.03) : darken(b.base00, 0.15),
|
|
110
|
-
"--border": b.base02,
|
|
111
|
-
"--border-subtle": mixColors(b.base00, b.base02, 0.6),
|
|
112
|
-
"--input-bg": isLight ? darken(b.base00, 0.04) : mixColors(b.base01, b.base02, 0.5),
|
|
113
|
-
"--ask-mate-bg": isLight ? mixColors("#ffffff", darken(b.base00, 0.04), 0.6) : mixColors(b.base00, mixColors(b.base01, b.base02, 0.5), 0.6),
|
|
114
|
-
"--user-bubble": isLight ? darken(b.base01, 0.03) : mixColors(b.base01, b.base02, 0.3),
|
|
115
|
-
"--error": b.base08,
|
|
116
|
-
"--success": b.base0B,
|
|
117
|
-
"--warning": b.base0A,
|
|
118
|
-
"--sidebar-bg": isLight ? darken(b.base00, 0.02) : darken(b.base00, 0.10),
|
|
119
|
-
"--sidebar-hover": isLight ? darken(b.base00, 0.06) : mixColors(b.base00, b.base01, 0.5),
|
|
120
|
-
"--sidebar-active": isLight ? darken(b.base01, 0.05) : mixColors(b.base01, b.base02, 0.5),
|
|
121
|
-
"--filebrowser-bg": isLight ? lighten(b.base00, 0.03) : lighten(b.base00, 0.04),
|
|
122
|
-
"--filebrowser-border": isLight ? darken(b.base00, 0.08) : mixColors(b.base02, b.base00, 0.5),
|
|
123
|
-
"--accent-8": hexToRgba(b.base09, 0.08),
|
|
124
|
-
"--accent-12": hexToRgba(b.base09, 0.12),
|
|
125
|
-
"--accent-15": hexToRgba(b.base09, 0.15),
|
|
126
|
-
"--accent-20": hexToRgba(b.base09, 0.20),
|
|
127
|
-
"--accent-25": hexToRgba(b.base09, 0.25),
|
|
128
|
-
"--accent-30": hexToRgba(b.base09, 0.30),
|
|
129
|
-
"--accent2": accent2,
|
|
130
|
-
"--accent2-hover": isLight ? darken(accent2, 0.12) : lighten(accent2, 0.12),
|
|
131
|
-
"--accent2-bg": hexToRgba(accent2, 0.12),
|
|
132
|
-
"--accent2-8": hexToRgba(accent2, 0.08),
|
|
133
|
-
"--accent2-12": hexToRgba(accent2, 0.12),
|
|
134
|
-
"--accent2-15": hexToRgba(accent2, 0.15),
|
|
135
|
-
"--accent2-20": hexToRgba(accent2, 0.20),
|
|
136
|
-
"--accent2-25": hexToRgba(accent2, 0.25),
|
|
137
|
-
"--accent2-30": hexToRgba(accent2, 0.30),
|
|
138
|
-
"--error-8": hexToRgba(b.base08, 0.08),
|
|
139
|
-
"--error-12": hexToRgba(b.base08, 0.12),
|
|
140
|
-
"--error-15": hexToRgba(b.base08, 0.15),
|
|
141
|
-
"--error-25": hexToRgba(b.base08, 0.25),
|
|
142
|
-
"--success-8": hexToRgba(b.base0B, 0.08),
|
|
143
|
-
"--success-12": hexToRgba(b.base0B, 0.12),
|
|
144
|
-
"--success-15": hexToRgba(b.base0B, 0.15),
|
|
145
|
-
"--success-25": hexToRgba(b.base0B, 0.25),
|
|
146
|
-
"--warning-bg": hexToRgba(b.base0A, 0.12),
|
|
147
|
-
"--overlay-rgb": isLight ? "0,0,0" : "255,255,255",
|
|
148
|
-
"--shadow-rgb": "0,0,0",
|
|
149
|
-
"--hl-comment": b.base03,
|
|
150
|
-
"--hl-keyword": b.base0E,
|
|
151
|
-
"--hl-string": b.base0B,
|
|
152
|
-
"--hl-number": b.base09,
|
|
153
|
-
"--hl-function": b.base0D,
|
|
154
|
-
"--hl-variable": b.base08,
|
|
155
|
-
"--hl-type": b.base0A,
|
|
156
|
-
"--hl-constant": b.base09,
|
|
157
|
-
"--hl-tag": b.base08,
|
|
158
|
-
"--hl-attr": b.base0D,
|
|
159
|
-
"--hl-regexp": b.base0C,
|
|
160
|
-
"--hl-meta": b.base0F,
|
|
161
|
-
"--hl-builtin": b.base09,
|
|
162
|
-
"--hl-symbol": b.base0F,
|
|
163
|
-
"--hl-addition": b.base0B,
|
|
164
|
-
"--hl-deletion": b.base08
|
|
165
|
-
};
|
|
166
|
-
}
|
|
8
|
+
import { hexToRgb, rgbToHex, darken, lighten, mixColors, hexToRgba, luminance, computeVars, validateTheme, defaultDarkFallback, defaultLightFallback, DEFAULT_DARK_THEME_ID, DEFAULT_LIGHT_THEME_ID } from './theme-palette.js';
|
|
167
9
|
|
|
168
10
|
var defaultExactVars = computeVars(defaultDarkFallback);
|
|
169
11
|
|
|
@@ -267,11 +109,6 @@ export function getTerminalTheme() {
|
|
|
267
109
|
return computeTerminalTheme(getTheme(DEFAULT_DARK_THEME_ID) || defaultDarkFallback);
|
|
268
110
|
}
|
|
269
111
|
|
|
270
|
-
export function getDockedTerminalTheme() {
|
|
271
|
-
var theme = getCurrentTheme();
|
|
272
|
-
return Object.assign({}, computeTerminalTheme(theme), { background: '#' + theme.base00 });
|
|
273
|
-
}
|
|
274
|
-
|
|
275
112
|
export function getMermaidThemeVars() {
|
|
276
113
|
return computeMermaidVars(getCurrentTheme());
|
|
277
114
|
}
|
|
@@ -332,7 +169,7 @@ export function applyTheme(themeId, fromPicker) {
|
|
|
332
169
|
// Terminals deliberately keep Clay Studio Dark for predictable ANSI
|
|
333
170
|
// contrast, even while the surrounding workspace uses a light theme.
|
|
334
171
|
var termTheme = getTerminalTheme();
|
|
335
|
-
try { setTerminalTheme(
|
|
172
|
+
try { setTerminalTheme(); } catch (e) {}
|
|
336
173
|
try { setTuiSessionTheme(termTheme); } catch (e) {}
|
|
337
174
|
try { setTuiAttentionTheme(termTheme); } catch (e) {}
|
|
338
175
|
|
|
@@ -401,21 +238,6 @@ function loadThemes() {
|
|
|
401
238
|
});
|
|
402
239
|
}
|
|
403
240
|
|
|
404
|
-
function validateTheme(t) {
|
|
405
|
-
if (!t || typeof t !== "object") return false;
|
|
406
|
-
if (!t.name || typeof t.name !== "string") return false;
|
|
407
|
-
var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
408
|
-
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
409
|
-
for (var i = 0; i < keys.length; i++) {
|
|
410
|
-
if (!t[keys[i]] || !/^[0-9a-fA-F]{6}$/.test(t[keys[i]])) return false;
|
|
411
|
-
}
|
|
412
|
-
if (t.variant && t.variant !== "dark" && t.variant !== "light") return false;
|
|
413
|
-
if (!t.variant) {
|
|
414
|
-
t.variant = luminance("#" + t.base00) > 0.5 ? "light" : "dark";
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
241
|
// --- Light / Dark mode toggle ---
|
|
420
242
|
|
|
421
243
|
// Returns the system preferred mode
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { WORKBENCH_PANELS } from './workbench-panels.js';
|
|
2
|
+
import { recordToolExpansion } from './view-presentation-state.js';
|
|
3
|
+
import { store } from './store.js';
|
|
4
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
5
|
+
import { TOOL_PANES } from './tool-pane-tree.js';
|
|
6
|
+
|
|
7
|
+
function titleFor(panel, name) {
|
|
8
|
+
if (name === 'terminal') {
|
|
9
|
+
var state = store.snap(), project = (state.projectsHubList || []).find(function (item) { return item && item.slug === state.currentSlug; });
|
|
10
|
+
var projectName = project && (project.title || project.project || project.name) || state.projectName || state.currentSlug;
|
|
11
|
+
return projectName ? projectName + ' · Terminal' : 'Terminal';
|
|
12
|
+
}
|
|
13
|
+
if (name === 'file-viewer') { var tab = panel.querySelector('.file-viewer-tab.active .file-viewer-tab-label'); return tab && tab.textContent || 'Files'; }
|
|
14
|
+
var browser = store.get('sharedBrowser');
|
|
15
|
+
try { return browser && browser.url ? new URL(browser.url).hostname : 'Browser'; } catch (error) { return 'Browser'; }
|
|
16
|
+
}
|
|
17
|
+
export function renderToolPaneChrome(panel, name) {
|
|
18
|
+
if (panel.dataset.fileInstance) return;
|
|
19
|
+
if (WORKBENCH_PANELS[name]) { renderWorkbenchChrome(panel, name); return; }
|
|
20
|
+
var definition = TOOL_PANES[name];
|
|
21
|
+
if (!definition) return;
|
|
22
|
+
var header = panel.querySelector(':scope > .tool-pane-header');
|
|
23
|
+
if (!header) {
|
|
24
|
+
var original = panel.querySelector(name === 'terminal' ? '.terminal-header' : name === 'browser' ? '.shared-browser-header' : '.file-viewer-tabbar');
|
|
25
|
+
if (!original) return;
|
|
26
|
+
header = document.createElement('header'); header.className = 'tool-pane-header split-pane-header'; header.dataset.toolPane = name;
|
|
27
|
+
var kind = document.createElement('span'); kind.className = 'tool-pane-kind' + (name === 'terminal' ? '' : ' split-view-runtime');
|
|
28
|
+
kind.innerHTML = iconHtml(definition.icon) + (name === 'terminal' ? '' : '<span class="split-view-model">' + definition.label + '</span>');
|
|
29
|
+
var title = document.createElement('span'); title.className = 'tool-pane-title split-pane-title';
|
|
30
|
+
var space = document.createElement('span'); space.className = 'split-pane-drag-space'; space.title = 'Drag to rearrange panes'; space.setAttribute('aria-hidden', 'true');
|
|
31
|
+
var actions = original.querySelector('.terminal-header-actions, .shared-browser-window, .file-viewer-window-actions');
|
|
32
|
+
header.append(kind, title, space); if (actions) header.appendChild(actions);
|
|
33
|
+
panel.insertBefore(header, panel.firstChild);
|
|
34
|
+
if (name === 'browser') {
|
|
35
|
+
header.classList.add('browser-pane-header');
|
|
36
|
+
var tabs = panel.querySelector('.shared-browser-tabs');
|
|
37
|
+
if (tabs) header.insertBefore(tabs, space);
|
|
38
|
+
kind.setAttribute('aria-label', 'Browser'); kind.setAttribute('data-tip', 'Browser');
|
|
39
|
+
original.hidden = true; var close = header.querySelector('[data-action="hide"]'); if (close) { close.title = 'Close browser pane'; close.setAttribute('aria-label', 'Close browser pane'); }
|
|
40
|
+
}
|
|
41
|
+
else original.classList.add('tool-pane-tab-row');
|
|
42
|
+
var observer = new MutationObserver(function () { update(); });
|
|
43
|
+
observer.observe(panel, { childList: true, characterData: true, subtree: true, attributes: true, attributeFilter: ['aria-selected'] });
|
|
44
|
+
panel.addEventListener('clay-tool-pane-dispose', function () { observer.disconnect(); }, { once: true });
|
|
45
|
+
refreshIcons();
|
|
46
|
+
}
|
|
47
|
+
function update() {
|
|
48
|
+
var label = titleFor(panel, name), title = header.querySelector('.tool-pane-title');
|
|
49
|
+
if (title.textContent !== label) { title.textContent = label; title.title = label; }
|
|
50
|
+
}
|
|
51
|
+
update();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
store.subscribe(function (state, previous) {
|
|
55
|
+
if (state.projectName === previous.projectName && state.projectsHubList === previous.projectsHubList && state.currentSlug === previous.currentSlug) return;
|
|
56
|
+
var panel = document.getElementById('terminal-container');
|
|
57
|
+
if (panel && panel.querySelector(':scope > .tool-pane-header')) renderToolPaneChrome(panel, 'terminal');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
function renderWorkbenchChrome(panel, name) {
|
|
61
|
+
panel.classList.add('workbench-pane-shell');
|
|
62
|
+
var header = panel.querySelector(':scope > header');
|
|
63
|
+
if (!header || header.dataset.toolPane === name) return;
|
|
64
|
+
header.dataset.toolPane = name;
|
|
65
|
+
header.classList.add('tool-pane-header', 'split-pane-header');
|
|
66
|
+
var actions = header.querySelector('[class*="window-actions"], :scope > div:last-child');
|
|
67
|
+
if (!actions) {
|
|
68
|
+
actions = document.createElement('div');
|
|
69
|
+
Array.from(header.querySelectorAll(':scope > button')).forEach(function (button) {
|
|
70
|
+
var label = button.getAttribute('aria-label') || '';
|
|
71
|
+
if (/^(Widen|Close)|fullscreen/i.test(label)) actions.appendChild(button);
|
|
72
|
+
});
|
|
73
|
+
header.appendChild(actions);
|
|
74
|
+
}
|
|
75
|
+
actions.classList.add('workbench-pane-actions');
|
|
76
|
+
var title = header.querySelector('strong, [class$="-title"]');
|
|
77
|
+
if (title) title.classList.add('tool-pane-title');
|
|
78
|
+
var space = document.createElement('span'); space.className = 'split-pane-drag-space';
|
|
79
|
+
space.title = 'Drag to rearrange panes'; space.setAttribute('aria-hidden', 'true');
|
|
80
|
+
header.insertBefore(space, actions);
|
|
81
|
+
var expanded = panel.classList.contains('panel-fullscreen');
|
|
82
|
+
var observer = new MutationObserver(function () {
|
|
83
|
+
var next = panel.classList.contains('panel-fullscreen');
|
|
84
|
+
if (next !== expanded) { expanded = next; recordToolExpansion(name, next); }
|
|
85
|
+
});
|
|
86
|
+
observer.observe(panel, { attributes: true, attributeFilter: ['class'] });
|
|
87
|
+
panel.addEventListener('clay-tool-pane-dispose', function () { observer.disconnect(); }, { once: true });
|
|
88
|
+
}
|