clay-server 5.3.0-beta.6 → 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/project-admin-overview.js +22 -11
- package/lib/project-background-tasks.js +76 -0
- package/lib/project-connection.js +1 -1
- package/lib/project-sessions.js +12 -5
- package/lib/project-split-views.js +12 -3
- package/lib/project-view-store.js +7 -5
- package/lib/project-worker-conversation.js +5 -0
- package/lib/public/app.js +7 -0
- package/lib/public/css/contextual-clay.css +2 -1
- package/lib/public/css/mate-conversation.css +1 -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/shared-browser.css +31 -8
- package/lib/public/css/split-view-layout.css +92 -7
- package/lib/public/css/tool-pane.css +4 -7
- package/lib/public/index.html +5 -5
- 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/contextual-clay-geometry.js +7 -3
- package/lib/public/modules/pane-activation.js +5 -3
- 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/project-admin-overview.js +125 -10
- package/lib/public/modules/project-grouping.js +9 -0
- 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/sidebar-projects.js +1 -10
- 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-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-renderer.js +8 -8
- 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/terminal-viewport.js +14 -0
- package/lib/public/modules/terminal.js +3 -4
- package/lib/public/modules/theme-palette.js +177 -0
- package/lib/public/modules/theme.js +1 -174
- package/lib/public/modules/tool-pane-chrome.js +7 -1
- package/lib/public/modules/tools.js +5 -89
- package/lib/public/modules/tooltip.js +32 -6
- package/lib/public/modules/wireframe-workbench.js +2 -2
- 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-BMHTBRMO.js → chunk-7OVNC5HT.js} +1 -1
- package/lib/public/pane-assets/chunk-BQN7B62H.js +3 -0
- package/lib/public/pane-assets/{chunk-2AIWCI6Y.js → chunk-EMLN2Y7L.js} +1 -1
- package/lib/public/pane-assets/{chunk-VKYBAVWT.js → chunk-ENPAHXLB.js} +1 -1
- 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-6NYCNWVF.js → chunk-FQTNR4ZS.js} +1 -1
- 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-RGAFZ3T2.js +1 -0
- package/lib/public/pane-assets/chunk-RNDRURMF.js +1 -0
- package/lib/public/pane-assets/{chunk-PV4PCH2V.js → chunk-SJOT74VW.js} +1 -1
- package/lib/public/pane-assets/{chunk-LDIZLKB2.js → chunk-SJTGHIN5.js} +1 -1
- 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-VNAV23CM.js → chunk-UPXU2IPC.js} +1 -1
- package/lib/public/pane-assets/{chunk-TMGSDFJI.js → chunk-VEBYD7TL.js} +1 -1
- package/lib/public/pane-assets/chunk-XBHYNXXT.js +1 -0
- package/lib/public/pane-assets/manifest.json +426 -414
- package/lib/public/pane-assets/style-BSKKK54Q.css +1 -0
- package/lib/sdk-message-processor.js +5 -2
- package/lib/server-storage.js +27 -3
- package/lib/server.js +4 -2
- package/lib/sessions.js +1 -1
- package/lib/storage-usage.js +29 -7
- package/lib/terminal-manager.js +2 -2
- 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-7UZ727NA.js +0 -1
- package/lib/public/pane-assets/chunk-6MIHIQ2W.js +0 -1
- package/lib/public/pane-assets/chunk-6UJ2ALOB.js +0 -1
- package/lib/public/pane-assets/chunk-6XK2OATZ.js +0 -1
- package/lib/public/pane-assets/chunk-BKIDR2ME.js +0 -1
- package/lib/public/pane-assets/chunk-GEFCFZEN.js +0 -1
- package/lib/public/pane-assets/chunk-GN2NQEVC.js +0 -2
- package/lib/public/pane-assets/chunk-IMLMBPT4.js +0 -166
- package/lib/public/pane-assets/chunk-K5S6AILM.js +0 -1
- package/lib/public/pane-assets/chunk-OWNNLZ36.js +0 -1
- package/lib/public/pane-assets/chunk-P2C3LOWL.js +0 -3
- package/lib/public/pane-assets/chunk-R4LMPTKU.js +0 -1
- package/lib/public/pane-assets/chunk-VWTHIQCE.js +0 -1
- package/lib/public/pane-assets/chunk-WM3K5AFH.js +0 -1
- package/lib/public/pane-assets/chunk-XOB3O327.js +0 -1
- package/lib/public/pane-assets/chunk-XOOUCFYT.js +0 -1
- package/lib/public/pane-assets/style-ZM7OOU3M.css +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Attachment snapshots describe the previous PTY size, not the current pane.
|
|
2
|
+
export function hasTerminalViewport(tab) {
|
|
3
|
+
var rect = tab && tab.bodyEl && tab.bodyEl.getBoundingClientRect();
|
|
4
|
+
return !!(rect && rect.width > 0 && rect.height > 0);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function applyTerminalSize(tab, message, active, refit) {
|
|
8
|
+
if (!tab || !tab.xterm || !(message.cols > 0 && message.rows > 0)) return;
|
|
9
|
+
if (message.initial === true && active) {
|
|
10
|
+
if (hasTerminalViewport(tab)) refit();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
tab.xterm.resize(message.cols, message.rows);
|
|
14
|
+
}
|
|
@@ -8,6 +8,7 @@ import { copyToClipboard } from './utils.js';
|
|
|
8
8
|
import { getTerminalTheme } from './theme.js';
|
|
9
9
|
import { getTerminalFontFamily, getTerminalFontSize, onTerminalFontChange } from './terminal-prefs.js';
|
|
10
10
|
import { createKeyToolbar } from './terminal-toolbar.js';
|
|
11
|
+
import { applyTerminalSize, hasTerminalViewport } from './terminal-viewport.js';
|
|
11
12
|
|
|
12
13
|
var ctx;
|
|
13
14
|
var tabs = new Map(); // termId -> { id, title, exited, xterm, fitAddon, bodyEl }
|
|
@@ -482,7 +483,7 @@ function fitTerminal() {
|
|
|
482
483
|
fitRafId = null;
|
|
483
484
|
if (!activeTabId) return;
|
|
484
485
|
var tab = tabs.get(activeTabId);
|
|
485
|
-
if (!tab || !tab.fitAddon || !tab.xterm) return;
|
|
486
|
+
if (!isOpen || !tab || !tab.fitAddon || !tab.xterm || !hasTerminalViewport(tab)) return;
|
|
486
487
|
|
|
487
488
|
try {
|
|
488
489
|
tab.fitAddon.fit();
|
|
@@ -787,9 +788,7 @@ export function handleTermResized(msg) {
|
|
|
787
788
|
handleTerminalProjection(msg);
|
|
788
789
|
if (!msg.id) return;
|
|
789
790
|
var tab = tabs.get(msg.id);
|
|
790
|
-
|
|
791
|
-
tab.xterm.resize(msg.cols, msg.rows);
|
|
792
|
-
}
|
|
791
|
+
applyTerminalSize(tab, msg, isOpen && msg.id === activeTabId, fitTerminal);
|
|
793
792
|
}
|
|
794
793
|
|
|
795
794
|
export function handleTermExited(msg) {
|
|
@@ -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
|
|
|
@@ -396,21 +238,6 @@ function loadThemes() {
|
|
|
396
238
|
});
|
|
397
239
|
}
|
|
398
240
|
|
|
399
|
-
function validateTheme(t) {
|
|
400
|
-
if (!t || typeof t !== "object") return false;
|
|
401
|
-
if (!t.name || typeof t.name !== "string") return false;
|
|
402
|
-
var keys = ["base00","base01","base02","base03","base04","base05","base06","base07",
|
|
403
|
-
"base08","base09","base0A","base0B","base0C","base0D","base0E","base0F"];
|
|
404
|
-
for (var i = 0; i < keys.length; i++) {
|
|
405
|
-
if (!t[keys[i]] || !/^[0-9a-fA-F]{6}$/.test(t[keys[i]])) return false;
|
|
406
|
-
}
|
|
407
|
-
if (t.variant && t.variant !== "dark" && t.variant !== "light") return false;
|
|
408
|
-
if (!t.variant) {
|
|
409
|
-
t.variant = luminance("#" + t.base00) > 0.5 ? "light" : "dark";
|
|
410
|
-
}
|
|
411
|
-
return true;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
241
|
// --- Light / Dark mode toggle ---
|
|
415
242
|
|
|
416
243
|
// Returns the system preferred mode
|
|
@@ -31,7 +31,13 @@ export function renderToolPaneChrome(panel, name) {
|
|
|
31
31
|
var actions = original.querySelector('.terminal-header-actions, .shared-browser-window, .file-viewer-window-actions');
|
|
32
32
|
header.append(kind, title, space); if (actions) header.appendChild(actions);
|
|
33
33
|
panel.insertBefore(header, panel.firstChild);
|
|
34
|
-
if (name === 'browser') {
|
|
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
|
+
}
|
|
35
41
|
else original.classList.add('tool-pane-tab-row');
|
|
36
42
|
var observer = new MutationObserver(function () { update(); });
|
|
37
43
|
observer.observe(panel, { childList: true, characterData: true, subtree: true, attributes: true, attributeFilter: ['aria-selected'] });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { createSessionToolItem, createSessionToolGroup, sessionToolGroupSummary } from './session-tool-item.js';
|
|
1
2
|
import { renderProductReview } from './product-review.js';
|
|
2
|
-
import { clayToolGroupSummary } from './clay-tool-presentation.js';
|
|
3
3
|
import { applyClayToolItem, applyClayToolResult, finishClayToolItem, findEndedClayTool, clayToolResultGroup, bindToolGroupDisclosure, syncToolGroupDisclosure, syncClayToolGroup } from './clay-tool-activity.js';
|
|
4
4
|
import { rememberMountedToolGroup, mountedToolGroup, transcriptToolGroups, popupChatRenderingEnabled, popupChatRenderingActive, syncPopupActivityGroup, syncPopupChatToolGroups as syncPopupGroups } from './popup-chat-rendering.js';
|
|
5
5
|
import { escapeHtml, copyToClipboard } from './utils.js';
|
|
@@ -80,61 +80,12 @@ function findToolGroup(groupId) {
|
|
|
80
80
|
return toolGroups[groupId] || null;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
function toolGroupSummary(group) {
|
|
84
|
-
var claySummary = clayToolGroupSummary(group, tools);
|
|
85
|
-
if (claySummary) return claySummary;
|
|
86
|
-
var names = group.toolNames;
|
|
87
|
-
var count = names.length;
|
|
88
|
-
var allDone = group.doneCount >= count;
|
|
89
|
-
|
|
90
|
-
// Count by tool name
|
|
91
|
-
var counts = {};
|
|
92
|
-
for (var i = 0; i < names.length; i++) {
|
|
93
|
-
counts[names[i]] = (counts[names[i]] || 0) + 1;
|
|
94
|
-
}
|
|
95
|
-
var uniqueNames = Object.keys(counts);
|
|
96
|
-
|
|
97
|
-
if (uniqueNames.length === 1) {
|
|
98
|
-
var name = uniqueNames[0];
|
|
99
|
-
var n = counts[name];
|
|
100
|
-
if (allDone) {
|
|
101
|
-
switch (name) {
|
|
102
|
-
case "Read": return "Read " + n + " file" + (n > 1 ? "s" : "");
|
|
103
|
-
case "Edit": return "Edited " + n + " file" + (n > 1 ? "s" : "");
|
|
104
|
-
case "Write": return "Wrote " + n + " file" + (n > 1 ? "s" : "");
|
|
105
|
-
case "Bash": return "Ran " + n + " command" + (n > 1 ? "s" : "");
|
|
106
|
-
case "Grep": return "Searched " + n + " pattern" + (n > 1 ? "s" : "");
|
|
107
|
-
case "Glob": return "Found " + n + " pattern" + (n > 1 ? "s" : "");
|
|
108
|
-
case "Task": return "Ran " + n + " task" + (n > 1 ? "s" : "");
|
|
109
|
-
case "WebSearch": return "Searched " + n + " quer" + (n > 1 ? "ies" : "y");
|
|
110
|
-
case "WebFetch": return "Fetched " + n + " URL" + (n > 1 ? "s" : "");
|
|
111
|
-
default: return "Ran " + n + " tool" + (n > 1 ? "s" : "");
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
switch (name) {
|
|
115
|
-
case "Read": return "Reading " + n + " file" + (n > 1 ? "s" : "") + "...";
|
|
116
|
-
case "Edit": return "Editing " + n + " file" + (n > 1 ? "s" : "") + "...";
|
|
117
|
-
case "Write": return "Writing " + n + " file" + (n > 1 ? "s" : "") + "...";
|
|
118
|
-
case "Bash": return "Running " + n + " command" + (n > 1 ? "s" : "") + "...";
|
|
119
|
-
case "Grep": return "Searching " + n + " pattern" + (n > 1 ? "s" : "") + "...";
|
|
120
|
-
case "Glob": return "Finding " + n + " pattern" + (n > 1 ? "s" : "") + "...";
|
|
121
|
-
case "Task": return "Running " + n + " task" + (n > 1 ? "s" : "") + "...";
|
|
122
|
-
case "WebSearch": return "Searching " + n + " quer" + (n > 1 ? "ies" : "y") + "...";
|
|
123
|
-
case "WebFetch": return "Fetching " + n + " URL" + (n > 1 ? "s" : "") + "...";
|
|
124
|
-
default: return "Running " + n + " tool" + (n > 1 ? "s" : "") + "...";
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Mixed tools
|
|
129
|
-
if (allDone) return "Ran " + count + " tools";
|
|
130
|
-
return "Running " + count + " tools...";
|
|
131
|
-
}
|
|
132
83
|
|
|
133
84
|
function updateToolGroupHeader(group) {
|
|
134
85
|
if (!group || !group.el) return;
|
|
135
86
|
var popupChat = group.popupChat && popupChatRenderingActive();
|
|
136
87
|
var label = group.el.querySelector(".tool-group-label");
|
|
137
|
-
var summary =
|
|
88
|
+
var summary = sessionToolGroupSummary(group, tools);
|
|
138
89
|
if (label && !popupChat) label.textContent = summary;
|
|
139
90
|
|
|
140
91
|
var allDone = group.doneCount >= group.toolCount;
|
|
@@ -1644,31 +1595,12 @@ export function createToolItem(id, name) {
|
|
|
1644
1595
|
// Group management: create new group or reuse existing open group
|
|
1645
1596
|
if (!currentToolGroup || currentToolGroup.closed) {
|
|
1646
1597
|
toolGroupCounter++;
|
|
1647
|
-
var groupEl = document.createElement("div");
|
|
1648
|
-
groupEl.className = "tool-group";
|
|
1649
1598
|
var identity = resolveProjectAssistantIdentity();
|
|
1650
1599
|
var isMateToolGroup = identity.kind === 'mate';
|
|
1651
|
-
|
|
1600
|
+
var groupEl = createSessionToolGroup(isMateToolGroup ? identity.avatarUrl : null);
|
|
1601
|
+
if (isMateToolGroup) groupEl.classList.add('mate-tool-group');
|
|
1652
1602
|
groupEl.dataset.groupId = "g" + toolGroupCounter;
|
|
1653
1603
|
|
|
1654
|
-
var toolGroupInner =
|
|
1655
|
-
'<div class="tool-group-header" style="display:none">' +
|
|
1656
|
-
'<span class="tool-group-chevron">' + iconHtml("chevron-right") + '</span>' +
|
|
1657
|
-
'<span class="tool-group-bullet"></span>' +
|
|
1658
|
-
'<span class="tool-group-label">Running...</span>' +
|
|
1659
|
-
'<span class="tool-group-status-icon">' + iconHtml("loader", "icon-spin") + '</span>' +
|
|
1660
|
-
'</div>' +
|
|
1661
|
-
'<div class="tool-group-items"></div>';
|
|
1662
|
-
|
|
1663
|
-
if (isMateToolGroup) {
|
|
1664
|
-
var mateAvatar = identity.avatarUrl;
|
|
1665
|
-
groupEl.innerHTML =
|
|
1666
|
-
'<img class="dm-bubble-avatar dm-bubble-avatar-mate" src="' + escapeHtml(mateAvatar) + '" alt="">' +
|
|
1667
|
-
'<div class="dm-bubble-content">' + toolGroupInner + '</div>';
|
|
1668
|
-
} else {
|
|
1669
|
-
groupEl.innerHTML = toolGroupInner;
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
1604
|
applyProjectAssistantIdentity(groupEl, identity);
|
|
1673
1605
|
bindToolGroupDisclosure(groupEl, function () {
|
|
1674
1606
|
var group = mountedToolGroup(groupEl);
|
|
@@ -1694,23 +1626,7 @@ export function createToolItem(id, name) {
|
|
|
1694
1626
|
rememberMountedToolGroup(currentToolGroup);
|
|
1695
1627
|
}
|
|
1696
1628
|
|
|
1697
|
-
var el =
|
|
1698
|
-
el.className = "tool-item";
|
|
1699
|
-
el.dataset.toolId = id;
|
|
1700
|
-
el.innerHTML =
|
|
1701
|
-
'<div class="tool-header">' +
|
|
1702
|
-
'<span class="tool-chevron">' + iconHtml("chevron-right") + '</span>' +
|
|
1703
|
-
'<span class="tool-bullet"></span>' +
|
|
1704
|
-
'<span class="tool-name"></span>' +
|
|
1705
|
-
'<span class="tool-desc"></span>' +
|
|
1706
|
-
'<span class="tool-status-icon">' + iconHtml("loader", "icon-spin") + '</span>' +
|
|
1707
|
-
'</div>' +
|
|
1708
|
-
'<div class="tool-subtitle">' +
|
|
1709
|
-
'<span class="tool-connector">└</span>' +
|
|
1710
|
-
'<span class="tool-subtitle-text">Running...</span>' +
|
|
1711
|
-
'</div>';
|
|
1712
|
-
|
|
1713
|
-
el.querySelector(".tool-name").textContent = name;
|
|
1629
|
+
var el = createSessionToolItem(id, name);
|
|
1714
1630
|
|
|
1715
1631
|
tools[id] = { el: el, name: name, input: null, done: false, groupId: currentToolGroup.id };
|
|
1716
1632
|
applyClayToolItem(tools[id]);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { initPaneHeaderTooltips } from './pane-header-tooltips.js';
|
|
2
|
+
|
|
1
3
|
// --- Global JS tooltip system ---
|
|
2
4
|
// Unified tooltip using [data-tip] attribute.
|
|
3
5
|
// Usage: initTooltips() auto-binds, converts [title] to [data-tip].
|
|
@@ -9,13 +11,15 @@ var SHOW_DELAY = 120;
|
|
|
9
11
|
var currentTarget = null;
|
|
10
12
|
|
|
11
13
|
function initTooltips() {
|
|
14
|
+
if (tooltipEl) return;
|
|
12
15
|
// Create singleton tooltip element
|
|
13
16
|
tooltipEl = document.createElement("div");
|
|
14
|
-
tooltipEl.className = "tooltip";
|
|
17
|
+
tooltipEl.className = "tooltip"; tooltipEl.id = "clay-tooltip"; tooltipEl.setAttribute("role", "tooltip"); tooltipEl.setAttribute("aria-hidden", "true");
|
|
15
18
|
document.body.appendChild(tooltipEl);
|
|
16
19
|
|
|
17
20
|
// Convert existing title attributes to data-tip in target areas
|
|
18
21
|
convertTitles();
|
|
22
|
+
initPaneHeaderTooltips();
|
|
19
23
|
|
|
20
24
|
// Delegate hover events on document for [data-tip]
|
|
21
25
|
document.addEventListener("mouseover", function (e) {
|
|
@@ -34,6 +38,13 @@ function initTooltips() {
|
|
|
34
38
|
hideTooltip();
|
|
35
39
|
});
|
|
36
40
|
|
|
41
|
+
document.addEventListener("focusin", function (event) {
|
|
42
|
+
var target = event.target.closest("[data-tip], [data-tip-html]");
|
|
43
|
+
if (target) scheduleShow(target);
|
|
44
|
+
});
|
|
45
|
+
document.addEventListener("focusout", function () { cancelShow(); hideTooltip(); });
|
|
46
|
+
document.addEventListener("keydown", function (event) { if (event.key === "Escape") { cancelShow(); hideTooltip(); } });
|
|
47
|
+
window.addEventListener("blur", function () { cancelShow(); hideTooltip(); });
|
|
37
48
|
document.addEventListener("pointerdown", function () {
|
|
38
49
|
cancelShow();
|
|
39
50
|
hideTooltip();
|
|
@@ -58,8 +69,8 @@ function convertTitles() {
|
|
|
58
69
|
var el = els[i];
|
|
59
70
|
if (!el.getAttribute("data-tip")) {
|
|
60
71
|
el.setAttribute("data-tip", el.getAttribute("title"));
|
|
61
|
-
el.removeAttribute("title");
|
|
62
72
|
}
|
|
73
|
+
el.removeAttribute("title");
|
|
63
74
|
}
|
|
64
75
|
}
|
|
65
76
|
|
|
@@ -83,17 +94,23 @@ function cancelShow() {
|
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
function showTooltipAt(target) {
|
|
86
|
-
if (!tooltipEl) return;
|
|
97
|
+
if (!tooltipEl || !target.isConnected || !target.getClientRects().length) return;
|
|
98
|
+
// A message preview already describes this Worker/task tab.
|
|
99
|
+
if (target.getAttribute('aria-describedby') === 'agent-message-bubble' && document.getElementById('agent-message-bubble')) return;
|
|
87
100
|
// Suppress tooltip when an associated popover/picker is open
|
|
88
101
|
var suppressSel = target.getAttribute("data-tip-suppress-when-open");
|
|
89
102
|
if (suppressSel) {
|
|
90
103
|
var openEl = document.querySelector(suppressSel);
|
|
91
|
-
if (openEl && !openEl.classList.contains("hidden")) return;
|
|
104
|
+
if (openEl && !openEl.hidden && !openEl.classList.contains("hidden")) return;
|
|
92
105
|
}
|
|
93
106
|
var html = target.getAttribute("data-tip-html");
|
|
94
107
|
var text = target.getAttribute("data-tip");
|
|
95
108
|
if (!html && !text) return;
|
|
109
|
+
if (currentTarget && currentTarget !== target) hideTooltip();
|
|
96
110
|
currentTarget = target;
|
|
111
|
+
var described = (target.getAttribute('aria-describedby') || '').split(/\s+/).filter(Boolean);
|
|
112
|
+
if (described.indexOf('clay-tooltip') < 0) described.push('clay-tooltip');
|
|
113
|
+
target.setAttribute('aria-describedby', described.join(' '));
|
|
97
114
|
|
|
98
115
|
if (html) {
|
|
99
116
|
tooltipEl.innerHTML = html;
|
|
@@ -113,6 +130,7 @@ function showTooltipAt(target) {
|
|
|
113
130
|
tooltipEl.style.top = "-9999px";
|
|
114
131
|
tooltipEl.style.left = "0";
|
|
115
132
|
tooltipEl.style.right = "";
|
|
133
|
+
tooltipEl.setAttribute("aria-hidden", "false");
|
|
116
134
|
tooltipEl.classList.add("visible");
|
|
117
135
|
|
|
118
136
|
// Position after layout
|
|
@@ -144,9 +162,17 @@ function showTooltipAt(target) {
|
|
|
144
162
|
|
|
145
163
|
function hideTooltip() {
|
|
146
164
|
if (tooltipEl) {
|
|
147
|
-
tooltipEl.classList.remove("visible");
|
|
165
|
+
tooltipEl.classList.remove("visible"); tooltipEl.setAttribute("aria-hidden", "true");
|
|
166
|
+
}
|
|
167
|
+
if (currentTarget) {
|
|
168
|
+
var described = (currentTarget.getAttribute('aria-describedby') || '').split(/\s+/).filter(function (id) { return id && id !== 'clay-tooltip'; });
|
|
169
|
+
if (described.length) currentTarget.setAttribute('aria-describedby', described.join(' ')); else currentTarget.removeAttribute('aria-describedby');
|
|
148
170
|
}
|
|
149
171
|
currentTarget = null;
|
|
150
172
|
}
|
|
151
173
|
|
|
152
|
-
|
|
174
|
+
function pruneTooltip() { if (currentTarget && (!currentTarget.isConnected || !currentTarget.getClientRects().length)) { cancelShow(); hideTooltip(); } }
|
|
175
|
+
|
|
176
|
+
function dismissTooltip() { cancelShow(); hideTooltip(); }
|
|
177
|
+
|
|
178
|
+
export { initTooltips, registerTooltip, pruneTooltip, dismissTooltip };
|