@tutti-os/workbench-surface 0.0.37 → 0.0.39

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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { WorkbenchFrame as WorkbenchFrame$1, WorkbenchSnapshotDisplayModeV1, WorkbenchSnapshot, WorkbenchSnapshotNode } from '@tutti-os/workbench-snapshot';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import { HTMLAttributes, ReactNode } from 'react';
3
+ import { HTMLAttributes, ReactNode, CSSProperties } from 'react';
4
4
  import { I18nRuntime } from '@tutti-os/ui-i18n-runtime';
5
5
  import { c as WorkbenchWindowChromeI18nRuntime } from './workbenchHostI18n-YFXDkIA1.js';
6
6
  export { b as WorkbenchWindowChromeI18nKey, d as createWorkbenchHostI18nRuntime, e as createWorkbenchWindowChromeI18nRuntime, f as workbenchHostI18nResources, g as workbenchWindowChromeI18nNamespace, h as workbenchWindowChromeI18nResources } from './workbenchHostI18n-YFXDkIA1.js';
@@ -256,6 +256,16 @@ interface WorkbenchResolveWindowChromeModeContext<TData = unknown> {
256
256
  controller: WorkbenchController<TData>;
257
257
  }
258
258
  type WorkbenchResolveWindowChromeMode<TData = unknown> = (context: WorkbenchResolveWindowChromeModeContext<TData>) => WorkbenchWindowChromeMode;
259
+ type WorkbenchWindowSurfaceLayer = "default" | "dialog-popover";
260
+ interface WorkbenchResolveWindowSurfaceLayerContext<TData = unknown> {
261
+ node: WorkbenchNode<TData>;
262
+ }
263
+ type WorkbenchResolveWindowSurfaceLayer<TData = unknown> = (context: WorkbenchResolveWindowSurfaceLayerContext<TData>) => WorkbenchWindowSurfaceLayer;
264
+ interface WorkbenchResolveWindowZIndexContext<TData = unknown> {
265
+ baseZIndex: number;
266
+ node: WorkbenchNode<TData>;
267
+ }
268
+ type WorkbenchResolveWindowZIndex<TData = unknown> = (context: WorkbenchResolveWindowZIndexContext<TData>) => NonNullable<CSSProperties["zIndex"]>;
259
269
  type WorkbenchResolveFullscreenHeaderMode<TData = unknown> = (context: WorkbenchResolveWindowChromeModeContext<TData>) => WorkbenchFullscreenHeaderMode | undefined;
260
270
  type WorkbenchKeepMinimizedNodeMounted<TData = unknown> = (node: WorkbenchNode<TData>) => boolean;
