Naive copy&paste implementation of node resizer in svelte, some stuff pulled out to system

This commit is contained in:
peterkogo
2024-01-04 21:43:04 +01:00
parent a899f9b6ca
commit 296cc15fc1
22 changed files with 6256 additions and 9006 deletions
@@ -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} />