clay-server 3.8.1 → 4.0.0-beta.2
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/ask-user-mcp-server.js +5 -119
- package/lib/builtin-mates.js +6 -6
- package/lib/claude-hook-installer.js +15 -0
- package/lib/clay-history-mcp-server.js +62 -297
- package/lib/daemon.js +1 -1
- package/lib/debate-model-selection.js +119 -0
- package/lib/home-debate-tool-policy.js +164 -0
- package/lib/home-response-notifications.js +26 -0
- package/lib/mate-creation-mcp-server.js +55 -0
- package/lib/mate-ready-creation.js +95 -0
- package/lib/mates.js +2 -0
- package/lib/notes.js +2 -1
- package/lib/project-ask-user.js +64 -0
- package/lib/project-capsule-catalog.js +101 -0
- package/lib/project-connection.js +4 -0
- package/lib/project-debate-proposal.js +133 -17
- package/lib/project-debate.js +214 -110
- package/lib/project-delegated-follow-up.js +84 -0
- package/lib/project-delegated-session.js +53 -0
- package/lib/project-filesystem.js +7 -9
- package/lib/project-knowledge.js +1 -0
- package/lib/project-mate-creation-proposal.js +120 -0
- package/lib/project-memory.js +14 -7
- package/lib/project-models.js +157 -32
- package/lib/project-session-notes.js +2 -2
- package/lib/project-session-pair.js +8 -8
- package/lib/project-sessions.js +66 -51
- package/lib/project-vendor-login.js +397 -0
- package/lib/project-worker-proposal.js +25 -25
- package/lib/project-workspace-query.js +144 -0
- package/lib/project.js +349 -102
- package/lib/public/app.js +85 -42
- package/lib/public/css/avatar-imprints.css +0 -1
- package/lib/public/css/base.css +4 -0
- package/lib/public/css/capsule-ui.css +389 -0
- package/lib/public/css/command-palette.css +306 -6
- package/lib/public/css/home-capsule-library.css +243 -0
- package/lib/public/css/home-capsule-source.css +192 -0
- package/lib/public/css/home-debate-live.css +146 -0
- package/lib/public/css/home-debate-planning.css +125 -0
- package/lib/public/css/home-debates-archive.css +281 -0
- package/lib/public/css/home-hub.css +896 -405
- package/lib/public/css/home-mate-creation.css +34 -0
- package/lib/public/css/home-mate-model-picker.css +131 -0
- package/lib/public/css/home-mate-settings.css +344 -0
- package/lib/public/css/home-session-actions.css +265 -0
- package/lib/public/css/home-sidebar.css +667 -0
- package/lib/public/css/icon-strip.css +1 -2
- package/lib/public/css/mates.css +7 -34
- package/lib/public/css/pane.css +1 -1
- package/lib/public/css/playbook.css +0 -80
- package/lib/public/css/sticky-notes.css +53 -117
- package/lib/public/css/tui-attention.css +0 -44
- package/lib/public/css/workspace-assignment.css +45 -0
- package/lib/public/fonts/source-serif-4/LICENSE.md +93 -0
- package/lib/public/fonts/source-serif-4/SourceSerif4Caption-Semibold.ttf.woff2 +0 -0
- package/lib/public/index.html +93 -74
- package/lib/public/modules/app-connection.js +10 -1
- package/lib/public/modules/app-dm.js +43 -160
- package/lib/public/modules/app-home-hub.js +328 -585
- package/lib/public/modules/app-message-cards.js +242 -0
- package/lib/public/modules/app-message-router.js +84 -0
- package/lib/public/modules/app-messages.js +102 -37
- package/lib/public/modules/app-notifications.js +8 -119
- package/lib/public/modules/app-projects.js +9 -1
- package/lib/public/modules/app-rendering.js +21 -602
- package/lib/public/modules/avatar-imprint.js +11 -8
- package/lib/public/modules/chat-bubble-renderer.js +152 -0
- package/lib/public/modules/chat-render-runtime.js +198 -0
- package/lib/public/modules/command-palette.js +225 -436
- package/lib/public/modules/dm-render.js +82 -0
- package/lib/public/modules/home-capsule-creation-intent.js +31 -0
- package/lib/public/modules/home-capsule-library.js +146 -0
- package/lib/public/modules/home-capsule-source.js +383 -0
- package/lib/public/modules/home-chat-identity.js +35 -0
- package/lib/public/modules/home-chat-scroll.js +77 -0
- package/lib/public/modules/home-chat-stream-state.js +34 -0
- package/lib/public/modules/home-composer-focus.js +25 -0
- package/lib/public/modules/home-conversations-sheet.js +179 -0
- package/lib/public/modules/home-debate-activity.js +48 -0
- package/lib/public/modules/home-debate-controls.js +295 -0
- package/lib/public/modules/home-debate-launch.js +41 -0
- package/lib/public/modules/home-debate-live.js +284 -0
- package/lib/public/modules/home-debate-models.js +73 -0
- package/lib/public/modules/home-debate-planning.js +335 -0
- package/lib/public/modules/home-debates-archive.js +279 -0
- package/lib/public/modules/home-dock-resize.js +74 -0
- package/lib/public/modules/home-dock.js +446 -0
- package/lib/public/modules/home-mate-chat.js +496 -0
- package/lib/public/modules/home-mate-creation.js +109 -0
- package/lib/public/modules/home-mate-model-picker.js +281 -0
- package/lib/public/modules/home-mate-selection.js +38 -0
- package/lib/public/modules/home-mate-settings-menu.js +131 -0
- package/lib/public/modules/home-mate-settings.js +383 -0
- package/lib/public/modules/home-session-actions.js +373 -0
- package/lib/public/modules/home-session-model-confirmation.js +13 -0
- package/lib/public/modules/home-shell.js +9 -0
- package/lib/public/modules/home-sidebar-chat-list.js +63 -0
- package/lib/public/modules/home-sidebar.js +158 -0
- package/lib/public/modules/home-sub-surface.js +19 -0
- package/lib/public/modules/home-surface-boot.js +68 -0
- package/lib/public/modules/home-surface.js +141 -0
- package/lib/public/modules/home-tools.js +271 -0
- package/lib/public/modules/markdown.js +50 -2
- package/lib/public/modules/mate-management.js +86 -0
- package/lib/public/modules/mate-wizard.js +0 -7
- package/lib/public/modules/mention.js +17 -19
- package/lib/public/modules/pane-bridge.js +9 -0
- package/lib/public/modules/profile.js +4 -5
- package/lib/public/modules/project-settings.js +34 -28
- package/lib/public/modules/project-switcher.js +11 -5
- package/lib/public/modules/project-workspace-assignment.js +23 -0
- package/lib/public/modules/search-clay-chat.js +402 -0
- package/lib/public/modules/server-settings.js +14 -12
- package/lib/public/modules/session-actions.js +1 -1
- package/lib/public/modules/sidebar-mates.js +56 -552
- package/lib/public/modules/sidebar-mobile.js +7 -64
- package/lib/public/modules/sidebar-presence.js +37 -0
- package/lib/public/modules/split-pair-ui.js +13 -13
- package/lib/public/modules/split-view.js +7 -0
- package/lib/public/modules/sticky-notes.js +7 -6
- package/lib/public/modules/tool-input-composition.js +48 -0
- package/lib/public/modules/tool-llm-status.js +167 -0
- package/lib/public/modules/tool-renderer-advanced.js +285 -0
- package/lib/public/modules/tool-renderer-chart.js +158 -0
- package/lib/public/modules/tool-renderer-semantics.js +35 -0
- package/lib/public/modules/tool-renderer.js +464 -0
- package/lib/public/modules/tool-runtime.js +309 -0
- package/lib/public/modules/tool-ui-evaluator.js +97 -0
- package/lib/public/modules/tool-ui-tree.js +21 -0
- package/lib/public/modules/tui-attention.js +10 -0
- package/lib/public/modules/user-settings.js +16 -23
- package/lib/public/modules/vendor-login.js +287 -0
- package/lib/public/modules/worker-proposal.js +2 -2
- package/lib/public/modules/workspace-assignment-card.js +149 -0
- package/lib/public/modules/workspace-assignment-routing.js +4 -0
- package/lib/public/style.css +13 -2
- package/lib/runtime-env.js +65 -0
- package/lib/sdk-bridge.js +120 -32
- package/lib/sdk-message-processor.js +10 -6
- package/lib/server-home-capsule-creation.js +36 -0
- package/lib/server-home-chat-events.js +287 -0
- package/lib/server-home-chat.js +518 -0
- package/lib/server-home-clay-entry.js +65 -0
- package/lib/server-home-clay-session-links.js +26 -0
- package/lib/server-home-debate-planning.js +214 -0
- package/lib/server-home-debates.js +137 -0
- package/lib/server-home-mate-creation.js +261 -0
- package/lib/server-home-models.js +241 -0
- package/lib/server-home-preferences.js +61 -0
- package/lib/server-mates.js +37 -0
- package/lib/server-tools.js +377 -0
- package/lib/server.js +111 -59
- package/lib/session-pair-mcp-server.js +6 -6
- package/lib/sessions.js +18 -3
- package/lib/tool-capsule-source.js +142 -0
- package/lib/tool-control-mcp-server.js +126 -0
- package/lib/tool-llm.js +48 -0
- package/lib/tool-storage.js +77 -0
- package/lib/tool-ui-spec-advanced.js +82 -0
- package/lib/tool-ui-spec.js +261 -0
- package/lib/tools-registry.js +286 -0
- package/lib/users-home-dock-preferences.js +77 -0
- package/lib/users-home-surface-preferences.js +99 -0
- package/lib/users-preferences.js +4 -7
- package/lib/users.js +12 -0
- package/lib/whats-new-content.js +3 -3
- package/lib/workspace-assignment-service.js +420 -0
- package/lib/workspace-query-mcp-server.js +154 -0
- package/lib/workspace-query-service.js +492 -0
- package/lib/ws-schema.js +93 -12
- package/lib/yoke/adapters/acp.js +2 -1
- package/lib/yoke/adapters/antigravity.js +2 -1
- package/lib/yoke/adapters/claude-worker.js +11 -4
- package/lib/yoke/adapters/claude.js +73 -43
- package/lib/yoke/adapters/codex.js +40 -10
- package/lib/yoke/adapters/kiro.js +2 -1
- package/lib/yoke/claude-user-input.js +38 -0
- package/lib/yoke/codex-app-server.js +20 -2
- package/lib/yoke/codex-user-input.js +64 -0
- package/lib/yoke/complete-once.js +164 -0
- package/lib/yoke/index.js +5 -1
- package/lib/yoke/interface.js +19 -0
- package/lib/yoke/mcp-bridge-server.js +2 -6
- package/lib/yoke/user-input.js +254 -0
- package/package.json +3 -2
- package/lib/public/css/home-chat.css +0 -380
- package/lib/public/modules/home-chat.js +0 -438
- package/lib/server-clay-home.js +0 -245
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Pointer and keyboard resizing for the desktop home tool workbench.
|
|
2
|
+
|
|
3
|
+
var initialized = false;
|
|
4
|
+
var dragging = false;
|
|
5
|
+
var pointerOffset = 0;
|
|
6
|
+
|
|
7
|
+
export function clampHomeDockWidth(width) {
|
|
8
|
+
var workspace = document.getElementById("home-workspace");
|
|
9
|
+
var available = workspace ? workspace.getBoundingClientRect().width : window.innerWidth;
|
|
10
|
+
var maximum = Math.max(420, Math.min(window.innerWidth * 0.58, available - 504));
|
|
11
|
+
return Math.round(Math.max(420, Math.min(maximum, width)));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function defaultHomeDockWidth() {
|
|
15
|
+
return clampHomeDockWidth(Math.max(520, Math.min(window.innerWidth * 0.46, 760)));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function applyHomeDockWidth(width) {
|
|
19
|
+
var workspace = document.getElementById("home-workspace");
|
|
20
|
+
if (!workspace) return null;
|
|
21
|
+
var resolved = clampHomeDockWidth(typeof width === "number" ? width : defaultHomeDockWidth());
|
|
22
|
+
workspace.style.setProperty("--home-dock-width", resolved + "px");
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function dispatchWidth(type, width) {
|
|
27
|
+
window.dispatchEvent(new CustomEvent(type, { detail: { width: applyHomeDockWidth(width) } }));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function handlePointerMove(event) {
|
|
31
|
+
if (!dragging) return;
|
|
32
|
+
var workbench = document.getElementById("home-tool-workbench");
|
|
33
|
+
if (!workbench) return;
|
|
34
|
+
var rect = workbench.getBoundingClientRect();
|
|
35
|
+
dispatchWidth("clay:home-dock-width-preview", rect.right - event.clientX - pointerOffset);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function finishPointerResize(event) {
|
|
39
|
+
if (!dragging) return;
|
|
40
|
+
handlePointerMove(event);
|
|
41
|
+
dragging = false;
|
|
42
|
+
pointerOffset = 0;
|
|
43
|
+
document.body.classList.remove("home-dock-resizing");
|
|
44
|
+
window.removeEventListener("pointermove", handlePointerMove);
|
|
45
|
+
window.removeEventListener("pointerup", finishPointerResize);
|
|
46
|
+
window.removeEventListener("pointercancel", finishPointerResize);
|
|
47
|
+
var workbench = document.getElementById("home-tool-workbench");
|
|
48
|
+
dispatchWidth("clay:home-dock-width-commit", workbench ? workbench.getBoundingClientRect().width : defaultHomeDockWidth());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function initHomeDockResize() {
|
|
52
|
+
if (initialized) return;
|
|
53
|
+
initialized = true;
|
|
54
|
+
var divider = document.getElementById("home-dock-divider");
|
|
55
|
+
if (!divider) return;
|
|
56
|
+
divider.addEventListener("pointerdown", function (event) {
|
|
57
|
+
if (window.innerWidth < 1180 || event.button !== 0) return;
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
var workbench = document.getElementById("home-tool-workbench");
|
|
60
|
+
pointerOffset = workbench ? workbench.getBoundingClientRect().left - event.clientX : 0;
|
|
61
|
+
dragging = true;
|
|
62
|
+
document.body.classList.add("home-dock-resizing");
|
|
63
|
+
window.addEventListener("pointermove", handlePointerMove);
|
|
64
|
+
window.addEventListener("pointerup", finishPointerResize);
|
|
65
|
+
window.addEventListener("pointercancel", finishPointerResize);
|
|
66
|
+
});
|
|
67
|
+
divider.addEventListener("keydown", function (event) {
|
|
68
|
+
if (window.innerWidth < 1180 || (event.key !== "ArrowLeft" && event.key !== "ArrowRight")) return;
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
var workbench = document.getElementById("home-tool-workbench");
|
|
71
|
+
var current = workbench ? workbench.getBoundingClientRect().width : defaultHomeDockWidth();
|
|
72
|
+
dispatchWidth("clay:home-dock-width-commit", current + (event.key === "ArrowLeft" ? 24 : -24));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
// Home dock registry, three-state navigation, and preference synchronization.
|
|
2
|
+
|
|
3
|
+
import { store } from './store.js';
|
|
4
|
+
import { getWs } from './ws-ref.js';
|
|
5
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
6
|
+
import { escapeHtml } from './utils.js';
|
|
7
|
+
import { applyHomeDockWidth, initHomeDockResize } from './home-dock-resize.js';
|
|
8
|
+
import { renderHomeCapsuleLibrary } from './home-capsule-library.js';
|
|
9
|
+
|
|
10
|
+
var tools = [];
|
|
11
|
+
var toolsById = Object.create(null);
|
|
12
|
+
var mountedToolId = null;
|
|
13
|
+
var pulseTimers = Object.create(null);
|
|
14
|
+
var initialized = false;
|
|
15
|
+
var resizeSaveTimer = null;
|
|
16
|
+
var backstageView = null;
|
|
17
|
+
var backstageReturnTarget = null;
|
|
18
|
+
|
|
19
|
+
function clearBackstageView() {
|
|
20
|
+
var previous = backstageView;
|
|
21
|
+
backstageView = null;
|
|
22
|
+
backstageReturnTarget = null;
|
|
23
|
+
if (previous && typeof previous.onClose === "function") previous.onClose();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function send(message) {
|
|
27
|
+
var ws = getWs();
|
|
28
|
+
if (!ws || ws.readyState !== 1) return false;
|
|
29
|
+
ws.send(JSON.stringify(message));
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function activeTool() {
|
|
34
|
+
var activeId = store.get('dockActiveToolId');
|
|
35
|
+
return activeId && toolsById[activeId] ? toolsById[activeId] : tools[0] || null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function preference() {
|
|
39
|
+
return {
|
|
40
|
+
dockOpen: store.get('dockOpen') === true,
|
|
41
|
+
dockFocus: store.get('dockOpen') === true && store.get('dockFocus') === true,
|
|
42
|
+
dockWidth: store.get('dockWidth'),
|
|
43
|
+
activeToolId: store.get('dockActiveToolId') || null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function persistDock() {
|
|
48
|
+
send({ type: "home_dock_set", preference: preference() });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function hasVisibleEscapeLayer() {
|
|
52
|
+
var selector = '[role="dialog"], [role="menu"], .profile-popover, .project-ctx-menu, .cmd-palette, [id$="-modal"], [id$="-overlay"], .panel-fullscreen';
|
|
53
|
+
var layers = document.querySelectorAll(selector);
|
|
54
|
+
for (var i = 0; i < layers.length; i++) {
|
|
55
|
+
if (!layers[i].classList.contains("hidden") && layers[i].getClientRects().length > 0) return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function hasEditableEscapeTarget(target) {
|
|
61
|
+
if (!target || typeof target.matches !== "function") return false;
|
|
62
|
+
if (target.matches('input, textarea, select, [contenteditable="true"]')) return true;
|
|
63
|
+
return typeof target.closest === "function" && Boolean(target.closest('[contenteditable="true"]'));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function renderToolIdentity(tool) {
|
|
67
|
+
return '<span class="home-dock-tab-icon">' + iconHtml(tool.lucideIcon || "box") + '</span>'
|
|
68
|
+
+ '<span class="home-dock-tab-label">' + escapeHtml(tool.name) + '</span>';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function appendCapsuleHomeTab(switcherEl, active) {
|
|
72
|
+
var tab = document.createElement("button");
|
|
73
|
+
tab.type = "button";
|
|
74
|
+
tab.className = "home-dock-tool is-capsule-home" + (active ? " active" : "");
|
|
75
|
+
tab.dataset.dockHome = "true";
|
|
76
|
+
tab.setAttribute("aria-label", "Capsule Home");
|
|
77
|
+
if (active) tab.setAttribute("aria-current", "page");
|
|
78
|
+
tab.innerHTML = renderToolIdentity({ name: "Home", lucideIcon: "house" });
|
|
79
|
+
tab.addEventListener("click", openHomeCapsuleLibrary);
|
|
80
|
+
switcherEl.appendChild(tab);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function clearDockContext(contextEl) {
|
|
84
|
+
var mounted = mountedToolId ? toolsById[mountedToolId] : null;
|
|
85
|
+
if (mounted && typeof mounted.onChromeHide === "function") mounted.onChromeHide();
|
|
86
|
+
contextEl.innerHTML = "";
|
|
87
|
+
contextEl.hidden = true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function syncDockTrigger() {
|
|
91
|
+
var button = document.getElementById("home-tools-btn");
|
|
92
|
+
var label = document.getElementById("home-tools-label");
|
|
93
|
+
var activity = document.getElementById("home-tools-activity");
|
|
94
|
+
var hasActivity = store.get('dockHasActivity') === true;
|
|
95
|
+
if (label) label.textContent = "Capsules";
|
|
96
|
+
if (activity) activity.classList.toggle("is-active", hasActivity);
|
|
97
|
+
if (button) {
|
|
98
|
+
button.setAttribute("aria-expanded", store.get('dockOpen') === true ? "true" : "false");
|
|
99
|
+
button.setAttribute("aria-label", hasActivity ? "Capsules, new activity" : "Capsules");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function syncDockState() {
|
|
104
|
+
var hub = document.getElementById("home-hub");
|
|
105
|
+
if (!hub) return;
|
|
106
|
+
var open = store.get('dockOpen') === true;
|
|
107
|
+
var focus = open && store.get('dockFocus') === true;
|
|
108
|
+
hub.classList.toggle("dock-open", open);
|
|
109
|
+
hub.classList.toggle("dock-split", open && !focus);
|
|
110
|
+
hub.classList.toggle("dock-focus", focus);
|
|
111
|
+
applyHomeDockWidth(store.get('dockWidth'));
|
|
112
|
+
syncDockTrigger();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function setDockState(patch, persist) {
|
|
116
|
+
store.set(patch);
|
|
117
|
+
syncDockState();
|
|
118
|
+
renderDock();
|
|
119
|
+
if (persist) persistDock();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function activateTool(toolId) {
|
|
123
|
+
clearBackstageView();
|
|
124
|
+
setDockState({
|
|
125
|
+
dockActiveToolId: toolId,
|
|
126
|
+
dockOpen: true,
|
|
127
|
+
dockFocus: store.get('dockFocus') === true,
|
|
128
|
+
dockLibraryOpen: false,
|
|
129
|
+
dockBackstageOpen: false,
|
|
130
|
+
dockHasActivity: false,
|
|
131
|
+
dockActivityToolId: null,
|
|
132
|
+
}, true);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function openHomeDock(toolId) {
|
|
136
|
+
clearBackstageView();
|
|
137
|
+
var current = activeTool();
|
|
138
|
+
var requested = toolId && toolsById[toolId] ? toolId : (current ? current.id : null);
|
|
139
|
+
setDockState({ dockActiveToolId: requested, dockOpen: true, dockFocus: false, dockLibraryOpen: !requested, dockBackstageOpen: false, dockHasActivity: false, dockActivityToolId: null }, true);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function focusActiveCapsuleTab() {
|
|
143
|
+
var activeTab = document.querySelector("#home-dock-switcher .home-dock-tool.active");
|
|
144
|
+
if (activeTab) activeTab.focus();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function openLibraryCapsule(toolId) {
|
|
148
|
+
activateTool(toolId);
|
|
149
|
+
focusActiveCapsuleTab();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function openHomeCapsuleLibrary() {
|
|
153
|
+
clearBackstageView();
|
|
154
|
+
setDockState({
|
|
155
|
+
dockActiveToolId: null,
|
|
156
|
+
dockOpen: true,
|
|
157
|
+
dockFocus: false,
|
|
158
|
+
dockLibraryOpen: true,
|
|
159
|
+
dockBackstageOpen: false,
|
|
160
|
+
dockHasActivity: false,
|
|
161
|
+
dockActivityToolId: null,
|
|
162
|
+
}, true);
|
|
163
|
+
var title = document.getElementById("home-capsule-library-title");
|
|
164
|
+
if (title) title.focus();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function openHomeCapsules() {
|
|
168
|
+
var lastActiveId = store.get('dockActiveToolId');
|
|
169
|
+
if (lastActiveId && toolsById[lastActiveId]) {
|
|
170
|
+
openHomeDock(lastActiveId);
|
|
171
|
+
focusActiveCapsuleTab();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
openHomeCapsuleLibrary();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function toggleHomeCapsules() {
|
|
178
|
+
if (store.get('dockOpen')) closeHomeDock();
|
|
179
|
+
else openHomeCapsules();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function openHomeBackstage(view) {
|
|
183
|
+
if (!view || typeof view.render !== "function") return;
|
|
184
|
+
clearBackstageView();
|
|
185
|
+
backstageView = view;
|
|
186
|
+
var activeId = store.get('dockActiveToolId');
|
|
187
|
+
backstageReturnTarget = activeId && toolsById[activeId]
|
|
188
|
+
? { type: "capsule", toolId: activeId }
|
|
189
|
+
: { type: "library" };
|
|
190
|
+
setDockState({
|
|
191
|
+
dockOpen: true,
|
|
192
|
+
dockFocus: false,
|
|
193
|
+
dockLibraryOpen: backstageReturnTarget.type === "library",
|
|
194
|
+
dockBackstageOpen: true,
|
|
195
|
+
}, true);
|
|
196
|
+
var focusTarget = document.querySelector("#home-dock-content [data-home-backstage-focus]");
|
|
197
|
+
if (focusTarget) focusTarget.focus();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function closeHomeBackstage() {
|
|
201
|
+
var returnTarget = backstageReturnTarget;
|
|
202
|
+
clearBackstageView();
|
|
203
|
+
var returnToCapsule = returnTarget && returnTarget.type === "capsule" && toolsById[returnTarget.toolId];
|
|
204
|
+
setDockState({
|
|
205
|
+
dockActiveToolId: returnToCapsule ? returnTarget.toolId : store.get('dockActiveToolId'),
|
|
206
|
+
dockLibraryOpen: !returnToCapsule,
|
|
207
|
+
dockBackstageOpen: false,
|
|
208
|
+
}, false);
|
|
209
|
+
if (!returnToCapsule) {
|
|
210
|
+
var libraryTitle = document.getElementById("home-capsule-library-title");
|
|
211
|
+
if (libraryTitle) libraryTitle.focus();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
focusActiveCapsuleTab();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function closeHomeDock() {
|
|
218
|
+
clearBackstageView();
|
|
219
|
+
setDockState({ dockOpen: false, dockFocus: false, dockBackstageOpen: false }, true);
|
|
220
|
+
var homeControl = document.getElementById("home-tools-btn");
|
|
221
|
+
if (homeControl && homeControl.getClientRects().length) homeControl.focus({ preventScroll: true });
|
|
222
|
+
else {
|
|
223
|
+
var sidebarControl = document.getElementById("home-sidebar-expand");
|
|
224
|
+
if (sidebarControl && sidebarControl.getClientRects().length) sidebarControl.focus({ preventScroll: true });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function focusHomeDock() {
|
|
229
|
+
if (!store.get('dockOpen')) return;
|
|
230
|
+
setDockState({ dockFocus: true }, true);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function returnHomeDockToSplit() {
|
|
234
|
+
if (!store.get('dockOpen')) return;
|
|
235
|
+
setDockState({ dockFocus: false }, true);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function handleReturnHomeDock() {
|
|
239
|
+
if (window.innerWidth <= 768) {
|
|
240
|
+
closeHomeDock();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
returnHomeDockToSplit();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function resetHomeDockFocus() {
|
|
247
|
+
if (!store.get('dockFocus')) return;
|
|
248
|
+
store.set({ dockFocus: false });
|
|
249
|
+
syncDockState();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function requestHomeDockPreference() {
|
|
253
|
+
send({ type: "home_dock_get" });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function handleHomeDockState(msg) {
|
|
257
|
+
if (!msg) return;
|
|
258
|
+
if (msg.error || !msg.preference) {
|
|
259
|
+
store.set({ homeDockPreferenceLoaded: true });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
var saved = msg.preference;
|
|
263
|
+
store.set({
|
|
264
|
+
dockOpen: saved.dockOpen === true,
|
|
265
|
+
homeDockPreferenceLoaded: true,
|
|
266
|
+
dockWidth: typeof saved.dockWidth === "number" ? saved.dockWidth : null,
|
|
267
|
+
dockActiveToolId: saved.activeToolId || null,
|
|
268
|
+
dockFocus: saved.dockOpen === true && saved.dockFocus === true,
|
|
269
|
+
dockLibraryOpen: saved.dockOpen === true && !saved.activeToolId,
|
|
270
|
+
});
|
|
271
|
+
syncDockState();
|
|
272
|
+
if (store.get('homeToolRegistryLoaded') && reconcileDockActiveTool()) return;
|
|
273
|
+
renderDock();
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function reconcileDockActiveTool() {
|
|
277
|
+
var activeToolId = store.get('dockActiveToolId');
|
|
278
|
+
if (!activeToolId || toolsById[activeToolId]) return false;
|
|
279
|
+
store.set({
|
|
280
|
+
dockActiveToolId: null,
|
|
281
|
+
dockLibraryOpen: store.get('dockOpen') === true,
|
|
282
|
+
});
|
|
283
|
+
syncDockState();
|
|
284
|
+
renderDock();
|
|
285
|
+
persistDock();
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function markDockToolChanged(toolId) {
|
|
290
|
+
if (store.get('dockOpen')) {
|
|
291
|
+
pulseDockTool(toolId);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
store.set({ dockHasActivity: true, dockActivityToolId: toolId || null });
|
|
295
|
+
syncDockTrigger();
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function registerDockTool(tool) {
|
|
299
|
+
if (!tool || !tool.id || !tool.name || typeof tool.render !== "function") return;
|
|
300
|
+
if (toolsById[tool.id]) {
|
|
301
|
+
var existingIndex = tools.indexOf(toolsById[tool.id]);
|
|
302
|
+
if (existingIndex !== -1) tools[existingIndex] = tool;
|
|
303
|
+
} else {
|
|
304
|
+
tools.push(tool);
|
|
305
|
+
}
|
|
306
|
+
toolsById[tool.id] = tool;
|
|
307
|
+
syncDockTrigger();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function unregisterDockTool(toolId) {
|
|
311
|
+
var tool = toolsById[toolId];
|
|
312
|
+
if (!tool) return;
|
|
313
|
+
var wasMounted = mountedToolId === toolId;
|
|
314
|
+
if (wasMounted && typeof tool.onHide === "function") tool.onHide();
|
|
315
|
+
var index = tools.indexOf(tool);
|
|
316
|
+
if (index !== -1) tools.splice(index, 1);
|
|
317
|
+
delete toolsById[toolId];
|
|
318
|
+
if (store.get('dockActiveToolId') === toolId) {
|
|
319
|
+
store.set({
|
|
320
|
+
dockActiveToolId: null,
|
|
321
|
+
dockLibraryOpen: store.get('dockOpen') === true,
|
|
322
|
+
});
|
|
323
|
+
persistDock();
|
|
324
|
+
}
|
|
325
|
+
if (wasMounted) mountedToolId = null;
|
|
326
|
+
syncDockTrigger();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export function pulseDockTool(toolId) {
|
|
330
|
+
if (!store.get('dockOpen')) {
|
|
331
|
+
store.set({ dockHasActivity: true, dockActivityToolId: toolId || null });
|
|
332
|
+
syncDockTrigger();
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
var tabs = document.querySelectorAll("[data-dock-tool-id]");
|
|
336
|
+
for (var i = 0; i < tabs.length; i++) {
|
|
337
|
+
if (tabs[i].dataset.dockToolId !== toolId) continue;
|
|
338
|
+
tabs[i].classList.remove("mate-acted");
|
|
339
|
+
void tabs[i].offsetWidth;
|
|
340
|
+
tabs[i].classList.add("mate-acted");
|
|
341
|
+
}
|
|
342
|
+
if (pulseTimers[toolId]) clearTimeout(pulseTimers[toolId]);
|
|
343
|
+
pulseTimers[toolId] = setTimeout(function () {
|
|
344
|
+
var current = document.querySelectorAll("[data-dock-tool-id]");
|
|
345
|
+
for (var j = 0; j < current.length; j++) {
|
|
346
|
+
if (current[j].dataset.dockToolId === toolId) current[j].classList.remove("mate-acted");
|
|
347
|
+
}
|
|
348
|
+
delete pulseTimers[toolId];
|
|
349
|
+
}, 1600);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function renderDock() {
|
|
353
|
+
var switcherEl = document.getElementById("home-dock-switcher");
|
|
354
|
+
var contextEl = document.getElementById("home-dock-context");
|
|
355
|
+
var contentEl = document.getElementById("home-dock-content");
|
|
356
|
+
if (!switcherEl || !contextEl || !contentEl) return;
|
|
357
|
+
var backstageOpen = store.get('dockBackstageOpen') === true && !!backstageView;
|
|
358
|
+
var libraryOpen = store.get('dockLibraryOpen') === true;
|
|
359
|
+
var selected = backstageOpen || libraryOpen ? null : activeTool();
|
|
360
|
+
switcherEl.innerHTML = "";
|
|
361
|
+
clearDockContext(contextEl);
|
|
362
|
+
appendCapsuleHomeTab(switcherEl, libraryOpen && !backstageOpen);
|
|
363
|
+
for (var i = 0; i < tools.length; i++) {
|
|
364
|
+
(function (tool) {
|
|
365
|
+
var tab = document.createElement("button");
|
|
366
|
+
tab.type = "button";
|
|
367
|
+
tab.className = "home-dock-tool" + (selected && tool.id === selected.id ? " active" : "");
|
|
368
|
+
tab.dataset.dockToolId = tool.id;
|
|
369
|
+
if (selected && tool.id === selected.id) tab.setAttribute("aria-current", "page");
|
|
370
|
+
tab.innerHTML = renderToolIdentity(tool);
|
|
371
|
+
tab.addEventListener("click", function () { activateTool(tool.id); });
|
|
372
|
+
switcherEl.appendChild(tab);
|
|
373
|
+
})(tools[i]);
|
|
374
|
+
}
|
|
375
|
+
if (backstageOpen) {
|
|
376
|
+
contentEl.innerHTML = "";
|
|
377
|
+
backstageView.render(contentEl, closeHomeBackstage);
|
|
378
|
+
syncDockTrigger();
|
|
379
|
+
refreshIcons();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (libraryOpen) {
|
|
383
|
+
if (mountedToolId) {
|
|
384
|
+
var mounted = toolsById[mountedToolId];
|
|
385
|
+
if (mounted && typeof mounted.onHide === "function") mounted.onHide();
|
|
386
|
+
}
|
|
387
|
+
mountedToolId = null;
|
|
388
|
+
contentEl.innerHTML = "";
|
|
389
|
+
renderHomeCapsuleLibrary(contentEl, store.get('installedTools') || [], openLibraryCapsule);
|
|
390
|
+
syncDockTrigger();
|
|
391
|
+
refreshIcons();
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (!selected) {
|
|
395
|
+
contentEl.innerHTML = "";
|
|
396
|
+
syncDockTrigger();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (mountedToolId && mountedToolId !== selected.id) {
|
|
400
|
+
var previous = toolsById[mountedToolId];
|
|
401
|
+
if (previous && typeof previous.onHide === "function") previous.onHide();
|
|
402
|
+
}
|
|
403
|
+
mountedToolId = selected.id;
|
|
404
|
+
contentEl.innerHTML = "";
|
|
405
|
+
contextEl.hidden = false;
|
|
406
|
+
selected.render(contentEl, contextEl);
|
|
407
|
+
if (typeof selected.onShow === "function") selected.onShow();
|
|
408
|
+
syncDockTrigger();
|
|
409
|
+
refreshIcons();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export function initHomeDock() {
|
|
413
|
+
if (initialized) return;
|
|
414
|
+
initialized = true;
|
|
415
|
+
initHomeDockResize();
|
|
416
|
+
document.getElementById("home-dock-collapse").addEventListener("click", closeHomeDock);
|
|
417
|
+
document.getElementById("home-dock-focus").addEventListener("click", focusHomeDock);
|
|
418
|
+
document.getElementById("home-dock-return").addEventListener("click", handleReturnHomeDock);
|
|
419
|
+
document.getElementById("home-dock-backdrop").addEventListener("click", closeHomeDock);
|
|
420
|
+
window.addEventListener("clay:home-dock-width-preview", function (event) {
|
|
421
|
+
if (event.detail && typeof event.detail.width === "number") store.set({ dockWidth: event.detail.width });
|
|
422
|
+
});
|
|
423
|
+
window.addEventListener("clay:home-dock-width-commit", function (event) {
|
|
424
|
+
if (!event.detail || typeof event.detail.width !== "number") return;
|
|
425
|
+
store.set({ dockWidth: event.detail.width });
|
|
426
|
+
if (resizeSaveTimer) clearTimeout(resizeSaveTimer);
|
|
427
|
+
resizeSaveTimer = setTimeout(persistDock, 180);
|
|
428
|
+
});
|
|
429
|
+
window.addEventListener("resize", syncDockState);
|
|
430
|
+
document.addEventListener("keydown", function (event) {
|
|
431
|
+
if (event.key !== "Escape" || !document.body.classList.contains("home-active")) return;
|
|
432
|
+
if (hasVisibleEscapeLayer()) return;
|
|
433
|
+
if (store.get('dockOpen') && store.get('dockBackstageOpen') && backstageView) {
|
|
434
|
+
event.preventDefault();
|
|
435
|
+
event.stopPropagation();
|
|
436
|
+
closeHomeBackstage();
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (hasEditableEscapeTarget(event.target)) return;
|
|
440
|
+
if (!store.get('dockFocus')) return;
|
|
441
|
+
event.preventDefault();
|
|
442
|
+
event.stopPropagation();
|
|
443
|
+
returnHomeDockToSplit();
|
|
444
|
+
}, true);
|
|
445
|
+
syncDockState();
|
|
446
|
+
}
|