Skip to content

Commit 1015359

Browse files
committed
visual fix
1 parent beb0d26 commit 1015359

File tree

8 files changed

+195
-9
lines changed

8 files changed

+195
-9
lines changed

packages/react-grab/src/components/overlay-canvas.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
OPACITY_CONVERGENCE_THRESHOLD,
2020
OVERLAY_BORDER_COLOR_DEFAULT,
2121
OVERLAY_FILL_COLOR_DEFAULT,
22+
OVERLAY_BORDER_COLOR_INSPECT,
23+
OVERLAY_FILL_COLOR_INSPECT,
2224
} from "../constants.js";
2325
import {
2426
nativeCancelAnimationFrame,
@@ -32,6 +34,12 @@ const DEFAULT_LAYER_STYLE = {
3234
lerpFactor: SELECTION_LERP_FACTOR,
3335
} as const;
3436

37+
const INSPECT_LAYER_STYLE = {
38+
borderColor: OVERLAY_BORDER_COLOR_INSPECT,
39+
fillColor: OVERLAY_FILL_COLOR_INSPECT,
40+
lerpFactor: SELECTION_LERP_FACTOR,
41+
} as const;
42+
3543
const LAYER_STYLES = {
3644
drag: {
3745
borderColor: OVERLAY_BORDER_COLOR_DRAG,
@@ -41,9 +49,10 @@ const LAYER_STYLES = {
4149
selection: DEFAULT_LAYER_STYLE,
4250
grabbed: DEFAULT_LAYER_STYLE,
4351
processing: DEFAULT_LAYER_STYLE,
52+
inspect: INSPECT_LAYER_STYLE,
4453
} as const;
4554

46-
type LayerName = "drag" | "selection" | "grabbed" | "processing";
55+
type LayerName = "drag" | "selection" | "grabbed" | "processing" | "inspect";
4756

4857
interface OffscreenLayer {
4958
canvas: OffscreenCanvas | null;
@@ -68,6 +77,9 @@ export interface OverlayCanvasProps {
6877
selectionIsFading?: boolean;
6978
selectionShouldSnap?: boolean;
7079

80+
inspectVisible?: boolean;
81+
inspectBounds?: OverlayBounds[];
82+
7183
dragVisible?: boolean;
7284
dragBounds?: OverlayBounds;
7385

@@ -95,12 +107,14 @@ export const OverlayCanvas: Component<OverlayCanvasProps> = (props) => {
95107
selection: { canvas: null, context: null },
96108
grabbed: { canvas: null, context: null },
97109
processing: { canvas: null, context: null },
110+
inspect: { canvas: null, context: null },
98111
};
99112

100113
let selectionAnimations: AnimatedBounds[] = [];
101114
let dragAnimation: AnimatedBounds | null = null;
102115
let grabbedAnimations: AnimatedBounds[] = [];
103116
let processingAnimations: AnimatedBounds[] = [];
117+
let inspectAnimations: AnimatedBounds[] = [];
104118

105119
const canvasColorSpace: PredefinedColorSpace = supportsDisplayP3()
106120
? "display-p3"
@@ -327,8 +341,10 @@ export const OverlayCanvas: Component<OverlayCanvasProps> = (props) => {
327341
renderSelectionLayer();
328342
renderBoundsLayer("grabbed", grabbedAnimations);
329343
renderBoundsLayer("processing", processingAnimations);
344+
renderBoundsLayer("inspect", inspectAnimations);
330345

331346
const layerRenderOrder: LayerName[] = [
347+
"inspect",
332348
"drag",
333349
"selection",
334350
"grabbed",
@@ -466,6 +482,14 @@ export const OverlayCanvas: Component<OverlayCanvasProps> = (props) => {
466482
}
467483
}
468484

485+
for (const animation of inspectAnimations) {
486+
if (animation.isInitialized) {
487+
if (interpolateBounds(animation, LAYER_STYLES.inspect.lerpFactor)) {
488+
shouldContinueAnimating = true;
489+
}
490+
}
491+
}
492+
469493
compositeAllLayers();
470494

471495
if (shouldContinueAnimating) {
@@ -667,6 +691,35 @@ export const OverlayCanvas: Component<OverlayCanvasProps> = (props) => {
667691
),
668692
);
669693

694+
createEffect(
695+
on(
696+
() => [props.inspectVisible, props.inspectBounds] as const,
697+
([isVisible, bounds]) => {
698+
if (!isVisible || !bounds || bounds.length === 0) {
699+
inspectAnimations = [];
700+
scheduleAnimationFrame();
701+
return;
702+
}
703+
704+
inspectAnimations = bounds.map((ancestorBounds, index) => {
705+
const animationId = `inspect-${index}`;
706+
const existingAnimation = inspectAnimations.find(
707+
(animation) => animation.id === animationId,
708+
);
709+
710+
if (existingAnimation) {
711+
updateAnimationTarget(existingAnimation, ancestorBounds);
712+
return existingAnimation;
713+
}
714+
715+
return createAnimatedBounds(animationId, ancestorBounds);
716+
});
717+
718+
scheduleAnimationFrame();
719+
},
720+
),
721+
);
722+
670723
onMount(() => {
671724
initializeCanvas();
672725
scheduleAnimationFrame();

packages/react-grab/src/components/renderer.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export const ReactGrabRenderer: Component<ReactGrabRendererProps> = (props) => {
4141
selectionBoundsMultiple={props.selectionBoundsMultiple}
4242
selectionShouldSnap={props.selectionShouldSnap}
4343
selectionIsFading={props.selectionLabelStatus === "fading"}
44+
inspectVisible={props.inspectVisible}
45+
inspectBounds={props.inspectBounds}
4446
dragVisible={props.dragVisible}
4547
dragBounds={props.dragBounds}
4648
grabbedBoxes={props.grabbedBoxes}
@@ -136,6 +138,8 @@ export const ReactGrabRenderer: Component<ReactGrabRendererProps> = (props) => {
136138
actionCycleState={props.selectionActionCycleState}
137139
arrowNavigationState={props.selectionArrowNavigationState}
138140
onArrowNavigationSelect={props.onArrowNavigationSelect}
141+
inspectNavigationState={props.inspectNavigationState}
142+
onInspectSelect={props.onInspectSelect}
139143
filePath={props.selectionFilePath}
140144
onInputChange={props.onInputChange}
141145
onSubmit={props.onInputSubmit}

packages/react-grab/src/components/selection-label/index.tsx

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export const SelectionLabel: Component<SelectionLabelProps> = (props) => {
9595
return true;
9696
}
9797
if (props.arrowNavigationState?.isVisible) return true;
98+
if (props.inspectNavigationState?.isVisible) return true;
9899
return false;
99100
};
100101

@@ -354,6 +355,9 @@ export const SelectionLabel: Component<SelectionLabelProps> = (props) => {
354355
const isArrowNavigationVisible = () =>
355356
Boolean(props.arrowNavigationState?.isVisible);
356357

358+
const isInspectNavigationVisible = () =>
359+
Boolean(props.inspectNavigationState?.isVisible);
360+
357361
const handleTagClick = (event: MouseEvent) => {
358362
event.stopImmediatePropagation();
359363
if (props.filePath && props.onOpen) {
@@ -504,13 +508,19 @@ export const SelectionLabel: Component<SelectionLabelProps> = (props) => {
504508
<Show when={canInteract() && !props.isPromptMode}>
505509
<div
506510
class="contain-layout shrink-0 flex flex-col items-start w-fit h-fit"
507-
classList={{ "min-w-[100px]": isArrowNavigationVisible() }}
511+
classList={{
512+
"min-w-[100px]":
513+
isArrowNavigationVisible() || isInspectNavigationVisible(),
514+
}}
508515
>
509516
<div
510517
class="contain-layout shrink-0 flex items-center gap-1 w-fit h-fit px-2"
511518
classList={{
512-
"py-1.5": !isArrowNavigationVisible(),
513-
"pt-1.5 pb-1": isArrowNavigationVisible(),
519+
"py-1.5":
520+
!isArrowNavigationVisible() &&
521+
!isInspectNavigationVisible(),
522+
"pt-1.5 pb-1":
523+
isArrowNavigationVisible() || isInspectNavigationVisible(),
514524
}}
515525
>
516526
<TagBadge
@@ -521,7 +531,7 @@ export const SelectionLabel: Component<SelectionLabelProps> = (props) => {
521531
onHoverChange={handleTagHoverChange}
522532
shrink
523533
forceShowIcon={
524-
isArrowNavigationVisible()
534+
isArrowNavigationVisible() || isInspectNavigationVisible()
525535
? Boolean(props.filePath && props.onOpen)
526536
: Boolean(props.isContextMenuOpen)
527537
}
@@ -537,6 +547,22 @@ export const SelectionLabel: Component<SelectionLabelProps> = (props) => {
537547
<Show
538548
when={
539549
!isArrowNavigationVisible() &&
550+
isInspectNavigationVisible() &&
551+
props.inspectNavigationState
552+
}
553+
>
554+
{(state) => (
555+
<ArrowNavigationMenu
556+
items={state().items}
557+
activeIndex={state().activeIndex}
558+
onSelect={(index) => props.onInspectSelect?.(index)}
559+
/>
560+
)}
561+
</Show>
562+
<Show
563+
when={
564+
!isArrowNavigationVisible() &&
565+
!isInspectNavigationVisible() &&
540566
Boolean(props.actionCycleState?.isVisible)
541567
}
542568
>

packages/react-grab/src/components/toolbar/index.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
TOOLBAR_DEFAULT_HEIGHT_PX,
3535
TOOLBAR_DEFAULT_POSITION_RATIO,
3636
TOOLBAR_SHAKE_TOOLTIP_DURATION_MS,
37+
TOOLBAR_HINT_CENTER_OFFSET_PX,
3738
FEEDBACK_DURATION_MS,
3839
HINT_FLIP_IN_ANIMATION,
3940
SAFE_POLYGON_BUFFER_PX,
@@ -271,11 +272,18 @@ export const Toolbar: Component<ToolbarProps> = (props) => {
271272
if (isVertical()) {
272273
const placementClass =
273274
tooltipSide === "left" ? "right-full mr-0.5" : "left-full ml-0.5";
274-
return `top-1/2 -translate-y-1/2 ${placementClass}`;
275+
return `top-1/2 ${placementClass}`;
275276
}
276277
const placementClass =
277278
tooltipSide === "top" ? "bottom-full mb-0.5" : "top-full mt-0.5";
278-
return `left-1/2 -translate-x-1/2 ${placementClass}`;
279+
return `left-1/2 ${placementClass}`;
280+
};
281+
282+
const hintTranslateStyle = (): string => {
283+
if (isVertical()) {
284+
return `0 calc(-50% - ${TOOLBAR_HINT_CENTER_OFFSET_PX}px)`;
285+
}
286+
return `calc(-50% - ${TOOLBAR_HINT_CENTER_OFFSET_PX}px) 0`;
279287
};
280288

281289
const stopEventPropagation = (event: Event) => {
@@ -1277,7 +1285,10 @@ export const Toolbar: Component<ToolbarProps> = (props) => {
12771285
"bg-white",
12781286
shakeTooltipPositionClass(),
12791287
)}
1280-
style={{ "z-index": String(Z_INDEX_HOST) }}
1288+
style={{
1289+
"z-index": String(Z_INDEX_HOST),
1290+
translate: hintTranslateStyle(),
1291+
}}
12811292
>
12821293
<Show when={selectionHintIndex() === 0}>
12831294
<span
@@ -1323,7 +1334,10 @@ export const Toolbar: Component<ToolbarProps> = (props) => {
13231334
"bg-white",
13241335
shakeTooltipPositionClass(),
13251336
)}
1326-
style={{ "z-index": String(Z_INDEX_HOST) }}
1337+
style={{
1338+
"z-index": String(Z_INDEX_HOST),
1339+
translate: hintTranslateStyle(),
1340+
}}
13271341
>
13281342
Enable to continue
13291343
</div>

packages/react-grab/src/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export const OVERLAY_BORDER_COLOR_DRAG = overlayColor(0.4);
5151
export const OVERLAY_FILL_COLOR_DRAG = overlayColor(0.05);
5252
export const OVERLAY_BORDER_COLOR_DEFAULT = overlayColor(0.5);
5353
export const OVERLAY_FILL_COLOR_DEFAULT = overlayColor(0.08);
54+
export const OVERLAY_BORDER_COLOR_INSPECT = overlayColor(0.3);
55+
export const OVERLAY_FILL_COLOR_INSPECT = overlayColor(0.04);
5456
export const FROZEN_GLOW_COLOR = overlayColor(0.15);
5557
export const FROZEN_GLOW_EDGE_PX = 50;
5658

@@ -112,6 +114,7 @@ export const TOOLBAR_DEFAULT_HEIGHT_PX = 28;
112114
export const TOOLBAR_DEFAULT_POSITION_RATIO = 0.5;
113115
export const DEFAULT_ACTION_ID = "comment";
114116
export const TOOLBAR_SHAKE_TOOLTIP_DURATION_MS = 1500;
117+
export const TOOLBAR_HINT_CENTER_OFFSET_PX = 10;
115118
export const SELECTION_HINT_CYCLE_INTERVAL_MS = 3000;
116119
export const SELECTION_HINT_COUNT = 3;
117120

0 commit comments

Comments
 (0)