261
271
  interface WorkbenchWindowHeaderDragHandleProps {
@@ -324,6 +334,8 @@ interface WorkbenchSurfaceProps<TData = unknown> {
324
334
  renderWindowHeader?: WorkbenchRenderWindowHeader<TData>;
325
335
  shouldKeepMinimizedNodeMounted?: WorkbenchKeepMinimizedNodeMounted<TData>;
326
336
  resolveFullscreenHeaderMode?: WorkbenchResolveFullscreenHeaderMode<TData>;
337
+ resolveWindowSurfaceLayer?: WorkbenchResolveWindowSurfaceLayer<TData>;
338
+ resolveWindowZIndex?: WorkbenchResolveWindowZIndex<TData>;
327
339
  resolveDockAnchorKey?: (node: WorkbenchNode<TData>) => string;
328
340
  resolveDockPreviewCacheKey?: WorkbenchDockPreviewCacheKeyResolver<TData>;
329
341
  shortcutsEnabled?: boolean;
@@ -344,7 +356,7 @@ interface WorkbenchSurfaceWallpaper {
344
356
  position?: string;
345
357
  url: string;
346
358
  }
347
- declare function WorkbenchSurface<TData>({ captureNodePreviewImage, className, controller, debugDiagnostics, dockPreviewCache, dockPlacement, interactive, layoutConstraints, missionControlPhase, minimizeAnimation, presentation, renderBackdrop, renderBottomChrome, renderDock, renderNode, renderNodeGeniePreview, renderOverlay, renderTopChrome, renderWindowActions, renderWindowHeader, shouldKeepMinimizedNodeMounted, resolveFullscreenHeaderMode, resolveDockAnchorKey, resolveDockPreviewCacheKey, shortcutsEnabled, shouldCaptureNodePreviewImage, wallpaper, windowManagement, windowChromeMode, windowChromeI18n }: WorkbenchSurfaceProps<TData>): react_jsx_runtime.JSX.Element;
359
+ declare function WorkbenchSurface<TData>({ captureNodePreviewImage, className, controller, debugDiagnostics, dockPreviewCache, dockPlacement, interactive, layoutConstraints, missionControlPhase, minimizeAnimation, presentation, renderBackdrop, renderBottomChrome, renderDock, renderNode, renderNodeGeniePreview, renderOverlay, renderTopChrome, renderWindowActions, renderWindowHeader, shouldKeepMinimizedNodeMounted, resolveFullscreenHeaderMode, resolveWindowSurfaceLayer, resolveWindowZIndex, resolveDockAnchorKey, resolveDockPreviewCacheKey, shortcutsEnabled, shouldCaptureNodePreviewImage, wallpaper, windowManagement, windowChromeMode, windowChromeI18n }: WorkbenchSurfaceProps<TData>): react_jsx_runtime.JSX.Element;
348
360
 
349
361
  interface WorkbenchHostActivation<TPayload = unknown> {
350
362
  payload?: TPayload;
@@ -518,6 +530,11 @@ interface WorkbenchHostDockEntry {
518
530
  badge?: WorkbenchHostDockEntryBadge;
519
531
  capturePopupItemPreview?: WorkbenchHostNodePreviewCapture;
520
532
  clickActionId?: string;
533
+ /**
534
+ * `launch` keeps clicks on the launch request path even when matching nodes
535
+ * already exist.
536
+ */
537
+ clickBehavior?: "default" | "launch";
521
538
  hoverActions?: readonly WorkbenchHostDockEntryAction[];
522
539
  icon: ReactNode;
523
540
  iconSize?: "default" | "large";
@@ -554,7 +571,9 @@ interface WorkbenchHostNodeWindowCapabilities {
554
571
  minimizedDock?: WorkbenchHostNodeMinimizedDockCapability;
555
572
  persists?: boolean;
556
573
  restoreOnLoad?: boolean;
574
+ surfaceLayer?: WorkbenchHostNodeWindowSurfaceLayer;
557
575
  }
576
+ type WorkbenchHostNodeWindowSurfaceLayer = Exclude<WorkbenchWindowSurfaceLayer, "default">;
558
577
  type WorkbenchHostNodeMinimizedDockCapability = {
559
578
  capturePreview?: WorkbenchHostNodePreviewCapture;
560
579
  kind: "snapshot";
package/dist/index.js CHANGED
@@ -1927,7 +1927,8 @@ function mergePendingMinimizedDockNode(nodes, pendingNode) {
1927
1927
  }
1928
1928
 
1929
1929
  // src/react/WorkbenchNodeLayer.tsx
1930
- import { memo, useMemo as useMemo3 } from "react";
1930
+ import { Fragment as Fragment3, memo, useMemo as useMemo3 } from "react";
1931
+ import { createPortal } from "react-dom";
1931
1932
 
1932
1933
  // src/react/WorkbenchWindowFrame.tsx
1933
1934
  import { createI18nRuntime } from "@tutti-os/ui-i18n-runtime";
@@ -2205,13 +2206,18 @@ function WorkbenchWindowFrame({
2205
2206
  presentation = null,
2206
2207
  renderActions,
2207
2208
  renderHeader,
2209
+ resolveWindowZIndex,
2208
2210
  windowChromeMode = "system",
2209
2211
  windowChromeI18n
2210
2212
  }) {
2211
2213
  const controller = useWorkbenchController();
2212
- const zIndex = useWorkbenchSelector(
2214
+ const baseZIndex = useWorkbenchSelector(
2213
2215
  (state) => selectWorkbenchNodeZIndex(state, node.id)
2214
2216
  );
2217
+ const zIndex = resolveWindowZIndex?.({
2218
+ baseZIndex,
2219
+ node
2220
+ }) ?? baseZIndex;
2215
2221
  const isFocused = useWorkbenchSelector(
2216
2222
  (state) => selectFocusedWorkbenchNode(state)?.id === node.id
2217
2223
  );
@@ -2429,6 +2435,8 @@ function WorkbenchNodeLayer({
2429
2435
  renderWindowActions,
2430
2436
  renderWindowHeader,
2431
2437
  resolveFullscreenHeaderMode,
2438
+ resolveWindowSurfaceLayer,
2439
+ resolveWindowZIndex,
2432
2440
  windowChromeMode,
2433
2441
  windowChromeI18n
2434
2442
  }) {
@@ -2439,17 +2447,100 @@ function WorkbenchNodeLayer({
2439
2447
  const nodeIDs = useWorkbenchSelector(
2440
2448
  selectRenderedNodeIDs
2441
2449
  );
2450
+ const { defaultNodeIDs, dialogPopoverNodeIDs } = useWorkbenchSelector((state) => {
2451
+ if (!resolveWindowSurfaceLayer || presentation?.mode === "mission-control") {
2452
+ return {
2453
+ defaultNodeIDs: nodeIDs,
2454
+ dialogPopoverNodeIDs: []
2455
+ };
2456
+ }
2457
+ const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
2458
+ const nextDefaultNodeIDs = [];
2459
+ const nextDialogPopoverNodeIDs = [];
2460
+ for (const nodeID of nodeIDs) {
2461
+ const node = nodeByID.get(nodeID);
2462
+ if (node && resolveWindowSurfaceLayer({ node }) === "dialog-popover") {
2463
+ nextDialogPopoverNodeIDs.push(nodeID);
2464
+ } else {
2465
+ nextDefaultNodeIDs.push(nodeID);
2466
+ }
2467
+ }
2468
+ return {
2469
+ defaultNodeIDs: nextDefaultNodeIDs,
2470
+ dialogPopoverNodeIDs: nextDialogPopoverNodeIDs
2471
+ };
2472
+ });
2442
2473
  const snapPreviewRect = useWorkbenchSelector(selectWorkbenchSnapPreviewRect);
2443
2474
  const presentationInteraction = interactive && presentation?.mode === "mission-control" ? presentation.interaction ?? null : null;
2475
+ const dialogPopoverLayer = dialogPopoverNodeIDs.length > 0 ? /* @__PURE__ */ jsx6(
2476
+ WorkbenchNodeLayerGroup,
2477
+ {
2478
+ className: "workbench-node-layer workbench-node-layer--dialog-popover",
2479
+ edgeSnapEnabled,
2480
+ fullscreenHeaderMode: resolveFullscreenHeaderMode,
2481
+ genie,
2482
+ interactive,
2483
+ nodeIDs: dialogPopoverNodeIDs,
2484
+ presentation,
2485
+ renderNode,
2486
+ renderWindowActions,
2487
+ renderWindowHeader,
2488
+ resolveWindowZIndex,
2489
+ windowChromeI18n,
2490
+ windowChromeMode
2491
+ }
2492
+ ) : null;
2493
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
2494
+ /* @__PURE__ */ jsx6(
2495
+ WorkbenchNodeLayerGroup,
2496
+ {
2497
+ className: "workbench-node-layer",
2498
+ edgeSnapEnabled,
2499
+ fullscreenHeaderMode: resolveFullscreenHeaderMode,
2500
+ genie,
2501
+ interactive,
2502
+ nodeIDs: defaultNodeIDs,
2503
+ onBackdropPress: presentationInteraction?.onBackdropPress,
2504
+ presentation,
2505
+ renderNode,
2506
+ renderWindowActions,
2507
+ renderWindowHeader,
2508
+ resolveWindowZIndex,
2509
+ snapPreviewRect,
2510
+ windowChromeI18n,
2511
+ windowChromeMode
2512
+ }
2513
+ ),
2514
+ typeof document === "undefined" ? dialogPopoverLayer : dialogPopoverLayer ? createPortal(dialogPopoverLayer, document.body) : null
2515
+ ] });
2516
+ }
2517
+ function WorkbenchNodeLayerGroup({
2518
+ className,
2519
+ edgeSnapEnabled,
2520
+ fullscreenHeaderMode,
2521
+ genie,
2522
+ interactive,
2523
+ nodeIDs,
2524
+ onBackdropPress,
2525
+ presentation,
2526
+ renderNode,
2527
+ renderWindowActions,
2528
+ renderWindowHeader,
2529
+ resolveWindowZIndex,
2530
+ snapPreviewRect,
2531
+ windowChromeI18n,
2532
+ windowChromeMode
2533
+ }) {
2444
2534
  return /* @__PURE__ */ jsxs3(
2445
2535
  "div",
2446
2536
  {
2447
- className: "workbench-node-layer",
2448
- onClick: presentationInteraction ? (event) => {
2537
+ className,
2538
+ "data-workbench-interactive": interactive ? "true" : "false",
2539
+ onClick: onBackdropPress ? (event) => {
2449
2540
  if (event.target !== event.currentTarget) {
2450
2541
  return;
2451
2542
  }
2452
- presentationInteraction.onBackdropPress();
2543
+ onBackdropPress();
2453
2544
  } : void 0,
2454
2545
  children: [
2455
2546
  snapPreviewRect ? /* @__PURE__ */ jsx6(
@@ -2467,7 +2558,7 @@ function WorkbenchNodeLayer({
2467
2558
  nodeIDs.map((nodeID) => /* @__PURE__ */ jsx6(
2468
2559
  MemoizedWorkbenchNodeLayerItem,
2469
2560
  {
2470
- fullscreenHeaderMode: resolveFullscreenHeaderMode,
2561
+ fullscreenHeaderMode,
2471
2562
  genie,
2472
2563
  edgeSnapEnabled,
2473
2564
  interactive,
@@ -2476,6 +2567,7 @@ function WorkbenchNodeLayer({
2476
2567
  renderNode,
2477
2568
  renderWindowActions,
2478
2569
  renderWindowHeader,
2570
+ resolveWindowZIndex,
2479
2571
  windowChromeI18n,
2480
2572
  windowChromeMode
2481
2573
  },
@@ -2495,6 +2587,7 @@ function WorkbenchNodeLayerItem({
2495
2587
  renderNode,
2496
2588
  renderWindowActions,
2497
2589
  renderWindowHeader,
2590
+ resolveWindowZIndex,
2498
2591
  windowChromeI18n,
2499
2592
  windowChromeMode
2500
2593
  }) {
@@ -2520,6 +2613,7 @@ function WorkbenchNodeLayerItem({
2520
2613
  presentation,
2521
2614
  node,
2522
2615
  genie,
2616
+ resolveWindowZIndex,
2523
2617
  fullscreenHeaderMode: fullscreenHeaderMode?.({
2524
2618
  controller,
2525
2619
  node
@@ -2697,7 +2791,7 @@ import {
2697
2791
  useRef as useRef4,
2698
2792
  useState as useState4
2699
2793
  } from "react";
2700
- import { createPortal, flushSync } from "react-dom";
2794
+ import { createPortal as createPortal2, flushSync } from "react-dom";
2701
2795
 
2702
2796
  // src/react/genieAnimation.ts
2703
2797
  var genieHorizontalRowStagger = 0.65;
@@ -3024,8 +3118,9 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
3024
3118
  }
3025
3119
 
3026
3120
  // src/react/useWorkbenchGenieAnimation.tsx
3027
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
3121
+ import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
3028
3122
  var genieDurationMs = 400;
3123
+ var previewCaptureRaceTimeoutMs = 120;
3029
3124
  var scaleMinimizeDurationMs = 220;
3030
3125
  var genieMaxDevicePixelRatio = 2;
3031
3126
  var genieSnapshotScale = 1;
@@ -3050,6 +3145,26 @@ function waitForNextAnimationFrame() {
3050
3145
  window.requestAnimationFrame(() => resolve());
3051
3146
  });
3052
3147
  }
3148
+ function racePreviewImageCapture(promise, timeoutMs) {
3149
+ return new Promise((resolve) => {
3150
+ let settled = false;
3151
+ const timer = setTimeout(() => {
3152
+ if (settled) {
3153
+ return;
3154
+ }
3155
+ settled = true;
3156
+ resolve({ previewImageUrl: null, status: "pending" });
3157
+ }, timeoutMs);
3158
+ promise.then((previewImageUrl) => {
3159
+ if (settled) {
3160
+ return;
3161
+ }
3162
+ settled = true;
3163
+ clearTimeout(timer);
3164
+ resolve({ previewImageUrl, status: "resolved" });
3165
+ });
3166
+ });
3167
+ }
3053
3168
  function isFocusedWorkbenchNode(controller, nodeID) {
3054
3169
  return controller.getSnapshot().nodeStack.at(-1) === nodeID;
3055
3170
  }
@@ -4337,7 +4452,33 @@ function useWorkbenchGenieAnimation({
4337
4452
  const previewImageUrlPromise = shouldCapturePreview ? Promise.resolve(captureNodePreviewImage?.(target) ?? null).catch(
4338
4453
  () => null
4339
4454
  ) : Promise.resolve(null);
4340
- const previewImageUrl = await previewImageUrlPromise;
4455
+ const previewCaptureOutcome = await racePreviewImageCapture(
4456
+ previewImageUrlPromise,
4457
+ previewCaptureRaceTimeoutMs
4458
+ );
4459
+ const previewImageUrl = previewCaptureOutcome.previewImageUrl;
4460
+ if (previewCaptureOutcome.status === "pending") {
4461
+ logWorkbenchGenieDiagnostic(
4462
+ debugDiagnostics,
4463
+ "workbench.genie.preview_capture.deferred",
4464
+ {
4465
+ ...describeGenieNode(target),
4466
+ mode: "genie",
4467
+ timeoutMs: previewCaptureRaceTimeoutMs
4468
+ },
4469
+ "debug"
4470
+ );
4471
+ void previewImageUrlPromise.then((latePreviewImageUrl) => {
4472
+ if (!latePreviewImageUrl || generation !== animationGenerationRef.current) {
4473
+ return;
4474
+ }
4475
+ writeCachedWorkbenchNodePreviewImage(nodeID, latePreviewImageUrl);
4476
+ persistWorkbenchNodePreviewImage(target, latePreviewImageUrl, {
4477
+ dockPreviewCache,
4478
+ resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
4479
+ });
4480
+ });
4481
+ }
4341
4482
  const previewImageTexture = shouldCapturePreview && previewImageUrl ? await renderPreviewImageTexture({
4342
4483
  previewImageUrl,
4343
4484
  rect: windowRect
@@ -4508,8 +4649,8 @@ function useWorkbenchGenieAnimation({
4508
4649
  []
4509
4650
  );
4510
4651
  return {
4511
- genieLayer: typeof document === "undefined" ? null : createPortal(
4512
- /* @__PURE__ */ jsxs4(Fragment3, { children: [
4652
+ genieLayer: typeof document === "undefined" ? null : createPortal2(
4653
+ /* @__PURE__ */ jsxs4(Fragment4, { children: [
4513
4654
  /* @__PURE__ */ jsx7(
4514
4655
  "canvas",
4515
4656
  {
@@ -4579,6 +4720,8 @@ function WorkbenchSurface({
4579
4720
  renderWindowHeader,
4580
4721
  shouldKeepMinimizedNodeMounted,
4581
4722
  resolveFullscreenHeaderMode,
4723
+ resolveWindowSurfaceLayer,
4724
+ resolveWindowZIndex,
4582
4725
  resolveDockAnchorKey,
4583
4726
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
4584
4727
  shortcutsEnabled,
@@ -4612,6 +4755,8 @@ function WorkbenchSurface({
4612
4755
  renderWindowHeader,
4613
4756
  shouldKeepMinimizedNodeMounted,
4614
4757
  resolveFullscreenHeaderMode,
4758
+ resolveWindowSurfaceLayer,
4759
+ resolveWindowZIndex,
4615
4760
  resolveDockAnchorKey,
4616
4761
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
4617
4762
  shortcutsEnabled,
@@ -4645,6 +4790,8 @@ function WorkbenchSurfaceInner({
4645
4790
  renderWindowHeader,
4646
4791
  shouldKeepMinimizedNodeMounted,
4647
4792
  resolveFullscreenHeaderMode,
4793
+ resolveWindowSurfaceLayer,
4794
+ resolveWindowZIndex,
4648
4795
  resolveDockAnchorKey,
4649
4796
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
4650
4797
  shortcutsEnabled,
@@ -4721,6 +4868,8 @@ function WorkbenchSurfaceInner({
4721
4868
  renderWindowHeader,
4722
4869
  shouldKeepMinimizedNodeMounted,
4723
4870
  resolveFullscreenHeaderMode,
4871
+ resolveWindowSurfaceLayer,
4872
+ resolveWindowZIndex,
4724
4873
  windowChromeMode,
4725
4874
  windowChromeI18n
4726
4875
  }
@@ -6910,6 +7059,9 @@ function resolveWorkbenchDockEntryClick(input) {
6910
7059
  if (isWorkbenchDockEntryBlocked(input.entry)) {
6911
7060
  return { kind: "blocked" };
6912
7061
  }
7062
+ if (input.entry.clickBehavior === "launch") {
7063
+ return { kind: "launch" };
7064
+ }
6913
7065
  if (input.instanceMode === "multi" && input.matchedNodes.length > 0) {
6914
7066
  return { kind: "open-popup" };
6915
7067
  }
@@ -7531,7 +7683,7 @@ import {
7531
7683
  useRef as useRef7,
7532
7684
  useState as useState7
7533
7685
  } from "react";
7534
- import { createPortal as createPortal2 } from "react-dom";
7686
+ import { createPortal as createPortal3 } from "react-dom";
7535
7687
  import {
7536
7688
  Button as Button3,
7537
7689
  CheckIcon,
@@ -7675,7 +7827,7 @@ function resolveMinimizedStackTrackTranslateXPx(input) {
7675
7827
  }
7676
7828
 
7677
7829
  // src/host/WorkbenchHostDockPopup.tsx
7678
- import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
7830
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
7679
7831
  var dockPopupCardWidthPx = 165;
7680
7832
  var dockPopupGridGapPx = 8;
7681
7833
  var dockPopupPanelPaddingInlinePx = 12;
@@ -8228,7 +8380,7 @@ function WorkbenchHostDockPopup({
8228
8380
  showAllWindowsLabel,
8229
8381
  showOpen: showOpen === true
8230
8382
  }
8231
- ) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
8383
+ ) : /* @__PURE__ */ jsxs6(Fragment5, { children: [
8232
8384
  /* @__PURE__ */ jsx9("div", { className: "mb-2.5 flex items-center justify-between", children: /* @__PURE__ */ jsx9("span", { className: "min-w-0 truncate text-sm font-semibold", children: label }) }),
8233
8385
  isMinimizedStack ? /* @__PURE__ */ jsx9(
8234
8386
  "div",
@@ -8342,7 +8494,7 @@ function WorkbenchHostDockPopup({
8342
8494
  if (typeof document === "undefined" || !document.body) {
8343
8495
  return content;
8344
8496
  }
8345
- return createPortal2(content, document.body);
8497
+ return createPortal3(content, document.body);
8346
8498
  }
8347
8499
  function WorkbenchHostDockContextMenu({
8348
8500
  canCreateNew,
@@ -8377,7 +8529,7 @@ function WorkbenchHostDockContextMenu({
8377
8529
  "data-desktop-dock-context-menu": "true",
8378
8530
  role: "menu",
8379
8531
  children: [
8380
- hasOpenWindows ? /* @__PURE__ */ jsx9(Fragment4, { children: /* @__PURE__ */ jsx9("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx9(
8532
+ hasOpenWindows ? /* @__PURE__ */ jsx9(Fragment5, { children: /* @__PURE__ */ jsx9("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx9(
8381
8533
  WorkbenchHostDockContextMenuItem,
8382
8534
  {
8383
8535
  checked: !item.isMinimized,
@@ -8421,7 +8573,7 @@ function WorkbenchHostDockContextMenu({
8421
8573
  onSelect: onCreateNew
8422
8574
  }
8423
8575
  ) : null,
8424
- hasOpenWindows ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
8576
+ hasOpenWindows ? /* @__PURE__ */ jsxs6(Fragment5, { children: [
8425
8577
  hasDockActionGroup ? /* @__PURE__ */ jsx9(WorkbenchHostDockContextMenuSeparator, {}) : null,
8426
8578
  canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx9(
8427
8579
  WorkbenchHostDockContextMenuItem,
@@ -11724,7 +11876,7 @@ function resolveWorkbenchHostDockItemsWidth(items) {
11724
11876
  const gapWidth = Math.max(0, items.length - 1) * dockItemsGapPx;
11725
11877
  return itemWidth + gapWidth + dockItemsHorizontalPaddingPx;
11726
11878
  }
11727
- var dockHoverPanelOpenDelayMs = 450;
11879
+ var dockHoverPanelOpenDelayMs = 120;
11728
11880
  var dockHoverPanelCloseDelayMs = 160;
11729
11881
  var dockHoverPanelHitSlopPx = 12;
11730
11882
  var dockHoverPanelBridgeSlopPx = 6;
@@ -11856,7 +12008,7 @@ function createWorkbenchHostNodeHeaderContext({
11856
12008
 
11857
12009
  // src/host/WorkbenchHostWindowActions.tsx
11858
12010
  import { Button as Button5, CloseIcon as CloseIcon2, MinimizeIcon as MinimizeIcon2 } from "@tutti-os/ui-system";
11859
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
12011
+ import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
11860
12012
  function WorkbenchHostWindowActions({
11861
12013
  context,
11862
12014
  host,
@@ -11869,7 +12021,7 @@ function WorkbenchHostWindowActions({
11869
12021
  }
11870
12022
  const minimizable = definition.window?.minimizable !== false;
11871
12023
  const closable = definition.window?.closable !== false;
11872
- return /* @__PURE__ */ jsxs8(Fragment5, { children: [
12024
+ return /* @__PURE__ */ jsxs8(Fragment6, { children: [
11873
12025
  minimizable ? /* @__PURE__ */ jsx11(
11874
12026
  Button5,
11875
12027
  {
@@ -12224,6 +12376,11 @@ function useWorkbenchHostSurfaceRenderers(input) {
12224
12376
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.renderHeader ? "custom-header" : "system",
12225
12377
  [input.nodeDefinitionByType]
12226
12378
  );
12379
+ const resolveWindowZIndex = useCallback11(({ baseZIndex }) => baseZIndex, []);
12380
+ const resolveWindowSurfaceLayer = useCallback11(
12381
+ ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.surfaceLayer ?? "default",
12382
+ [input.nodeDefinitionByType]
12383
+ );
12227
12384
  const resolveFullscreenHeaderMode = useCallback11(
12228
12385
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.fullscreenHeaderMode,
12229
12386
  [input.nodeDefinitionByType]
@@ -12242,6 +12399,8 @@ function useWorkbenchHostSurfaceRenderers(input) {
12242
12399
  resolveDockAnchorKey,
12243
12400
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
12244
12401
  resolveFullscreenHeaderMode,
12402
+ resolveWindowSurfaceLayer,
12403
+ resolveWindowZIndex,
12245
12404
  windowChromeMode
12246
12405
  };
12247
12406
  }
@@ -12553,6 +12712,8 @@ function WorkbenchHost({
12553
12712
  shouldKeepMinimizedNodeMounted: surfaceRenderers.shouldKeepMinimizedNodeMounted,
12554
12713
  resolveDockPreviewCacheKey: surfaceRenderers.resolveDockPreviewCacheKey,
12555
12714
  resolveFullscreenHeaderMode: surfaceRenderers.resolveFullscreenHeaderMode,
12715
+ resolveWindowSurfaceLayer: surfaceRenderers.resolveWindowSurfaceLayer,
12716
+ resolveWindowZIndex: surfaceRenderers.resolveWindowZIndex,
12556
12717
  resolveDockAnchorKey: surfaceRenderers.resolveDockAnchorKey,
12557
12718
  shortcutsEnabled,
12558
12719
  shouldCaptureNodePreviewImage: surfaceRenderers.shouldCaptureNodePreviewImage,