clay-server 5.5.0-beta.1 → 5.5.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.
Files changed (42) hide show
  1. package/lib/public/modules/sidebar-sessions.js +3 -0
  2. package/lib/public/modules/split-view-arrange-menu.js +38 -0
  3. package/lib/public/modules/split-view-create-menu.js +9 -5
  4. package/lib/public/modules/split-view-member-actions.js +42 -0
  5. package/lib/public/modules/split-view-picker-actions.js +2 -2
  6. package/lib/public/modules/split-view-presentation-renderer.js +10 -35
  7. package/lib/public/modules/split-view-presentations.js +9 -8
  8. package/lib/public/modules/split-view-sidebar-menu.js +2 -1
  9. package/lib/public/modules/view-workspace-state.js +1 -1
  10. package/lib/public/pane-assets/{app-4IZ6F6ND.js → app-SEMVZ4AY.js} +1 -1
  11. package/lib/public/pane-assets/{chunk-L3FCTD7U.js → chunk-4YE4RU27.js} +1 -1
  12. package/lib/public/pane-assets/{chunk-SEELA2D2.js → chunk-5UBN6GR7.js} +1 -1
  13. package/lib/public/pane-assets/chunk-6AGSOAOD.js +1 -0
  14. package/lib/public/pane-assets/chunk-AATAIAXL.js +1 -0
  15. package/lib/public/pane-assets/{chunk-RRYWV5JT.js → chunk-BNNPJJVG.js} +1 -1
  16. package/lib/public/pane-assets/{chunk-3E6LDNXF.js → chunk-C6P7PICY.js} +1 -1
  17. package/lib/public/pane-assets/{chunk-ELL4UBGY.js → chunk-CQNPEH2M.js} +1 -1
  18. package/lib/public/pane-assets/chunk-D3CE5FZL.js +1 -0
  19. package/lib/public/pane-assets/{chunk-6ZF2FJT3.js → chunk-E4VM2IDB.js} +1 -1
  20. package/lib/public/pane-assets/{chunk-OB3KKICE.js → chunk-FK3YLGAP.js} +1 -1
  21. package/lib/public/pane-assets/{chunk-FILRACQB.js → chunk-GKSLBGVE.js} +95 -95
  22. package/lib/public/pane-assets/chunk-J5PTSKJ6.js +1 -0
  23. package/lib/public/pane-assets/{chunk-YXJ7ISEK.js → chunk-K4PAN77B.js} +1 -1
  24. package/lib/public/pane-assets/{chunk-DJ5WXQKT.js → chunk-M5CWIIIT.js} +1 -1
  25. package/lib/public/pane-assets/{chunk-A7OB7HQS.js → chunk-QBCM7QEA.js} +1 -1
  26. package/lib/public/pane-assets/chunk-QPBO6ID4.js +1 -0
  27. package/lib/public/pane-assets/{chunk-YWHBNEB2.js → chunk-QWQB2YRF.js} +1 -1
  28. package/lib/public/pane-assets/chunk-RA6VUJTY.js +1 -0
  29. package/lib/public/pane-assets/{chunk-A4MLSYBJ.js → chunk-U7EHYRJZ.js} +1 -1
  30. package/lib/public/pane-assets/chunk-XOZUM5ET.js +1 -0
  31. package/lib/public/pane-assets/{chunk-I6X5J2V5.js → chunk-XYZGVYWW.js} +1 -1
  32. package/lib/public/pane-assets/{chunk-ADGKPVFD.js → chunk-YR5GH3GI.js} +1 -1
  33. package/lib/public/pane-assets/{chunk-YFUORWA6.js → chunk-YVVT3CTV.js} +1 -1
  34. package/lib/public/pane-assets/manifest.json +433 -431
  35. package/package.json +1 -1
  36. package/lib/public/pane-assets/chunk-6KO36HMU.js +0 -1
  37. package/lib/public/pane-assets/chunk-H6MU72QE.js +0 -1
  38. package/lib/public/pane-assets/chunk-PJURCIJQ.js +0 -1
  39. package/lib/public/pane-assets/chunk-Q7RFSS5Q.js +0 -1
  40. package/lib/public/pane-assets/chunk-UTLQWAKG.js +0 -1
  41. package/lib/public/pane-assets/chunk-WE4NWXNK.js +0 -1
  42. package/lib/public/pane-assets/chunk-Z2MHS43B.js +0 -1
