Naive copy&paste implementation of node resizer in svelte, some stuff pulled out to system
This commit is contained in:
@@ -9,7 +9,7 @@ const DefaultResizerNode: FC<NodeProps> = ({ data, selected }) => {
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
isVisible={data.isVisible ?? selected}
|
||||
isVisible={data.isVisible ?? !!selected}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
'usenodesdata',
|
||||
'usesvelteflow',
|
||||
'useupdatenodeinternals',
|
||||
'validation'
|
||||
'validation',
|
||||
'node-resizer'
|
||||
];
|
||||
|
||||
const onChange = (event: Event) => {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<script lang="ts">
|
||||
import { SvelteFlow, Controls, Panel, type Node, type Edge } from '@xyflow/svelte';
|
||||
|
||||
import DefaultResizer from './DefaultResizer.svelte';
|
||||
import CustomResizer from './CustomResizer.svelte';
|
||||
import VerticalResizer from './VerticalResizer.svelte';
|
||||
import HorizontalResizer from './HorizontalResizer.svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
import '@xyflow/svelte/dist/style.css';
|
||||
|
||||
const nodeTypes = {
|
||||
defaultResizer: DefaultResizer,
|
||||
customResizer: CustomResizer,
|
||||
verticalResizer: VerticalResizer,
|
||||
horizontalResizer: HorizontalResizer
|
||||
};
|
||||
|
||||
const nodeStyle = 'border: 1px solid #222; font-size: 10px; background-color: #ddd;';
|
||||
|
||||
const edges = writable<Edge[]>([]);
|
||||
|
||||
const nodes = writable<Node[]>([
|
||||
{
|
||||
id: '1',
|
||||
type: 'defaultResizer',
|
||||
data: { label: 'default resizer' },
|
||||
position: { x: 0, y: 0 },
|
||||
style: nodeStyle
|
||||
},
|
||||
{
|
||||
id: '1a',
|
||||
type: 'defaultResizer',
|
||||
data: {
|
||||
label: 'default resizer with min and max dimensions',
|
||||
minWidth: 100,
|
||||
minHeight: 80,
|
||||
maxWidth: 200,
|
||||
maxHeight: 200
|
||||
},
|
||||
position: { x: 0, y: 60 },
|
||||
style: nodeStyle + ' width: 100px; height: 80px;'
|
||||
},
|
||||
{
|
||||
id: '1b',
|
||||
type: 'defaultResizer',
|
||||
data: {
|
||||
label: 'default resizer with initial size and aspect ratio',
|
||||
keepAspectRatio: true,
|
||||
minWidth: 100,
|
||||
minHeight: 60,
|
||||
maxWidth: 400,
|
||||
maxHeight: 400
|
||||
},
|
||||
position: { x: 250, y: 0 },
|
||||
style: nodeStyle + ' width: 174px; height: 123px;'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'customResizer',
|
||||
data: { label: 'custom resize icon' },
|
||||
position: { x: 0, y: 200 },
|
||||
style: nodeStyle + ' width: 100px; height: 60px;'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'verticalResizer',
|
||||
data: { label: 'vertical resizer' },
|
||||
position: { x: 250, y: 200 },
|
||||
style: nodeStyle
|
||||
},
|
||||
{
|
||||
id: '3a',
|
||||
type: 'verticalResizer',
|
||||
data: {
|
||||
label: 'vertical resizer with min/maxHeight and aspect ratio',
|
||||
minHeight: 50,
|
||||
maxHeight: 200,
|
||||
keepAspectRatio: true
|
||||
},
|
||||
position: { x: 400, y: 200 },
|
||||
style: nodeStyle + ' height: 50px;'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'horizontalResizer',
|
||||
data: {
|
||||
label: 'horizontal resizer with aspect ratio',
|
||||
keepAspectRatio: true,
|
||||
minHeight: 20,
|
||||
maxHeight: 80,
|
||||
maxWidth: 300
|
||||
},
|
||||
position: { x: 250, y: 300 },
|
||||
style: nodeStyle
|
||||
},
|
||||
{
|
||||
id: '4a',
|
||||
type: 'horizontalResizer',
|
||||
data: { label: 'horizontal resizer with maxWidth', maxWidth: 300 },
|
||||
position: { x: 250, y: 400 },
|
||||
style: nodeStyle
|
||||
}
|
||||
]);
|
||||
|
||||
let snapToGrid = false;
|
||||
</script>
|
||||
|
||||
<SvelteFlow
|
||||
{nodes}
|
||||
{edges}
|
||||
{nodeTypes}
|
||||
minZoom={0.2}
|
||||
maxZoom={5}
|
||||
snapGrid={snapToGrid ? [10, 10] : undefined}
|
||||
fitView
|
||||
>
|
||||
<Controls />
|
||||
<Panel position="bottom-right">
|
||||
<button
|
||||
on:click={() => {
|
||||
snapToGrid = !snapToGrid;
|
||||
}}
|
||||
>
|
||||
snapToGrid: {snapToGrid ? 'on' : 'off'}
|
||||
</button>
|
||||
</Panel>
|
||||
</SvelteFlow>
|
||||
@@ -0,0 +1,42 @@
|
||||
<script lang="ts">
|
||||
import { Handle, Position, type NodeProps, NodeResizeControl } from '@xyflow/svelte';
|
||||
|
||||
type $$Props = NodeProps;
|
||||
|
||||
export let data: $$Props['data'] = undefined;
|
||||
</script>
|
||||
|
||||
<NodeResizeControl
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
style="background: transparent; border: none;"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="8"
|
||||
height="8"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
style="position: absolute; right: 2px; bottom: 2px;"
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<polyline points="16 20 20 20 20 16" />
|
||||
<line x1="14" y1="14" x2="20" y2="20" />
|
||||
<polyline points="8 4 4 4 4 8" />
|
||||
<line x1="4" y1="4" x2="10" y2="10" />
|
||||
</svg>
|
||||
</NodeResizeControl>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div>{data.label}</div>
|
||||
<Handle type="source" position={Position.Right} />
|
||||
@@ -0,0 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { Handle, NodeResizer, Position, type NodeProps } from '@xyflow/svelte';
|
||||
|
||||
type $$Props = NodeProps;
|
||||
|
||||
export let data: $$Props['data'] = undefined;
|
||||
export let selected: $$Props['selected'] = undefined;
|
||||
</script>
|
||||
|
||||
<NodeResizer
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
isVisible={data.isVisible ?? !!selected}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
/>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div>{data.label}</div>
|
||||
<Handle type="source" position={Position.Right} />
|
||||
@@ -0,0 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
|
||||
|
||||
type $$Props = NodeProps;
|
||||
|
||||
export let data: $$Props['data'] = undefined;
|
||||
</script>
|
||||
|
||||
<NodeResizeControl
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
color="red"
|
||||
position={Position.Left}
|
||||
/>
|
||||
<NodeResizeControl
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
color="red"
|
||||
position={Position.Right}
|
||||
/>
|
||||
<Handle type="target" position={Position.Top} />
|
||||
<div style="padding: 10px;">{data.label}</div>
|
||||
<Handle type="source" position={Position.Bottom} />
|
||||
@@ -0,0 +1,24 @@
|
||||
function ResizeIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="8"
|
||||
height="8"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth="2"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
style={{ position: 'absolute', right: 2, bottom: 2 }}
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<polyline points="16 20 20 20 20 16" />
|
||||
<line x1="14" y1="14" x2="20" y2="20" />
|
||||
<polyline points="8 4 4 4 4 8" />
|
||||
<line x1="4" y1="4" x2="10" y2="10" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default ResizeIcon;
|
||||
@@ -0,0 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { Handle, NodeResizeControl, Position, type NodeProps } from '@xyflow/svelte';
|
||||
|
||||
type $$Props = NodeProps;
|
||||
|
||||
export let data: $$Props['data'] = undefined;
|
||||
</script>
|
||||
|
||||
<NodeResizeControl
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
color="red"
|
||||
position={Position.Top}
|
||||
/>
|
||||
<NodeResizeControl
|
||||
minWidth={data.minWidth ?? undefined}
|
||||
maxWidth={data.maxWidth ?? undefined}
|
||||
minHeight={data.minHeight ?? undefined}
|
||||
maxHeight={data.maxHeight ?? undefined}
|
||||
shouldResize={data.shouldResize ?? undefined}
|
||||
onResizeStart={data.onResizeStart ?? undefined}
|
||||
onResize={data.onResize ?? undefined}
|
||||
onResizeEnd={data.onResizeEnd ?? undefined}
|
||||
keepAspectRatio={data.keepAspectRatio ?? undefined}
|
||||
color="red"
|
||||
position={Position.Bottom}
|
||||
/>
|
||||
<Handle type="target" position={Position.Left} />
|
||||
<div style="padding: 10px;">{data.label}</div>
|
||||
<Handle type="source" position={Position.Right} />
|
||||
Reference in New Issue
Block a user