@tutti-os/workbench-surface 0.0.3 → 0.0.5

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.js CHANGED
@@ -1756,7 +1756,7 @@ function WorkbenchWindowFullscreenToggle({
1756
1756
  title: label,
1757
1757
  type: "button",
1758
1758
  variant: "chrome",
1759
- onClick: () => {
1759
+ onClick: (event) => {
1760
1760
  if (disabled) {
1761
1761
  return;
1762
1762
  }
@@ -1765,6 +1765,7 @@ function WorkbenchWindowFullscreenToggle({
1765
1765
  controller.commands.exitFullscreen(node.id);
1766
1766
  return;
1767
1767
  }
1768
+ event.currentTarget.blur();
1768
1769
  controller.commands.enterFullscreen(node.id);
1769
1770
  },
1770
1771
  children: /* @__PURE__ */ jsx4(Icon, { "aria-hidden": true, className: "size-[15px]" })
@@ -5394,7 +5395,10 @@ import {
5394
5395
  Button as Button4,
5395
5396
  ChevronDownIcon,
5396
5397
  ChevronUpIcon,
5397
- TooltipProvider
5398
+ Tooltip,
5399
+ TooltipContent,
5400
+ TooltipProvider,
5401
+ TooltipTrigger
5398
5402
  } from "@tutti-os/ui-system";
5399
5403
 
5400
5404
  // src/host/dockEntries.ts
@@ -7016,6 +7020,23 @@ function WorkbenchHostDock({
7016
7020
  setDockHoverPanelOpen
7017
7021
  ]
7018
7022
  );
7023
+ const scheduleHoverPanelClose = useCallback10(
7024
+ (entryId) => {
7025
+ clearHoverPanelOpenTimer();
7026
+ clearHoverPanelCloseTimer();
7027
+ hoverPanelCloseTimerRef.current = setTimeout(() => {
7028
+ hoverPanelCloseTimerRef.current = null;
7029
+ closeHoverPanelImmediate(entryId);
7030
+ handleDockPointerLeave();
7031
+ }, dockHoverPanelCloseDelayMs);
7032
+ },
7033
+ [
7034
+ clearHoverPanelCloseTimer,
7035
+ clearHoverPanelOpenTimer,
7036
+ closeHoverPanelImmediate,
7037
+ handleDockPointerLeave
7038
+ ]
7039
+ );
7019
7040
  const showHoverPanel = useCallback10(
7020
7041
  (entryId, anchorKey, anchorElement) => {
7021
7042
  const dockElement = dockMeasureRef.current;
@@ -7079,6 +7100,38 @@ function WorkbenchHostDock({
7079
7100
  },
7080
7101
  []
7081
7102
  );
7103
+ const isPointerInsideActiveHoverPanelRegion = useCallback10(
7104
+ (clientX, clientY) => {
7105
+ const activeHoverPanel2 = activeHoverPanelRef.current;
7106
+ if (!activeHoverPanel2) {
7107
+ return false;
7108
+ }
7109
+ const anchorSlot = slotRefs.current.get(activeHoverPanel2.anchorKey);
7110
+ const panel = hoverPanelRef.current;
7111
+ if (!anchorSlot || !panel || !anchorSlot.isConnected || !panel.isConnected) {
7112
+ return false;
7113
+ }
7114
+ const anchorRect = anchorSlot.getBoundingClientRect();
7115
+ const panelRect = panel.getBoundingClientRect();
7116
+ return rectContainsPoint(
7117
+ anchorRect,
7118
+ clientX,
7119
+ clientY,
7120
+ dockHoverPanelHitSlopPx
7121
+ ) || rectContainsPoint(
7122
+ panelRect,
7123
+ clientX,
7124
+ clientY,
7125
+ dockHoverPanelHitSlopPx
7126
+ ) || rectContainsPoint(
7127
+ createHoverPanelBridgeRect(anchorRect, panelRect),
7128
+ clientX,
7129
+ clientY,
7130
+ dockHoverPanelBridgeSlopPx
7131
+ );
7132
+ },
7133
+ []
7134
+ );
7082
7135
  const scheduleHoverPanelAtPointAfterRest = useCallback10(
7083
7136
  (clientX, clientY) => {
7084
7137
  const scheduledPoint = hoverPanelScheduledPointRef.current;
@@ -7168,7 +7221,11 @@ function WorkbenchHostDock({
7168
7221
  const handleDockPointerTravel = useCallback10(
7169
7222
  (clientX, clientY) => {
7170
7223
  if (activeHoverPanelRef.current !== null) {
7171
- closeHoverPanelImmediate();
7224
+ if (isPointerInsideActiveHoverPanelRegion(clientX, clientY)) {
7225
+ clearHoverPanelCloseTimer();
7226
+ return;
7227
+ }
7228
+ scheduleHoverPanelClose(activeHoverPanelRef.current.entryId);
7172
7229
  handleDockPointerLeave();
7173
7230
  return;
7174
7231
  }
@@ -7176,9 +7233,11 @@ function WorkbenchHostDock({
7176
7233
  scheduleHoverPanelAtPointAfterRest(clientX, clientY);
7177
7234
  },
7178
7235
  [
7179
- closeHoverPanelImmediate,
7236
+ clearHoverPanelCloseTimer,
7180
7237
  handleDockPointerMove,
7181
7238
  handleDockPointerLeave,
7239
+ isPointerInsideActiveHoverPanelRegion,
7240
+ scheduleHoverPanelClose,
7182
7241
  scheduleHoverPanelAtPointAfterRest
7183
7242
  ]
7184
7243
  );
@@ -7619,7 +7678,17 @@ function WorkbenchHostDock({
7619
7678
  closeHoverPanelImmediate(entry.id);
7620
7679
  handleDockPointerLeave();
7621
7680
  },
7622
- children: dockButton2
7681
+ children: hasHoverPanel ? dockButton2 : /* @__PURE__ */ jsxs6(Tooltip, { children: [
7682
+ /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: dockButton2 }),
7683
+ /* @__PURE__ */ jsx10(
7684
+ TooltipContent,
7685
+ {
7686
+ side: dockPlacement === "left" ? "right" : "top",
7687
+ sideOffset: DOCK_MAGNIFIED_TOOLTIP_SIDE_OFFSET,
7688
+ children: entry.label
7689
+ }
7690
+ )
7691
+ ] })
7623
7692
  },
7624
7693
  dockItem.key
7625
7694
  );
@@ -7712,7 +7781,17 @@ function WorkbenchHostDock({
7712
7781
  "data-presence": dockItem.presence,
7713
7782
  "data-section-id": "minimized",
7714
7783
  "data-stack-dispatching": stackDispatching ? "true" : void 0,
7715
- children: stackButton
7784
+ children: /* @__PURE__ */ jsxs6(Tooltip, { children: [
7785
+ /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: stackButton }),
7786
+ /* @__PURE__ */ jsx10(
7787
+ TooltipContent,
7788
+ {
7789
+ side: dockPlacement === "left" ? "right" : "top",
7790
+ sideOffset: DOCK_MAGNIFIED_TOOLTIP_SIDE_OFFSET,
7791
+ children: i18n.t("minimizedWindows")
7792
+ }
7793
+ )
7794
+ ] })
7716
7795
  },
7717
7796
  dockItem.key
7718
7797
  );
@@ -7767,7 +7846,17 @@ function WorkbenchHostDock({
7767
7846
  "data-presence": dockItem.presence,
7768
7847
  "data-promoted-from-stack": promotedNodeId === node.id ? "true" : void 0,
7769
7848
  "data-section-id": "minimized",
7770
- children: dockButton
7849
+ children: /* @__PURE__ */ jsxs6(Tooltip, { children: [
7850
+ /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: dockButton }),
7851
+ /* @__PURE__ */ jsx10(
7852
+ TooltipContent,
7853
+ {
7854
+ side: dockPlacement === "left" ? "right" : "top",
7855
+ sideOffset: DOCK_MAGNIFIED_TOOLTIP_SIDE_OFFSET,
7856
+ children: node.title
7857
+ }
7858
+ )
7859
+ ] })
7771
7860
  },
7772
7861
  dockItem.key
7773
7862
  );
@@ -7814,7 +7903,7 @@ function WorkbenchHostDock({
7814
7903
  if (relatedTarget instanceof Node && anchorSlot?.contains(relatedTarget)) {
7815
7904
  return;
7816
7905
  }
7817
- closeHoverPanelImmediate(activeHoverPanel.entryId);
7906
+ scheduleHoverPanelClose(activeHoverPanel.entryId);
7818
7907
  handleDockPointerLeave();
7819
7908
  }
7820
7909
  }
@@ -8254,7 +8343,11 @@ function resolveNextDockItemPresence(item, initialized, previousPresence, should
8254
8343
  }
8255
8344
  function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
8256
8345
  const latestItemsByKey = useRef8(/* @__PURE__ */ new Map());
8346
+ const shouldAnimateMinimizedDockEnterRef = useRef8(
8347
+ shouldAnimateMinimizedDockEnter
8348
+ );
8257
8349
  latestItemsByKey.current = new Map(items.map((item) => [item.key, item]));
8350
+ shouldAnimateMinimizedDockEnterRef.current = shouldAnimateMinimizedDockEnter;
8258
8351
  const itemKeys = items.map((item) => item.key).join("\0");
8259
8352
  const [presentItems, setPresentItems] = useState8(
8260
8353
  () => items.map((item) => ({
@@ -8310,7 +8403,7 @@ function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
8310
8403
  item,
8311
8404
  initialized.current,
8312
8405
  currentByKey.get(item.key)?.presence,
8313
- shouldAnimateMinimizedDockEnter
8406
+ shouldAnimateMinimizedDockEnterRef.current
8314
8407
  )
8315
8408
  });
8316
8409
  }
@@ -8345,7 +8438,7 @@ function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
8345
8438
  );
8346
8439
  }, nextSettleMs);
8347
8440
  return () => globalThis.clearTimeout(timeout);
8348
- }, [itemKeys, shouldAnimateMinimizedDockEnter]);
8441
+ }, [itemKeys]);
8349
8442
  return presentItems.map((presentItem) => {
8350
8443
  const latestItem = latestItemsByKey.current.get(presentItem.key);
8351
8444
  return latestItem ? { ...presentItem, item: latestItem } : presentItem;
@@ -8411,8 +8504,28 @@ function resolveWorkbenchHostDockItemsWidth(items) {
8411
8504
  return itemWidth + gapWidth + dockItemsHorizontalPaddingPx;
8412
8505
  }
8413
8506
  var dockHoverPanelOpenDelayMs = 450;
8507
+ var dockHoverPanelCloseDelayMs = 160;
8414
8508
  var dockHoverPanelHitSlopPx = 12;
8509
+ var dockHoverPanelBridgeSlopPx = 6;
8415
8510
  var dockHoverPanelPointerRestTolerancePx = 4;
8511
+ var DOCK_MAGNIFIED_TOOLTIP_SIDE_OFFSET = 40;
8512
+ function rectContainsPoint(rect, clientX, clientY, slopPx = 0) {
8513
+ return clientX >= rect.left - slopPx && clientX <= rect.right + slopPx && clientY >= rect.top - slopPx && clientY <= rect.bottom + slopPx;
8514
+ }
8515
+ function createHoverPanelBridgeRect(anchor, panel) {
8516
+ if (anchor.right <= panel.left || panel.right <= anchor.left) {
8517
+ const left2 = Math.min(anchor.right, panel.right);
8518
+ const right2 = Math.max(anchor.left, panel.left);
8519
+ const top2 = Math.max(anchor.top, panel.top);
8520
+ const bottom2 = Math.min(anchor.bottom, panel.bottom);
8521
+ return new DOMRect(left2, top2, right2 - left2, Math.max(0, bottom2 - top2));
8522
+ }
8523
+ const left = Math.max(anchor.left, panel.left);
8524
+ const right = Math.min(anchor.right, panel.right);
8525
+ const top = Math.min(anchor.bottom, panel.bottom);
8526
+ const bottom = Math.max(anchor.top, panel.top);
8527
+ return new DOMRect(left, top, Math.max(0, right - left), bottom - top);
8528
+ }
8416
8529
  var dockPresenceAnimationMs = 300;
8417
8530
  var minimizedDockSlotLayoutAnimationMs = 720;
8418
8531
  var dockItemsGapPx = 10.8;