@k2b/ui 0.28.0 → 0.29.0
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/dist/browser/actions/ContextMenu.js +5 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/DragAndDrop.js +89 -0
- package/dist/browser/actions/DragAndDrop.js.map +1 -0
- package/dist/browser/actions/GestureMenu.js +26 -3
- package/dist/browser/actions/GestureMenu.js.map +1 -1
- package/dist/browser/actions/drag-and-drop-messages.js +75 -0
- package/dist/browser/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/browser/actions/drag-and-drop.js +692 -0
- package/dist/browser/actions/drag-and-drop.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +385 -265
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatDecision.js +778 -0
- package/dist/browser/chat/ChatDecision.js.map +1 -0
- package/dist/browser/chat/ChatPrimitives.js +34 -28
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +6 -0
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/command-search.js +10 -3
- package/dist/browser/chat/command-search.js.map +1 -1
- package/dist/browser/chat/index.js +6 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/chat/types.js.map +1 -1
- package/dist/browser/content/Calendar.js +3 -3
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/Chart.js +54 -71
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/FileBrowser.js +2 -2
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileTree.js +42 -36
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileTypeIcon.js +72 -0
- package/dist/browser/content/FileTypeIcon.js.map +1 -0
- package/dist/browser/content/FileView.js +2 -2
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/ReferenceChip.js +162 -0
- package/dist/browser/content/ReferenceChip.js.map +1 -0
- package/dist/browser/content/calendar-pointer.js +9 -0
- package/dist/browser/content/calendar-pointer.js.map +1 -1
- package/dist/browser/content/calendar-time-view.js +6 -3
- package/dist/browser/content/calendar-time-view.js.map +1 -1
- package/dist/browser/content/index.js +2 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/layout/AppOverview.js +1 -1
- package/dist/browser/layout/AppOverview.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +644 -445
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/PanelDialog.js +88 -86
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/ResizeSeparator.js +81 -0
- package/dist/browser/layout/ResizeSeparator.js.map +1 -0
- package/dist/browser/layout/SidebarSwitcher.js +9 -2
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
- package/dist/browser/layout/TabBar.js +15 -12
- package/dist/browser/layout/TabBar.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +130 -17
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/index.js +3 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/resize-separator.js +90 -0
- package/dist/browser/layout/resize-separator.js.map +1 -0
- package/dist/browser/layout/workspace-messages.js +12 -2
- package/dist/browser/layout/workspace-messages.js.map +1 -1
- package/dist/browser/surfaces/LinkCard.js +1 -1
- package/dist/browser/surfaces/LinkCard.js.map +1 -1
- package/dist/browser/surfaces/Placeholder.js +14 -3
- package/dist/browser/surfaces/Placeholder.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +23 -0
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/widgets/Widget.js +1 -1
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +5 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/DragAndDrop.js +63 -0
- package/dist/ssr/actions/DragAndDrop.js.map +1 -0
- package/dist/ssr/actions/GestureMenu.js +26 -3
- package/dist/ssr/actions/GestureMenu.js.map +1 -1
- package/dist/ssr/actions/drag-and-drop-messages.js +75 -0
- package/dist/ssr/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/ssr/actions/drag-and-drop.js +692 -0
- package/dist/ssr/actions/drag-and-drop.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +131 -14
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatDecision.js +465 -0
- package/dist/ssr/chat/ChatDecision.js.map +1 -0
- package/dist/ssr/chat/ChatPrimitives.js +2 -2
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +6 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/command-search.js +10 -3
- package/dist/ssr/chat/command-search.js.map +1 -1
- package/dist/ssr/chat/index.js +6 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/chat/types.js.map +1 -1
- package/dist/ssr/content/Calendar.js +3 -3
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/Chart.js +19 -23
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/FileBrowser.js +2 -2
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileTree.js +21 -14
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileTypeIcon.js +50 -0
- package/dist/ssr/content/FileTypeIcon.js.map +1 -0
- package/dist/ssr/content/FileView.js +2 -2
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/ReferenceChip.js +121 -0
- package/dist/ssr/content/ReferenceChip.js.map +1 -0
- package/dist/ssr/content/calendar-pointer.js +9 -0
- package/dist/ssr/content/calendar-pointer.js.map +1 -1
- package/dist/ssr/content/calendar-time-view.js +6 -3
- package/dist/ssr/content/calendar-time-view.js.map +1 -1
- package/dist/ssr/content/index.js +2 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/layout/AppOverview.js +1 -1
- package/dist/ssr/layout/AppOverview.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +272 -95
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/PanelDialog.js +7 -6
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/ResizeSeparator.js +45 -0
- package/dist/ssr/layout/ResizeSeparator.js.map +1 -0
- package/dist/ssr/layout/SidebarSwitcher.js +9 -2
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
- package/dist/ssr/layout/TabBar.js +1 -1
- package/dist/ssr/layout/TabBar.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +130 -17
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/index.js +3 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/resize-separator.js +90 -0
- package/dist/ssr/layout/resize-separator.js.map +1 -0
- package/dist/ssr/layout/workspace-messages.js +12 -2
- package/dist/ssr/layout/workspace-messages.js.map +1 -1
- package/dist/ssr/surfaces/LinkCard.js +1 -1
- package/dist/ssr/surfaces/LinkCard.js.map +1 -1
- package/dist/ssr/surfaces/Placeholder.js +4 -2
- package/dist/ssr/surfaces/Placeholder.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +23 -0
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/widgets/Widget.js +1 -1
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +1 -0
- package/dist/types/actions/DragAndDrop.d.ts +29 -0
- package/dist/types/actions/drag-and-drop-messages.d.ts +35 -0
- package/dist/types/actions/drag-and-drop.d.ts +36 -0
- package/dist/types/actions/index.d.ts +2 -0
- package/dist/types/chat/ChatComposer.d.ts +19 -1
- package/dist/types/chat/ChatDecision.d.ts +133 -0
- package/dist/types/chat/ChatPrimitives.d.ts +4 -1
- package/dist/types/chat/ChatTimeline.d.ts +2 -1
- package/dist/types/chat/chat-messages.d.ts +3 -0
- package/dist/types/chat/command-search.d.ts +3 -0
- package/dist/types/chat/index.d.ts +23 -1
- package/dist/types/chat/types.d.ts +54 -1
- package/dist/types/content/Chart.d.ts +9 -3
- package/dist/types/content/FileTypeIcon.d.ts +27 -0
- package/dist/types/content/ReferenceChip.d.ts +49 -0
- package/dist/types/content/calendar-pointer.d.ts +6 -0
- package/dist/types/content/index.d.ts +3 -0
- package/dist/types/layout/AppWorkspace.d.ts +5 -3
- package/dist/types/layout/ResizeSeparator.d.ts +9 -0
- package/dist/types/layout/TabBar.d.ts +7 -0
- package/dist/types/layout/app-workspace-controller.d.ts +2 -0
- package/dist/types/layout/index.d.ts +3 -1
- package/dist/types/layout/resize-separator.d.ts +18 -0
- package/dist/types/layout/workspace-messages.d.ts +5 -0
- package/dist/types/surfaces/StatCell.d.ts +6 -0
- package/package.json +2 -2
|
@@ -6,8 +6,36 @@ const HANDLE_SELECTOR = "[data-app-workspace-resize]";
|
|
|
6
6
|
const ROOT_SELECTOR = "[data-k2b-app-workspace]";
|
|
7
7
|
const LAYOUT_REGION_SELECTOR = [ROOT_SELECTOR, ".k2b-app-workspace__sidebar", ".k2b-app-workspace__main-pane", ".k2b-app-workspace__detail", ".k2b-app-workspace__drawer", HANDLE_SELECTOR].join(",");
|
|
8
8
|
const TOGGLE_SELECTOR = "[data-app-workspace-sidebar-toggle]";
|
|
9
|
-
/**
|
|
10
|
-
const
|
|
9
|
+
/** Touch-tablet gestures remain viewport decisions. */
|
|
10
|
+
const TOUCH_DRAWER_QUERY = "(min-width: 48rem) and (max-width: 63.999rem) and (pointer: coarse)";
|
|
11
|
+
const DETAIL_TOGGLE_SELECTOR = "[data-app-workspace-detail-toggle]";
|
|
12
|
+
const DETAIL_DRAWER_SELECTOR = '.k2b-app-workspace__detail[data-workspace-detail-drawer="open"]';
|
|
13
|
+
const cssState = (element, name) => getComputedStyle(element).getPropertyValue(name).trim();
|
|
14
|
+
const detailWaiting = aside => cssState(aside, "--k2b-workspace-detail-waiting") === "1";
|
|
15
|
+
const detailDrawer = aside => aside.dataset.workspaceDetailDrawer === "open";
|
|
16
|
+
const detailToggle = aside => {
|
|
17
|
+
const root = workspaceRoot(aside);
|
|
18
|
+
return rootElements(root ?? aside, DETAIL_TOGGLE_SELECTOR).find(toggle => toggle.getAttribute("aria-controls") === aside.id);
|
|
19
|
+
};
|
|
20
|
+
// The trail's registered property accepts a length, not the drawer's percentage
|
|
21
|
+
// cap. Only a user-opened drawer needs this measurement; the first frame stays CSS-owned.
|
|
22
|
+
const detailDrawerContent = aside => aside.closest(".k2b-app-workspace__content");
|
|
23
|
+
const syncDetailDrawerSpace = aside => detailDrawerContent(aside)?.style.setProperty("--k2b-detail-space", `${aside.getBoundingClientRect().width}px`);
|
|
24
|
+
const parkDetailDrawer = (aside, focus = false) => {
|
|
25
|
+
if (!detailDrawer(aside)) return;
|
|
26
|
+
delete aside.dataset.workspaceDetailDrawer;
|
|
27
|
+
detailDrawerContent(aside)?.style.removeProperty("--k2b-detail-space");
|
|
28
|
+
const toggle = detailToggle(aside);
|
|
29
|
+
toggle?.setAttribute("aria-expanded", "false");
|
|
30
|
+
if (focus) toggle?.focus({
|
|
31
|
+
preventScroll: true
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** Parks open waiting-detail drawers; focus follows only when it was inside one. */
|
|
36
|
+
export const parkWorkspaceDetailDrawers = (root = document) => {
|
|
37
|
+
for (const aside of root.querySelectorAll(DETAIL_DRAWER_SELECTOR)) parkDetailDrawer(aside, aside.contains(aside.ownerDocument.activeElement));
|
|
38
|
+
};
|
|
11
39
|
const FOCUSABLE_SELECTOR = ["a[href]", "button:not([disabled])", "input:not([disabled]):not([type='hidden'])", "select:not([disabled])", "textarea:not([disabled])", "[tabindex]:not([tabindex='-1'])"].join(",");
|
|
12
40
|
/** Text entry, menus, dialogs, and open popups keep their own keys. */
|
|
13
41
|
const KEY_OWNER_SELECTOR = "input, textarea, select, [contenteditable]:not([contenteditable='false']), [role='textbox'], [role='combobox'], [role='searchbox'], [role='spinbutton'], [role='menu'], [role='listbox'], [role='dialog'], dialog, [aria-haspopup]:not([aria-haspopup='false'])[aria-expanded='true']";
|
|
@@ -59,8 +87,9 @@ const controlledPanel = (root, handle) => {
|
|
|
59
87
|
};
|
|
60
88
|
const flexibleLevel = pane => {
|
|
61
89
|
if (!pane.hasAttribute("data-workspace-level")) return false;
|
|
62
|
-
const
|
|
63
|
-
|
|
90
|
+
const root = workspaceRoot(pane);
|
|
91
|
+
const widthClass = root ? cssState(root, "--k2b-workspace-level-class") : "";
|
|
92
|
+
return Boolean(widthClass && pane.dataset.workspaceLevelLast?.split(" ").includes(widthClass));
|
|
64
93
|
};
|
|
65
94
|
const levelsMain = handle => handle.closest(".k2b-app-workspace__main")?.hasAttribute("data-workspace-levels") ?? false;
|
|
66
95
|
const controlsResizableRegion = (root, handle, kind) => {
|
|
@@ -228,7 +257,6 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
228
257
|
const ownerDocument = eventRoot.ownerDocument ?? document;
|
|
229
258
|
const ownerWindow = ownerDocument.defaultView ?? window;
|
|
230
259
|
let overlay = null;
|
|
231
|
-
const compact = typeof window.matchMedia === "function" ? window.matchMedia(COMPACT_QUERY) : null;
|
|
232
260
|
// A server-rendered head names the sidebar before the sidebar renders; the button learns its real id now.
|
|
233
261
|
for (const toggle of eventRoot.querySelectorAll(TOGGLE_SELECTOR)) overlayTarget(toggle);
|
|
234
262
|
const openOverlay = target => {
|
|
@@ -269,12 +297,28 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
269
297
|
};
|
|
270
298
|
const onClick = event => {
|
|
271
299
|
const target = eventElement(event);
|
|
300
|
+
const detailButton = target?.closest(DETAIL_TOGGLE_SELECTOR);
|
|
301
|
+
if (detailButton) {
|
|
302
|
+
const root = workspaceRoot(detailButton);
|
|
303
|
+
const aside = root ? controlledPanel(root, detailButton) : null;
|
|
304
|
+
if (!aside || aside.hidden || !detailWaiting(aside) || claimedToggleClicks.has(event)) return;
|
|
305
|
+
claimedToggleClicks.add(event);
|
|
306
|
+
if (detailDrawer(aside)) parkDetailDrawer(aside);else {
|
|
307
|
+
aside.dataset.workspaceDetailDrawer = "open";
|
|
308
|
+
detailButton.setAttribute("aria-expanded", "true");
|
|
309
|
+
syncDetailDrawerSpace(aside);
|
|
310
|
+
if (event.detail === 0) requestTitle(aside);else detailButton.focus({
|
|
311
|
+
preventScroll: true
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
272
316
|
const toggle = target?.closest(TOGGLE_SELECTOR);
|
|
273
317
|
if (toggle) {
|
|
274
318
|
const next = overlayTarget(toggle);
|
|
275
319
|
if (!next || claimedToggleClicks.has(event)) return;
|
|
276
320
|
claimedToggleClicks.add(event);
|
|
277
|
-
if (overlay?.sidebar === next.sidebar) closeOverlay("button");else if (
|
|
321
|
+
if (overlay?.sidebar === next.sidebar) closeOverlay("button");else if (cssState(next.root, "--k2b-workspace-sidebar-form") === "overlay") openOverlay(next);
|
|
278
322
|
return;
|
|
279
323
|
}
|
|
280
324
|
if (!overlay || !target) return;
|
|
@@ -310,6 +354,11 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
310
354
|
// Dialogs and popovers keep their own Tab order.
|
|
311
355
|
const page = phone?.matches ? allRoots().flatMap(openDetails).find(phonePage) : undefined;
|
|
312
356
|
if (!page || ownerDocument.querySelector("dialog[open], [aria-modal='true']") || target.closest("[popover]")) return;
|
|
357
|
+
if (target !== ownerDocument.body) {
|
|
358
|
+
const rect = target.getBoundingClientRect();
|
|
359
|
+
const hit = ownerDocument.elementFromPoint(rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
360
|
+
if (hit && target.contains(hit)) return;
|
|
361
|
+
}
|
|
313
362
|
const stops = tabStopsIn(page);
|
|
314
363
|
event.preventDefault();
|
|
315
364
|
(event.shiftKey ? stops.at(-1) : stops[0])?.focus();
|
|
@@ -334,12 +383,37 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
334
383
|
first.focus();
|
|
335
384
|
}
|
|
336
385
|
};
|
|
337
|
-
|
|
338
|
-
|
|
386
|
+
// Whether each open detail waited at the last check, so a column that starts
|
|
387
|
+
// waiting under focus hands that focus to its Details button.
|
|
388
|
+
const detailWasWaiting = new WeakMap();
|
|
389
|
+
const syncHostState = () => {
|
|
390
|
+
if (overlay && cssState(overlay.root, "--k2b-workspace-sidebar-form") !== "overlay") closeOverlay("none");
|
|
391
|
+
for (const root of allRoots()) {
|
|
392
|
+
// A drawer removed with its panel leaves no space behind in Content.
|
|
393
|
+
for (const content of rootElements(root, ".k2b-app-workspace__content")) if (content.style.getPropertyValue("--k2b-detail-space") && !content.querySelector(DETAIL_DRAWER_SELECTOR)) content.style.removeProperty("--k2b-detail-space");
|
|
394
|
+
for (const aside of rootElements(root, detailSelector)) {
|
|
395
|
+
if (aside.hidden) {
|
|
396
|
+
detailWasWaiting.delete(aside);
|
|
397
|
+
parkDetailDrawer(aside);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const waiting = detailWaiting(aside);
|
|
401
|
+
const before = detailWasWaiting.get(aside);
|
|
402
|
+
detailWasWaiting.set(aside, waiting);
|
|
403
|
+
if (!waiting) {
|
|
404
|
+
// The Details button hides with the waiting; its focus moves to the returning column's title.
|
|
405
|
+
const toggleFocused = detailToggle(aside)?.contains(ownerDocument.activeElement) ?? false;
|
|
406
|
+
parkDetailDrawer(aside);
|
|
407
|
+
if (toggleFocused) focusTitle(aside);
|
|
408
|
+
} else if (detailDrawer(aside)) syncDetailDrawerSpace(aside);else if (before !== true && aside.contains(ownerDocument.activeElement)) detailToggle(aside)?.focus({
|
|
409
|
+
preventScroll: true
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
339
413
|
};
|
|
340
414
|
const phone = typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 47.999rem)") : null;
|
|
341
415
|
const wide = typeof window.matchMedia === "function" ? window.matchMedia("(min-width: 48rem)") : null;
|
|
342
|
-
const touchDrawer = typeof window.matchMedia === "function" ? window.matchMedia(
|
|
416
|
+
const touchDrawer = typeof window.matchMedia === "function" ? window.matchMedia(TOUCH_DRAWER_QUERY) : null;
|
|
343
417
|
const detailSelector = ".k2b-app-workspace__detail";
|
|
344
418
|
const grabberSelector = ".k2b-app-workspace__detail-grabber";
|
|
345
419
|
const detailHidden = new WeakMap();
|
|
@@ -499,7 +573,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
499
573
|
delete aside.dataset.workspaceDetailDragging;
|
|
500
574
|
};
|
|
501
575
|
const anchorItem = (root, aside, snapshot) => {
|
|
502
|
-
if (!wide?.matches || touchDrawer?.matches && closable(aside) || !snapshot?.item.isConnected) return;
|
|
576
|
+
if (!wide?.matches || touchDrawer?.matches && closable(aside) || detailDrawer(aside) || !snapshot?.item.isConnected) return;
|
|
503
577
|
if (!mainElement(root)?.contains(snapshot.item) || snapshot.item.closest(ROOT_SELECTOR) !== root) return;
|
|
504
578
|
const scroller = snapshot.scroller;
|
|
505
579
|
if (scroller?.isConnected && scroller.scrollTop === snapshot.scrollTop) scroller.scrollTop += snapshot.item.getBoundingClientRect().top - snapshot.top;
|
|
@@ -605,6 +679,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
605
679
|
const followedInteraction = snapshot?.fresh ?? false;
|
|
606
680
|
if (snapshot) snapshot.fresh = false;
|
|
607
681
|
if (aside.hidden) {
|
|
682
|
+
parkDetailDrawer(aside);
|
|
608
683
|
if (pendingTitle?.aside === aside) cancelTitle();
|
|
609
684
|
if (panelStep === aside) panelStep = null;
|
|
610
685
|
if (root.hasAttribute("data-workspace-motion") && !prefersReducedMotion() && wide?.matches) {
|
|
@@ -633,6 +708,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
633
708
|
if (detailDrag?.aside === aside) finishDetailDrag(true);
|
|
634
709
|
return;
|
|
635
710
|
}
|
|
711
|
+
if (detailWaiting(aside) && !detailDrawer(aside)) return;
|
|
636
712
|
anchorItem(root, aside, snapshot);
|
|
637
713
|
if (phone?.matches) setDetent(aside, false);
|
|
638
714
|
if (followedInteraction && snapshot) {
|
|
@@ -653,13 +729,18 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
653
729
|
const root = target.closest(ROOT_SELECTOR);
|
|
654
730
|
let aside = target.closest(detailSelector);
|
|
655
731
|
if (aside?.hidden || aside && (!eventRoot.contains(aside) || aside.closest(ROOT_SELECTOR) !== root)) aside = null;
|
|
656
|
-
if (!aside && root && observedRoots.has(root) && mainElement(root)?.contains(target)) aside = openDetails(root)
|
|
732
|
+
if (!aside && root && observedRoots.has(root) && (mainElement(root)?.contains(target) || target.closest(DETAIL_TOGGLE_SELECTOR))) aside = openDetails(root).find(isVisible) ?? null;
|
|
657
733
|
if (!aside && target === ownerDocument.body) {
|
|
658
|
-
const open = allRoots().flatMap(openDetails);
|
|
734
|
+
const open = allRoots().flatMap(openDetails).filter(isVisible);
|
|
659
735
|
if (open.length === 1) aside = open[0];
|
|
660
736
|
}
|
|
661
737
|
const owningRoot = aside?.closest(ROOT_SELECTOR);
|
|
662
|
-
if (!aside || !owningRoot) return;
|
|
738
|
+
if (!aside || !owningRoot || !isVisible(aside)) return;
|
|
739
|
+
if (event.key === "Escape" && detailDrawer(aside)) {
|
|
740
|
+
parkDetailDrawer(aside, true);
|
|
741
|
+
event.preventDefault();
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
663
744
|
if (event.key === "Escape" && closable(aside)) requestClose(aside);else if ((event.key.toLowerCase() === "j" || event.key.toLowerCase() === "k") && aside.hasAttribute("data-workspace-detail-steppable")) {
|
|
664
745
|
const main = mainElement(owningRoot);
|
|
665
746
|
const inMain = remembered.get(owningRoot)?.item.contains(target) || main?.contains(target);
|
|
@@ -1196,14 +1277,43 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1196
1277
|
reconcileFrame = requestAnimationFrame(() => {
|
|
1197
1278
|
reconcileFrame = null;
|
|
1198
1279
|
reconcile();
|
|
1280
|
+
// Reconciling can restore a drawer's persisted width; its trail space follows.
|
|
1281
|
+
for (const root of allRoots()) for (const aside of rootElements(root, DETAIL_DRAWER_SELECTOR)) syncDetailDrawerSpace(aside);
|
|
1199
1282
|
});
|
|
1200
1283
|
};
|
|
1201
|
-
const onResize = () =>
|
|
1284
|
+
const onResize = () => {
|
|
1285
|
+
syncHostState();
|
|
1286
|
+
scheduleReconcile();
|
|
1287
|
+
};
|
|
1202
1288
|
const observedRoots = new Set();
|
|
1203
1289
|
const resizeObserver = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => {
|
|
1290
|
+
syncHostState();
|
|
1204
1291
|
scheduleReconcile();
|
|
1205
1292
|
});
|
|
1293
|
+
// A host can change its width while a workspace with a fixed width keeps
|
|
1294
|
+
// its own, so the controller also watches each root's nearest named host.
|
|
1295
|
+
const observedHosts = new Set();
|
|
1296
|
+
// Found once per root: reading styles on every mutation would cost a style pass.
|
|
1297
|
+
const rootHosts = new WeakMap();
|
|
1298
|
+
const hostOf = root => {
|
|
1299
|
+
if (rootHosts.has(root)) return rootHosts.get(root);
|
|
1300
|
+
let host = null;
|
|
1301
|
+
for (let element = root.parentElement; element && !host; element = element.parentElement) if (getComputedStyle(element).containerName.split(/\s+/).includes("k2b-app-area")) host = element;
|
|
1302
|
+
rootHosts.set(root, host);
|
|
1303
|
+
return host;
|
|
1304
|
+
};
|
|
1206
1305
|
const syncObservedRoots = () => {
|
|
1306
|
+
const hosts = new Set(allRoots().map(hostOf).filter(host => host !== null));
|
|
1307
|
+
observedHosts.forEach(host => {
|
|
1308
|
+
if (hosts.has(host)) return;
|
|
1309
|
+
resizeObserver?.unobserve(host);
|
|
1310
|
+
observedHosts.delete(host);
|
|
1311
|
+
});
|
|
1312
|
+
hosts.forEach(host => {
|
|
1313
|
+
if (observedHosts.has(host)) return;
|
|
1314
|
+
observedHosts.add(host);
|
|
1315
|
+
resizeObserver?.observe(host);
|
|
1316
|
+
});
|
|
1207
1317
|
for (const elements of [touchedDetails, titleTabIndices, motionRoots]) {
|
|
1208
1318
|
elements.forEach(element => {
|
|
1209
1319
|
if (!element.isConnected) elements.delete(element);
|
|
@@ -1265,6 +1375,8 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1265
1375
|
const changed = records.some(record => record.type === "attributes" ? record.target instanceof Element && record.target.matches(LAYOUT_REGION_SELECTOR) : [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some(layoutNode));
|
|
1266
1376
|
if (!changed) return;
|
|
1267
1377
|
syncObservedRoots();
|
|
1378
|
+
// A new width token or a removed panel can end waiting without any box resizing.
|
|
1379
|
+
if (records.some(record => record.type === "childList" || record.attributeName === "data-width")) syncHostState();
|
|
1268
1380
|
scheduleReconcile();
|
|
1269
1381
|
});
|
|
1270
1382
|
eventRoot.addEventListener("pointerdown", onPointerDown);
|
|
@@ -1289,7 +1401,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1289
1401
|
});
|
|
1290
1402
|
eventRoot.addEventListener("touchend", onDetailTouchEnd);
|
|
1291
1403
|
eventRoot.addEventListener("touchcancel", onDetailTouchEnd);
|
|
1292
|
-
|
|
1404
|
+
phone?.addEventListener("change", syncHostState);
|
|
1293
1405
|
phone?.addEventListener("change", syncPhonePages);
|
|
1294
1406
|
eventRoot.addEventListener("keydown", onKeyDown);
|
|
1295
1407
|
eventRoot.addEventListener("focusin", onFocusIn);
|
|
@@ -1299,7 +1411,7 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1299
1411
|
mutationObserver?.observe(eventRoot, {
|
|
1300
1412
|
attributes: true,
|
|
1301
1413
|
attributeOldValue: true,
|
|
1302
|
-
attributeFilter: ["hidden", "data-workspace-level-shown"],
|
|
1414
|
+
attributeFilter: ["hidden", "data-workspace-level-shown", "data-width"],
|
|
1303
1415
|
childList: true,
|
|
1304
1416
|
subtree: true
|
|
1305
1417
|
});
|
|
@@ -1348,11 +1460,12 @@ export const installAppWorkspaceController = (options = {}) => {
|
|
|
1348
1460
|
mutationObserver?.disconnect();
|
|
1349
1461
|
resizeObserver?.disconnect();
|
|
1350
1462
|
observedRoots.clear();
|
|
1463
|
+
observedHosts.clear();
|
|
1351
1464
|
closeOverlay("none");
|
|
1352
1465
|
eventRoot.removeEventListener("pointerdown", onPointerDown);
|
|
1353
1466
|
eventRoot.removeEventListener("click", onClick);
|
|
1354
1467
|
ownerDocument.removeEventListener("keydown", onOverlayKeyDown);
|
|
1355
|
-
|
|
1468
|
+
phone?.removeEventListener("change", syncHostState);
|
|
1356
1469
|
eventRoot.removeEventListener("keydown", onKeyDown);
|
|
1357
1470
|
eventRoot.removeEventListener("focusin", onFocusIn);
|
|
1358
1471
|
window.removeEventListener("resize", onResize);
|