@@ -1,3 +1,4 @@
1
+ import { appendRemoveFromView } from './split-view-member-actions.js';
1
2
  import { appendGithubWork } from './session-github.js';
2
3
  // sidebar-sessions.js - Session list, search, presence, countdown, CLI picker
3
4
  // Extracted from sidebar.js (PR-35)
@@ -290,6 +291,8 @@ function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData, po
290
291
  menu.appendChild(renameItem);
291
292
 
292
293
 
294
+ appendRemoveFromView(menu, sessionData, currentAnchor);
295
+
293
296
  // Session visibility toggle (only the session owner can change)
294
297
  if (!isMateWorkspace(store.snap()) && store.get('isMultiUserMode') && sessionData && !sessionData.isMate && sessionData.ownerId && sessionData.ownerId === store.get('myUserId')) {
295
298
  var currentVis = (sessionData && sessionData.sessionVisibility) || "private";
@@ -0,0 +1,38 @@
1
+ import { iconHtml } from './icons.js';
2
+ import { appendLayoutOption } from './split-view-layout-icons.js';
3
+ import { SPLIT_SIDES } from './split-view-picker-render.js';
4
+
5
+ export function ensureArrangeMenu(closePresentationArrange) {
6
+ var menu = document.getElementById("split-view-arrange-menu");
7
+ if (menu) return menu;
8
+ menu = document.createElement("div"); menu.id = "split-view-arrange-menu"; menu.className = "split-view-arrange";
9
+ menu.setAttribute("role", "dialog"); menu.setAttribute("aria-label", "Arrange Split view"); menu.hidden = true;
10
+ var header = document.createElement("div"); header.className = "split-view-arrange-header";
11
+ var title = document.createElement("strong"); title.textContent = "Arrange Split view"; header.appendChild(title);
12
+ var close = document.createElement("button"); close.type = "button"; close.setAttribute("aria-label", "Close arrangement menu"); close.innerHTML = iconHtml("x"); header.appendChild(close);
13
+ close.addEventListener("click", function () { closePresentationArrange(); }); menu.appendChild(header);
14
+ var presets = [["balanced", "Balanced"], ["columns", "Columns"], ["rows", "Rows"], ["grid", "Grid"], ["main-left", "Main left"], ["main-right", "Main right"]];
15
+ var presetGrid = document.createElement("div"); presetGrid.className = "split-view-arrange-grid";
16
+ presets.forEach(function (item) { var button = document.createElement("button"); button.type = "button"; button.dataset.preset = item[0]; appendLayoutOption(button, item[1], "preset", item[0]); presetGrid.appendChild(button); });
17
+ menu.appendChild(presetGrid);
18
+ var positions = [["left", "Left half"], ["right", "Right half"], ["top", "Top half"], ["bottom", "Bottom half"], ["top-left", "Top left"], ["top-right", "Top right"], ["bottom-left", "Bottom left"], ["bottom-right", "Bottom right"], ["left-third", "Left third"], ["right-third", "Right third"]];
19
+ var positionGrid = document.createElement("div"); positionGrid.className = "split-view-arrange-grid split-view-arrange-positions";
20
+ positions.forEach(function (item) { var button = document.createElement("button"); button.type = "button"; button.dataset.position = item[0]; appendLayoutOption(button, item[1], "position", item[0]); positionGrid.appendChild(button); });
21
+ menu.appendChild(positionGrid);
22
+ var additions = document.createElement('div'); additions.className = 'split-session-directions';
23
+ SPLIT_SIDES.forEach(function (side) {
24
+ var button = document.createElement('button'); button.type = 'button'; button.dataset.arrangeAddSide = side[0];
25
+ button.innerHTML = iconHtml(side[2]); var label = document.createElement('span'); label.textContent = 'Add ' + side[1] + ' Split'; button.appendChild(label); additions.appendChild(button);
26
+ });
27
+ menu.appendChild(additions);
28
+ var focusButton = document.createElement("button"); focusButton.type = "button"; focusButton.dataset.focusLayout = "true"; menu.appendChild(focusButton);
29
+ var membership = document.createElement("button"); membership.type = "button"; membership.dataset.arrangeMembership = "true";
30
+ membership.textContent = "Choose sessions"; menu.appendChild(membership);
31
+ var context = document.createElement("div"); context.className = "split-view-arrange-context";
32
+ var contextButton = document.createElement("button"); contextButton.type = "button"; contextButton.dataset.arrangeContext = "true";
33
+ contextButton.setAttribute("aria-expanded", "false"); contextButton.setAttribute("aria-controls", "split-view-arrange-context-list");
34
+ var contextTitle = document.createElement("span"); contextTitle.dataset.arrangeContextTitle = "true"; contextButton.appendChild(contextTitle); context.appendChild(contextButton);
35
+ var contextList = document.createElement("div"); contextList.id = "split-view-arrange-context-list"; contextList.hidden = true; contextList.setAttribute("role", "listbox");
36
+ context.appendChild(contextList); menu.insertBefore(context, presetGrid);
37
+ document.body.appendChild(menu); return menu;
38
+ }
@@ -29,8 +29,8 @@ function position() {
29
29
  menu.style.left = Math.max(8, Math.min(rect.right - width, innerWidth - width - 8)) + 'px';
30
30
  menu.style.top = Math.max(8, Math.min(rect.bottom + 5, innerHeight - menu.offsetHeight - 8)) + 'px';
31
31
  }
32
- function open(anchor) {
33
- var receipt = pickerReceipt(anchor);
32
+ function open(anchor, side, origin) {
33
+ var receipt = pickerReceipt(anchor, origin);
34
34
  if (!receipt || !pickerCurrent(receipt)) { showToast('Wait for this View to finish loading, then try again.', 'warn'); return; }
35
35
  var menu = menuElement();
36
36
  if (menu && !menu.hidden && menu.clayCreateAnchor === anchor) { close(true); return; }
@@ -41,8 +41,12 @@ function open(anchor) {
41
41
  }
42
42
  receipt.reservationId = 'split-picker-' + Date.now().toString(36) + '-' + Math.random().toString(36).slice(2);
43
43
  menu.clayCreateAnchor = anchor; anchor.setAttribute('aria-expanded', 'true');
44
- store.set({ splitSessionPicker: { receipt: receipt, side: null, query: '', error: '', priorFocus: store.get('projectSplitViewFocusedOrigin') } });
45
- renderPicker(menu); menu.hidden = false; position(); menu.querySelector('[data-split-side]').focus();
44
+ store.set({ splitSessionPicker: { receipt: receipt, side: side || null, query: '', error: '', priorFocus: store.get('projectSplitViewFocusedOrigin') } });
45
+ if (side) store.set({ projectSplitViewFocusedOrigin: null });
46
+ renderPicker(menu); menu.hidden = false;
47
+ if (side) document.dispatchEvent(new CustomEvent('clay-split-picker-layout'));
48
+ position(); menu.querySelector(side ? 'input' : '[data-split-side]').focus();
49
+ if (side) retryOptions();
46
50
  }
47
51
  function onClick(event) {
48
52
  var menu = menuElement(), state = store.get('splitSessionPicker'); if (!menu || menu.hidden || !state) return;
@@ -76,7 +80,7 @@ function onKey(event) {
76
80
  items[next].focus();
77
81
  }
78
82
  export function initSplitViewCreateMenu() {
79
- document.addEventListener('clay-split-view-open-create', function (event) { if (event.detail && event.detail.anchor) open(event.detail.anchor); });
83
+ document.addEventListener('clay-split-view-open-create', function (event) { if (event.detail && event.detail.anchor) open(event.detail.anchor, event.detail.side, event.detail.origin); });
80
84
  document.addEventListener('click', onClick, true); document.addEventListener('keydown', onKey, true);
81
85
  document.addEventListener('input', function (event) {
82
86
  var state = store.get('splitSessionPicker'); if (!state || !event.target.matches('#split-view-create-menu input')) return;
@@ -0,0 +1,42 @@
1
+ import { store } from './store.js';
2
+ import { getWs } from './ws-ref.js';
3
+ import { mutation } from './view-mutations.js';
4
+ import { remove, validateTree } from './split-view-layout-client.js';
5
+ import { showToast } from './utils.js';
6
+ import { iconHtml } from './icons.js';
7
+ import { closeSessionContextMenu } from './session-context-menu.js';
8
+
9
+ export function removeViewSession(view, origin) {
10
+ var live = (store.get('projectSplitViews') || []).find(function (item) { return item.id === view.id && item.revision === view.revision; });
11
+ if (!live || !live.sessions.some(function (session) { return session.sessionOriginId === origin; })) return false;
12
+ var active = live.id === store.get('projectSplitViewActiveId');
13
+ if (active) {
14
+ try {
15
+ document.querySelectorAll('#split-host .split-pane-frame').forEach(function (frame) { if (frame.clayPane) frame.clayPane.checkDraft(); });
16
+ } catch (error) { showToast(error.message, 'warn'); return false; }
17
+ }
18
+ var origins = live.sessions.map(function (session) { return session.sessionOriginId; }).filter(function (item) { return item !== origin; });
19
+ var tree = remove(live.tree, origin);
20
+ if (!validateTree(tree, origins).ok) return false;
21
+ var nextActive = live.activeSessionOriginId === origin ? origins[0] || null : live.activeSessionOriginId;
22
+ return mutation('project_split_view_update', { id: live.id, sessionOrigins: origins, tree: tree,
23
+ layout: live.layout, activeSessionOriginId: nextActive, active: active }, active ? { closedOrigin: origin, activeOrigin: nextActive } : null);
24
+ }
25
+
26
+ export function appendRemoveFromView(menu, session, currentAnchor) {
27
+ if (!session || session.sessionRole === 'worker') return;
28
+ var view = (store.get('projectSplitViews') || []).find(function (item) {
29
+ return item.sessions.length > 1 && item.sessions.some(function (ref) { return ref.sessionOriginId === session.sessionOriginId; });
30
+ });
31
+ if (!view) return;
32
+ var socket = getWs(), slug = store.get('currentSlug'), viewer = store.get('myUserId'), generation = store.get('projectSplitViewSocketGeneration');
33
+ var button = document.createElement('button'); button.className = 'session-ctx-item';
34
+ button.innerHTML = iconHtml('panel-left-close') + ' <span>Remove from View</span>';
35
+ button.disabled = !!store.get('projectSplitViewPending');
36
+ button.addEventListener('click', function (event) {
37
+ event.stopPropagation(); var anchor = currentAnchor(); closeSessionContextMenu(false);
38
+ if (!anchor || socket !== getWs() || slug !== store.get('currentSlug') || viewer !== store.get('myUserId') || generation !== store.get('projectSplitViewSocketGeneration')) return;
39
+ removeViewSession(view, session.sessionOriginId);
40
+ });
41
+ menu.appendChild(button);
42
+ }
@@ -11,9 +11,9 @@ import { checkComposerDeparture } from './session-rich-drafts.js';
11
11
  import { createOptions } from './session-create.js';
12
12
  import { showToast } from './utils.js';
13
13
 
14
- export function pickerReceipt(anchor) {
14
+ export function pickerReceipt(anchor, targetOrigin) {
15
15
  var view = activeSavedView(), pane = anchor && anchor.closest('.split-pane'), frame = pane && pane.querySelector('.split-pane-frame');
16
- var origin = pane && pane.dataset.presentationOrigin || frame && frame.dataset.sessionOriginId || store.get('sessionOriginId');
16
+ var origin = targetOrigin || pane && pane.dataset.presentationOrigin || frame && frame.dataset.sessionOriginId || store.get('sessionOriginId');
17
17
  return view && view.sessions.some(function (session) { return session.sessionOriginId === origin; }) ? { scope: layoutScope(view), origin: origin } : null;
18
18
  }
19
19
  export function pickerCurrent(receipt) {
@@ -16,7 +16,8 @@ import { createSplitPane, updateSplitPaneMetadata, updateSplitPaneCloseVisibilit
16
16
  import { syncPaneHeaderState } from './split-pane-header-state.js';
17
17
  import { rectangles, resize, validateTree, listIds } from './split-view-layout-client.js';
18
18
  import { iconHtml, refreshIcons } from './icons.js';
19
- import { appendLayoutOption } from './split-view-layout-icons.js';
19
+ import { ensureArrangeMenu as buildArrangeMenu } from './split-view-arrange-menu.js';
20
+ import { pickerCapacity } from './split-view-picker-actions.js';
20
21
  import { reserveEmptySplit, clearEmptySplit } from './split-session-empty-pane.js';
21
22
 
22
23
  var host = null;
@@ -51,7 +52,7 @@ function dispatch(name, detail) {
51
52
  export function initPresentationRenderer(hostElement) {
52
53
  host = hostElement;
53
54
  app = document.getElementById("app");
54
- ensureArrangeMenu();
55
+ buildArrangeMenu(closePresentationArrange);
55
56
  document.addEventListener('clay-split-picker-layout', renderCurrentGeometry);
56
57
  document.addEventListener("click", onClick, true);
57
58
  document.addEventListener("keydown", onKeyDown, true);
@@ -60,7 +61,7 @@ export function initPresentationRenderer(hostElement) {
60
61
  document.addEventListener("pointercancel", onPointerCancel, true);
61
62
  document.addEventListener("lostpointercapture", onPointerCancel, true);
62
63
  window.addEventListener("blur", onWindowBlur);
63
- window.addEventListener("resize", function () { renderCurrentGeometry(); });
64
+ window.addEventListener("resize", function () { closePresentationArrange(false); renderCurrentGeometry(); });
64
65
  window.addEventListener("scroll", closePresentationArrange, true);
65
66
  if (typeof ResizeObserver === "function") {
66
67
  resizeObserver = new ResizeObserver(function () { renderCurrentGeometry(); });
@@ -136,7 +137,7 @@ export function renderPresentationView(view, tree, sessions) {
136
137
  if (app) app.classList.add("split-native-hidden");
137
138
  reconcileSplitPanes(host, panes, function (pane) { return createSplitPane(pane, function (sessionId) { dispatch("clay-split-view-close-pane", { sessionId: sessionId }); }); }, updateSplitPaneMetadata, paneRetention(host));
138
139
  Array.from(host.querySelectorAll(':scope > .split-pane .split-pane-header')).forEach(function (header) { ensureArrangeTrigger(header); });
139
- ensureArrangeMenu();
140
+ buildArrangeMenu(closePresentationArrange);
140
141
  Array.from(host.querySelectorAll(':scope > .split-pane')).forEach(function (node) {
141
142
  var target = panes.find(function (pane) { return node.dataset.splitPaneKey === pane.slug + '#' + pane.sessionId; });
142
143
  var session = target && sessions.find(function (item) { return item.id === target.sessionId; });
@@ -278,34 +279,6 @@ export function ensureArrangeTrigger(header) {
278
279
  if (pane) syncPaneHeaderState(pane);
279
280
  }
280
281
 
281
- function ensureArrangeMenu() {
282
- var menu = document.getElementById("split-view-arrange-menu");
283
- if (menu) return menu;
284
- menu = document.createElement("div"); menu.id = "split-view-arrange-menu"; menu.className = "split-view-arrange";
285
- menu.setAttribute("role", "dialog"); menu.setAttribute("aria-label", "Arrange Split view"); menu.hidden = true;
286
- var header = document.createElement("div"); header.className = "split-view-arrange-header";
287
- var title = document.createElement("strong"); title.textContent = "Arrange Split view"; header.appendChild(title);
288
- var close = document.createElement("button"); close.type = "button"; close.setAttribute("aria-label", "Close arrangement menu"); close.innerHTML = iconHtml("x"); header.appendChild(close);
289
- close.addEventListener("click", function () { closePresentationArrange(); }); menu.appendChild(header);
290
- var presets = [["balanced", "Balanced"], ["columns", "Columns"], ["rows", "Rows"], ["grid", "Grid"], ["main-left", "Main left"], ["main-right", "Main right"]];
291
- var presetGrid = document.createElement("div"); presetGrid.className = "split-view-arrange-grid";
292
- presets.forEach(function (item) { var button = document.createElement("button"); button.type = "button"; button.dataset.preset = item[0]; appendLayoutOption(button, item[1], "preset", item[0]); presetGrid.appendChild(button); });
293
- menu.appendChild(presetGrid);
294
- var positions = [["left", "Left half"], ["right", "Right half"], ["top", "Top half"], ["bottom", "Bottom half"], ["top-left", "Top left"], ["top-right", "Top right"], ["bottom-left", "Bottom left"], ["bottom-right", "Bottom right"], ["left-third", "Left third"], ["right-third", "Right third"]];
295
- var positionGrid = document.createElement("div"); positionGrid.className = "split-view-arrange-grid split-view-arrange-positions";
296
- positions.forEach(function (item) { var button = document.createElement("button"); button.type = "button"; button.dataset.position = item[0]; appendLayoutOption(button, item[1], "position", item[0]); positionGrid.appendChild(button); });
297
- menu.appendChild(positionGrid);
298
- var focusButton = document.createElement("button"); focusButton.type = "button"; focusButton.dataset.focusLayout = "true"; menu.appendChild(focusButton);
299
- var membership = document.createElement("button"); membership.type = "button"; membership.dataset.arrangeMembership = "true";
300
- membership.textContent = "Choose sessions"; menu.appendChild(membership);
301
- var context = document.createElement("div"); context.className = "split-view-arrange-context";
302
- var contextButton = document.createElement("button"); contextButton.type = "button"; contextButton.dataset.arrangeContext = "true";
303
- contextButton.setAttribute("aria-expanded", "false"); contextButton.setAttribute("aria-controls", "split-view-arrange-context-list");
304
- var contextTitle = document.createElement("span"); contextTitle.dataset.arrangeContextTitle = "true"; contextButton.appendChild(contextTitle); context.appendChild(contextButton);
305
- var contextList = document.createElement("div"); contextList.id = "split-view-arrange-context-list"; contextList.hidden = true; contextList.setAttribute("role", "listbox");
306
- context.appendChild(contextList); menu.insertBefore(context, presetGrid);
307
- document.body.appendChild(menu); return menu;
308
- }
309
282
 
310
283
  function openArrangeMenu(trigger) {
311
284
  if (!syncPaneHeaderState(trigger.closest('.split-pane'))) return;
@@ -313,7 +286,7 @@ function openArrangeMenu(trigger) {
313
286
  dispatch("clay-split-view-open-create", { anchor: trigger });
314
287
  return;
315
288
  }
316
- var menu = ensureArrangeMenu();
289
+ var menu = buildArrangeMenu(closePresentationArrange);
317
290
  if (!menu.hidden && menuTrigger === trigger) { closePresentationArrange(); return; }
318
291
  closePresentationArrange(false); menuTrigger = trigger; menu.hidden = false;
319
292
  trigger.setAttribute("aria-expanded", "true");
@@ -340,6 +313,7 @@ function openArrangeMenu(trigger) {
340
313
  Array.from(menu.querySelectorAll('[data-position*="-"]:not([data-position$="-third"])')).forEach(function (button) {
341
314
  button.disabled = count < 3; button.title = count < 3 ? "Quarter layouts require at least three sessions" : "";
342
315
  });
316
+ menu.querySelectorAll('[data-arrange-add-side]').forEach(function (button) { button.disabled = !pickerCapacity() || !!store.get('projectSplitViewPending'); });
343
317
  var rect = trigger.getBoundingClientRect(), width = Math.min(280, window.innerWidth - 16);
344
318
  menu.style.left = Math.max(8, Math.min(rect.left, window.innerWidth - width - 8)) + "px";
345
319
  menu.style.top = Math.max(8, Math.min(rect.bottom + 4, window.innerHeight - menu.offsetHeight - 8)) + "px";
@@ -362,10 +336,11 @@ function onClick(event) {
362
336
  if (trigger) { event.preventDefault(); event.stopImmediatePropagation(); openArrangeMenu(trigger); return; }
363
337
  var menu = event.target.closest('#split-view-arrange-menu');
364
338
  if (menu) {
365
- if (event.target.closest('[data-arrange-membership]')) {
339
+ var addSide = event.target.closest('[data-arrange-add-side]');
340
+ if (addSide || event.target.closest('[data-arrange-membership]')) {
366
341
  event.preventDefault(); event.stopImmediatePropagation();
367
342
  var anchor = menuTrigger; closePresentationArrange(false);
368
- if (anchor && anchor.isConnected) dispatch("clay-split-view-open-create", { anchor: anchor });
343
+ if (anchor && anchor.isConnected) dispatch("clay-split-view-open-create", { anchor: anchor, side: addSide && addSide.dataset.arrangeAddSide, origin: menu.dataset.sourceOrigin });
369
344
  return;
370
345
  }
371
346
  var contextButton = event.target.closest('[data-arrange-context]');
@@ -19,10 +19,11 @@ import { initPresentationDrag, restorePresentationDrag } from './split-view-pres
19
19
  import { detachTuiView } from './session-tui-view.js';
20
20
  import { checkComposerDeparture } from './session-rich-drafts.js';
21
21
  import { showToast } from './utils.js';
22
- import { preset, listIds, validateTree, remove, arrangeRegion } from './split-view-layout-client.js';
22
+ import { preset, listIds, validateTree, arrangeRegion } from './split-view-layout-client.js';
23
23
  import { viewIdForOrigin, updateActiveSession, exactDriverForOrigin, restorablePresentation } from './split-view-presentation-lookup.js';
24
24
  import { groupedSessionIds } from './split-group-helpers.js';
25
25
  import { handleSplitViewCreateEvent } from './split-view-create-action.js';
26
+ import { removeViewSession } from './split-view-member-actions.js';
26
27
  import { initSplitViewCreateMenu } from './split-view-create-menu.js';
27
28
  import { currentSingletonPresentation } from './split-view-singleton.js';
28
29
  var host = null;
@@ -333,6 +334,12 @@ function toggleGroupMenu(group, anchor, point) {
333
334
  }
334
335
  function runGroupAction(view, action, root) {
335
336
  closeGroupMenus(false);
337
+ if (action === 'add-pane') {
338
+ if (!setActiveView(view.id)) return;
339
+ var anchor = host && host.querySelector('.split-pane:not(.split-pane-cached) [data-action="arrange"]');
340
+ if (anchor) document.dispatchEvent(new CustomEvent('clay-split-view-open-create', { detail: { anchor: anchor, side: 'right', origin: view.activeSessionOriginId || view.sessions[0].sessionOriginId } }));
341
+ return;
342
+ }
336
343
  if (action === 'favorite' || action === 'folder') { organizeViewAction(view, action); return; }
337
344
  if (action === "rename") { startRename(root, view); return; }
338
345
  if (action === "separate") {
@@ -418,13 +425,7 @@ function onClosePane(event) {
418
425
  if (!view || !event.detail || !validPresentationClose(event.detail)) return;
419
426
  var session = (getCachedSessions() || []).find(function (item) { return item.id === Number(event.detail.sessionId); });
420
427
  if (!session || !view.sessions.some(function (item) { return item.sessionOriginId === session.sessionOriginId; })) return;
421
- try { checkMountedPaneDrafts(); } catch (error) { showToast(error.message, "warn"); return; }
422
- var origins = view.sessions.map(function (item) { return item.sessionOriginId; }).filter(function (origin) { return origin !== session.sessionOriginId; });
423
- var nextTree = remove(view.tree, session.sessionOriginId);
424
- if (!validateTree(nextTree, origins).ok) return;
425
- var nextActive = view.activeSessionOriginId === session.sessionOriginId ? origins[0] || null : view.activeSessionOriginId;
426
- mutation("project_split_view_update", { id: view.id, sessionOrigins: origins, tree: nextTree,
427
- layout: view.layout, activeSessionOriginId: nextActive }, { closedOrigin: session.sessionOriginId, activeOrigin: nextActive });
428
+ removeViewSession(view, session.sessionOriginId);
428
429
  }
429
430
  function onFocus(event) {
430
431
  var view = viewExists(store.get('projectSplitViews'), store.get('projectSplitViewActiveId'));
@@ -25,8 +25,9 @@ export function openSplitViewMenu(group, anchor, point, onAction) {
25
25
  }
26
26
  closeFolderMenu(false); closeSessionContextMenu(false);
27
27
  var menu = document.createElement('div'); menu.className = 'session-ctx-menu split-view-menu';
28
- [['favorite', view.favorite ? 'Remove from Favorites' : 'Add to Favorites', 'star'], ['folder', 'Move to folder', 'folder-input'], ['rename', 'Rename', 'pencil'], ['separate', 'Separate', 'columns-2']].forEach(function (entry) {
28
+ [['add-pane', 'Add pane', 'panel-right-open'], ['favorite', view.favorite ? 'Remove from Favorites' : 'Add to Favorites', 'star'], ['folder', 'Move to folder', 'folder-input'], ['rename', 'Rename', 'pencil'], ['separate', 'Separate', 'columns-2']].forEach(function (entry) {
29
29
  var button = document.createElement('button'); button.className = 'session-ctx-item'; button.dataset.splitViewAction = entry[0];
30
+ if (entry[0] === 'add-pane') button.disabled = !view.sessions.length || view.sessions.length + (view.workspace && view.workspace.linkedPair ? view.workspace.linkedPair.workerOrigins.length : 0) >= 8 || !!store.get('projectSplitViewPending');
30
31
  button.innerHTML = iconHtml(entry[2]) + ' <span>' + entry[1] + '</span>';
31
32
  button.addEventListener('click', function (event) {
32
33
  event.stopPropagation(); var root = currentRoot(); closeSessionContextMenu(false);
@@ -81,7 +81,7 @@ export function prepareViewMutation(type, message) {
81
81
  if (type === 'project_split_view_create' || type === 'project_split_view_update') {
82
82
  if (!message.workspace) message.workspace = recomposeWorkspace(view && view.workspace, message.tree, message.activeSessionOriginId);
83
83
  message.tree = sessionTree(message.workspace);
84
- message.active = true;
84
+ message.active = message.active !== false;
85
85
  }
86
86
  if (type === 'project_split_view_move') {
87
87
  var target = views.find(function (item) { return item.id === message.targetViewId; });