migrate some components

This commit is contained in:
peterkogo
2024-11-13 13:33:49 +01:00
parent 880ed8886b
commit 28e4fad342
31 changed files with 505 additions and 459 deletions

View File

@@ -2,13 +2,10 @@
import { Panel } from '$lib/container/Panel';
import type { AttributionProps } from './types';
type $$Props = AttributionProps;
export let proOptions: $$Props['proOptions'] = undefined;
export let position: $$Props['position'] = 'bottom-right';
let { proOptions, position = 'bottom-right' }: AttributionProps = $props();
</script>
{#if !proOptions?.hideAttribution}
{#if proOptions?.hideAttribution}
<Panel
{position}
class="svelte-flow__attribution"

View File

@@ -3,22 +3,19 @@
import type { BaseEdgeProps } from './types';
import EdgeLabel from '../EdgeLabel/EdgeLabel.svelte';
type $$Props = BaseEdgeProps;
export let id: $$Props['id'] = undefined;
export let path: $$Props['path'];
export let label: $$Props['label'] = undefined;
export let labelX: $$Props['labelX'] = undefined;
export let labelY: $$Props['labelY'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let style: $$Props['style'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = 20;
let className: $$Props['class'] = undefined;
export { className as class };
let interactionWidthValue = interactionWidth === undefined ? 20 : interactionWidth;
let {
id,
path,
label,
labelX,
labelY,
labelStyle,
markerStart,
markerEnd,
style,
interactionWidth = 20,
class: className
}: BaseEdgeProps = $props();
</script>
<path
@@ -31,11 +28,11 @@
{style}
/>
{#if interactionWidthValue}
{#if interactionWidth > 0}
<path
d={path}
stroke-opacity={0}
stroke-width={interactionWidthValue}
stroke-width={interactionWidth}
fill="none"
class="svelte-flow__edge-interaction"
/>

View File

@@ -1,7 +1,6 @@
<script lang="ts">
import cc from 'classcat';
import { useStore } from '$lib/store';
import type { Snippet } from 'svelte';
import {
ConnectionLineType,
getBezierPath,
@@ -10,50 +9,61 @@
getStraightPath
} from '@xyflow/system';
export let containerStyle: string = '';
export let style: string = '';
export let isCustomComponent: boolean = false;
import { useStore } from '$lib/store';
let {
containerStyle = '',
style = '',
connectionLine
}: {
containerStyle: string;
style: string;
connectionLine?: Snippet;
} = $props();
const { width, height, connection, connectionLineType } = useStore();
let path: string | null = null;
let path = $derived.by(() => {
if (!$connection.inProgress) {
return '';
}
$: if ($connection.inProgress && !isCustomComponent) {
const { from, to, fromPosition, toPosition } = $connection;
const pathParams = {
sourceX: from.x,
sourceY: from.y,
sourcePosition: fromPosition,
targetX: to.x,
targetY: to.y,
targetPosition: toPosition
sourceX: $connection.from.x,
sourceY: $connection.from.y,
sourcePosition: $connection.fromPosition,
targetX: $connection.to.x,
targetY: $connection.to.y,
targetPosition: $connection.toPosition
};
switch ($connectionLineType) {
case ConnectionLineType.Bezier:
[path] = getBezierPath(pathParams);
break;
case ConnectionLineType.Bezier: {
const [path] = getBezierPath(pathParams);
return path;
}
case ConnectionLineType.Straight: {
const [path] = getStraightPath(pathParams);
return path;
}
case ConnectionLineType.Step:
[path] = getSmoothStepPath({
case ConnectionLineType.SmoothStep: {
const [path] = getSmoothStepPath({
...pathParams,
borderRadius: 0
borderRadius: $connectionLineType === ConnectionLineType.Step ? 0 : undefined
});
break;
case ConnectionLineType.SmoothStep:
[path] = getSmoothStepPath(pathParams);
break;
default:
[path] = getStraightPath(pathParams);
return path;
}
}
}
});
</script>
{#if $connection.inProgress}
<svg width={$width} height={$height} class="svelte-flow__connectionline" style={containerStyle}>
<g class={cc(['svelte-flow__connection', getConnectionStatus($connection.isValid)])}>
<slot name="connectionLine" />
<!-- slot fallbacks do not work if slots are forwarded in parent -->
{#if !isCustomComponent}
{#if connectionLine}
{@render connectionLine()}
{:else}
<path d={path} {style} fill="none" class="svelte-flow__connection-path" />
{/if}
</g>

View File

@@ -1,13 +1,20 @@
<script lang="ts">
import { getContext } from 'svelte';
import { getContext, type Snippet } from 'svelte';
import { EdgeLabelRenderer } from '$lib/components/EdgeLabelRenderer';
import { useHandleEdgeSelect } from '$lib/hooks/useHandleEdgeSelect';
import type { BaseEdgeProps } from '$lib/components/BaseEdge/types';
export let style: BaseEdgeProps['labelStyle'] = undefined;
export let x: BaseEdgeProps['labelX'] = undefined;
export let y: BaseEdgeProps['labelY'] = undefined;
let {
style,
x,
y,
children
}: {
style?: string;
x?: number;
y?: number;
children?: Snippet;
} = $props();
const handleEdgeSelect = useHandleEdgeSelect();
@@ -21,11 +28,11 @@
style={'pointer-events: all;' + style}
role="button"
tabindex="-1"
on:keyup={() => {}}
on:click={() => {
onkeyup={() => {}}
onclick={() => {
if (id) handleEdgeSelect(id);
}}
>
<slot />
{@render children?.()}
</div>
</EdgeLabelRenderer>

View File

@@ -1,10 +1,13 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import portal from '$lib/actions/portal';
import { useStore } from '$lib/store';
const { domNode } = useStore();
let { children }: { children?: Snippet } = $props();
</script>
<div use:portal={{ target: '.svelte-flow__edgelabel-renderer', domNode: $domNode }}>
<slot />
{@render children?.()}
</div>

View File

@@ -40,6 +40,8 @@
export let ariaLabel: $$Props['ariaLabel'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
// TODO SVELTE5
// @ todo: support edge updates
let className: string = '';
export { className as class };

View File

@@ -1,4 +1,5 @@
<script lang="ts">
//TODO SVELTE5
import { getContext } from 'svelte';
import type { Writable } from 'svelte/store';
import cc from 'classcat';

View File

@@ -1,22 +1,23 @@
<script lang="ts">
import { get } from 'svelte/store';
import {
shortcut,
type ShortcutEventDetail,
type ShortcutModifierDefinition
} from '@svelte-put/shortcut';
import { isInputDOMNode, isMacOs } from '@xyflow/system';
import { getElementsToRemove, isInputDOMNode, isMacOs } from '@xyflow/system';
import { useStore } from '$lib/store';
import type { KeyHandlerProps } from './types';
import type { KeyDefinition, KeyDefinitionObject } from '$lib/types';
type $$Props = KeyHandlerProps;
export let selectionKey: $$Props['selectionKey'] = 'Shift';
export let multiSelectionKey: $$Props['multiSelectionKey'] = isMacOs() ? 'Meta' : 'Control';
export let deleteKey: $$Props['deleteKey'] = 'Backspace';
export let panActivationKey: $$Props['panActivationKey'] = ' ';
export let zoomActivationKey: $$Props['zoomActivationKey'] = isMacOs() ? 'Meta' : 'Control';
let {
selectionKey = 'Shift',
multiSelectionKey = isMacOs() ? 'Meta' : 'Control',
deleteKey = 'Backspace',
panActivationKey = ' ',
zoomActivationKey = isMacOs() ? 'Meta' : 'Control'
}: KeyHandlerProps = $props();
const {
selectionKeyPressed,
@@ -24,7 +25,11 @@
deleteKeyPressed,
panActivationKeyPressed,
zoomActivationKeyPressed,
selectionRect
selectionRect,
onbeforedelete,
ondelete,
nodes: _nodes,
edges: _edges
} = useStore();
function isKeyObject(key?: KeyDefinition | null): key is KeyDefinitionObject {
@@ -69,6 +74,31 @@
panActivationKeyPressed.set(false);
zoomActivationKeyPressed.set(false);
}
async function handleDelete() {
const nodes = get(_nodes);
const edges = get(_edges);
const selectedNodes = nodes.filter((node) => node.selected);
const selectedEdges = edges.filter((edge) => edge.selected);
const { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
nodesToRemove: selectedNodes,
edgesToRemove: selectedEdges,
nodes,
edges,
onBeforeDelete: get(onbeforedelete)
});
if (matchingNodes.length || matchingEdges.length) {
_nodes.update((nds) => nds.filter((node) => !matchingNodes.some((mN) => mN.id === node.id)));
_edges.update((eds) => eds.filter((edge) => !matchingEdges.some((mE) => mE.id === edge.id)));
get(ondelete)?.({
nodes: matchingNodes,
edges: matchingEdges
});
}
}
</script>
<svelte:window
@@ -98,6 +128,7 @@
detail.originalEvent.shiftKey;
if (!isModifierKey && !isInputDOMNode(detail.originalEvent)) {
deleteKeyPressed.set(true);
handleDelete();
}
}),
type: 'keydown'

View File

@@ -1,37 +1,39 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { getInternalNodesBounds, isNumeric, type Rect } from '@xyflow/system';
import { useStore } from '$lib/store';
import { Selection } from '$lib/components/Selection';
import drag from '$lib/actions/drag';
import type { Node, NodeEventMap } from '$lib/types';
import type { NodeSelectionProps } from './types';
let {
onnodedrag,
onnodedragstart,
onnodedragstop,
onselectionclick,
onselectioncontextmenu
}: NodeSelectionProps = $props();
const store = useStore();
const { selectionRectMode, nodes, nodeLookup } = store;
const dispatch = createEventDispatcher<
NodeEventMap & {
selectioncontextmenu: { nodes: Node[]; event: MouseEvent | TouchEvent };
selectionclick: { nodes: Node[]; event: MouseEvent | TouchEvent };
let bounds: Rect | null = $derived.by(() => {
if ($selectionRectMode === 'nodes') {
$nodes;
return getInternalNodesBounds($nodeLookup, { filter: (node) => !!node.selected });
}
>();
return null;
});
let bounds: Rect | null = null;
$: if ($selectionRectMode === 'nodes') {
bounds = getInternalNodesBounds($nodeLookup, { filter: (node) => !!node.selected });
$nodes;
function oncontextmenu(event: MouseEvent | TouchEvent) {
const selectedNodes = $nodes.filter((n) => n.selected);
onselectioncontextmenu?.({ nodes: selectedNodes, event });
}
function onContextMenu(event: MouseEvent | TouchEvent) {
function onclick(event: MouseEvent | TouchEvent) {
const selectedNodes = $nodes.filter((n) => n.selected);
dispatch('selectioncontextmenu', { nodes: selectedNodes, event });
}
function onClick(event: MouseEvent | TouchEvent) {
const selectedNodes = $nodes.filter((n) => n.selected);
dispatch('selectionclick', { nodes: selectedNodes, event });
onselectionclick?.({ nodes: selectedNodes, event });
}
</script>
@@ -43,20 +45,20 @@
disabled: false,
store,
onDrag: (event, _, __, nodes) => {
dispatch('nodedrag', { event, targetNode: null, nodes });
onnodedrag?.({ event, targetNode: null, nodes });
},
onDragStart: (event, _, __, nodes) => {
dispatch('nodedragstart', { event, targetNode: null, nodes });
onnodedragstart?.({ event, targetNode: null, nodes });
},
onDragStop: (event, _, __, nodes) => {
dispatch('nodedragstop', { event, targetNode: null, nodes });
onnodedragstop?.({ event, targetNode: null, nodes });
}
}}
on:contextmenu={onContextMenu}
on:click={onClick}
{oncontextmenu}
{onclick}
role="button"
tabindex="-1"
on:keyup={() => {}}
onkeyup={() => {}}
>
<Selection width="100%" height="100%" x={0} y={0} />
</div>

View File

@@ -0,0 +1,4 @@
import type { NodeEvents, NodeSelectionEvents } from '$lib/types';
export type NodeSelectionProps = NodeSelectionEvents &
Pick<NodeEvents, 'onnodedrag' | 'onnodedragstart' | 'onnodedragstop'>;

View File

@@ -1,7 +1,5 @@
<svelte:options immutable />
<script lang="ts">
import { setContext, onDestroy, createEventDispatcher } from 'svelte';
import { setContext, onDestroy } from 'svelte';
import { get, writable } from 'svelte/store';
import cc from 'classcat';
import { errorMessages, Position } from '@xyflow/system';
@@ -11,42 +9,48 @@
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
import type { NodeWrapperProps } from './types';
import { getNodeInlineStyleDimensions } from './utils';
import type { NodeEventMap } from '$lib/types';
import type { NodeEvents } from '$lib/types';
interface $$Props extends NodeWrapperProps {}
export let node: $$Props['node'];
export let id: $$Props['id'];
export let data: $$Props['data'] = {};
export let selected: $$Props['selected'] = false;
export let draggable: $$Props['draggable'] = undefined;
export let selectable: $$Props['selectable'] = undefined;
export let connectable: $$Props['connectable'] = true;
export let deletable: $$Props['deletable'] = true;
export let hidden: $$Props['hidden'] = false;
export let dragging: boolean = false;
export let resizeObserver: $$Props['resizeObserver'] = null;
export let style: $$Props['style'] = undefined;
export let type: $$Props['type'] = 'default';
export let isParent: $$Props['isParent'] = false;
export let positionX: $$Props['positionX'];
export let positionY: $$Props['positionY'];
export let sourcePosition: $$Props['sourcePosition'] = undefined;
export let targetPosition: $$Props['targetPosition'] = undefined;
export let zIndex: $$Props['zIndex'];
export let measuredWidth: $$Props['measuredWidth'] = undefined;
export let measuredHeight: $$Props['measuredHeight'] = undefined;
export let initialWidth: $$Props['initialWidth'] = undefined;
export let initialHeight: $$Props['initialHeight'] = undefined;
export let width: $$Props['width'] = undefined;
export let height: $$Props['height'] = undefined;
export let dragHandle: $$Props['dragHandle'] = undefined;
export let initialized: $$Props['initialized'] = false;
export let parentId: $$Props['parentId'] = undefined;
export let nodeClickDistance: $$Props['nodeClickDistance'] = undefined;
let className: string = '';
export { className as class };
let {
node,
id,
data = {},
selected = false,
draggable,
selectable,
deletable,
connectable = true,
hidden = false,
dragging = false,
resizeObserver = null,
style,
class: className,
type = 'default',
isParent = false,
parentId,
positionX,
positionY,
sourcePosition,
targetPosition,
zIndex,
measuredWidth,
measuredHeight,
initialWidth,
initialHeight,
width,
height,
dragHandle,
initialized = false,
nodeClickDistance,
onnodeclick,
onnodedrag,
onnodedragstart,
onnodedragstop,
onnodemouseenter,
onnodemouseleave,
onnodemousemove,
onnodecontextmenu
}: NodeWrapperProps & NodeEvents = $props();
const store = useStore();
const {
@@ -57,78 +61,85 @@
updateNodeInternals
} = store;
let nodeRef: HTMLDivElement;
let nodeRef: HTMLDivElement | null = $state(null);
let prevNodeRef: HTMLDivElement | null = null;
const dispatchNodeEvent = createEventDispatcher<NodeEventMap>();
const connectableStore = writable(connectable);
let prevType: string | undefined = undefined;
let prevSourcePosition: Position | undefined = undefined;
let prevTargetPosition: Position | undefined = undefined;
$: nodeType = type || 'default';
$: nodeTypeValid = !!$nodeTypes[nodeType];
$: nodeComponent = $nodeTypes[nodeType] || DefaultNode;
let prevType: string | undefined;
let prevSourcePosition: Position | undefined;
let prevTargetPosition: Position | undefined;
$: {
if (!nodeTypeValid) {
console.warn('003', errorMessages['error003'](type!));
}
let NodeComponent = $derived($nodeTypes[type] ?? DefaultNode);
if (process.env.NODE_ENV === 'development') {
$effect(() => {
const valid = !!$nodeTypes[type];
if (!valid) {
console.warn('003', errorMessages['error003'](type!));
}
});
}
$: inlineStyleDimensions = getNodeInlineStyleDimensions({
width,
height,
initialWidth,
initialHeight,
measuredWidth,
measuredHeight
let inlineStyleDimensions = $derived(
getNodeInlineStyleDimensions({
width,
height,
initialWidth,
initialHeight,
measuredWidth,
measuredHeight
})
);
$effect(() => {
connectableStore.set(!!connectable);
});
$: {
connectableStore.set(!!connectable);
}
$: {
$effect(() => {
// if type, sourcePosition or targetPosition changes,
// we need to re-calculate the handle positions
const doUpdate =
(prevType && nodeType !== prevType) ||
(prevType && type !== prevType) ||
(prevSourcePosition && sourcePosition !== prevSourcePosition) ||
(prevTargetPosition && targetPosition !== prevTargetPosition);
if (doUpdate) {
requestAnimationFrame(() =>
updateNodeInternals(
new Map([
[
id,
{
if (doUpdate && nodeRef !== null) {
requestAnimationFrame(() => {
if (nodeRef !== null) {
updateNodeInternals(
new Map([
[
id,
nodeElement: nodeRef,
force: true
}
]
])
)
);
{
id,
nodeElement: nodeRef,
force: true
}
]
])
);
}
});
}
prevType = nodeType;
prevType = type;
prevSourcePosition = sourcePosition;
prevTargetPosition = targetPosition;
}
});
setContext('svelteflow__node_id', id);
setContext('svelteflow__node_connectable', connectableStore);
$: {
if (resizeObserver && (nodeRef !== prevNodeRef || !initialized)) {
// TODO: extract this part!
$effect(() => {
// TODO: HOLY MOLY! changing the order of the initialized breaks effect subscriptions
if (resizeObserver && (!initialized || nodeRef !== prevNodeRef)) {
prevNodeRef && resizeObserver.unobserve(prevNodeRef);
nodeRef && resizeObserver.observe(nodeRef);
prevNodeRef = nodeRef;
}
}
});
onDestroy(() => {
if (prevNodeRef) {
@@ -143,12 +154,12 @@
handleNodeSelection(id);
}
dispatchNodeEvent('nodeclick', { node: node.internals.userNode, event });
onnodeclick?.({ node: node.internals.userNode, event });
}
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
{#if !hidden}
<div
use:drag={{
@@ -160,19 +171,19 @@
nodeClickDistance,
onNodeMouseDown: handleNodeSelection,
onDrag: (event, _, targetNode, nodes) => {
dispatchNodeEvent('nodedrag', { event, targetNode, nodes });
onnodedrag?.({ event, targetNode, nodes });
},
onDragStart: (event, _, targetNode, nodes) => {
dispatchNodeEvent('nodedragstart', { event, targetNode, nodes });
onnodedragstart?.({ event, targetNode, nodes });
},
onDragStop: (event, _, targetNode, nodes) => {
dispatchNodeEvent('nodedragstop', { event, targetNode, nodes });
onnodedragstop?.({ event, targetNode, nodes });
},
store
}}
bind:this={nodeRef}
data-id={id}
class={cc(['svelte-flow__node', `svelte-flow__node-${nodeType}`, className])}
class={cc(['svelte-flow__node', `svelte-flow__node-${type}`, className])}
class:dragging
class:selected
class:draggable
@@ -184,14 +195,13 @@
style:transform="translate({positionX}px, {positionY}px)"
style:visibility={initialized ? 'visible' : 'hidden'}
style="{style ?? ''};{inlineStyleDimensions.width}{inlineStyleDimensions.height}"
on:click={onSelectNodeHandler}
on:mouseenter={(event) => dispatchNodeEvent('nodemouseenter', { node, event })}
on:mouseleave={(event) => dispatchNodeEvent('nodemouseleave', { node, event })}
on:mousemove={(event) => dispatchNodeEvent('nodemousemove', { node, event })}
on:contextmenu={(event) => dispatchNodeEvent('nodecontextmenu', { node, event })}
onclick={onSelectNodeHandler}
onmouseenter={onnodemouseenter ? (event) => onnodemouseenter({ node, event }) : undefined}
onmouseleave={onnodemouseleave ? (event) => onnodemouseleave({ node, event }) : undefined}
onmousemove={onnodemousemove ? (event) => onnodemousemove({ node, event }) : undefined}
oncontextmenu={onnodecontextmenu ? (event) => onnodecontextmenu({ node, event }) : undefined}
>
<svelte:component
this={nodeComponent}
<NodeComponent
{data}
{id}
{selected}
@@ -204,7 +214,7 @@
{draggable}
{dragHandle}
{parentId}
type={nodeType}
{type}
isConnectable={$connectableStore}
positionAbsoluteX={positionX}
positionAbsoluteY={positionY}

View File

@@ -34,5 +34,5 @@ export type NodeWrapperProps = Pick<
zIndex: number;
node: InternalNode;
initialized: boolean;
nodeClickDistance?: number;
nodeClickDistance: number;
};

View File

@@ -1,9 +1,17 @@
<script lang="ts">
export let x: number | null = 0;
export let y: number | null = 0;
export let width: number | string | null = 0;
export let height: number | string | null = 0;
export let isVisible: boolean = true;
let {
x = 0,
y = 0,
width = 0,
height = 0,
isVisible = true
}: {
x?: number | null;
y?: number | null;
width?: number | string | null;
height?: number | string | null;
isVisible?: boolean;
} = $props();
</script>
{#if isVisible}
@@ -12,7 +20,7 @@
style:width={typeof width === 'string' ? width : `${width}px`}
style:height={typeof height === 'string' ? height : `${height}px`}
style:transform={`translate(${x}px, ${y}px)`}
/>
></div>
{/if}
<style>

View File

@@ -1,10 +1,14 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import portal from '$lib/actions/portal';
import { useStore } from '$lib/store';
let { children }: { children?: Snippet } = $props();
const { domNode } = useStore();
</script>
<div use:portal={{ target: '.svelte-flow__viewport-portal', domNode: $domNode }}>
<slot />
{@render children?.()}
</div>

View File

@@ -2,36 +2,37 @@
import { getBezierPath } from '@xyflow/system';
import type { BezierEdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = BezierEdgeProps;
export let id: $$Props['id'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let pathOptions: $$Props['pathOptions'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getBezierPath({
let {
id,
label,
labelStyle,
style,
markerStart,
markerEnd,
pathOptions,
interactionWidth,
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition,
curvature: pathOptions?.curvature
});
targetPosition
}: BezierEdgeProps = $props();
let [path, labelX, labelY] = $derived(
getBezierPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
curvature: pathOptions?.curvature
})
);
</script>
<BaseEdge

View File

@@ -3,35 +3,31 @@
import type { EdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = EdgeProps;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getBezierPath({
let {
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition
});
targetPosition,
label,
labelStyle,
markerStart,
markerEnd,
interactionWidth,
style
}: EdgeProps = $props();
// this is a workaround for suppressing the warning about unused props
$$restProps;
let [path, labelX, labelY] = $derived(
getBezierPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition
})
);
</script>
<BaseEdge

View File

@@ -4,35 +4,35 @@
import type { SmoothStepEdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = SmoothStepEdgeProps;
export let id: $$Props['id'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let pathOptions: $$Props['pathOptions'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getSmoothStepPath({
let {
id,
label,
labelStyle,
style,
markerStart,
markerEnd,
pathOptions,
interactionWidth,
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: pathOptions?.borderRadius,
offset: pathOptions?.offset
});
targetPosition
}: SmoothStepEdgeProps = $props();
let [path, labelX, labelY] = $derived(
getSmoothStepPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: pathOptions?.borderRadius,
offset: pathOptions?.offset
})
);
</script>
<BaseEdge

View File

@@ -4,34 +4,31 @@
import type { EdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = EdgeProps;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getSmoothStepPath({
let {
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition
});
targetPosition,
label,
labelStyle,
markerStart,
markerEnd,
interactionWidth,
style
}: EdgeProps = $props();
// this is a workaround for suppressing the warning about unused props
$$restProps;
let [path, labelX, labelY] = $derived(
getSmoothStepPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition
})
);
</script>
<BaseEdge

View File

@@ -4,35 +4,35 @@
import type { StepEdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = StepEdgeProps;
export let id: $$Props['id'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let pathOptions: $$Props['pathOptions'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getSmoothStepPath({
let {
id,
label,
labelStyle,
style,
markerStart,
markerEnd,
pathOptions,
interactionWidth,
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: 0,
offset: pathOptions?.offset
});
targetPosition
}: StepEdgeProps = $props();
let [path, labelX, labelY] = $derived(
getSmoothStepPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: 0,
offset: pathOptions?.offset
})
);
</script>
<BaseEdge

View File

@@ -4,35 +4,32 @@
import type { EdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = EdgeProps;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let sourcePosition: $$Props['sourcePosition'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
export let targetPosition: $$Props['targetPosition'];
$: [path, labelX, labelY] = getSmoothStepPath({
let {
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: 0
});
label,
labelStyle,
markerStart,
markerEnd,
interactionWidth,
style
}: EdgeProps = $props();
// this is a workaround for suppressing the warning about unused props
$$restProps;
let [path, labelX, labelY] = $derived(
getSmoothStepPath({
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
borderRadius: 0
})
);
</script>
<BaseEdge

View File

@@ -4,28 +4,28 @@
import type { StraightEdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = StraightEdgeProps;
export let id: $$Props['id'] = undefined;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
$: [path, labelX, labelY] = getStraightPath({
let {
id,
label,
labelStyle,
style,
markerStart,
markerEnd,
interactionWidth,
sourceX,
sourceY,
targetX,
targetY
});
}: StraightEdgeProps = $props();
let [path, labelX, labelY] = $derived(
getStraightPath({
sourceX,
sourceY,
targetX,
targetY
})
);
</script>
<BaseEdge

View File

@@ -4,30 +4,27 @@
import type { EdgeProps } from '$lib/types';
import { BaseEdge } from '$lib/components/BaseEdge';
type $$Props = EdgeProps;
export let label: $$Props['label'] = undefined;
export let labelStyle: $$Props['labelStyle'] = undefined;
export let style: $$Props['style'] = undefined;
export let markerStart: $$Props['markerStart'] = undefined;
export let markerEnd: $$Props['markerEnd'] = undefined;
export let interactionWidth: $$Props['interactionWidth'] = undefined;
export let sourceX: $$Props['sourceX'];
export let sourceY: $$Props['sourceY'];
export let targetX: $$Props['targetX'];
export let targetY: $$Props['targetY'];
$: [path, labelX, labelY] = getStraightPath({
let {
sourceX,
sourceY,
targetX,
targetY
});
targetY,
label,
labelStyle,
markerStart,
markerEnd,
interactionWidth,
style
}: EdgeProps = $props();
// this is a workaround for suppressing the warning about unused props
$$restProps;
let [path, labelX, labelY] = $derived(
getStraightPath({
sourceX,
sourceY,
targetX,
targetY
})
);
</script>
<BaseEdge

View File

@@ -4,16 +4,14 @@
import { Handle } from '$lib/components/Handle';
import type { NodeProps } from '$lib/types';
interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' };
export let targetPosition: $$Props['targetPosition'] = undefined;
export let sourcePosition: $$Props['sourcePosition'] = undefined;
// this is a workaround for suppressing the warning about unused props
$$restProps;
let {
// TODO: do we really want this!?
data = { label: 'Node' },
targetPosition = Position.Top,
sourcePosition = Position.Bottom
}: NodeProps = $props();
</script>
<Handle type="target" position={targetPosition ?? Position.Top} />
<Handle type="target" position={targetPosition} />
{data?.label}
<Handle type="source" position={sourcePosition ?? Position.Bottom} />
<Handle type="source" position={sourcePosition} />

View File

@@ -1,9 +1,5 @@
<script lang="ts">
import type { NodeProps } from '$lib/types';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface $$Props extends NodeProps {}
// this is a workaround for suppressing the warning about unused props
$$restProps;
let {}: NodeProps = $props();
</script>

View File

@@ -4,14 +4,8 @@
import { Handle } from '$lib/components/Handle';
interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' };
export let sourcePosition: $$Props['sourcePosition'] = undefined;
// this is a workaround for suppressing the warning about unused props
$$restProps;
let { data = { label: 'Node' }, sourcePosition = Position.Bottom }: NodeProps = $props();
</script>
{data?.label}
<Handle type="source" position={sourcePosition ?? Position.Bottom} />
<Handle type="source" position={sourcePosition} />

View File

@@ -4,14 +4,8 @@
import { Handle } from '$lib/components/Handle';
interface $$Props extends NodeProps {}
export let data: $$Props['data'] = { label: 'Node' };
export let targetPosition: $$Props['targetPosition'] = undefined;
// this is a workaround for suppressing the warning about unused props
$$restProps;
let { data = { label: 'Node' }, targetPosition = Position.Top }: NodeProps = $props();
</script>
{data?.label}
<Handle type="target" position={targetPosition ?? Position.Top} />
<Handle type="target" position={targetPosition} />

View File

@@ -3,24 +3,24 @@
import type { PanelProps } from './types';
import { useStore } from '$lib/store';
type $$Props = PanelProps;
export let position: $$Props['position'] = 'top-right';
export let style: $$Props['style'] = undefined;
let className: $$Props['class'] = undefined;
export { className as class };
let {
position = 'top-right',
style,
class: className,
children,
...restProps
}: PanelProps = $props();
const { selectionRectMode } = useStore();
$: positionClasses = `${position}`.split('-');
let positionClasses = $derived(`${position}`.split('-'));
</script>
<div
class={cc(['svelte-flow__panel', className, ...positionClasses])}
{style}
style:pointer-events={$selectionRectMode ? 'none' : ''}
{...$$restProps}
{...restProps}
>
<slot />
{@render children?.()}
</div>

View File

@@ -79,8 +79,8 @@
onbeforedelete,
oninit,
nodeOrigin,
paneClickDistance = 0,
nodeClickDistance = 0,
paneClickDistance = 1,
nodeClickDistance = 1,
defaultMarkerColor = '#b1b1b7',
style,
class: className,
@@ -109,6 +109,8 @@
const initViewport = $viewport || initialViewport;
//TODO SVELTE5
const store = hasContext(key)
? useStore()
: createStoreContext({
@@ -262,15 +264,11 @@
{onedgemouseleave}
{defaultEdgeOptions}
/>
<!-- <ConnectionLine
<ConnectionLine
containerStyle={connectionLineContainerStyle}
style={connectionLineStyle}
isCustomComponent={connectionLine}
>
{#snippet connectionLine()}
{@render connectionLine_render?.()}
{/snippet}
</ConnectionLine> -->
{connectionLine}
/>
<div class="svelte-flow__edgelabel-renderer"></div>
<div class="svelte-flow__viewport-portal"></div>
<NodeRenderer

View File

@@ -271,36 +271,36 @@ export function createStore({
if (resetEdges) store.edges.set(get(store.edges));
}
store.deleteKeyPressed.subscribe(async (deleteKeyPressed) => {
if (deleteKeyPressed) {
const nodes = get(store.nodes);
const edges = get(store.edges);
const selectedNodes = nodes.filter((node) => node.selected);
const selectedEdges = edges.filter((edge) => edge.selected);
// store.deleteKeyPressed.subscribe(async (deleteKeyPressed) => {
// if (deleteKeyPressed) {
// const nodes = get(store.nodes);
// const edges = get(store.edges);
// const selectedNodes = nodes.filter((node) => node.selected);
// const selectedEdges = edges.filter((edge) => edge.selected);
const { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
nodesToRemove: selectedNodes,
edgesToRemove: selectedEdges,
nodes,
edges,
onBeforeDelete: get(store.onbeforedelete)
});
// const { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
// nodesToRemove: selectedNodes,
// edgesToRemove: selectedEdges,
// nodes,
// edges,
// onBeforeDelete: get(store.onbeforedelete)
// });
if (matchingNodes.length || matchingEdges.length) {
store.nodes.update((nds) =>
nds.filter((node) => !matchingNodes.some((mN) => mN.id === node.id))
);
store.edges.update((eds) =>
eds.filter((edge) => !matchingEdges.some((mE) => mE.id === edge.id))
);
// if (matchingNodes.length || matchingEdges.length) {
// store.nodes.update((nds) =>
// nds.filter((node) => !matchingNodes.some((mN) => mN.id === node.id))
// );
// store.edges.update((eds) =>
// eds.filter((edge) => !matchingEdges.some((mE) => mE.id === edge.id))
// );
get(store.ondelete)?.({
nodes: matchingNodes,
edges: matchingEdges
});
}
}
});
// get(store.ondelete)?.({
// nodes: matchingNodes,
// edges: matchingEdges
// });
// }
// }
// });
function addSelectedNodes(ids: string[]) {
const isMultiSelection = get(store.multiselectionKeyPressed);

View File

@@ -1,3 +1,4 @@
export * from './nodes';
export * from './edges';
export * from './general';
export * from './events';

View File

@@ -44,6 +44,7 @@ export type DefaultNodeOptions = Partial<Omit<Node, 'id'>>;
export type BuiltInNode = Node<{ label: string }, 'input' | 'output' | 'default'>;
// TODO SVELTE5 remove this
export type NodeEventMap = {
nodeclick: { node: Node; event: MouseEvent | TouchEvent };
nodecontextmenu: { node: Node; event: MouseEvent | TouchEvent };