@tutti-os/workbench-surface 0.0.47 → 0.0.49
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 +233 -48
- package/dist/index.js.map +1 -1
- package/dist/styles/workbench.css +2 -0
- package/dist/styles/workbenchStyle.test.ts +4 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -7178,6 +7178,59 @@ function isWorkbenchDockEntryBlocked(entry) {
|
|
|
7178
7178
|
|
|
7179
7179
|
// src/host/dockMagnification.ts
|
|
7180
7180
|
import { useCallback as useCallback8, useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
7181
|
+
|
|
7182
|
+
// src/host/dockMagnificationBounds.ts
|
|
7183
|
+
function resolveDockMagnificationViewportBounds(viewportRect, dockPlacement) {
|
|
7184
|
+
return dockPlacement === "left" ? {
|
|
7185
|
+
crossEnd: viewportRect.right,
|
|
7186
|
+
crossStart: viewportRect.left,
|
|
7187
|
+
mainEnd: viewportRect.bottom,
|
|
7188
|
+
mainStart: viewportRect.top
|
|
7189
|
+
} : {
|
|
7190
|
+
crossEnd: viewportRect.bottom,
|
|
7191
|
+
crossStart: viewportRect.top,
|
|
7192
|
+
mainEnd: viewportRect.right,
|
|
7193
|
+
mainStart: viewportRect.left
|
|
7194
|
+
};
|
|
7195
|
+
}
|
|
7196
|
+
function resolveDockMagnificationVisibleHitBounds({
|
|
7197
|
+
dockPlacement,
|
|
7198
|
+
hitBounds,
|
|
7199
|
+
viewportRect
|
|
7200
|
+
}) {
|
|
7201
|
+
if (!hitBounds || !viewportRect) {
|
|
7202
|
+
return hitBounds;
|
|
7203
|
+
}
|
|
7204
|
+
const viewportBounds = resolveDockMagnificationViewportBounds(
|
|
7205
|
+
viewportRect,
|
|
7206
|
+
dockPlacement
|
|
7207
|
+
);
|
|
7208
|
+
const visibleBounds = {
|
|
7209
|
+
crossEnd: Math.min(hitBounds.crossEnd, viewportBounds.crossEnd),
|
|
7210
|
+
crossStart: Math.max(hitBounds.crossStart, viewportBounds.crossStart),
|
|
7211
|
+
mainEnd: Math.min(hitBounds.mainEnd, viewportBounds.mainEnd),
|
|
7212
|
+
mainStart: Math.max(hitBounds.mainStart, viewportBounds.mainStart)
|
|
7213
|
+
};
|
|
7214
|
+
if (visibleBounds.mainStart > visibleBounds.mainEnd || visibleBounds.crossStart > visibleBounds.crossEnd) {
|
|
7215
|
+
return null;
|
|
7216
|
+
}
|
|
7217
|
+
return visibleBounds;
|
|
7218
|
+
}
|
|
7219
|
+
function isDockMagnificationPointInsideHitBounds({
|
|
7220
|
+
clientX,
|
|
7221
|
+
clientY,
|
|
7222
|
+
dockPlacement,
|
|
7223
|
+
hitBounds
|
|
7224
|
+
}) {
|
|
7225
|
+
if (!hitBounds) {
|
|
7226
|
+
return false;
|
|
7227
|
+
}
|
|
7228
|
+
const mainAxis = dockPlacement === "left" ? clientY : clientX;
|
|
7229
|
+
const crossAxis = dockPlacement === "left" ? clientX : clientY;
|
|
7230
|
+
return mainAxis >= hitBounds.mainStart && mainAxis <= hitBounds.mainEnd && crossAxis >= hitBounds.crossStart && crossAxis <= hitBounds.crossEnd;
|
|
7231
|
+
}
|
|
7232
|
+
|
|
7233
|
+
// src/host/dockMagnification.ts
|
|
7181
7234
|
var DOCK_ICON_BASE_SIZE = 43.2;
|
|
7182
7235
|
var DOCK_ICON_PEAK_SIZE = DOCK_ICON_BASE_SIZE * 1.7;
|
|
7183
7236
|
var DOCK_MAGNIFICATION_HALF_RANGE = DOCK_ICON_BASE_SIZE * 2.4;
|
|
@@ -7191,6 +7244,10 @@ var MAGNIFICATION_INFLUENCE_PADDING = 8;
|
|
|
7191
7244
|
var DOCK_MAGNIFICATION_ENTRY_RAMP_MS = 90;
|
|
7192
7245
|
var DOCK_MAGNIFICATION_CROSS_AXIS_PADDING = 8;
|
|
7193
7246
|
var dockMagnificationShellBySlot = /* @__PURE__ */ new WeakMap();
|
|
7247
|
+
var globalPointerListenerOptions = {
|
|
7248
|
+
capture: true,
|
|
7249
|
+
passive: true
|
|
7250
|
+
};
|
|
7194
7251
|
function mapDistanceToTargetSize(distance, baseSize = DOCK_ICON_BASE_SIZE, peakSize = DOCK_ICON_PEAK_SIZE, halfRange = DOCK_MAGNIFICATION_HALF_RANGE) {
|
|
7195
7252
|
const absoluteDistance = Math.abs(distance);
|
|
7196
7253
|
if (absoluteDistance >= halfRange) {
|
|
@@ -7232,18 +7289,60 @@ function resolveDockMagnificationHitBounds(slotRects, dockPlacement, crossAxisPa
|
|
|
7232
7289
|
mainStart
|
|
7233
7290
|
};
|
|
7234
7291
|
}
|
|
7235
|
-
function
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7292
|
+
function createDockMagnificationGlobalPointerTracker({
|
|
7293
|
+
blurTarget,
|
|
7294
|
+
onPointerCancel,
|
|
7295
|
+
onPointerMove,
|
|
7296
|
+
pointerTarget
|
|
7240
7297
|
}) {
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7298
|
+
let active = false;
|
|
7299
|
+
const handlePointerMove = (event) => {
|
|
7300
|
+
const pointerEvent = event;
|
|
7301
|
+
onPointerMove(pointerEvent.clientX, pointerEvent.clientY);
|
|
7302
|
+
};
|
|
7303
|
+
const handlePointerCancel = () => {
|
|
7304
|
+
stop();
|
|
7305
|
+
onPointerCancel();
|
|
7306
|
+
};
|
|
7307
|
+
const start = () => {
|
|
7308
|
+
if (active) {
|
|
7309
|
+
return;
|
|
7310
|
+
}
|
|
7311
|
+
active = true;
|
|
7312
|
+
pointerTarget.addEventListener(
|
|
7313
|
+
"pointermove",
|
|
7314
|
+
handlePointerMove,
|
|
7315
|
+
globalPointerListenerOptions
|
|
7316
|
+
);
|
|
7317
|
+
pointerTarget.addEventListener(
|
|
7318
|
+
"pointercancel",
|
|
7319
|
+
handlePointerCancel,
|
|
7320
|
+
globalPointerListenerOptions
|
|
7321
|
+
);
|
|
7322
|
+
blurTarget?.addEventListener("blur", handlePointerCancel);
|
|
7323
|
+
};
|
|
7324
|
+
const stop = () => {
|
|
7325
|
+
if (!active) {
|
|
7326
|
+
return;
|
|
7327
|
+
}
|
|
7328
|
+
active = false;
|
|
7329
|
+
pointerTarget.removeEventListener(
|
|
7330
|
+
"pointermove",
|
|
7331
|
+
handlePointerMove,
|
|
7332
|
+
globalPointerListenerOptions
|
|
7333
|
+
);
|
|
7334
|
+
pointerTarget.removeEventListener(
|
|
7335
|
+
"pointercancel",
|
|
7336
|
+
handlePointerCancel,
|
|
7337
|
+
globalPointerListenerOptions
|
|
7338
|
+
);
|
|
7339
|
+
blurTarget?.removeEventListener("blur", handlePointerCancel);
|
|
7340
|
+
};
|
|
7341
|
+
return {
|
|
7342
|
+
isActive: () => active,
|
|
7343
|
+
start,
|
|
7344
|
+
stop
|
|
7345
|
+
};
|
|
7247
7346
|
}
|
|
7248
7347
|
function resolveDockMagnificationSlotCenter(rect, dockPlacement, baseSize = DOCK_ICON_BASE_SIZE) {
|
|
7249
7348
|
return dockPlacement === "left" ? rect.top + baseSize / 2 : rect.left + baseSize / 2;
|
|
@@ -7336,6 +7435,7 @@ function clearDockSlotMagnification(slotElement, appliedStylesRef) {
|
|
|
7336
7435
|
function useDockMagnification({
|
|
7337
7436
|
dockPlacement,
|
|
7338
7437
|
dockRootRef,
|
|
7438
|
+
dockViewportRef,
|
|
7339
7439
|
slotRefs
|
|
7340
7440
|
}) {
|
|
7341
7441
|
const pointerAxisRef = useRef5(null);
|
|
@@ -7351,6 +7451,13 @@ function useDockMagnification({
|
|
|
7351
7451
|
const hitBoundsRef = useRef5(null);
|
|
7352
7452
|
const slotOrderRef = useRef5([]);
|
|
7353
7453
|
const magnifyActiveRef = useRef5(false);
|
|
7454
|
+
const globalPointerTrackerRef = useRef5(null);
|
|
7455
|
+
const handleGlobalPointerMoveRef = useRef5(() => {
|
|
7456
|
+
return;
|
|
7457
|
+
});
|
|
7458
|
+
const handleGlobalPointerCancelRef = useRef5(() => {
|
|
7459
|
+
return;
|
|
7460
|
+
});
|
|
7354
7461
|
const setMagnifyActive = useCallback8(
|
|
7355
7462
|
(active) => {
|
|
7356
7463
|
if (magnifyActiveRef.current === active) {
|
|
@@ -7377,6 +7484,7 @@ function useDockMagnification({
|
|
|
7377
7484
|
const centers = /* @__PURE__ */ new Map();
|
|
7378
7485
|
const slotRects = [];
|
|
7379
7486
|
const order = [];
|
|
7487
|
+
const viewportRect = dockViewportRef.current?.getBoundingClientRect();
|
|
7380
7488
|
for (const [anchorKey, slotElement] of slots) {
|
|
7381
7489
|
order.push(anchorKey);
|
|
7382
7490
|
const rect = slotElement.getBoundingClientRect();
|
|
@@ -7390,12 +7498,18 @@ function useDockMagnification({
|
|
|
7390
7498
|
centers.set(anchorKey, center);
|
|
7391
7499
|
}
|
|
7392
7500
|
slotOrderRef.current = order;
|
|
7393
|
-
hitBoundsRef.current =
|
|
7394
|
-
|
|
7395
|
-
dockPlacement
|
|
7396
|
-
|
|
7501
|
+
hitBoundsRef.current = resolveDockMagnificationVisibleHitBounds({
|
|
7502
|
+
dockPlacement,
|
|
7503
|
+
hitBounds: resolveDockMagnificationHitBounds(slotRects, dockPlacement),
|
|
7504
|
+
viewportRect: viewportRect ? {
|
|
7505
|
+
bottom: viewportRect.bottom,
|
|
7506
|
+
left: viewportRect.left,
|
|
7507
|
+
right: viewportRect.right,
|
|
7508
|
+
top: viewportRect.top
|
|
7509
|
+
} : null
|
|
7510
|
+
});
|
|
7397
7511
|
restCentersRef.current = centers;
|
|
7398
|
-
}, [dockPlacement, slotRefs]);
|
|
7512
|
+
}, [dockPlacement, dockViewportRef, slotRefs]);
|
|
7399
7513
|
const runAnimationFrame = useCallback8(
|
|
7400
7514
|
(frameTime) => {
|
|
7401
7515
|
if (pendingPointerAxisRef.current !== null) {
|
|
@@ -7511,6 +7625,35 @@ function useDockMagnification({
|
|
|
7511
7625
|
}
|
|
7512
7626
|
animationFrameRef.current = requestAnimationFrame(runAnimationFrame);
|
|
7513
7627
|
}, [runAnimationFrame]);
|
|
7628
|
+
const stopGlobalPointerTracking = useCallback8(() => {
|
|
7629
|
+
globalPointerTrackerRef.current?.stop();
|
|
7630
|
+
}, []);
|
|
7631
|
+
const startGlobalPointerTracking = useCallback8(() => {
|
|
7632
|
+
if (typeof document === "undefined") {
|
|
7633
|
+
return;
|
|
7634
|
+
}
|
|
7635
|
+
globalPointerTrackerRef.current ??= createDockMagnificationGlobalPointerTracker({
|
|
7636
|
+
blurTarget: typeof window === "undefined" ? null : window,
|
|
7637
|
+
onPointerCancel: () => {
|
|
7638
|
+
handleGlobalPointerCancelRef.current();
|
|
7639
|
+
},
|
|
7640
|
+
onPointerMove: (clientX, clientY) => {
|
|
7641
|
+
handleGlobalPointerMoveRef.current(clientX, clientY);
|
|
7642
|
+
},
|
|
7643
|
+
pointerTarget: document
|
|
7644
|
+
});
|
|
7645
|
+
globalPointerTrackerRef.current.start();
|
|
7646
|
+
}, []);
|
|
7647
|
+
const clearTrackedPointer = useCallback8(() => {
|
|
7648
|
+
pendingPointerAxisRef.current = null;
|
|
7649
|
+
pointerAxisRef.current = null;
|
|
7650
|
+
entryRampStartedAtRef.current = null;
|
|
7651
|
+
scheduleAnimation();
|
|
7652
|
+
}, [scheduleAnimation]);
|
|
7653
|
+
const handleGlobalPointerCancel = useCallback8(() => {
|
|
7654
|
+
stopGlobalPointerTracking();
|
|
7655
|
+
clearTrackedPointer();
|
|
7656
|
+
}, [clearTrackedPointer, stopGlobalPointerTracking]);
|
|
7514
7657
|
const handlePointerMove = useCallback8(
|
|
7515
7658
|
(clientX, clientY) => {
|
|
7516
7659
|
if (restCentersRef.current === null) {
|
|
@@ -7522,20 +7665,29 @@ function useDockMagnification({
|
|
|
7522
7665
|
dockPlacement,
|
|
7523
7666
|
hitBounds: hitBoundsRef.current
|
|
7524
7667
|
})) {
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
entryRampStartedAtRef.current = null;
|
|
7528
|
-
scheduleAnimation();
|
|
7668
|
+
stopGlobalPointerTracking();
|
|
7669
|
+
clearTrackedPointer();
|
|
7529
7670
|
return;
|
|
7530
7671
|
}
|
|
7531
7672
|
pendingPointerAxisRef.current = dockPlacement === "left" ? clientY : clientX;
|
|
7532
7673
|
if (!magnifyActiveRef.current) {
|
|
7533
7674
|
setMagnifyActive(true);
|
|
7534
7675
|
}
|
|
7676
|
+
startGlobalPointerTracking();
|
|
7535
7677
|
scheduleAnimation();
|
|
7536
7678
|
},
|
|
7537
|
-
[
|
|
7679
|
+
[
|
|
7680
|
+
captureRestCenters,
|
|
7681
|
+
clearTrackedPointer,
|
|
7682
|
+
dockPlacement,
|
|
7683
|
+
scheduleAnimation,
|
|
7684
|
+
setMagnifyActive,
|
|
7685
|
+
startGlobalPointerTracking,
|
|
7686
|
+
stopGlobalPointerTracking
|
|
7687
|
+
]
|
|
7538
7688
|
);
|
|
7689
|
+
handleGlobalPointerMoveRef.current = handlePointerMove;
|
|
7690
|
+
handleGlobalPointerCancelRef.current = handleGlobalPointerCancel;
|
|
7539
7691
|
const handlePointerLeave = useCallback8(() => {
|
|
7540
7692
|
pendingPointerAxisRef.current = null;
|
|
7541
7693
|
pointerAxisRef.current = null;
|
|
@@ -7558,13 +7710,15 @@ function useDockMagnification({
|
|
|
7558
7710
|
[slotRefs]
|
|
7559
7711
|
);
|
|
7560
7712
|
const pauseMagnification = useCallback8(() => {
|
|
7713
|
+
stopGlobalPointerTracking();
|
|
7561
7714
|
stopAnimation();
|
|
7562
7715
|
pendingPointerAxisRef.current = null;
|
|
7563
7716
|
pointerAxisRef.current = null;
|
|
7564
7717
|
entryRampStartedAtRef.current = null;
|
|
7565
7718
|
lastFrameTimeRef.current = null;
|
|
7566
|
-
}, [stopAnimation]);
|
|
7719
|
+
}, [stopAnimation, stopGlobalPointerTracking]);
|
|
7567
7720
|
const resetMagnification = useCallback8(() => {
|
|
7721
|
+
stopGlobalPointerTracking();
|
|
7568
7722
|
stopAnimation();
|
|
7569
7723
|
for (const slotElement of slotRefs.current.values()) {
|
|
7570
7724
|
clearDockSlotMagnification(slotElement, appliedStylesRef.current);
|
|
@@ -7578,7 +7732,7 @@ function useDockMagnification({
|
|
|
7578
7732
|
pendingPointerAxisRef.current = null;
|
|
7579
7733
|
entryRampStartedAtRef.current = null;
|
|
7580
7734
|
setMagnifyActive(false);
|
|
7581
|
-
}, [setMagnifyActive, slotRefs, stopAnimation]);
|
|
7735
|
+
}, [setMagnifyActive, slotRefs, stopAnimation, stopGlobalPointerTracking]);
|
|
7582
7736
|
useEffect6(
|
|
7583
7737
|
() => () => {
|
|
7584
7738
|
resetMagnification();
|
|
@@ -9316,6 +9470,7 @@ function WorkbenchHostDock({
|
|
|
9316
9470
|
} = useDockMagnification({
|
|
9317
9471
|
dockPlacement,
|
|
9318
9472
|
dockRootRef: dockMeasureRef,
|
|
9473
|
+
dockViewportRef: dockItemsRef,
|
|
9319
9474
|
slotRefs
|
|
9320
9475
|
});
|
|
9321
9476
|
const clearSlotMagnificationRef = useRef8(() => {
|
|
@@ -10161,6 +10316,7 @@ function WorkbenchHostDock({
|
|
|
10161
10316
|
"aria-disabled": clickResolution.kind === "blocked" ? true : void 0,
|
|
10162
10317
|
className: "desktop-dock__btn",
|
|
10163
10318
|
"data-interactive": clickResolution.kind === "blocked" ? "false" : "true",
|
|
10319
|
+
"data-dock-hover-panel-trigger": hasHoverPanel ? "true" : void 0,
|
|
10164
10320
|
type: "button",
|
|
10165
10321
|
onPointerDown: (event) => {
|
|
10166
10322
|
if (event.button !== 0) {
|
|
@@ -11359,9 +11515,40 @@ function WorkbenchHostDockHoverPanel({
|
|
|
11359
11515
|
setPendingActionKeys,
|
|
11360
11516
|
state
|
|
11361
11517
|
}) {
|
|
11518
|
+
const lastPointerActionAtRef = useRef8(/* @__PURE__ */ new Map());
|
|
11362
11519
|
if (!entry) {
|
|
11363
11520
|
return null;
|
|
11364
11521
|
}
|
|
11522
|
+
const hoverPanelEntry = entry;
|
|
11523
|
+
const runHoverAction = (actionKey, actionId, disabled) => {
|
|
11524
|
+
if (disabled || pendingActionKeys.has(actionKey)) {
|
|
11525
|
+
return;
|
|
11526
|
+
}
|
|
11527
|
+
setPendingActionKeys((current) => {
|
|
11528
|
+
const next = new Set(current);
|
|
11529
|
+
next.add(actionKey);
|
|
11530
|
+
return next;
|
|
11531
|
+
});
|
|
11532
|
+
void (async () => {
|
|
11533
|
+
try {
|
|
11534
|
+
await onDockEntryAction?.({
|
|
11535
|
+
actionId,
|
|
11536
|
+
entryId: hoverPanelEntry.id,
|
|
11537
|
+
host
|
|
11538
|
+
});
|
|
11539
|
+
} catch {
|
|
11540
|
+
} finally {
|
|
11541
|
+
setPendingActionKeys((current) => {
|
|
11542
|
+
if (!current.has(actionKey)) {
|
|
11543
|
+
return current;
|
|
11544
|
+
}
|
|
11545
|
+
const next = new Set(current);
|
|
11546
|
+
next.delete(actionKey);
|
|
11547
|
+
return next;
|
|
11548
|
+
});
|
|
11549
|
+
}
|
|
11550
|
+
})();
|
|
11551
|
+
};
|
|
11365
11552
|
return /* @__PURE__ */ jsxs8(
|
|
11366
11553
|
"div",
|
|
11367
11554
|
{
|
|
@@ -11394,36 +11581,34 @@ function WorkbenchHostDockHoverPanel({
|
|
|
11394
11581
|
className: "desktop-dock__hover-action",
|
|
11395
11582
|
disabled: action.disabled || isLocallyPending,
|
|
11396
11583
|
type: "button",
|
|
11584
|
+
onPointerDown: (event) => {
|
|
11585
|
+
if (event.button !== 0) {
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
event.preventDefault();
|
|
11589
|
+
event.stopPropagation();
|
|
11590
|
+
lastPointerActionAtRef.current.set(
|
|
11591
|
+
actionKey,
|
|
11592
|
+
performance.now()
|
|
11593
|
+
);
|
|
11594
|
+
runHoverAction(
|
|
11595
|
+
actionKey,
|
|
11596
|
+
action.id,
|
|
11597
|
+
action.disabled === true
|
|
11598
|
+
);
|
|
11599
|
+
},
|
|
11397
11600
|
onClick: (event) => {
|
|
11398
11601
|
event.preventDefault();
|
|
11399
11602
|
event.stopPropagation();
|
|
11400
|
-
|
|
11603
|
+
const lastPointerAt = lastPointerActionAtRef.current.get(actionKey);
|
|
11604
|
+
if (lastPointerAt !== void 0 && performance.now() - lastPointerAt < 700) {
|
|
11401
11605
|
return;
|
|
11402
11606
|
}
|
|
11403
|
-
|
|
11404
|
-
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
|
|
11408
|
-
void (async () => {
|
|
11409
|
-
try {
|
|
11410
|
-
await onDockEntryAction?.({
|
|
11411
|
-
actionId: action.id,
|
|
11412
|
-
entryId: entry.id,
|
|
11413
|
-
host
|
|
11414
|
-
});
|
|
11415
|
-
} catch {
|
|
11416
|
-
} finally {
|
|
11417
|
-
setPendingActionKeys((current) => {
|
|
11418
|
-
if (!current.has(actionKey)) {
|
|
11419
|
-
return current;
|
|
11420
|
-
}
|
|
11421
|
-
const next = new Set(current);
|
|
11422
|
-
next.delete(actionKey);
|
|
11423
|
-
return next;
|
|
11424
|
-
});
|
|
11425
|
-
}
|
|
11426
|
-
})();
|
|
11607
|
+
runHoverAction(
|
|
11608
|
+
actionKey,
|
|
11609
|
+
action.id,
|
|
11610
|
+
action.disabled === true
|
|
11611
|
+
);
|
|
11427
11612
|
},
|
|
11428
11613
|
children: isPending ? action.pendingLabel ?? action.label : action.label
|
|
11429
11614
|
},
|