@tutti-os/workbench-surface 0.0.21 → 0.0.23
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 +12 -1
- package/dist/index.js +666 -159
- package/dist/index.js.map +1 -1
- package/dist/styles/workbench.css +35 -5
- package/dist/styles/workbenchStyle.test.ts +8 -3
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -2687,9 +2687,11 @@ function cloneMeaningfulGenieElement(source, rootRect) {
|
|
|
2687
2687
|
function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
2688
2688
|
const { direction, dockPoint, texture, textureRect } = frame;
|
|
2689
2689
|
const progress = clampGenieProgress(frame.progress);
|
|
2690
|
-
const
|
|
2691
|
-
const
|
|
2692
|
-
const
|
|
2690
|
+
const sourceWidth = Math.max(1, texture.width);
|
|
2691
|
+
const sourceHeight = Math.max(1, texture.height);
|
|
2692
|
+
const destinationWidth = Math.max(1, textureRect.width);
|
|
2693
|
+
const destinationHeight = Math.max(1, textureRect.height);
|
|
2694
|
+
const scanlineStride = resolveGenieScanlineStride(sourceHeight);
|
|
2693
2695
|
const dirtyRect = resolveGenieDirtyRect({
|
|
2694
2696
|
dockPoint,
|
|
2695
2697
|
textureRect,
|
|
@@ -2702,10 +2704,10 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
|
2702
2704
|
dirtyRect.width,
|
|
2703
2705
|
dirtyRect.height
|
|
2704
2706
|
);
|
|
2705
|
-
for (let y = 0; y <
|
|
2706
|
-
const
|
|
2707
|
-
const sourceMidY = y +
|
|
2708
|
-
const rowProgress = sourceMidY /
|
|
2707
|
+
for (let y = 0; y < sourceHeight; y += scanlineStride) {
|
|
2708
|
+
const sourceSliceHeight = Math.min(scanlineStride, sourceHeight - y);
|
|
2709
|
+
const sourceMidY = y + sourceSliceHeight / 2;
|
|
2710
|
+
const rowProgress = sourceMidY / sourceHeight;
|
|
2709
2711
|
const horizontalProgress = resolveGenieRowProgress({
|
|
2710
2712
|
direction,
|
|
2711
2713
|
progress,
|
|
@@ -2715,28 +2717,30 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
|
2715
2717
|
const horizontalEase = easeInOutCubic(horizontalProgress);
|
|
2716
2718
|
const left = direction === "minimize" ? lerpGenieValue(textureRect.left, dockPoint.x, horizontalEase) : lerpGenieValue(dockPoint.x, textureRect.left, horizontalEase);
|
|
2717
2719
|
const right = direction === "minimize" ? lerpGenieValue(
|
|
2718
|
-
textureRect.left +
|
|
2720
|
+
textureRect.left + destinationWidth,
|
|
2719
2721
|
dockPoint.x,
|
|
2720
2722
|
horizontalEase
|
|
2721
2723
|
) : lerpGenieValue(
|
|
2722
2724
|
dockPoint.x,
|
|
2723
|
-
textureRect.left +
|
|
2725
|
+
textureRect.left + destinationWidth,
|
|
2724
2726
|
horizontalEase
|
|
2725
2727
|
);
|
|
2728
|
+
const destinationSourceTop = y / sourceHeight * destinationHeight;
|
|
2729
|
+
const destinationSourceBottom = (y + sourceSliceHeight) / sourceHeight * destinationHeight;
|
|
2726
2730
|
const targetTop = resolveGenieRowTargetY({
|
|
2727
2731
|
direction,
|
|
2728
2732
|
dockPoint,
|
|
2729
2733
|
progress,
|
|
2730
|
-
sourceY:
|
|
2731
|
-
textureHeight,
|
|
2734
|
+
sourceY: destinationSourceTop,
|
|
2735
|
+
textureHeight: destinationHeight,
|
|
2732
2736
|
textureRect
|
|
2733
2737
|
});
|
|
2734
2738
|
const targetBottom = resolveGenieRowTargetY({
|
|
2735
2739
|
direction,
|
|
2736
2740
|
dockPoint,
|
|
2737
2741
|
progress,
|
|
2738
|
-
sourceY:
|
|
2739
|
-
textureHeight,
|
|
2742
|
+
sourceY: destinationSourceBottom,
|
|
2743
|
+
textureHeight: destinationHeight,
|
|
2740
2744
|
textureRect
|
|
2741
2745
|
});
|
|
2742
2746
|
const targetY = Math.min(targetTop, targetBottom) - 0.5;
|
|
@@ -2749,8 +2753,8 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
|
2749
2753
|
texture,
|
|
2750
2754
|
0,
|
|
2751
2755
|
y,
|
|
2752
|
-
|
|
2753
|
-
|
|
2756
|
+
sourceWidth,
|
|
2757
|
+
sourceSliceHeight,
|
|
2754
2758
|
left,
|
|
2755
2759
|
targetY,
|
|
2756
2760
|
rowWidth,
|
|
@@ -2782,12 +2786,14 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
|
2782
2786
|
}
|
|
2783
2787
|
|
|
2784
2788
|
// src/react/useWorkbenchGenieAnimation.tsx
|
|
2785
|
-
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2789
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2786
2790
|
var genieDurationMs = 400;
|
|
2787
2791
|
var scaleMinimizeDurationMs = 220;
|
|
2788
2792
|
var genieMaxDevicePixelRatio = 2;
|
|
2789
2793
|
var genieSnapshotScale = 1;
|
|
2794
|
+
var renderedGeniePreviewHeaderOffsetPx = 40;
|
|
2790
2795
|
var minimizedDockSlotEnterAnimationMs = 720;
|
|
2796
|
+
var dockAnchorResolveMaxAnimationFrames = 3;
|
|
2791
2797
|
var dockPreviewMaxWidth = 260;
|
|
2792
2798
|
var dockPreviewMaxHeight = 170;
|
|
2793
2799
|
var dockPreviewImageCacheMaxEntries = 96;
|
|
@@ -2809,6 +2815,37 @@ function waitForNextAnimationFrame() {
|
|
|
2809
2815
|
function isFocusedWorkbenchNode(controller, nodeID) {
|
|
2810
2816
|
return controller.getSnapshot().nodeStack.at(-1) === nodeID;
|
|
2811
2817
|
}
|
|
2818
|
+
function isEmptyGeniePreview(preview) {
|
|
2819
|
+
return preview === null || preview === void 0 || preview === false;
|
|
2820
|
+
}
|
|
2821
|
+
function logWorkbenchGenieDiagnostic(debugDiagnostics, event, details, level = "info") {
|
|
2822
|
+
if (!debugDiagnostics?.isEnabled() || !debugDiagnostics.log) {
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2825
|
+
void Promise.resolve(
|
|
2826
|
+
debugDiagnostics.log({
|
|
2827
|
+
details,
|
|
2828
|
+
event,
|
|
2829
|
+
level,
|
|
2830
|
+
source: "workbench-genie"
|
|
2831
|
+
})
|
|
2832
|
+
).catch(() => void 0);
|
|
2833
|
+
}
|
|
2834
|
+
function describeGenieNode(node) {
|
|
2835
|
+
if (!node) {
|
|
2836
|
+
return {};
|
|
2837
|
+
}
|
|
2838
|
+
const data = node.data && typeof node.data === "object" ? node.data : {};
|
|
2839
|
+
return {
|
|
2840
|
+
displayMode: node.displayMode,
|
|
2841
|
+
instanceId: typeof data.instanceId === "string" ? data.instanceId : null,
|
|
2842
|
+
isMinimized: node.isMinimized,
|
|
2843
|
+
minimizedAtUnixMs: node.minimizedAtUnixMs,
|
|
2844
|
+
nodeId: node.id,
|
|
2845
|
+
title: node.title,
|
|
2846
|
+
typeId: typeof data.typeId === "string" ? data.typeId : null
|
|
2847
|
+
};
|
|
2848
|
+
}
|
|
2812
2849
|
function shouldReduceMotion() {
|
|
2813
2850
|
return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
2814
2851
|
}
|
|
@@ -2974,6 +3011,25 @@ function prepareElementTextureCapture(element) {
|
|
|
2974
3011
|
rect: windowRect
|
|
2975
3012
|
};
|
|
2976
3013
|
}
|
|
3014
|
+
function prepareRenderedGeniePreviewCloneForTexture(clone, textureRect) {
|
|
3015
|
+
clone.style.width = `${textureRect.width}px`;
|
|
3016
|
+
clone.style.height = `${textureRect.height}px`;
|
|
3017
|
+
const previewElement = clone.querySelector(
|
|
3018
|
+
".workbench-genie-preview-capture__preview"
|
|
3019
|
+
);
|
|
3020
|
+
if (!previewElement) {
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
previewElement.style.display = "block";
|
|
3024
|
+
previewElement.style.width = `${textureRect.width}px`;
|
|
3025
|
+
previewElement.style.height = `${textureRect.height}px`;
|
|
3026
|
+
previewElement.style.padding = "0";
|
|
3027
|
+
previewElement.style.border = "0";
|
|
3028
|
+
previewElement.style.borderRadius = "0";
|
|
3029
|
+
previewElement.style.background = "var(--background-panel)";
|
|
3030
|
+
previewElement.style.boxShadow = "none";
|
|
3031
|
+
previewElement.style.transform = `translateY(${renderedGeniePreviewHeaderOffsetPx}px)`;
|
|
3032
|
+
}
|
|
2977
3033
|
async function renderPreparedElementTexture({
|
|
2978
3034
|
clone,
|
|
2979
3035
|
images,
|
|
@@ -2992,6 +3048,8 @@ async function renderPreparedElementTexture({
|
|
|
2992
3048
|
if (!context) {
|
|
2993
3049
|
return null;
|
|
2994
3050
|
}
|
|
3051
|
+
context.imageSmoothingEnabled = true;
|
|
3052
|
+
context.imageSmoothingQuality = "high";
|
|
2995
3053
|
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
2996
3054
|
return { canvas, rect };
|
|
2997
3055
|
}
|
|
@@ -3018,6 +3076,28 @@ function createDockPreviewDataUrl(canvas) {
|
|
|
3018
3076
|
context.drawImage(canvas, 0, 0, output.width, output.height);
|
|
3019
3077
|
return output.toDataURL("image/png");
|
|
3020
3078
|
}
|
|
3079
|
+
async function renderPreviewImageTexture({
|
|
3080
|
+
previewImageUrl,
|
|
3081
|
+
rect
|
|
3082
|
+
}) {
|
|
3083
|
+
if (!isUsableGenieRect(rect)) {
|
|
3084
|
+
return null;
|
|
3085
|
+
}
|
|
3086
|
+
const image = new Image();
|
|
3087
|
+
image.src = previewImageUrl;
|
|
3088
|
+
await image.decode();
|
|
3089
|
+
const canvas = document.createElement("canvas");
|
|
3090
|
+
canvas.width = Math.max(1, Math.round(rect.width * genieSnapshotScale));
|
|
3091
|
+
canvas.height = Math.max(1, Math.round(rect.height * genieSnapshotScale));
|
|
3092
|
+
const context = canvas.getContext("2d");
|
|
3093
|
+
if (!context) {
|
|
3094
|
+
return null;
|
|
3095
|
+
}
|
|
3096
|
+
context.imageSmoothingEnabled = true;
|
|
3097
|
+
context.imageSmoothingQuality = "high";
|
|
3098
|
+
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
|
3099
|
+
return { canvas, rect };
|
|
3100
|
+
}
|
|
3021
3101
|
function readDockAnchorFallbackSize(element) {
|
|
3022
3102
|
const cssValue = window.getComputedStyle(element).getPropertyValue("--desktop-dock-size");
|
|
3023
3103
|
const parsed = Number.parseFloat(cssValue);
|
|
@@ -3123,8 +3203,10 @@ function createGenieSvgTexture(element, rect) {
|
|
|
3123
3203
|
function useWorkbenchGenieAnimation({
|
|
3124
3204
|
captureNodePreviewImage,
|
|
3125
3205
|
controller,
|
|
3206
|
+
debugDiagnostics,
|
|
3126
3207
|
dockPreviewCache,
|
|
3127
3208
|
minimizeAnimation = "genie",
|
|
3209
|
+
renderNodeGeniePreview,
|
|
3128
3210
|
resolveDockAnchorKey,
|
|
3129
3211
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
|
|
3130
3212
|
shouldCaptureNodePreviewImage
|
|
@@ -3138,11 +3220,18 @@ function useWorkbenchGenieAnimation({
|
|
|
3138
3220
|
const minimizedDockEnterAnimationTimersRef = useRef4(
|
|
3139
3221
|
/* @__PURE__ */ new Map()
|
|
3140
3222
|
);
|
|
3223
|
+
const minimizedGenieTextureByNodeIDRef = useRef4(
|
|
3224
|
+
/* @__PURE__ */ new Map()
|
|
3225
|
+
);
|
|
3226
|
+
const renderedPreviewCaptureIDRef = useRef4(0);
|
|
3227
|
+
const renderedPreviewCaptureElementRef = useRef4(null);
|
|
3228
|
+
const pendingRenderedPreviewCaptureRef = useRef4(null);
|
|
3141
3229
|
const [isCanvasActive, setIsCanvasActive] = useState4(false);
|
|
3142
3230
|
const [genieHiddenNodeIDs, setGenieHiddenNodeIDs] = useState4(
|
|
3143
3231
|
() => /* @__PURE__ */ new Set()
|
|
3144
3232
|
);
|
|
3145
3233
|
const [pendingMinimizedNode, setPendingMinimizedNode] = useState4(null);
|
|
3234
|
+
const [pendingRenderedPreviewCapture, setPendingRenderedPreviewCapture] = useState4(null);
|
|
3146
3235
|
const registerDockAnchor = useCallback6(
|
|
3147
3236
|
(anchorKey, element) => {
|
|
3148
3237
|
if (element) {
|
|
@@ -3155,8 +3244,25 @@ function useWorkbenchGenieAnimation({
|
|
|
3155
3244
|
);
|
|
3156
3245
|
const resolveDockAnchorRect = useCallback6((anchorKey) => {
|
|
3157
3246
|
const element = dockAnchorElementsRef.current.get(anchorKey) ?? null;
|
|
3158
|
-
|
|
3247
|
+
if (!element) {
|
|
3248
|
+
return null;
|
|
3249
|
+
}
|
|
3250
|
+
return resolveDockAnchorViewportRect(element);
|
|
3159
3251
|
}, []);
|
|
3252
|
+
const resolveDockAnchorRectAfterRender = useCallback6(
|
|
3253
|
+
async (anchorKey, isCurrent) => {
|
|
3254
|
+
let dockRect = resolveDockAnchorRect(anchorKey);
|
|
3255
|
+
for (let frame = 0; (!dockRect || !isUsableGenieRect(dockRect)) && frame < dockAnchorResolveMaxAnimationFrames; frame += 1) {
|
|
3256
|
+
await waitForNextAnimationFrame();
|
|
3257
|
+
if (!isCurrent()) {
|
|
3258
|
+
return null;
|
|
3259
|
+
}
|
|
3260
|
+
dockRect = resolveDockAnchorRect(anchorKey);
|
|
3261
|
+
}
|
|
3262
|
+
return dockRect;
|
|
3263
|
+
},
|
|
3264
|
+
[resolveDockAnchorRect]
|
|
3265
|
+
);
|
|
3160
3266
|
const resolveNodeElement = useCallback6((nodeID) => {
|
|
3161
3267
|
return Array.from(
|
|
3162
3268
|
document.querySelectorAll("[data-workbench-window-id]")
|
|
@@ -3200,6 +3306,36 @@ function useWorkbenchGenieAnimation({
|
|
|
3200
3306
|
const shouldAnimateMinimizedDockEnter = useCallback6((nodeID) => {
|
|
3201
3307
|
return minimizedDockEnterAnimationNodeIdsRef.current.has(nodeID);
|
|
3202
3308
|
}, []);
|
|
3309
|
+
const readMinimizedGenieTexture = useCallback6((nodeID) => {
|
|
3310
|
+
return minimizedGenieTextureByNodeIDRef.current.get(nodeID) ?? null;
|
|
3311
|
+
}, []);
|
|
3312
|
+
const writeMinimizedGenieTexture = useCallback6(
|
|
3313
|
+
(nodeID, texture) => {
|
|
3314
|
+
const cache = minimizedGenieTextureByNodeIDRef.current;
|
|
3315
|
+
cache.delete(nodeID);
|
|
3316
|
+
cache.set(nodeID, texture);
|
|
3317
|
+
},
|
|
3318
|
+
[]
|
|
3319
|
+
);
|
|
3320
|
+
const clearMinimizedGenieTexture = useCallback6((nodeID) => {
|
|
3321
|
+
minimizedGenieTextureByNodeIDRef.current.delete(nodeID);
|
|
3322
|
+
}, []);
|
|
3323
|
+
const pruneMinimizedGenieTextures = useCallback6(
|
|
3324
|
+
(retainNodeID) => {
|
|
3325
|
+
const minimizedNodeIDs = new Set(
|
|
3326
|
+
controller.getSnapshot().nodes.filter((node) => node.isMinimized === true).map((node) => node.id)
|
|
3327
|
+
);
|
|
3328
|
+
if (retainNodeID) {
|
|
3329
|
+
minimizedNodeIDs.add(retainNodeID);
|
|
3330
|
+
}
|
|
3331
|
+
for (const nodeID of minimizedGenieTextureByNodeIDRef.current.keys()) {
|
|
3332
|
+
if (!minimizedNodeIDs.has(nodeID)) {
|
|
3333
|
+
minimizedGenieTextureByNodeIDRef.current.delete(nodeID);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
},
|
|
3337
|
+
[controller]
|
|
3338
|
+
);
|
|
3203
3339
|
const hideNodeForGenie = useCallback6((nodeID) => {
|
|
3204
3340
|
setGenieHiddenNodeIDs((current) => {
|
|
3205
3341
|
if (current.has(nodeID)) {
|
|
@@ -3223,6 +3359,81 @@ function useWorkbenchGenieAnimation({
|
|
|
3223
3359
|
(current) => current?.id === nodeID ? null : current
|
|
3224
3360
|
);
|
|
3225
3361
|
}, []);
|
|
3362
|
+
const clearRenderedPreviewCapture = useCallback6((id) => {
|
|
3363
|
+
if (pendingRenderedPreviewCaptureRef.current?.id !== id) {
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
pendingRenderedPreviewCaptureRef.current = null;
|
|
3367
|
+
renderedPreviewCaptureElementRef.current = null;
|
|
3368
|
+
setPendingRenderedPreviewCapture(null);
|
|
3369
|
+
}, []);
|
|
3370
|
+
const requestRenderedGeniePreviewTexture = useCallback6(
|
|
3371
|
+
async ({
|
|
3372
|
+
node,
|
|
3373
|
+
textureRect
|
|
3374
|
+
}) => {
|
|
3375
|
+
if (!isUsableGenieRect(textureRect)) {
|
|
3376
|
+
return null;
|
|
3377
|
+
}
|
|
3378
|
+
const previewViewport = {
|
|
3379
|
+
height: textureRect.height,
|
|
3380
|
+
width: textureRect.width
|
|
3381
|
+
};
|
|
3382
|
+
let preview = null;
|
|
3383
|
+
try {
|
|
3384
|
+
preview = renderNodeGeniePreview?.(node, {
|
|
3385
|
+
previewViewport
|
|
3386
|
+
}) ?? null;
|
|
3387
|
+
} catch {
|
|
3388
|
+
preview = null;
|
|
3389
|
+
}
|
|
3390
|
+
if (isEmptyGeniePreview(preview)) {
|
|
3391
|
+
return null;
|
|
3392
|
+
}
|
|
3393
|
+
const captureID = renderedPreviewCaptureIDRef.current + 1;
|
|
3394
|
+
renderedPreviewCaptureIDRef.current = captureID;
|
|
3395
|
+
const pendingCapture = {
|
|
3396
|
+
id: captureID,
|
|
3397
|
+
nodeID: node.id,
|
|
3398
|
+
preview,
|
|
3399
|
+
rect: textureRect,
|
|
3400
|
+
usedFallbackPreview: false
|
|
3401
|
+
};
|
|
3402
|
+
pendingRenderedPreviewCaptureRef.current = pendingCapture;
|
|
3403
|
+
flushSync(() => {
|
|
3404
|
+
setPendingRenderedPreviewCapture(pendingCapture);
|
|
3405
|
+
});
|
|
3406
|
+
try {
|
|
3407
|
+
await waitForNextAnimationFrame();
|
|
3408
|
+
await waitForNextAnimationFrame();
|
|
3409
|
+
if (pendingRenderedPreviewCaptureRef.current?.id !== captureID) {
|
|
3410
|
+
return null;
|
|
3411
|
+
}
|
|
3412
|
+
const element = renderedPreviewCaptureElementRef.current;
|
|
3413
|
+
if (!element) {
|
|
3414
|
+
return null;
|
|
3415
|
+
}
|
|
3416
|
+
const preparedCapture = prepareElementTextureCapture(element);
|
|
3417
|
+
if (!preparedCapture) {
|
|
3418
|
+
return null;
|
|
3419
|
+
}
|
|
3420
|
+
prepareRenderedGeniePreviewCloneForTexture(
|
|
3421
|
+
preparedCapture.clone,
|
|
3422
|
+
textureRect
|
|
3423
|
+
);
|
|
3424
|
+
const texture = await renderPreparedElementTexture({
|
|
3425
|
+
...preparedCapture,
|
|
3426
|
+
rect: textureRect
|
|
3427
|
+
});
|
|
3428
|
+
return texture;
|
|
3429
|
+
} catch {
|
|
3430
|
+
return null;
|
|
3431
|
+
} finally {
|
|
3432
|
+
clearRenderedPreviewCapture(captureID);
|
|
3433
|
+
}
|
|
3434
|
+
},
|
|
3435
|
+
[clearRenderedPreviewCapture, renderNodeGeniePreview]
|
|
3436
|
+
);
|
|
3226
3437
|
const setupCanvas = useCallback6(() => {
|
|
3227
3438
|
const canvas = canvasRef.current;
|
|
3228
3439
|
if (!canvas) {
|
|
@@ -3428,11 +3639,12 @@ function useWorkbenchGenieAnimation({
|
|
|
3428
3639
|
);
|
|
3429
3640
|
useEffect3(() => () => stopAnimation(false), [stopAnimation]);
|
|
3430
3641
|
const startOpenOrRestoreAnimation = useCallback6(
|
|
3431
|
-
async (nodeID, anchorKey, generation, dockRectFallback) => {
|
|
3642
|
+
async (nodeID, anchorKey, generation, dockRectFallback, minimizedNode) => {
|
|
3432
3643
|
const effectiveMinimizeAnimation = shouldReduceMotion() ? "off" : minimizeAnimation;
|
|
3433
3644
|
if (effectiveMinimizeAnimation === "off") {
|
|
3434
3645
|
animationCleanupRef.current = null;
|
|
3435
3646
|
showNodeForGenie(nodeID);
|
|
3647
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3436
3648
|
return;
|
|
3437
3649
|
}
|
|
3438
3650
|
await waitForNextAnimationFrame();
|
|
@@ -3446,6 +3658,7 @@ function useWorkbenchGenieAnimation({
|
|
|
3446
3658
|
if (!dockRect || !nodeElement || !isUsableGenieRect(dockRect)) {
|
|
3447
3659
|
animationCleanupRef.current = null;
|
|
3448
3660
|
showNodeForGenie(nodeID);
|
|
3661
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3449
3662
|
return;
|
|
3450
3663
|
}
|
|
3451
3664
|
flushSync(() => {
|
|
@@ -3459,30 +3672,48 @@ function useWorkbenchGenieAnimation({
|
|
|
3459
3672
|
flushSync(() => {
|
|
3460
3673
|
showNodeForGenie(nodeID);
|
|
3461
3674
|
});
|
|
3675
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3462
3676
|
},
|
|
3463
3677
|
onComplete: () => {
|
|
3464
3678
|
flushSync(() => {
|
|
3465
3679
|
showNodeForGenie(nodeID);
|
|
3466
3680
|
});
|
|
3681
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3467
3682
|
}
|
|
3468
3683
|
});
|
|
3469
3684
|
return;
|
|
3470
3685
|
}
|
|
3471
|
-
|
|
3472
|
-
if (!dockRect || !nodeElement || !captureTarget || !isUsableGenieRect(dockRect)) {
|
|
3686
|
+
if (!dockRect || !isUsableGenieRect(dockRect)) {
|
|
3473
3687
|
animationCleanupRef.current = null;
|
|
3474
3688
|
showNodeForGenie(nodeID);
|
|
3689
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3475
3690
|
return;
|
|
3476
3691
|
}
|
|
3477
|
-
const
|
|
3478
|
-
|
|
3479
|
-
);
|
|
3692
|
+
const cachedTexture = readMinimizedGenieTexture(nodeID);
|
|
3693
|
+
const restoredWindowRect = nodeElement ? viewportRectFromElement(nodeElement) : null;
|
|
3694
|
+
const shouldRestoreFromRenderedPreview = minimizedNode !== null && (shouldCaptureNodePreviewImage?.(minimizedNode) ?? true) === false;
|
|
3695
|
+
const renderedPreviewTexture = cachedTexture || !shouldRestoreFromRenderedPreview || !restoredWindowRect || !isUsableGenieRect(restoredWindowRect) ? null : await requestRenderedGeniePreviewTexture({
|
|
3696
|
+
node: minimizedNode,
|
|
3697
|
+
textureRect: restoredWindowRect
|
|
3698
|
+
}).catch(() => null);
|
|
3699
|
+
if (generation !== animationGenerationRef.current) {
|
|
3700
|
+
return;
|
|
3701
|
+
}
|
|
3702
|
+
const captureTarget = cachedTexture || renderedPreviewTexture || !nodeElement ? null : resolveWorkbenchCaptureElement(nodeElement);
|
|
3703
|
+
if (!cachedTexture && !renderedPreviewTexture && !captureTarget) {
|
|
3704
|
+
animationCleanupRef.current = null;
|
|
3705
|
+
showNodeForGenie(nodeID);
|
|
3706
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3709
|
+
const texture = cachedTexture ?? renderedPreviewTexture ?? (captureTarget ? await captureElementTexture(captureTarget).catch(() => null) : null);
|
|
3480
3710
|
if (generation !== animationGenerationRef.current) {
|
|
3481
3711
|
return;
|
|
3482
3712
|
}
|
|
3483
3713
|
if (!texture) {
|
|
3484
3714
|
animationCleanupRef.current = null;
|
|
3485
3715
|
showNodeForGenie(nodeID);
|
|
3716
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3486
3717
|
return;
|
|
3487
3718
|
}
|
|
3488
3719
|
runGenieAnimation({
|
|
@@ -3492,12 +3723,14 @@ function useWorkbenchGenieAnimation({
|
|
|
3492
3723
|
flushSync(() => {
|
|
3493
3724
|
showNodeForGenie(nodeID);
|
|
3494
3725
|
});
|
|
3726
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3495
3727
|
clearCanvas();
|
|
3496
3728
|
},
|
|
3497
3729
|
onComplete: () => {
|
|
3498
3730
|
flushSync(() => {
|
|
3499
3731
|
showNodeForGenie(nodeID);
|
|
3500
3732
|
});
|
|
3733
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3501
3734
|
clearCanvas();
|
|
3502
3735
|
},
|
|
3503
3736
|
skipStop: true,
|
|
@@ -3506,11 +3739,15 @@ function useWorkbenchGenieAnimation({
|
|
|
3506
3739
|
},
|
|
3507
3740
|
[
|
|
3508
3741
|
clearCanvas,
|
|
3742
|
+
clearMinimizedGenieTexture,
|
|
3509
3743
|
minimizeAnimation,
|
|
3744
|
+
readMinimizedGenieTexture,
|
|
3745
|
+
requestRenderedGeniePreviewTexture,
|
|
3510
3746
|
resolveDockAnchorRect,
|
|
3511
3747
|
resolveNodeElement,
|
|
3512
3748
|
runGenieAnimation,
|
|
3513
3749
|
runScaleWindowAnimation,
|
|
3750
|
+
shouldCaptureNodePreviewImage,
|
|
3514
3751
|
showNodeForGenie
|
|
3515
3752
|
]
|
|
3516
3753
|
);
|
|
@@ -3541,24 +3778,39 @@ function useWorkbenchGenieAnimation({
|
|
|
3541
3778
|
const dockRectFallback = resolveDockAnchorRect(anchorKey);
|
|
3542
3779
|
hideNodeForGenie(nodeID);
|
|
3543
3780
|
animationCleanupRef.current = () => {
|
|
3781
|
+
if (rafRef.current !== null) {
|
|
3782
|
+
window.cancelAnimationFrame(rafRef.current);
|
|
3783
|
+
rafRef.current = null;
|
|
3784
|
+
}
|
|
3544
3785
|
flushSync(() => {
|
|
3545
3786
|
showNodeForGenie(nodeID);
|
|
3546
3787
|
});
|
|
3788
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3547
3789
|
clearCanvas();
|
|
3548
3790
|
};
|
|
3549
3791
|
const generation = animationGenerationRef.current;
|
|
3550
|
-
|
|
3551
|
-
|
|
3792
|
+
rafRef.current = window.requestAnimationFrame(() => {
|
|
3793
|
+
rafRef.current = null;
|
|
3794
|
+
if (generation !== animationGenerationRef.current) {
|
|
3795
|
+
return;
|
|
3796
|
+
}
|
|
3797
|
+
void Promise.resolve(launch()).catch(() => null).then(() => {
|
|
3798
|
+
if (generation !== animationGenerationRef.current) {
|
|
3799
|
+
return;
|
|
3800
|
+
}
|
|
3801
|
+
void startOpenOrRestoreAnimation(
|
|
3802
|
+
nodeID,
|
|
3803
|
+
anchorKey,
|
|
3804
|
+
generation,
|
|
3805
|
+
dockRectFallback,
|
|
3806
|
+
target
|
|
3807
|
+
);
|
|
3808
|
+
});
|
|
3552
3809
|
});
|
|
3553
|
-
void startOpenOrRestoreAnimation(
|
|
3554
|
-
nodeID,
|
|
3555
|
-
anchorKey,
|
|
3556
|
-
generation,
|
|
3557
|
-
dockRectFallback
|
|
3558
|
-
);
|
|
3559
3810
|
},
|
|
3560
3811
|
[
|
|
3561
3812
|
clearCanvas,
|
|
3813
|
+
clearMinimizedGenieTexture,
|
|
3562
3814
|
controller,
|
|
3563
3815
|
hideNodeForGenie,
|
|
3564
3816
|
minimizeAnimation,
|
|
@@ -3571,10 +3823,21 @@ function useWorkbenchGenieAnimation({
|
|
|
3571
3823
|
const minimizeNodeToAnchor = useCallback6(
|
|
3572
3824
|
(nodeID, minimize) => {
|
|
3573
3825
|
void (async () => {
|
|
3826
|
+
pruneMinimizedGenieTextures();
|
|
3574
3827
|
const target = controller.getSnapshot().nodes.find((node) => node.id === nodeID);
|
|
3575
3828
|
if (!target) {
|
|
3829
|
+
logWorkbenchGenieDiagnostic(
|
|
3830
|
+
debugDiagnostics,
|
|
3831
|
+
"workbench.genie.minimize.skipped",
|
|
3832
|
+
{
|
|
3833
|
+
nodeId: nodeID,
|
|
3834
|
+
reason: "target_missing"
|
|
3835
|
+
},
|
|
3836
|
+
"warn"
|
|
3837
|
+
);
|
|
3576
3838
|
return;
|
|
3577
3839
|
}
|
|
3840
|
+
clearMinimizedGenieTexture(nodeID);
|
|
3578
3841
|
const runMinimize = minimize ?? (() => controller.commands.minimizeNode(nodeID));
|
|
3579
3842
|
const effectiveMinimizeAnimation = shouldReduceMotion() ? "off" : minimizeAnimation;
|
|
3580
3843
|
const shouldCapturePreview = shouldCaptureNodePreviewImage?.(target) ?? true;
|
|
@@ -3635,6 +3898,16 @@ function useWorkbenchGenieAnimation({
|
|
|
3635
3898
|
const generation2 = animationGenerationRef.current;
|
|
3636
3899
|
const nodeElement2 = resolveNodeElement(nodeID);
|
|
3637
3900
|
if (!nodeElement2) {
|
|
3901
|
+
logWorkbenchGenieDiagnostic(
|
|
3902
|
+
debugDiagnostics,
|
|
3903
|
+
"workbench.genie.minimize.skipped",
|
|
3904
|
+
{
|
|
3905
|
+
...describeGenieNode(target),
|
|
3906
|
+
mode: "scale",
|
|
3907
|
+
reason: "node_element_missing"
|
|
3908
|
+
},
|
|
3909
|
+
"warn"
|
|
3910
|
+
);
|
|
3638
3911
|
runMinimize();
|
|
3639
3912
|
return;
|
|
3640
3913
|
}
|
|
@@ -3685,8 +3958,30 @@ function useWorkbenchGenieAnimation({
|
|
|
3685
3958
|
return;
|
|
3686
3959
|
}
|
|
3687
3960
|
const anchorKey2 = resolveAnchorKeyForNode(pendingMinimizedNode3);
|
|
3688
|
-
const dockRect2 =
|
|
3961
|
+
const dockRect2 = await resolveDockAnchorRectAfterRender(
|
|
3962
|
+
anchorKey2,
|
|
3963
|
+
() => generation2 === animationGenerationRef.current
|
|
3964
|
+
);
|
|
3965
|
+
if (generation2 !== animationGenerationRef.current) {
|
|
3966
|
+
return;
|
|
3967
|
+
}
|
|
3689
3968
|
if (!nodeElement2.isConnected || !dockRect2 || !isUsableGenieRect(dockRect2)) {
|
|
3969
|
+
logWorkbenchGenieDiagnostic(
|
|
3970
|
+
debugDiagnostics,
|
|
3971
|
+
"workbench.genie.minimize.skipped",
|
|
3972
|
+
{
|
|
3973
|
+
...describeGenieNode(target),
|
|
3974
|
+
anchorKey: anchorKey2,
|
|
3975
|
+
dockRect: dockRect2,
|
|
3976
|
+
mode: "scale",
|
|
3977
|
+
nodeElementConnected: nodeElement2.isConnected,
|
|
3978
|
+
registeredDockAnchorKeys: Array.from(
|
|
3979
|
+
dockAnchorElementsRef.current.keys()
|
|
3980
|
+
).filter((key) => key.startsWith("minimized:")),
|
|
3981
|
+
reason: "dock_rect_unusable"
|
|
3982
|
+
},
|
|
3983
|
+
"warn"
|
|
3984
|
+
);
|
|
3690
3985
|
cleanupPendingMinimize();
|
|
3691
3986
|
return;
|
|
3692
3987
|
}
|
|
@@ -3712,18 +4007,87 @@ function useWorkbenchGenieAnimation({
|
|
|
3712
4007
|
stopAnimation();
|
|
3713
4008
|
const generation = animationGenerationRef.current;
|
|
3714
4009
|
const nodeElement = resolveNodeElement(nodeID);
|
|
3715
|
-
|
|
3716
|
-
|
|
4010
|
+
if (!nodeElement) {
|
|
4011
|
+
logWorkbenchGenieDiagnostic(
|
|
4012
|
+
debugDiagnostics,
|
|
4013
|
+
"workbench.genie.minimize.skipped",
|
|
4014
|
+
{
|
|
4015
|
+
...describeGenieNode(target),
|
|
4016
|
+
mode: "genie",
|
|
4017
|
+
reason: "node_element_missing"
|
|
4018
|
+
},
|
|
4019
|
+
"warn"
|
|
4020
|
+
);
|
|
3717
4021
|
runMinimize();
|
|
3718
4022
|
return;
|
|
3719
4023
|
}
|
|
3720
|
-
const
|
|
3721
|
-
if (!
|
|
4024
|
+
const windowRect = viewportRectFromElement(nodeElement);
|
|
4025
|
+
if (!isUsableGenieRect(windowRect)) {
|
|
4026
|
+
logWorkbenchGenieDiagnostic(
|
|
4027
|
+
debugDiagnostics,
|
|
4028
|
+
"workbench.genie.minimize.skipped",
|
|
4029
|
+
{
|
|
4030
|
+
...describeGenieNode(target),
|
|
4031
|
+
mode: "genie",
|
|
4032
|
+
reason: "window_rect_unusable",
|
|
4033
|
+
windowRect
|
|
4034
|
+
},
|
|
4035
|
+
"warn"
|
|
4036
|
+
);
|
|
3722
4037
|
runMinimize();
|
|
3723
4038
|
return;
|
|
3724
4039
|
}
|
|
4040
|
+
const pendingMinimizedNode2 = {
|
|
4041
|
+
...target,
|
|
4042
|
+
isMinimized: true,
|
|
4043
|
+
minimizedAtUnixMs: Date.now()
|
|
4044
|
+
};
|
|
4045
|
+
const componentPreviewTexture = shouldCapturePreview ? null : await requestRenderedGeniePreviewTexture({
|
|
4046
|
+
node: pendingMinimizedNode2,
|
|
4047
|
+
textureRect: windowRect
|
|
4048
|
+
}).catch(() => null);
|
|
4049
|
+
if (generation !== animationGenerationRef.current) {
|
|
4050
|
+
return;
|
|
4051
|
+
}
|
|
4052
|
+
if (!shouldCapturePreview) {
|
|
4053
|
+
if (!componentPreviewTexture) {
|
|
4054
|
+
logWorkbenchGenieDiagnostic(
|
|
4055
|
+
debugDiagnostics,
|
|
4056
|
+
"workbench.genie.texture.missing",
|
|
4057
|
+
{
|
|
4058
|
+
...describeGenieNode(target),
|
|
4059
|
+
mode: "genie",
|
|
4060
|
+
reason: "component_preview_texture_missing",
|
|
4061
|
+
shouldCapturePreview,
|
|
4062
|
+
windowRect
|
|
4063
|
+
},
|
|
4064
|
+
"warn"
|
|
4065
|
+
);
|
|
4066
|
+
runMinimize();
|
|
4067
|
+
return;
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
const captureTarget = resolveWorkbenchCaptureElement(nodeElement);
|
|
4071
|
+
const preparedTexture = shouldCapturePreview ? prepareElementTextureCapture(captureTarget) : null;
|
|
4072
|
+
if (!preparedTexture) {
|
|
4073
|
+
if (!componentPreviewTexture) {
|
|
4074
|
+
logWorkbenchGenieDiagnostic(
|
|
4075
|
+
debugDiagnostics,
|
|
4076
|
+
"workbench.genie.minimize.skipped",
|
|
4077
|
+
{
|
|
4078
|
+
...describeGenieNode(target),
|
|
4079
|
+
mode: "genie",
|
|
4080
|
+
reason: "prepared_texture_missing",
|
|
4081
|
+
shouldCapturePreview
|
|
4082
|
+
},
|
|
4083
|
+
"warn"
|
|
4084
|
+
);
|
|
4085
|
+
runMinimize();
|
|
4086
|
+
return;
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
3725
4089
|
const wasFocusedForCapture = isFocusedWorkbenchNode(controller, nodeID);
|
|
3726
|
-
if (!wasFocusedForCapture) {
|
|
4090
|
+
if (shouldCapturePreview && !wasFocusedForCapture) {
|
|
3727
4091
|
flushSync(() => {
|
|
3728
4092
|
controller.commands.focusNode(nodeID);
|
|
3729
4093
|
});
|
|
@@ -3732,17 +4096,35 @@ function useWorkbenchGenieAnimation({
|
|
|
3732
4096
|
return;
|
|
3733
4097
|
}
|
|
3734
4098
|
}
|
|
3735
|
-
const previewImageUrlPromise = Promise.resolve(
|
|
3736
|
-
|
|
3737
|
-
).
|
|
3738
|
-
const texture = await renderPreparedElementTexture(
|
|
3739
|
-
preparedTexture
|
|
3740
|
-
).catch(() => null);
|
|
4099
|
+
const previewImageUrlPromise = shouldCapturePreview ? Promise.resolve(captureNodePreviewImage?.(target) ?? null).catch(
|
|
4100
|
+
() => null
|
|
4101
|
+
) : Promise.resolve(null);
|
|
3741
4102
|
const previewImageUrl = await previewImageUrlPromise;
|
|
4103
|
+
const previewImageTexture = shouldCapturePreview && previewImageUrl ? await renderPreviewImageTexture({
|
|
4104
|
+
previewImageUrl,
|
|
4105
|
+
rect: windowRect
|
|
4106
|
+
}).catch(() => null) : null;
|
|
4107
|
+
const texture = componentPreviewTexture ?? previewImageTexture ?? (preparedTexture ? await renderPreparedElementTexture(preparedTexture).catch(
|
|
4108
|
+
() => null
|
|
4109
|
+
) : null);
|
|
3742
4110
|
if (generation !== animationGenerationRef.current) {
|
|
3743
4111
|
return;
|
|
3744
4112
|
}
|
|
3745
4113
|
if (!texture) {
|
|
4114
|
+
logWorkbenchGenieDiagnostic(
|
|
4115
|
+
debugDiagnostics,
|
|
4116
|
+
"workbench.genie.minimize.skipped",
|
|
4117
|
+
{
|
|
4118
|
+
...describeGenieNode(target),
|
|
4119
|
+
hasComponentPreviewTexture: Boolean(componentPreviewTexture),
|
|
4120
|
+
hasPreparedDomTexture: Boolean(preparedTexture),
|
|
4121
|
+
hasPreviewImageTexture: Boolean(previewImageTexture),
|
|
4122
|
+
mode: "genie",
|
|
4123
|
+
reason: "texture_missing",
|
|
4124
|
+
shouldCapturePreview
|
|
4125
|
+
},
|
|
4126
|
+
"warn"
|
|
4127
|
+
);
|
|
3746
4128
|
if (previewImageUrl) {
|
|
3747
4129
|
writeCachedWorkbenchNodePreviewImage(nodeID, previewImageUrl);
|
|
3748
4130
|
persistWorkbenchNodePreviewImage(target, previewImageUrl, {
|
|
@@ -3769,6 +4151,8 @@ function useWorkbenchGenieAnimation({
|
|
|
3769
4151
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
|
|
3770
4152
|
});
|
|
3771
4153
|
}
|
|
4154
|
+
writeMinimizedGenieTexture(nodeID, texture);
|
|
4155
|
+
pruneMinimizedGenieTextures(nodeID);
|
|
3772
4156
|
let minimizeCommitted = false;
|
|
3773
4157
|
const commitMinimize = () => {
|
|
3774
4158
|
if (minimizeCommitted) {
|
|
@@ -3777,11 +4161,6 @@ function useWorkbenchGenieAnimation({
|
|
|
3777
4161
|
minimizeCommitted = true;
|
|
3778
4162
|
runMinimize();
|
|
3779
4163
|
};
|
|
3780
|
-
const pendingMinimizedNode2 = {
|
|
3781
|
-
...target,
|
|
3782
|
-
isMinimized: true,
|
|
3783
|
-
minimizedAtUnixMs: Date.now()
|
|
3784
|
-
};
|
|
3785
4164
|
const cleanupPendingGenieMinimize = () => {
|
|
3786
4165
|
releaseMinimizedDockEnterAnimation(nodeID);
|
|
3787
4166
|
flushSync(() => {
|
|
@@ -3795,15 +4174,35 @@ function useWorkbenchGenieAnimation({
|
|
|
3795
4174
|
registerMinimizedDockEnterAnimation(nodeID);
|
|
3796
4175
|
flushSync(() => {
|
|
3797
4176
|
setPendingMinimizedNode(pendingMinimizedNode2);
|
|
3798
|
-
hideNodeForGenie(nodeID);
|
|
3799
4177
|
});
|
|
3800
4178
|
await waitForNextAnimationFrame();
|
|
3801
4179
|
if (generation !== animationGenerationRef.current) {
|
|
3802
4180
|
return;
|
|
3803
4181
|
}
|
|
3804
4182
|
const anchorKey = resolveAnchorKeyForNode(pendingMinimizedNode2);
|
|
3805
|
-
const dockRect =
|
|
4183
|
+
const dockRect = await resolveDockAnchorRectAfterRender(
|
|
4184
|
+
anchorKey,
|
|
4185
|
+
() => generation === animationGenerationRef.current
|
|
4186
|
+
);
|
|
4187
|
+
if (generation !== animationGenerationRef.current) {
|
|
4188
|
+
return;
|
|
4189
|
+
}
|
|
3806
4190
|
if (!dockRect || !isUsableGenieRect(dockRect)) {
|
|
4191
|
+
logWorkbenchGenieDiagnostic(
|
|
4192
|
+
debugDiagnostics,
|
|
4193
|
+
"workbench.genie.minimize.skipped",
|
|
4194
|
+
{
|
|
4195
|
+
...describeGenieNode(target),
|
|
4196
|
+
anchorKey,
|
|
4197
|
+
dockRect,
|
|
4198
|
+
mode: "genie",
|
|
4199
|
+
registeredDockAnchorKeys: Array.from(
|
|
4200
|
+
dockAnchorElementsRef.current.keys()
|
|
4201
|
+
).filter((key) => key.startsWith("minimized:")),
|
|
4202
|
+
reason: "dock_rect_unusable"
|
|
4203
|
+
},
|
|
4204
|
+
"warn"
|
|
4205
|
+
);
|
|
3807
4206
|
animationCleanupRef.current = null;
|
|
3808
4207
|
cleanupPendingGenieMinimize();
|
|
3809
4208
|
return;
|
|
@@ -3826,18 +4225,25 @@ function useWorkbenchGenieAnimation({
|
|
|
3826
4225
|
skipStop: true,
|
|
3827
4226
|
texture
|
|
3828
4227
|
});
|
|
4228
|
+
flushSync(() => {
|
|
4229
|
+
hideNodeForGenie(nodeID);
|
|
4230
|
+
});
|
|
3829
4231
|
})();
|
|
3830
4232
|
},
|
|
3831
4233
|
[
|
|
3832
4234
|
clearCanvas,
|
|
4235
|
+
clearMinimizedGenieTexture,
|
|
3833
4236
|
controller,
|
|
3834
4237
|
captureNodePreviewImage,
|
|
3835
4238
|
clearPendingMinimizedNode,
|
|
4239
|
+
debugDiagnostics,
|
|
3836
4240
|
dockPreviewCache,
|
|
3837
4241
|
hideNodeForGenie,
|
|
3838
4242
|
minimizeAnimation,
|
|
4243
|
+
pruneMinimizedGenieTextures,
|
|
3839
4244
|
registerMinimizedDockEnterAnimation,
|
|
3840
4245
|
releaseMinimizedDockEnterAnimation,
|
|
4246
|
+
requestRenderedGeniePreviewTexture,
|
|
3841
4247
|
resolveAnchorKeyForNode,
|
|
3842
4248
|
resolveDockPreviewCacheKey2,
|
|
3843
4249
|
resolveDockAnchorRect,
|
|
@@ -3848,7 +4254,8 @@ function useWorkbenchGenieAnimation({
|
|
|
3848
4254
|
shouldCaptureNodePreviewImage,
|
|
3849
4255
|
setupCanvas,
|
|
3850
4256
|
showNodeForGenie,
|
|
3851
|
-
stopAnimation
|
|
4257
|
+
stopAnimation,
|
|
4258
|
+
writeMinimizedGenieTexture
|
|
3852
4259
|
]
|
|
3853
4260
|
);
|
|
3854
4261
|
useEffect3(
|
|
@@ -3858,20 +4265,39 @@ function useWorkbenchGenieAnimation({
|
|
|
3858
4265
|
}
|
|
3859
4266
|
minimizedDockEnterAnimationTimersRef.current.clear();
|
|
3860
4267
|
minimizedDockEnterAnimationNodeIdsRef.current.clear();
|
|
4268
|
+
minimizedGenieTextureByNodeIDRef.current.clear();
|
|
3861
4269
|
},
|
|
3862
4270
|
[]
|
|
3863
4271
|
);
|
|
3864
4272
|
return {
|
|
3865
4273
|
genieLayer: typeof document === "undefined" ? null : createPortal(
|
|
3866
|
-
/* @__PURE__ */
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
4274
|
+
/* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
4275
|
+
/* @__PURE__ */ jsx7(
|
|
4276
|
+
"canvas",
|
|
4277
|
+
{
|
|
4278
|
+
ref: canvasRef,
|
|
4279
|
+
className: "workbench-genie-layer",
|
|
4280
|
+
"data-workbench-genie-layer-state": isCanvasActive ? "active" : "idle",
|
|
4281
|
+
"aria-hidden": true
|
|
4282
|
+
}
|
|
4283
|
+
),
|
|
4284
|
+
pendingRenderedPreviewCapture ? /* @__PURE__ */ jsx7(
|
|
4285
|
+
"div",
|
|
4286
|
+
{
|
|
4287
|
+
ref: renderedPreviewCaptureElementRef,
|
|
4288
|
+
className: "workbench-genie-preview-capture",
|
|
4289
|
+
"data-workbench-genie-preview-capture-id": pendingRenderedPreviewCapture.id,
|
|
4290
|
+
"data-workbench-genie-preview-node-id": pendingRenderedPreviewCapture.nodeID,
|
|
4291
|
+
"data-workbench-genie-preview-used-fallback": pendingRenderedPreviewCapture.usedFallbackPreview ? "true" : "false",
|
|
4292
|
+
style: {
|
|
4293
|
+
height: pendingRenderedPreviewCapture.rect.height,
|
|
4294
|
+
width: pendingRenderedPreviewCapture.rect.width
|
|
4295
|
+
},
|
|
4296
|
+
"aria-hidden": true,
|
|
4297
|
+
children: pendingRenderedPreviewCapture.preview
|
|
4298
|
+
}
|
|
4299
|
+
) : null
|
|
4300
|
+
] }),
|
|
3875
4301
|
document.body
|
|
3876
4302
|
),
|
|
3877
4303
|
isNodeGenieHidden: useCallback6(
|
|
@@ -3891,11 +4317,12 @@ function useWorkbenchGenieAnimation({
|
|
|
3891
4317
|
}
|
|
3892
4318
|
|
|
3893
4319
|
// src/react/WorkbenchSurface.tsx
|
|
3894
|
-
import { jsx as jsx8, jsxs as
|
|
4320
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3895
4321
|
function WorkbenchSurface({
|
|
3896
4322
|
captureNodePreviewImage,
|
|
3897
4323
|
className,
|
|
3898
4324
|
controller,
|
|
4325
|
+
debugDiagnostics,
|
|
3899
4326
|
dockPreviewCache,
|
|
3900
4327
|
dockPlacement,
|
|
3901
4328
|
interactive,
|
|
@@ -3907,6 +4334,7 @@ function WorkbenchSurface({
|
|
|
3907
4334
|
renderBottomChrome,
|
|
3908
4335
|
renderDock,
|
|
3909
4336
|
renderNode,
|
|
4337
|
+
renderNodeGeniePreview,
|
|
3910
4338
|
renderOverlay,
|
|
3911
4339
|
renderTopChrome,
|
|
3912
4340
|
renderWindowActions,
|
|
@@ -3926,6 +4354,7 @@ function WorkbenchSurface({
|
|
|
3926
4354
|
{
|
|
3927
4355
|
captureNodePreviewImage,
|
|
3928
4356
|
className,
|
|
4357
|
+
debugDiagnostics,
|
|
3929
4358
|
dockPreviewCache,
|
|
3930
4359
|
dockPlacement,
|
|
3931
4360
|
interactive,
|
|
@@ -3937,6 +4366,7 @@ function WorkbenchSurface({
|
|
|
3937
4366
|
renderBottomChrome,
|
|
3938
4367
|
renderDock,
|
|
3939
4368
|
renderNode,
|
|
4369
|
+
renderNodeGeniePreview,
|
|
3940
4370
|
renderOverlay,
|
|
3941
4371
|
renderTopChrome,
|
|
3942
4372
|
renderWindowActions,
|
|
@@ -3956,6 +4386,7 @@ function WorkbenchSurface({
|
|
|
3956
4386
|
function WorkbenchSurfaceInner({
|
|
3957
4387
|
captureNodePreviewImage,
|
|
3958
4388
|
className,
|
|
4389
|
+
debugDiagnostics,
|
|
3959
4390
|
dockPreviewCache,
|
|
3960
4391
|
dockPlacement,
|
|
3961
4392
|
interactive = true,
|
|
@@ -3967,6 +4398,7 @@ function WorkbenchSurfaceInner({
|
|
|
3967
4398
|
renderBottomChrome,
|
|
3968
4399
|
renderDock,
|
|
3969
4400
|
renderNode,
|
|
4401
|
+
renderNodeGeniePreview,
|
|
3970
4402
|
renderOverlay,
|
|
3971
4403
|
renderTopChrome,
|
|
3972
4404
|
renderWindowActions,
|
|
@@ -3992,8 +4424,10 @@ function WorkbenchSurfaceInner({
|
|
|
3992
4424
|
const genie = useWorkbenchGenieAnimation({
|
|
3993
4425
|
captureNodePreviewImage,
|
|
3994
4426
|
controller,
|
|
4427
|
+
debugDiagnostics,
|
|
3995
4428
|
dockPreviewCache,
|
|
3996
4429
|
minimizeAnimation,
|
|
4430
|
+
renderNodeGeniePreview,
|
|
3997
4431
|
resolveDockAnchorKey,
|
|
3998
4432
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
|
|
3999
4433
|
shouldCaptureNodePreviewImage
|
|
@@ -4012,7 +4446,7 @@ function WorkbenchSurfaceInner({
|
|
|
4012
4446
|
wallpaper.fit ?? "cover"
|
|
4013
4447
|
)
|
|
4014
4448
|
} : void 0;
|
|
4015
|
-
return /* @__PURE__ */
|
|
4449
|
+
return /* @__PURE__ */ jsxs5(
|
|
4016
4450
|
"div",
|
|
4017
4451
|
{
|
|
4018
4452
|
ref,
|
|
@@ -6996,7 +7430,7 @@ function resolveMinimizedStackTrackTranslateXPx(input) {
|
|
|
6996
7430
|
}
|
|
6997
7431
|
|
|
6998
7432
|
// src/host/WorkbenchHostDockPopup.tsx
|
|
6999
|
-
import { Fragment as
|
|
7433
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
7000
7434
|
var dockPopupCardWidthPx = 165;
|
|
7001
7435
|
var dockPopupGridGapPx = 8;
|
|
7002
7436
|
var dockPopupPanelPaddingInlinePx = 12;
|
|
@@ -7549,7 +7983,7 @@ function WorkbenchHostDockPopup({
|
|
|
7549
7983
|
showAllWindowsLabel,
|
|
7550
7984
|
showOpen: showOpen === true
|
|
7551
7985
|
}
|
|
7552
|
-
) : /* @__PURE__ */
|
|
7986
|
+
) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
7553
7987
|
/* @__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 }) }),
|
|
7554
7988
|
isMinimizedStack ? /* @__PURE__ */ jsx9(
|
|
7555
7989
|
"div",
|
|
@@ -7608,7 +8042,7 @@ function WorkbenchHostDockPopup({
|
|
|
7608
8042
|
}
|
|
7609
8043
|
)
|
|
7610
8044
|
}
|
|
7611
|
-
) : /* @__PURE__ */
|
|
8045
|
+
) : /* @__PURE__ */ jsxs6("div", { className: "grid max-h-[min(52vh,420px)] grid-cols-[repeat(var(--desktop-dock-popup-columns,2),165px)] gap-2 overflow-auto overscroll-contain", children: [
|
|
7612
8046
|
items.map((item) => {
|
|
7613
8047
|
const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
|
|
7614
8048
|
item.node,
|
|
@@ -7635,7 +8069,7 @@ function WorkbenchHostDockPopup({
|
|
|
7635
8069
|
item.node.id
|
|
7636
8070
|
);
|
|
7637
8071
|
}),
|
|
7638
|
-
showCreateNew !== false ? /* @__PURE__ */
|
|
8072
|
+
showCreateNew !== false ? /* @__PURE__ */ jsxs6(
|
|
7639
8073
|
"button",
|
|
7640
8074
|
{
|
|
7641
8075
|
className: "flex h-[103px] w-[165px] min-w-0 flex-col items-center justify-center gap-2 rounded-[8px] border border-dashed border-[var(--border-1)] bg-transparency-block text-center text-[var(--text-secondary)] transition-colors hover:bg-transparency-hover hover:text-[var(--text-primary)]",
|
|
@@ -7691,14 +8125,14 @@ function WorkbenchHostDockContextMenu({
|
|
|
7691
8125
|
const hasOpenCommand = !hasOpenWindows;
|
|
7692
8126
|
const hasDockActionGroup = Boolean(dockRetention) || hasNewWindowCommand || hasOpenCommand;
|
|
7693
8127
|
const hasWindowActionGroup = hasOpenWindows;
|
|
7694
|
-
return /* @__PURE__ */
|
|
8128
|
+
return /* @__PURE__ */ jsxs6(
|
|
7695
8129
|
"div",
|
|
7696
8130
|
{
|
|
7697
8131
|
className: "flex min-w-0 flex-col gap-1",
|
|
7698
8132
|
"data-desktop-dock-context-menu": "true",
|
|
7699
8133
|
role: "menu",
|
|
7700
8134
|
children: [
|
|
7701
|
-
hasOpenWindows ? /* @__PURE__ */ jsx9(
|
|
8135
|
+
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(
|
|
7702
8136
|
WorkbenchHostDockContextMenuItem,
|
|
7703
8137
|
{
|
|
7704
8138
|
checked: !item.isMinimized,
|
|
@@ -7742,7 +8176,7 @@ function WorkbenchHostDockContextMenu({
|
|
|
7742
8176
|
onSelect: onCreateNew
|
|
7743
8177
|
}
|
|
7744
8178
|
) : null,
|
|
7745
|
-
hasOpenWindows ? /* @__PURE__ */
|
|
8179
|
+
hasOpenWindows ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
7746
8180
|
hasDockActionGroup ? /* @__PURE__ */ jsx9(WorkbenchHostDockContextMenuSeparator, {}) : null,
|
|
7747
8181
|
canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx9(
|
|
7748
8182
|
WorkbenchHostDockContextMenuItem,
|
|
@@ -7792,7 +8226,7 @@ function WorkbenchHostDockContextMenuItem({
|
|
|
7792
8226
|
label,
|
|
7793
8227
|
onSelect
|
|
7794
8228
|
}) {
|
|
7795
|
-
return /* @__PURE__ */
|
|
8229
|
+
return /* @__PURE__ */ jsxs6(
|
|
7796
8230
|
"button",
|
|
7797
8231
|
{
|
|
7798
8232
|
className: cn(
|
|
@@ -7971,7 +8405,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
|
|
|
7971
8405
|
[handleSelect]
|
|
7972
8406
|
);
|
|
7973
8407
|
const hasReadyPreview = previewState.status === "ready";
|
|
7974
|
-
return /* @__PURE__ */
|
|
8408
|
+
return /* @__PURE__ */ jsxs6(
|
|
7975
8409
|
"div",
|
|
7976
8410
|
{
|
|
7977
8411
|
ref,
|
|
@@ -7986,7 +8420,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
|
|
|
7986
8420
|
"data-minimized": item.isMinimized ? "true" : void 0,
|
|
7987
8421
|
style,
|
|
7988
8422
|
children: [
|
|
7989
|
-
/* @__PURE__ */
|
|
8423
|
+
/* @__PURE__ */ jsxs6(
|
|
7990
8424
|
"div",
|
|
7991
8425
|
{
|
|
7992
8426
|
"aria-label": title,
|
|
@@ -8039,7 +8473,7 @@ function WorkbenchHostDockPopupCardPreview({
|
|
|
8039
8473
|
previewState
|
|
8040
8474
|
}) {
|
|
8041
8475
|
if (previewState.status !== "ready") {
|
|
8042
|
-
return /* @__PURE__ */
|
|
8476
|
+
return /* @__PURE__ */ jsxs6(
|
|
8043
8477
|
"span",
|
|
8044
8478
|
{
|
|
8045
8479
|
className: "flex min-h-0 min-w-0 flex-1 flex-col justify-center gap-[7px] rounded-md border border-[var(--border-1)] bg-transparency-block px-3 py-[11px]",
|
|
@@ -8100,7 +8534,11 @@ function WorkbenchHostDockPopupCardLabel({ title }) {
|
|
|
8100
8534
|
}
|
|
8101
8535
|
|
|
8102
8536
|
// src/host/WorkbenchHostDock.tsx
|
|
8103
|
-
import { jsx as jsx10, jsxs as
|
|
8537
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
8538
|
+
var minimizedDockPreviewViewport = {
|
|
8539
|
+
height: 34.2,
|
|
8540
|
+
width: 46.8
|
|
8541
|
+
};
|
|
8104
8542
|
function stripDockDescriptionTerminalPunctuation(value) {
|
|
8105
8543
|
const trimmed = value.trim();
|
|
8106
8544
|
if (!trimmed || trimmed.endsWith("...") || trimmed.endsWith("\u2026")) {
|
|
@@ -8108,6 +8546,13 @@ function stripDockDescriptionTerminalPunctuation(value) {
|
|
|
8108
8546
|
}
|
|
8109
8547
|
return trimmed.replace(/[。..]+$/u, "");
|
|
8110
8548
|
}
|
|
8549
|
+
function activateDockButtonFromKeyboard(event, disabled = false) {
|
|
8550
|
+
if (disabled || event.key !== "Enter" && event.key !== " ") {
|
|
8551
|
+
return;
|
|
8552
|
+
}
|
|
8553
|
+
event.preventDefault();
|
|
8554
|
+
event.currentTarget.click();
|
|
8555
|
+
}
|
|
8111
8556
|
function isDockVisualMutationActive(element) {
|
|
8112
8557
|
if (!element) {
|
|
8113
8558
|
return false;
|
|
@@ -8997,7 +9442,8 @@ function WorkbenchHostDock({
|
|
|
8997
9442
|
host,
|
|
8998
9443
|
isFocused: context.focusedNodeId === node.id,
|
|
8999
9444
|
isMinimized: node.isMinimized,
|
|
9000
|
-
node
|
|
9445
|
+
node,
|
|
9446
|
+
previewViewport: minimizedDockPreviewViewport
|
|
9001
9447
|
});
|
|
9002
9448
|
},
|
|
9003
9449
|
[
|
|
@@ -9121,7 +9567,7 @@ function WorkbenchHostDock({
|
|
|
9121
9567
|
instanceMode: dockContextMenuInstanceMode,
|
|
9122
9568
|
matchedNodes: popupEntry.matchedNodes
|
|
9123
9569
|
}).kind === "launch";
|
|
9124
|
-
return /* @__PURE__ */
|
|
9570
|
+
return /* @__PURE__ */ jsxs7(
|
|
9125
9571
|
"div",
|
|
9126
9572
|
{
|
|
9127
9573
|
className: "flex justify-center pointer-events-none",
|
|
@@ -9134,7 +9580,7 @@ function WorkbenchHostDock({
|
|
|
9134
9580
|
style: dockFrameSize === null ? void 0 : {
|
|
9135
9581
|
"--desktop-dock-frame-size": `${dockFrameSize}px`
|
|
9136
9582
|
},
|
|
9137
|
-
children: /* @__PURE__ */
|
|
9583
|
+
children: /* @__PURE__ */ jsxs7(
|
|
9138
9584
|
"div",
|
|
9139
9585
|
{
|
|
9140
9586
|
ref: dockMeasureRef,
|
|
@@ -9369,7 +9815,7 @@ function WorkbenchHostDock({
|
|
|
9369
9815
|
entryId: entry.id
|
|
9370
9816
|
});
|
|
9371
9817
|
},
|
|
9372
|
-
children: /* @__PURE__ */
|
|
9818
|
+
children: /* @__PURE__ */ jsxs7(
|
|
9373
9819
|
"span",
|
|
9374
9820
|
{
|
|
9375
9821
|
className: "desktop-dock__icon-shell",
|
|
@@ -9489,14 +9935,16 @@ function WorkbenchHostDock({
|
|
|
9489
9935
|
stackLabel
|
|
9490
9936
|
);
|
|
9491
9937
|
const stackButton = /* @__PURE__ */ jsx10(
|
|
9492
|
-
"
|
|
9938
|
+
"span",
|
|
9493
9939
|
{
|
|
9494
9940
|
"aria-expanded": stackPopupActive,
|
|
9495
9941
|
"aria-haspopup": "dialog",
|
|
9496
9942
|
"aria-label": stackLabel,
|
|
9497
9943
|
className: "desktop-dock__btn desktop-dock__minimized-btn",
|
|
9498
9944
|
"data-interactive": "true",
|
|
9499
|
-
|
|
9945
|
+
role: "button",
|
|
9946
|
+
tabIndex: 0,
|
|
9947
|
+
onKeyDown: activateDockButtonFromKeyboard,
|
|
9500
9948
|
onPointerDown: (event) => {
|
|
9501
9949
|
if (event.button !== 0) {
|
|
9502
9950
|
return;
|
|
@@ -9520,7 +9968,7 @@ function WorkbenchHostDock({
|
|
|
9520
9968
|
}
|
|
9521
9969
|
);
|
|
9522
9970
|
},
|
|
9523
|
-
children: /* @__PURE__ */
|
|
9971
|
+
children: /* @__PURE__ */ jsxs7(
|
|
9524
9972
|
"span",
|
|
9525
9973
|
{
|
|
9526
9974
|
className: "desktop-dock__minimized-stack-icon",
|
|
@@ -9621,13 +10069,18 @@ function WorkbenchHostDock({
|
|
|
9621
10069
|
node.title
|
|
9622
10070
|
);
|
|
9623
10071
|
const dockButton = /* @__PURE__ */ jsx10(
|
|
9624
|
-
"
|
|
10072
|
+
"span",
|
|
9625
10073
|
{
|
|
9626
10074
|
"aria-label": i18n.t("launch", { title: node.title }),
|
|
10075
|
+
"aria-disabled": isPendingMinimizedNode ? true : void 0,
|
|
9627
10076
|
className: "desktop-dock__btn desktop-dock__minimized-btn",
|
|
9628
|
-
"data-interactive": "true",
|
|
9629
|
-
|
|
9630
|
-
|
|
10077
|
+
"data-interactive": isPendingMinimizedNode ? "false" : "true",
|
|
10078
|
+
role: "button",
|
|
10079
|
+
tabIndex: isPendingMinimizedNode ? -1 : 0,
|
|
10080
|
+
onKeyDown: (event) => activateDockButtonFromKeyboard(
|
|
10081
|
+
event,
|
|
10082
|
+
isPendingMinimizedNode
|
|
10083
|
+
),
|
|
9631
10084
|
onPointerDown: (event) => {
|
|
9632
10085
|
if (event.button !== 0 || isPendingMinimizedNode) {
|
|
9633
10086
|
return;
|
|
@@ -10228,7 +10681,7 @@ function WorkbenchHostDockMinimizedNodePreview({
|
|
|
10228
10681
|
return renderMinimizedDockPreviewPlaceholder(className);
|
|
10229
10682
|
}
|
|
10230
10683
|
function renderMinimizedDockPreviewPlaceholder(className) {
|
|
10231
|
-
return /* @__PURE__ */
|
|
10684
|
+
return /* @__PURE__ */ jsxs7(
|
|
10232
10685
|
"span",
|
|
10233
10686
|
{
|
|
10234
10687
|
className: ["desktop-dock__minimized-preview", className].filter(Boolean).join(" "),
|
|
@@ -10412,7 +10865,7 @@ function WorkbenchHostDockHoverPanel({
|
|
|
10412
10865
|
if (!entry) {
|
|
10413
10866
|
return null;
|
|
10414
10867
|
}
|
|
10415
|
-
return /* @__PURE__ */
|
|
10868
|
+
return /* @__PURE__ */ jsxs7(
|
|
10416
10869
|
"div",
|
|
10417
10870
|
{
|
|
10418
10871
|
ref: hoverPanelRef,
|
|
@@ -10593,6 +11046,77 @@ function resolveNextDockItemPresence(item, initialized, previousPresence, should
|
|
|
10593
11046
|
}
|
|
10594
11047
|
return previousPresence ?? "entering";
|
|
10595
11048
|
}
|
|
11049
|
+
function resolveDockPresenceItems(input) {
|
|
11050
|
+
const currentByKey = new Map(input.current.map((item) => [item.key, item]));
|
|
11051
|
+
const currentIndexByKey = new Map(
|
|
11052
|
+
input.current.map((item, index) => [item.key, index])
|
|
11053
|
+
);
|
|
11054
|
+
const nextByKey = new Map(
|
|
11055
|
+
input.nextSourceItems.map((item) => [item.key, item])
|
|
11056
|
+
);
|
|
11057
|
+
const nextKeys = new Set(input.nextSourceItems.map((item) => item.key));
|
|
11058
|
+
const currentVisibleItemCount = input.current.filter(
|
|
11059
|
+
(item) => item.presence !== "exiting"
|
|
11060
|
+
).length;
|
|
11061
|
+
const shouldRetainExitingItems = input.nextSourceItems.length < currentVisibleItemCount;
|
|
11062
|
+
const emittedKeys = /* @__PURE__ */ new Set();
|
|
11063
|
+
const nextItems = [];
|
|
11064
|
+
let currentIndex = 0;
|
|
11065
|
+
const emitExitingUntil = (nextCurrentIndex) => {
|
|
11066
|
+
while (currentIndex < nextCurrentIndex) {
|
|
11067
|
+
const currentItem = input.current[currentIndex];
|
|
11068
|
+
currentIndex += 1;
|
|
11069
|
+
if (shouldRetainExitingItems && currentItem && !nextKeys.has(currentItem.key) && !emittedKeys.has(currentItem.key)) {
|
|
11070
|
+
emittedKeys.add(currentItem.key);
|
|
11071
|
+
nextItems.push({
|
|
11072
|
+
...currentItem,
|
|
11073
|
+
presence: "exiting"
|
|
11074
|
+
});
|
|
11075
|
+
}
|
|
11076
|
+
}
|
|
11077
|
+
};
|
|
11078
|
+
for (const item of input.nextSourceItems) {
|
|
11079
|
+
const previousIndex = currentIndexByKey.get(item.key);
|
|
11080
|
+
if (previousIndex !== void 0) {
|
|
11081
|
+
emitExitingUntil(previousIndex);
|
|
11082
|
+
currentIndex = Math.max(currentIndex, previousIndex + 1);
|
|
11083
|
+
}
|
|
11084
|
+
emittedKeys.add(item.key);
|
|
11085
|
+
nextItems.push({
|
|
11086
|
+
item,
|
|
11087
|
+
key: item.key,
|
|
11088
|
+
presence: resolveNextDockItemPresence(
|
|
11089
|
+
item,
|
|
11090
|
+
input.initialized,
|
|
11091
|
+
currentByKey.get(item.key)?.presence,
|
|
11092
|
+
input.shouldAnimateMinimizedDockEnter
|
|
11093
|
+
)
|
|
11094
|
+
});
|
|
11095
|
+
}
|
|
11096
|
+
for (const currentItem of input.current) {
|
|
11097
|
+
if (shouldRetainExitingItems && !nextKeys.has(currentItem.key)) {
|
|
11098
|
+
if (emittedKeys.has(currentItem.key)) {
|
|
11099
|
+
continue;
|
|
11100
|
+
}
|
|
11101
|
+
emittedKeys.add(currentItem.key);
|
|
11102
|
+
nextItems.push({
|
|
11103
|
+
...currentItem,
|
|
11104
|
+
presence: "exiting"
|
|
11105
|
+
});
|
|
11106
|
+
}
|
|
11107
|
+
}
|
|
11108
|
+
return nextItems.filter(
|
|
11109
|
+
(item) => nextByKey.has(item.key) || item.presence === "exiting"
|
|
11110
|
+
);
|
|
11111
|
+
}
|
|
11112
|
+
function resolveDockPresenceSettleMs(items) {
|
|
11113
|
+
if (items.some(
|
|
11114
|
+
(item) => item.item.kind === "minimized" && (item.presence === "entering" || item.presence === "exiting")
|
|
11115
|
+
)) {
|
|
11116
|
+
return minimizedDockSlotLayoutAnimationMs;
|
|
11117
|
+
}
|
|
11118
|
+
return dockPresenceAnimationMs;
|
|
11119
|
+
}
|
|
10596
11120
|
function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
|
|
10597
11121
|
const latestItemsByKey = useRef8(/* @__PURE__ */ new Map());
|
|
10598
11122
|
const shouldAnimateMinimizedDockEnterRef = useRef8(
|
|
@@ -10612,73 +11136,13 @@ function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
|
|
|
10612
11136
|
useEffect9(() => {
|
|
10613
11137
|
let nextSettleMs = dockPresenceAnimationMs;
|
|
10614
11138
|
setPresentItems((current) => {
|
|
10615
|
-
const
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
current.
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
);
|
|
10623
|
-
const nextKeys = new Set(nextSourceItems.map((item) => item.key));
|
|
10624
|
-
const currentVisibleItemCount = current.filter(
|
|
10625
|
-
(item) => item.presence !== "exiting"
|
|
10626
|
-
).length;
|
|
10627
|
-
const shouldRetainExitingItems = nextSourceItems.length < currentVisibleItemCount;
|
|
10628
|
-
const emittedKeys = /* @__PURE__ */ new Set();
|
|
10629
|
-
const nextItems = [];
|
|
10630
|
-
let currentIndex = 0;
|
|
10631
|
-
const emitExitingUntil = (nextCurrentIndex) => {
|
|
10632
|
-
while (currentIndex < nextCurrentIndex) {
|
|
10633
|
-
const currentItem = current[currentIndex];
|
|
10634
|
-
currentIndex += 1;
|
|
10635
|
-
if (shouldRetainExitingItems && currentItem && !nextKeys.has(currentItem.key) && !emittedKeys.has(currentItem.key)) {
|
|
10636
|
-
emittedKeys.add(currentItem.key);
|
|
10637
|
-
nextItems.push({
|
|
10638
|
-
...currentItem,
|
|
10639
|
-
presence: "exiting"
|
|
10640
|
-
});
|
|
10641
|
-
}
|
|
10642
|
-
}
|
|
10643
|
-
};
|
|
10644
|
-
for (const item of nextSourceItems) {
|
|
10645
|
-
const previousIndex = currentIndexByKey.get(item.key);
|
|
10646
|
-
if (previousIndex !== void 0) {
|
|
10647
|
-
emitExitingUntil(previousIndex);
|
|
10648
|
-
currentIndex = Math.max(currentIndex, previousIndex + 1);
|
|
10649
|
-
}
|
|
10650
|
-
emittedKeys.add(item.key);
|
|
10651
|
-
nextItems.push({
|
|
10652
|
-
item,
|
|
10653
|
-
key: item.key,
|
|
10654
|
-
presence: resolveNextDockItemPresence(
|
|
10655
|
-
item,
|
|
10656
|
-
initialized.current,
|
|
10657
|
-
currentByKey.get(item.key)?.presence,
|
|
10658
|
-
shouldAnimateMinimizedDockEnterRef.current
|
|
10659
|
-
)
|
|
10660
|
-
});
|
|
10661
|
-
}
|
|
10662
|
-
for (const currentItem of current) {
|
|
10663
|
-
if (shouldRetainExitingItems && !nextKeys.has(currentItem.key)) {
|
|
10664
|
-
if (emittedKeys.has(currentItem.key)) {
|
|
10665
|
-
continue;
|
|
10666
|
-
}
|
|
10667
|
-
emittedKeys.add(currentItem.key);
|
|
10668
|
-
nextItems.push({
|
|
10669
|
-
...currentItem,
|
|
10670
|
-
presence: "exiting"
|
|
10671
|
-
});
|
|
10672
|
-
}
|
|
10673
|
-
}
|
|
10674
|
-
const filteredItems = nextItems.filter(
|
|
10675
|
-
(item) => nextByKey.has(item.key) || item.presence === "exiting"
|
|
10676
|
-
);
|
|
10677
|
-
if (filteredItems.some(
|
|
10678
|
-
(item) => item.item.kind === "minimized" && (item.presence === "entering" || item.presence === "exiting")
|
|
10679
|
-
)) {
|
|
10680
|
-
nextSettleMs = minimizedDockSlotLayoutAnimationMs;
|
|
10681
|
-
}
|
|
11139
|
+
const filteredItems = resolveDockPresenceItems({
|
|
11140
|
+
current,
|
|
11141
|
+
initialized: initialized.current,
|
|
11142
|
+
nextSourceItems: [...latestItemsByKey.current.values()],
|
|
11143
|
+
shouldAnimateMinimizedDockEnter: shouldAnimateMinimizedDockEnterRef.current
|
|
11144
|
+
});
|
|
11145
|
+
nextSettleMs = resolveDockPresenceSettleMs(filteredItems);
|
|
10682
11146
|
return filteredItems;
|
|
10683
11147
|
});
|
|
10684
11148
|
initialized.current = true;
|
|
@@ -10691,7 +11155,13 @@ function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
|
|
|
10691
11155
|
}, nextSettleMs);
|
|
10692
11156
|
return () => globalThis.clearTimeout(timeout);
|
|
10693
11157
|
}, [itemKeys]);
|
|
10694
|
-
|
|
11158
|
+
const renderedPresentItems = resolveDockPresenceItems({
|
|
11159
|
+
current: presentItems,
|
|
11160
|
+
initialized: initialized.current,
|
|
11161
|
+
nextSourceItems: [...latestItemsByKey.current.values()],
|
|
11162
|
+
shouldAnimateMinimizedDockEnter
|
|
11163
|
+
});
|
|
11164
|
+
return renderedPresentItems.map((presentItem) => {
|
|
10695
11165
|
const latestItem = latestItemsByKey.current.get(presentItem.key);
|
|
10696
11166
|
return latestItem ? { ...presentItem, item: latestItem } : presentItem;
|
|
10697
11167
|
});
|
|
@@ -11139,7 +11609,7 @@ function createWorkbenchHostNodeHeaderContext({
|
|
|
11139
11609
|
|
|
11140
11610
|
// src/host/WorkbenchHostWindowActions.tsx
|
|
11141
11611
|
import { Button as Button5, CloseIcon as CloseIcon2, MinimizeIcon as MinimizeIcon2 } from "@tutti-os/ui-system";
|
|
11142
|
-
import { Fragment as
|
|
11612
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
11143
11613
|
function WorkbenchHostWindowActions({
|
|
11144
11614
|
context,
|
|
11145
11615
|
host,
|
|
@@ -11152,7 +11622,7 @@ function WorkbenchHostWindowActions({
|
|
|
11152
11622
|
}
|
|
11153
11623
|
const minimizable = definition.window?.minimizable !== false;
|
|
11154
11624
|
const closable = definition.window?.closable !== false;
|
|
11155
|
-
return /* @__PURE__ */
|
|
11625
|
+
return /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
11156
11626
|
minimizable ? /* @__PURE__ */ jsx11(
|
|
11157
11627
|
Button5,
|
|
11158
11628
|
{
|
|
@@ -11190,7 +11660,7 @@ function WorkbenchHostWindowActions({
|
|
|
11190
11660
|
}
|
|
11191
11661
|
|
|
11192
11662
|
// src/host/useWorkbenchHostSurfaceRenderers.tsx
|
|
11193
|
-
import { jsx as jsx12, jsxs as
|
|
11663
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
11194
11664
|
function useWorkbenchHostSurfaceRenderers(input) {
|
|
11195
11665
|
const renderBottomChrome = useMemo6(() => {
|
|
11196
11666
|
const renderChrome = input.renderBottomChrome;
|
|
@@ -11426,6 +11896,40 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
11426
11896
|
},
|
|
11427
11897
|
[input.nodeDefinitionByType]
|
|
11428
11898
|
);
|
|
11899
|
+
const renderNodeGeniePreview = useCallback11(
|
|
11900
|
+
(node, {
|
|
11901
|
+
previewViewport
|
|
11902
|
+
}) => {
|
|
11903
|
+
const minimizedDock = input.nodeDefinitionByType.get(node.data.typeId)?.window?.minimizedDock;
|
|
11904
|
+
if (minimizedDock?.kind !== "component") {
|
|
11905
|
+
return null;
|
|
11906
|
+
}
|
|
11907
|
+
const externalState = readWorkbenchHostExternalState({
|
|
11908
|
+
externalStateSource: input.externalStateSource,
|
|
11909
|
+
node,
|
|
11910
|
+
workspaceId: input.workspaceId
|
|
11911
|
+
});
|
|
11912
|
+
const preview = minimizedDock.providePreview({
|
|
11913
|
+
externalNodeState: externalState.externalNodeState,
|
|
11914
|
+
externalWorkspaceState: externalState.externalWorkspaceState,
|
|
11915
|
+
host: input.hostSession,
|
|
11916
|
+
isFocused: input.hostSession.getSnapshot().nodeStack.at(-1) === node.id,
|
|
11917
|
+
isMinimized: node.isMinimized,
|
|
11918
|
+
node,
|
|
11919
|
+
previewViewport
|
|
11920
|
+
});
|
|
11921
|
+
return preview ? renderMinimizedDockPreviewContent(
|
|
11922
|
+
preview,
|
|
11923
|
+
"workbench-genie-preview-capture__preview"
|
|
11924
|
+
) : null;
|
|
11925
|
+
},
|
|
11926
|
+
[
|
|
11927
|
+
input.externalStateSource,
|
|
11928
|
+
input.hostSession,
|
|
11929
|
+
input.nodeDefinitionByType,
|
|
11930
|
+
input.workspaceId
|
|
11931
|
+
]
|
|
11932
|
+
);
|
|
11429
11933
|
const resolveDockAnchorKey = useCallback11(
|
|
11430
11934
|
(node) => {
|
|
11431
11935
|
if (node.isMinimized && isWorkbenchMinimizedDockEligibleNode({
|
|
@@ -11482,6 +11986,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
11482
11986
|
renderBottomChrome,
|
|
11483
11987
|
renderDock,
|
|
11484
11988
|
renderNode,
|
|
11989
|
+
renderNodeGeniePreview,
|
|
11485
11990
|
renderTopChrome,
|
|
11486
11991
|
renderWindowActions,
|
|
11487
11992
|
renderWindowHeader,
|
|
@@ -11578,7 +12083,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
|
|
|
11578
12083
|
}
|
|
11579
12084
|
render() {
|
|
11580
12085
|
if (this.state.hasError) {
|
|
11581
|
-
return /* @__PURE__ */
|
|
12086
|
+
return /* @__PURE__ */ jsxs9(
|
|
11582
12087
|
"div",
|
|
11583
12088
|
{
|
|
11584
12089
|
"data-workbench-node-render-error": "true",
|
|
@@ -11767,6 +12272,7 @@ function WorkbenchHost({
|
|
|
11767
12272
|
className,
|
|
11768
12273
|
captureNodePreviewImage: surfaceRenderers.captureNodePreviewImage,
|
|
11769
12274
|
controller: hostSession.controller,
|
|
12275
|
+
debugDiagnostics,
|
|
11770
12276
|
dockPreviewCache,
|
|
11771
12277
|
dockPlacement,
|
|
11772
12278
|
interactive: !isHydrating,
|
|
@@ -11784,6 +12290,7 @@ function WorkbenchHost({
|
|
|
11784
12290
|
renderBottomChrome: surfaceRenderers.renderBottomChrome,
|
|
11785
12291
|
renderDock: surfaceRenderers.renderDock,
|
|
11786
12292
|
renderNode: surfaceRenderers.renderNode,
|
|
12293
|
+
renderNodeGeniePreview: surfaceRenderers.renderNodeGeniePreview,
|
|
11787
12294
|
renderOverlay: missionControlRenderedState ? () => /* @__PURE__ */ jsx13(
|
|
11788
12295
|
WorkbenchMissionControlOverlay,
|
|
11789
12296
|
{
|