Skip to content

Commit 5ea9d9f

Browse files
add isolation mode
1 parent 74d0cb5 commit 5ea9d9f

10 files changed

Lines changed: 384 additions & 106 deletions

File tree

editor-packages/editor-canvas/canvas/canvas.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
import { transform_by_zoom_delta, get_hovering_target } from "../math";
1818
import { utils } from "@design-sdk/core";
1919
import { LazyFrame } from "@code-editor/canvas/lazy-frame";
20-
import { HudSurface } from "./hud-surface";
20+
import { HudCustomRenderers, HudSurface } from "./hud-surface";
2121
import type { XY, XYWH } from "../types";
2222

2323
const designq = utils.query;
@@ -39,6 +39,10 @@ interface CanvasState {
3939
readonly?: boolean;
4040
}
4141

42+
type CanvasCustomRenderers = HudCustomRenderers & {
43+
renderItem: (node: ReflectSceneNode) => React.ReactNode;
44+
};
45+
4246
interface CanvsPreferences {
4347
can_highlight_selected_layer?: boolean;
4448
}
@@ -61,11 +65,12 @@ export function Canvas({
6165
selectedNodes,
6266
readonly = true,
6367
config = default_canvas_preferences,
68+
...props
6469
}: {
65-
renderItem: (node: ReflectSceneNode) => React.ReactNode;
6670
onSelectNode?: (node: ReflectSceneNode) => void;
6771
onClearSelection?: () => void;
68-
} & CanvasState & {
72+
} & CanvasCustomRenderers &
73+
CanvasState & {
6974
config?: CanvsPreferences;
7075
}) {
7176
const [zoom, setZoom] = useState(INITIAL_SCALE);
@@ -189,6 +194,7 @@ export function Canvas({
189194
{nodes?.map((node) => {
190195
return (
191196
<LazyFrame
197+
key={node.id}
192198
xy={[node.x, node.y]}
193199
size={node}
194200
zoom={zoom}
@@ -224,6 +230,7 @@ export function Canvas({
224230
onSelectNode={(id) => {
225231
onSelectNode(node(id));
226232
}}
233+
renderFrameTitle={props.renderFrameTitle}
227234
/>
228235
</>
229236
);

editor-packages/editor-canvas/canvas/hud-surface.tsx

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { HoverOutlineHighlight, ReadonlySelectHightlight } from "../overlay";
2-
import { FrameTitle } from "../frame-title";
2+
import { FrameTitle, FrameTitleProps } from "../frame-title";
33
import type { XY, XYWH } from "../types";
44

55
interface HudControls {
66
onSelectNode: (node: string) => void;
77
onHoverNode: (node: string) => void;
88
}
99

10+
export interface HudCustomRenderers {
11+
renderFrameTitle?: (props: FrameTitleProps) => React.ReactNode;
12+
}
13+
1014
/**
1115
* minimum meta of displaying nodes for hud surface
1216
*/
@@ -29,6 +33,8 @@ export function HudSurface({
2933
readonly,
3034
onSelectNode,
3135
onHoverNode,
36+
//
37+
renderFrameTitle = frame_title_default_renderer,
3238
}: {
3339
offset: XY;
3440
zoom: number;
@@ -37,7 +43,8 @@ export function HudSurface({
3743
selectedNodes: DisplayNodeMeta[];
3844
hide: boolean;
3945
readonly: boolean;
40-
} & HudControls) {
46+
} & HudControls &
47+
HudCustomRenderers) {
4148
const [ox, oy] = offset;
4249
return (
4350
<div
@@ -58,31 +65,27 @@ export function HudSurface({
5865
{labelDisplayNodes &&
5966
labelDisplayNodes.map((node) => {
6067
const absxy: XY = [node.absoluteX * zoom, node.absoluteY * zoom];
61-
return (
62-
<FrameTitle
63-
key={node.id}
64-
name={node.name}
65-
xy={absxy}
66-
wh={[node.width, node.height]}
67-
zoom={zoom}
68-
selected={selectedNodes.some(
69-
(selectedNode) => selectedNode.id === node.id
70-
)}
71-
onSelect={() => onSelectNode(node.id)}
72-
onHoverChange={(hv) => {
73-
if (hv) {
74-
onHoverNode(node.id);
75-
} else {
76-
onHoverNode(null);
77-
}
78-
}}
79-
highlight={
80-
!![...highlights, ...selectedNodes].find(
81-
(n) => n.id === node.id
82-
)
68+
return renderFrameTitle({
69+
id: node.id,
70+
name: node.name,
71+
xy: absxy,
72+
wh: [node.width, node.height],
73+
zoom: zoom,
74+
selected: selectedNodes.some(
75+
(selectedNode) => selectedNode.id === node.id
76+
),
77+
onSelect: () => onSelectNode(node.id),
78+
onHoverChange: (hv) => {
79+
if (hv) {
80+
onHoverNode(node.id);
81+
} else {
82+
onHoverNode(null);
8383
}
84-
/>
85-
);
84+
},
85+
highlight: !![...highlights, ...selectedNodes].find(
86+
(n) => n.id === node.id
87+
),
88+
});
8689
})}
8790
{highlights &&
8891
highlights.map((h) => {
@@ -121,3 +124,7 @@ export function HudSurface({
121124
</div>
122125
);
123126
}
127+
128+
const frame_title_default_renderer = (p: FrameTitleProps) => (
129+
<FrameTitle key={p.id} {...p} />
130+
);

editor-packages/editor-canvas/frame-title/frame-title.tsx

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,8 @@ import { useHover } from "@editor-ui/hooks";
33
import styled from "@emotion/styled";
44
import { color_frame_title } from "../theme";
55

6-
export function FrameTitle({
7-
name,
8-
xy,
9-
wh,
10-
zoom,
11-
highlight = false,
12-
selected,
13-
onHoverChange,
14-
onSelect,
15-
}: {
6+
export interface FrameTitleProps {
7+
id?: string;
168
name: string;
179
/**
1810
* absolute x, y
@@ -27,7 +19,18 @@ export function FrameTitle({
2719
selected?: boolean;
2820
onHoverChange?: (hover: boolean) => void;
2921
onSelect?: () => void;
30-
}) {
22+
}
23+
24+
export function FrameTitle({
25+
name,
26+
xy,
27+
wh,
28+
zoom,
29+
highlight = false,
30+
selected,
31+
onHoverChange,
32+
onSelect,
33+
}: FrameTitleProps) {
3134
const [x, y] = xy;
3235
const [w, h] = wh;
3336
const view_height = 24;
@@ -46,38 +49,46 @@ export function FrameTitle({
4649
});
4750

4851
return (
49-
<div
52+
<FrameTitleContainer
5053
id="frame-title"
5154
onClick={onSelect}
52-
style={{
53-
position: "fixed",
54-
width: w * zoom,
55-
height: view_height,
56-
fontSize: 12,
57-
willChange: "transform",
58-
cursor: "default",
59-
overflow: "hidden",
60-
transform: `translateX(${x}px) translateY(${height_considered_y_transform}px)`,
61-
display: "flex",
62-
flexDirection: "row",
63-
alignItems: "center",
64-
}}
55+
width={w * zoom}
56+
height={view_height}
57+
xy={[x, height_considered_y_transform]}
6558
{...hoverProps}
6659
>
67-
<TitleLabel
60+
<FrameTitleLabel
6861
color={
6962
selected || highlight || hoverred
7063
? color_frame_title.highlight
7164
: color_frame_title.default
7265
}
7366
>
7467
{name}
75-
</TitleLabel>
76-
</div>
68+
</FrameTitleLabel>
69+
</FrameTitleContainer>
7770
);
7871
}
7972

80-
const TitleLabel = styled.span<{
73+
export const FrameTitleContainer = styled.div<{
74+
width: number;
75+
height: number;
76+
xy: [number, number];
77+
}>`
78+
position: fixed;
79+
width: ${(p) => p.width}px;
80+
height: ${(p) => p.height}px;
81+
will-change: transform;
82+
cursor: default;
83+
overflow: hidden;
84+
transform: translateX(${(p) => p.xy[0]}px) translateY(${(p) => p.xy[1]}px);
85+
display: flex;
86+
font-size: 12px;
87+
flex-direction: row;
88+
align-items: center;
89+
`;
90+
91+
export const FrameTitleLabel = styled.span<{
8192
color: string;
8293
}>`
8394
color: ${(p) => p.color};

editor/components/canvas/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "./interactive-canvas";
1+
export * from "./isolated-canvas";

editor/components/canvas/interactive-canvas.tsx renamed to editor/components/canvas/isolated-canvas.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ type InitialTransform = {
5656
transformOrigin: string;
5757
};
5858

59-
export function InteractiveCanvas({
59+
export function IsolatedCanvas({
6060
children,
6161
defaultSize,
62+
onExit,
6263
}: {
6364
defaultSize: { width: number; height: number };
6465
children?: React.ReactNode;
66+
onExit?: () => void;
6567
}) {
6668
const _margin = 20;
6769
const [canvasSizingRef, canvasBounds] = useMeasure();
@@ -133,6 +135,7 @@ export function InteractiveCanvas({
133135
scale={scale}
134136
onChange={setScale}
135137
/>
138+
{onExit && <ExitButton onClick={onExit}>End Isolation</ExitButton>}
136139
</Controls>
137140
{/* <ScalingAreaStaticRoot> */}
138141
<TransformContainer
@@ -151,6 +154,17 @@ export function InteractiveCanvas({
151154
);
152155
}
153156

157+
const ExitButton = styled.button`
158+
align-self: center;
159+
outline: none;
160+
border: none;
161+
cursor: pointer;
162+
background: none;
163+
color: white;
164+
border-radius: 2px;
165+
height: 24px;
166+
`;
167+
154168
const InteractiveCanvasWrapper = styled.div`
155169
display: flex;
156170
flex-direction: column;

0 commit comments

Comments
 (0)