feat(editor): inspector rect x/y/w/h
This commit is contained in:
parent
4e4b0e428d
commit
b252a80a8e
@ -563,6 +563,7 @@ export function EditorApp() {
|
||||
|
||||
<Inspector
|
||||
selected={selected}
|
||||
onUpdateRect={(id, patch) => dispatch({ type: 'updateWidgetRect', id, rect: patch })}
|
||||
onUpdateTextProps={(id, props) =>
|
||||
dispatch({ type: 'updateWidgetProps', widgetType: 'text', id, props })
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Input, InputNumber, Select, Space, Typography } from 'antd';
|
||||
import { Divider, Input, InputNumber, Select, Space, Typography } from 'antd';
|
||||
import { assertNever, type WidgetNode, type TextWidgetNode, type WidgetNodeByType } from '@astralview/sdk';
|
||||
|
||||
type ImageWidgetNode = WidgetNodeByType['image'];
|
||||
@ -7,6 +7,7 @@ type VideoWidgetNode = WidgetNodeByType['video'];
|
||||
|
||||
export function Inspector(props: {
|
||||
selected?: WidgetNode;
|
||||
onUpdateRect: (id: string, patch: Partial<WidgetNode['rect']>) => void;
|
||||
onUpdateTextProps: (id: string, patch: Partial<TextWidgetNode['props']>) => void;
|
||||
onUpdateImageProps: (id: string, patch: Partial<ImageWidgetNode['props']>) => void;
|
||||
onUpdateIframeProps: (id: string, patch: Partial<IframeWidgetNode['props']>) => void;
|
||||
@ -18,6 +19,60 @@ export function Inspector(props: {
|
||||
return <Typography.Paragraph style={{ color: '#666' }}>No selection.</Typography.Paragraph>;
|
||||
}
|
||||
|
||||
const rectDisabled = !!node.locked;
|
||||
|
||||
const RectSection = (
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<Typography.Text type="secondary">Rect</Typography.Text>
|
||||
<Space style={{ width: '100%', marginTop: 6 }} size={8} wrap>
|
||||
<InputNumber
|
||||
size="small"
|
||||
value={node.rect.x}
|
||||
controls={false}
|
||||
disabled={rectDisabled}
|
||||
onChange={(v) => props.onUpdateRect(node.id, { x: typeof v === 'number' ? v : node.rect.x })}
|
||||
style={{ width: 90 }}
|
||||
addonBefore="X"
|
||||
/>
|
||||
<InputNumber
|
||||
size="small"
|
||||
value={node.rect.y}
|
||||
controls={false}
|
||||
disabled={rectDisabled}
|
||||
onChange={(v) => props.onUpdateRect(node.id, { y: typeof v === 'number' ? v : node.rect.y })}
|
||||
style={{ width: 90 }}
|
||||
addonBefore="Y"
|
||||
/>
|
||||
<InputNumber
|
||||
size="small"
|
||||
value={node.rect.w}
|
||||
controls={false}
|
||||
disabled={rectDisabled}
|
||||
min={1}
|
||||
onChange={(v) => props.onUpdateRect(node.id, { w: typeof v === 'number' ? v : node.rect.w })}
|
||||
style={{ width: 96 }}
|
||||
addonBefore="W"
|
||||
/>
|
||||
<InputNumber
|
||||
size="small"
|
||||
value={node.rect.h}
|
||||
controls={false}
|
||||
disabled={rectDisabled}
|
||||
min={1}
|
||||
onChange={(v) => props.onUpdateRect(node.id, { h: typeof v === 'number' ? v : node.rect.h })}
|
||||
style={{ width: 96 }}
|
||||
addonBefore="H"
|
||||
/>
|
||||
</Space>
|
||||
{rectDisabled ? (
|
||||
<Typography.Text style={{ display: 'block', marginTop: 4, color: '#64748b', fontSize: 12 }}>
|
||||
Locked layer: rect editing disabled.
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
<Divider style={{ margin: '12px 0', borderColor: 'rgba(255,255,255,0.08)' }} />
|
||||
</div>
|
||||
);
|
||||
|
||||
switch (node.type) {
|
||||
case 'image':
|
||||
return (
|
||||
@ -26,6 +81,8 @@ export function Inspector(props: {
|
||||
Image
|
||||
</Typography.Title>
|
||||
|
||||
{RectSection}
|
||||
|
||||
<Typography.Text type="secondary">Source</Typography.Text>
|
||||
<Input
|
||||
value={node.props.src}
|
||||
@ -65,6 +122,8 @@ export function Inspector(props: {
|
||||
Iframe
|
||||
</Typography.Title>
|
||||
|
||||
{RectSection}
|
||||
|
||||
<Typography.Text type="secondary">Source</Typography.Text>
|
||||
<Input
|
||||
value={node.props.src}
|
||||
@ -90,6 +149,8 @@ export function Inspector(props: {
|
||||
Video
|
||||
</Typography.Title>
|
||||
|
||||
{RectSection}
|
||||
|
||||
<Typography.Text type="secondary">Source</Typography.Text>
|
||||
<Input
|
||||
value={node.props.src}
|
||||
@ -173,6 +234,8 @@ export function Inspector(props: {
|
||||
Text
|
||||
</Typography.Title>
|
||||
|
||||
{RectSection}
|
||||
|
||||
<Typography.Text type="secondary">Content</Typography.Text>
|
||||
<Input
|
||||
value={node.props.text}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user