WIP: migrated store and useSvelteFlow hook to signals & solved state propagation for provider
This commit is contained in:
@@ -9,35 +9,37 @@
|
||||
getStraightPath
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
|
||||
let {
|
||||
store,
|
||||
containerStyle = '',
|
||||
style = '',
|
||||
connectionLine
|
||||
}: {
|
||||
store: SvelteFlowStore;
|
||||
containerStyle: string;
|
||||
style: string;
|
||||
connectionLine?: Snippet;
|
||||
} = $props();
|
||||
|
||||
const { width, height, connection, connectionLineType } = useStore();
|
||||
// $inspect(store.connection);
|
||||
|
||||
let path = $derived.by(() => {
|
||||
if (!$connection.inProgress) {
|
||||
if (!store.connection.inProgress) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const pathParams = {
|
||||
sourceX: $connection.from.x,
|
||||
sourceY: $connection.from.y,
|
||||
sourcePosition: $connection.fromPosition,
|
||||
targetX: $connection.to.x,
|
||||
targetY: $connection.to.y,
|
||||
targetPosition: $connection.toPosition
|
||||
sourceX: store.connection.from.x,
|
||||
sourceY: store.connection.from.y,
|
||||
sourcePosition: store.connection.fromPosition,
|
||||
targetX: store.connection.to.x,
|
||||
targetY: store.connection.to.y,
|
||||
targetPosition: store.connection.toPosition
|
||||
};
|
||||
|
||||
switch ($connectionLineType) {
|
||||
switch (store.connectionLineType) {
|
||||
case ConnectionLineType.Bezier: {
|
||||
const [path] = getBezierPath(pathParams);
|
||||
return path;
|
||||
@@ -50,7 +52,7 @@
|
||||
case ConnectionLineType.SmoothStep: {
|
||||
const [path] = getSmoothStepPath({
|
||||
...pathParams,
|
||||
borderRadius: $connectionLineType === ConnectionLineType.Step ? 0 : undefined
|
||||
borderRadius: store.connectionLineType === ConnectionLineType.Step ? 0 : undefined
|
||||
});
|
||||
return path;
|
||||
}
|
||||
@@ -58,9 +60,14 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if $connection.inProgress}
|
||||
<svg width={$width} height={$height} class="svelte-flow__connectionline" style={containerStyle}>
|
||||
<g class={cc(['svelte-flow__connection', getConnectionStatus($connection.isValid)])}>
|
||||
{#if store.connection.inProgress}
|
||||
<svg
|
||||
width={store.width}
|
||||
height={store.height}
|
||||
class="svelte-flow__connectionline"
|
||||
style={containerStyle}
|
||||
>
|
||||
<g class={cc(['svelte-flow__connection', getConnectionStatus(store.connection.isValid)])}>
|
||||
{#if connectionLine}
|
||||
{@render connectionLine()}
|
||||
{:else}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
import portal from '$lib/actions/portal';
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
const { domNode } = useStore();
|
||||
const store = useStore();
|
||||
|
||||
let { children }: { children?: Snippet } = $props();
|
||||
</script>
|
||||
|
||||
<div use:portal={{ target: '.svelte-flow__edgelabel-renderer', domNode: $domNode }}>
|
||||
<div use:portal={{ target: '.svelte-flow__edgelabel-renderer', domNode: store.domNode }}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
import { useHandleEdgeSelect } from '$lib/hooks/useHandleEdgeSelect';
|
||||
|
||||
import type { EdgeLayouted, Edge, EdgeEvents } from '$lib/types';
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
|
||||
const {
|
||||
id,
|
||||
type = 'default',
|
||||
store,
|
||||
source,
|
||||
target,
|
||||
data = {},
|
||||
@@ -42,24 +44,24 @@
|
||||
onedgecontextmenu,
|
||||
onedgemouseenter,
|
||||
onedgemouseleave
|
||||
}: EdgeLayouted & EdgeEvents = $props();
|
||||
}: { store: SvelteFlowStore } & EdgeLayouted & EdgeEvents = $props();
|
||||
|
||||
setContext('svelteflow__edge_id', id);
|
||||
|
||||
const { edgeLookup, edgeTypes, flowId, elementsSelectable } = useStore();
|
||||
|
||||
let edgeType = $derived(type ?? 'default');
|
||||
let EdgeComponent = $derived($edgeTypes[edgeType] ?? BezierEdgeInternal);
|
||||
let EdgeComponent = $derived(store.edgeTypes[edgeType] ?? BezierEdgeInternal);
|
||||
let markerStartUrl = $derived(
|
||||
markerStart ? `url('#${getMarkerId(markerStart, $flowId)}')` : undefined
|
||||
markerStart ? `url('#${getMarkerId(markerStart, store.flowId)}')` : undefined
|
||||
);
|
||||
let markerEndUrl = $derived(markerEnd ? `url('#${getMarkerId(markerEnd, $flowId)}')` : undefined);
|
||||
let isSelectable = $derived(selectable ?? $elementsSelectable);
|
||||
let markerEndUrl = $derived(
|
||||
markerEnd ? `url('#${getMarkerId(markerEnd, store.flowId)}')` : undefined
|
||||
);
|
||||
let isSelectable = $derived(selectable ?? store.elementsSelectable);
|
||||
|
||||
const handleEdgeSelect = useHandleEdgeSelect();
|
||||
|
||||
function onclick(event: MouseEvent | TouchEvent) {
|
||||
const edge = $edgeLookup.get(id);
|
||||
const edge = store.edgeLookup.get(id);
|
||||
|
||||
if (edge) {
|
||||
handleEdgeSelect(id);
|
||||
@@ -71,7 +73,7 @@
|
||||
event: MouseEvent,
|
||||
callback: ({ edge, event }: { edge: Edge; event: MouseEvent }) => void
|
||||
) {
|
||||
const edge = $edgeLookup.get(id);
|
||||
const edge = store.edgeLookup.get(id);
|
||||
|
||||
if (edge) {
|
||||
callback({ event, edge });
|
||||
|
||||
@@ -39,28 +39,8 @@
|
||||
isConnectableProp !== undefined ? isConnectableProp : isConnectableContext.value
|
||||
);
|
||||
|
||||
const {
|
||||
connectionMode,
|
||||
domNode,
|
||||
nodeLookup,
|
||||
connectionRadius,
|
||||
viewport,
|
||||
isValidConnection: isValidConnectionStore,
|
||||
lib,
|
||||
addEdge,
|
||||
onedgecreate,
|
||||
panBy,
|
||||
cancelConnection,
|
||||
updateConnection,
|
||||
autoPanOnConnect,
|
||||
edges,
|
||||
connectionLookup,
|
||||
onconnect: onConnectAction,
|
||||
onconnectstart: onConnectStartAction,
|
||||
onconnectend: onConnectEndAction,
|
||||
flowId,
|
||||
connection
|
||||
} = useStore();
|
||||
let store = useStore();
|
||||
let { viewport, edges } = store;
|
||||
|
||||
function onPointerDown(event: MouseEvent | TouchEvent) {
|
||||
const isMouseTriggered = isMouseEvent(event);
|
||||
@@ -70,39 +50,39 @@
|
||||
handleId,
|
||||
nodeId,
|
||||
isTarget,
|
||||
connectionRadius: $connectionRadius,
|
||||
domNode: $domNode,
|
||||
nodeLookup: $nodeLookup,
|
||||
connectionMode: $connectionMode,
|
||||
lib: $lib,
|
||||
autoPanOnConnect: $autoPanOnConnect,
|
||||
flowId: $flowId,
|
||||
isValidConnection: isValidConnectionProp ?? $isValidConnectionStore,
|
||||
updateConnection,
|
||||
cancelConnection,
|
||||
panBy,
|
||||
connectionRadius: store.connectionRadius,
|
||||
domNode: store.domNode,
|
||||
nodeLookup: store.nodeLookup,
|
||||
connectionMode: store.connectionMode,
|
||||
lib: 'svelte',
|
||||
autoPanOnConnect: store.autoPanOnConnect,
|
||||
flowId: store.flowId,
|
||||
isValidConnection: isValidConnectionProp ?? store.isValidConnection,
|
||||
updateConnection: store.updateConnection,
|
||||
cancelConnection: store.cancelConnection,
|
||||
panBy: store.panBy,
|
||||
onConnect: (connection) => {
|
||||
const edge = $onedgecreate ? $onedgecreate(connection) : connection;
|
||||
const edge = store.onedgecreate ? store.onedgecreate(connection) : connection;
|
||||
|
||||
if (!edge) {
|
||||
return;
|
||||
}
|
||||
|
||||
addEdge(edge);
|
||||
$onConnectAction?.(connection);
|
||||
store.addEdge(edge);
|
||||
store.onconnect?.(connection);
|
||||
},
|
||||
onConnectStart: (event, startParams) => {
|
||||
$onConnectStartAction?.(event, {
|
||||
store.onconnectstart?.(event, {
|
||||
nodeId: startParams.nodeId,
|
||||
handleId: startParams.handleId,
|
||||
handleType: startParams.handleType
|
||||
});
|
||||
},
|
||||
onConnectEnd: (event, connectionState) => {
|
||||
$onConnectEndAction?.(event, connectionState);
|
||||
store.onconnectend?.(event, connectionState);
|
||||
},
|
||||
getTransform: () => [$viewport.x, $viewport.y, $viewport.zoom],
|
||||
getFromHandle: () => $connection.fromHandle
|
||||
getFromHandle: () => store.connection.fromHandle
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -113,7 +93,7 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
$edges;
|
||||
if (onconnect || ondisconnect) {
|
||||
let connections = $connectionLookup.get(`${nodeId}-${type}-${handleId}`);
|
||||
let connections = store.connectionLookup.get(`${nodeId}-${type}-${handleId}`);
|
||||
|
||||
if (prevConnections && !areConnectionMapsEqual(connections, prevConnections)) {
|
||||
const _connections = connections ?? new Map();
|
||||
@@ -128,7 +108,7 @@
|
||||
|
||||
let [connectionInProcess, connectingFrom, connectingTo, isPossibleEndHandle, valid] = $derived.by(
|
||||
() => {
|
||||
const { fromHandle, toHandle, isValid } = $connection;
|
||||
const { fromHandle, toHandle, isValid } = store.connection;
|
||||
|
||||
const connectionInProcess = !!fromHandle;
|
||||
|
||||
@@ -139,7 +119,7 @@
|
||||
toHandle?.nodeId === nodeId && toHandle?.type === type && toHandle?.id === handleId;
|
||||
|
||||
const isPossibleEndHandle =
|
||||
$connectionMode === ConnectionMode.Strict
|
||||
store.connectionMode === ConnectionMode.Strict
|
||||
? fromHandle?.type !== type
|
||||
: nodeId !== fromHandle?.nodeId || handleId !== fromHandle?.id;
|
||||
|
||||
@@ -158,7 +138,7 @@ The Handle component is the part of a node that can be used to connect nodes.
|
||||
data-handleid={handleId}
|
||||
data-nodeid={nodeId}
|
||||
data-handlepos={position}
|
||||
data-id="{$flowId}-{nodeId}-{handleId}-{type}"
|
||||
data-id="{store.flowId}-{nodeId}-{handleId}-{type}"
|
||||
class={cc([
|
||||
'svelte-flow__handle',
|
||||
`svelte-flow__handle-${position}`,
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import type { KeyDefinition, KeyDefinitionObject } from '$lib/types';
|
||||
|
||||
let {
|
||||
store,
|
||||
selectionKey = 'Shift',
|
||||
multiSelectionKey = isMacOs() ? 'Meta' : 'Control',
|
||||
deleteKey = 'Backspace',
|
||||
@@ -19,18 +20,7 @@
|
||||
zoomActivationKey = isMacOs() ? 'Meta' : 'Control'
|
||||
}: KeyHandlerProps = $props();
|
||||
|
||||
const {
|
||||
selectionKeyPressed,
|
||||
multiselectionKeyPressed,
|
||||
deleteKeyPressed,
|
||||
panActivationKeyPressed,
|
||||
zoomActivationKeyPressed,
|
||||
selectionRect,
|
||||
onbeforedelete,
|
||||
ondelete,
|
||||
nodes: _nodes,
|
||||
edges: _edges
|
||||
} = useStore();
|
||||
const { nodes: _nodes, edges: _edges } = store;
|
||||
|
||||
function isKeyObject(key?: KeyDefinition | null): key is KeyDefinitionObject {
|
||||
return key !== null && typeof key === 'object';
|
||||
@@ -67,12 +57,12 @@
|
||||
}
|
||||
|
||||
function resetKeysAndSelection() {
|
||||
selectionRect.set(null);
|
||||
selectionKeyPressed.set(false);
|
||||
multiselectionKeyPressed.set(false);
|
||||
deleteKeyPressed.set(false);
|
||||
panActivationKeyPressed.set(false);
|
||||
zoomActivationKeyPressed.set(false);
|
||||
store.selectionRect = null;
|
||||
store.selectionKeyPressed = false;
|
||||
store.multiselectionKeyPressed = false;
|
||||
store.deleteKeyPressed = false;
|
||||
store.panActivationKeyPressed = false;
|
||||
store.zoomActivationKeyPressed = false;
|
||||
}
|
||||
|
||||
async function handleDelete() {
|
||||
@@ -86,14 +76,14 @@
|
||||
edgesToRemove: selectedEdges,
|
||||
nodes,
|
||||
edges,
|
||||
onBeforeDelete: get(onbeforedelete)
|
||||
onBeforeDelete: store.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)?.({
|
||||
store.ondelete?.({
|
||||
nodes: matchingNodes,
|
||||
edges: matchingEdges
|
||||
});
|
||||
@@ -105,19 +95,19 @@
|
||||
on:blur={resetKeysAndSelection}
|
||||
on:contextmenu={resetKeysAndSelection}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(selectionKey, () => selectionKeyPressed.set(true)),
|
||||
trigger: getShortcutTrigger(selectionKey, () => (store.selectionKeyPressed = true)),
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(selectionKey, () => selectionKeyPressed.set(false)),
|
||||
trigger: getShortcutTrigger(selectionKey, () => (store.selectionKeyPressed = false)),
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(multiSelectionKey, () => multiselectionKeyPressed.set(true)),
|
||||
trigger: getShortcutTrigger(multiSelectionKey, () => (store.multiselectionKeyPressed = true)),
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(multiSelectionKey, () => multiselectionKeyPressed.set(false)),
|
||||
trigger: getShortcutTrigger(multiSelectionKey, () => (store.multiselectionKeyPressed = false)),
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
@@ -127,30 +117,30 @@
|
||||
detail.originalEvent.metaKey ||
|
||||
detail.originalEvent.shiftKey;
|
||||
if (!isModifierKey && !isInputDOMNode(detail.originalEvent)) {
|
||||
deleteKeyPressed.set(true);
|
||||
store.deleteKeyPressed = true;
|
||||
handleDelete();
|
||||
}
|
||||
}),
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(deleteKey, () => deleteKeyPressed.set(false)),
|
||||
trigger: getShortcutTrigger(deleteKey, () => (store.deleteKeyPressed = false)),
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(panActivationKey, () => panActivationKeyPressed.set(true)),
|
||||
trigger: getShortcutTrigger(panActivationKey, () => (store.panActivationKeyPressed = true)),
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(panActivationKey, () => panActivationKeyPressed.set(false)),
|
||||
trigger: getShortcutTrigger(panActivationKey, () => (store.panActivationKeyPressed = false)),
|
||||
type: 'keyup'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(zoomActivationKey, () => zoomActivationKeyPressed.set(true)),
|
||||
trigger: getShortcutTrigger(zoomActivationKey, () => (store.zoomActivationKeyPressed = true)),
|
||||
type: 'keydown'
|
||||
}}
|
||||
use:shortcut={{
|
||||
trigger: getShortcutTrigger(zoomActivationKey, () => zoomActivationKeyPressed.set(false)),
|
||||
trigger: getShortcutTrigger(zoomActivationKey, () => (store.zoomActivationKeyPressed = false)),
|
||||
type: 'keyup'
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
import type { KeyDefinition } from '$lib/types';
|
||||
|
||||
export type KeyHandlerProps = {
|
||||
store: SvelteFlowStore;
|
||||
selectionKey?: KeyDefinition | KeyDefinition[] | null;
|
||||
multiSelectionKey?: KeyDefinition | KeyDefinition[] | null;
|
||||
deleteKey?: KeyDefinition | KeyDefinition[] | null;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
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 { NodeSelectionProps } from './types';
|
||||
|
||||
let {
|
||||
store,
|
||||
onnodedrag,
|
||||
onnodedragstart,
|
||||
onnodedragstop,
|
||||
@@ -15,14 +15,13 @@
|
||||
onselectioncontextmenu
|
||||
}: NodeSelectionProps = $props();
|
||||
|
||||
const store = useStore();
|
||||
const { selectionRectMode, nodes, nodeLookup } = store;
|
||||
const { nodes } = store;
|
||||
|
||||
let bounds: Rect | null = $derived.by(() => {
|
||||
if ($selectionRectMode === 'nodes') {
|
||||
if (store.selectionRectMode === 'nodes') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
$nodes;
|
||||
return getInternalNodesBounds($nodeLookup, { filter: (node) => !!node.selected });
|
||||
return getInternalNodesBounds(store.nodeLookup, { filter: (node) => !!node.selected });
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@@ -38,7 +37,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $selectionRectMode === 'nodes' && bounds && isNumeric(bounds.x) && isNumeric(bounds.y)}
|
||||
{#if store.selectionRectMode === 'nodes' && bounds && isNumeric(bounds.x) && isNumeric(bounds.y)}
|
||||
<div
|
||||
class="selection-wrapper nopan"
|
||||
style="width: {bounds.width}px; height: {bounds.height}px; transform: translate({bounds.x}px, {bounds.y}px)"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
import type { NodeEvents, NodeSelectionEvents } from '$lib/types';
|
||||
|
||||
export type NodeSelectionProps = NodeSelectionEvents &
|
||||
export type NodeSelectionProps = { store: SvelteFlowStore } & NodeSelectionEvents &
|
||||
Pick<NodeEvents, 'onnodedrag' | 'onnodedragstart' | 'onnodedragstop'>;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
<script lang="ts">
|
||||
import { setContext, onDestroy } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import cc from 'classcat';
|
||||
import { errorMessages, Position } from '@xyflow/system';
|
||||
|
||||
import drag from '$lib/actions/drag';
|
||||
import { useStore } from '$lib/store';
|
||||
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
|
||||
import type { ConnectableContext, NodeWrapperProps } from './types';
|
||||
import { getNodeInlineStyleDimensions } from './utils';
|
||||
import type { NodeEvents } from '$lib/types';
|
||||
|
||||
let {
|
||||
store,
|
||||
node,
|
||||
id,
|
||||
data = {},
|
||||
@@ -52,15 +51,6 @@
|
||||
onnodecontextmenu
|
||||
}: NodeWrapperProps & NodeEvents = $props();
|
||||
|
||||
const store = useStore();
|
||||
const {
|
||||
nodeTypes,
|
||||
nodeDragThreshold,
|
||||
selectNodesOnDrag,
|
||||
handleNodeSelection,
|
||||
updateNodeInternals
|
||||
} = store;
|
||||
|
||||
let nodeRef: HTMLDivElement | null = $state(null);
|
||||
let prevNodeRef: HTMLDivElement | null = null;
|
||||
|
||||
@@ -68,7 +58,7 @@
|
||||
let prevSourcePosition: Position | undefined;
|
||||
let prevTargetPosition: Position | undefined;
|
||||
|
||||
let NodeComponent = $derived($nodeTypes[type] ?? DefaultNode);
|
||||
let NodeComponent = $derived(store.nodeTypes[type] ?? DefaultNode);
|
||||
|
||||
let connectableContext: ConnectableContext = {
|
||||
get value() {
|
||||
@@ -80,7 +70,7 @@
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
$effect(() => {
|
||||
const valid = !!$nodeTypes[type];
|
||||
const valid = !!store.nodeTypes[type];
|
||||
if (!valid) {
|
||||
console.warn('003', errorMessages['error003'](type!));
|
||||
}
|
||||
@@ -109,7 +99,7 @@
|
||||
if (doUpdate && nodeRef !== null) {
|
||||
requestAnimationFrame(() => {
|
||||
if (nodeRef !== null) {
|
||||
updateNodeInternals(
|
||||
store.updateNodeInternals(
|
||||
new Map([
|
||||
[
|
||||
id,
|
||||
@@ -148,10 +138,10 @@
|
||||
});
|
||||
|
||||
function onSelectNodeHandler(event: MouseEvent | TouchEvent) {
|
||||
if (selectable && (!get(selectNodesOnDrag) || !draggable || get(nodeDragThreshold) > 0)) {
|
||||
if (selectable && (!store.selectNodesOnDrag || !draggable || store.nodeDragThreshold > 0)) {
|
||||
// this handler gets called by XYDrag on drag start when selectNodesOnDrag=true
|
||||
// here we only need to call it when selectNodesOnDrag=false
|
||||
handleNodeSelection(id);
|
||||
store.handleNodeSelection(id);
|
||||
}
|
||||
|
||||
onnodeclick?.({ node: node.internals.userNode, event });
|
||||
@@ -169,7 +159,7 @@
|
||||
handleSelector: dragHandle,
|
||||
noDragClass: 'nodrag',
|
||||
nodeClickDistance,
|
||||
onNodeMouseDown: handleNodeSelection,
|
||||
onNodeMouseDown: store.handleNodeSelection,
|
||||
onDrag: (event, _, targetNode, nodes) => {
|
||||
onnodedrag?.({ event, targetNode, nodes });
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
import type { InternalNode, Node } from '$lib/types';
|
||||
|
||||
export type ConnectableContext = {
|
||||
@@ -39,4 +40,5 @@ export type NodeWrapperProps = Pick<
|
||||
node: InternalNode;
|
||||
initialized: boolean;
|
||||
nodeClickDistance?: number;
|
||||
store: SvelteFlowStore;
|
||||
};
|
||||
|
||||
@@ -3,29 +3,21 @@
|
||||
|
||||
import { createStore, key } from '$lib/store';
|
||||
import type { SvelteFlowProviderProps } from './types';
|
||||
import type { ProviderContext, SvelteFlowStore } from '$lib/store/types';
|
||||
|
||||
let {
|
||||
initialNodes,
|
||||
initialEdges,
|
||||
initialWidth,
|
||||
initialHeight,
|
||||
nodeOrigin,
|
||||
fitView,
|
||||
children
|
||||
}: SvelteFlowProviderProps = $props();
|
||||
let { children }: SvelteFlowProviderProps = $props();
|
||||
|
||||
const store = createStore({
|
||||
nodes: initialNodes,
|
||||
edges: initialEdges,
|
||||
width: initialWidth,
|
||||
height: initialHeight,
|
||||
nodeOrigin,
|
||||
fitView
|
||||
});
|
||||
let store = $state.raw(createStore({ props: {} }));
|
||||
|
||||
setContext(key, {
|
||||
getStore: () => store
|
||||
});
|
||||
provider: true,
|
||||
getStore() {
|
||||
return store;
|
||||
},
|
||||
setStore: (newStore: SvelteFlowStore) => {
|
||||
store = newStore;
|
||||
}
|
||||
} satisfies ProviderContext);
|
||||
|
||||
onDestroy(() => {
|
||||
store.reset();
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
import { useStore } from '$lib/store';
|
||||
import { Selection } from '$lib/components/Selection';
|
||||
|
||||
const { selectionRect, selectionRectMode } = useStore();
|
||||
const store = useStore();
|
||||
</script>
|
||||
|
||||
<Selection
|
||||
isVisible={!!($selectionRect && $selectionRectMode === 'user')}
|
||||
width={$selectionRect?.width}
|
||||
height={$selectionRect?.height}
|
||||
x={$selectionRect?.x}
|
||||
y={$selectionRect?.y}
|
||||
isVisible={!!(store.selectionRect && store.selectionRectMode === 'user')}
|
||||
width={store.selectionRect?.width}
|
||||
height={store.selectionRect?.height}
|
||||
x={store.selectionRect?.x}
|
||||
y={store.selectionRect?.y}
|
||||
/>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
let { children }: { children?: Snippet } = $props();
|
||||
|
||||
const { domNode } = useStore();
|
||||
const store = useStore();
|
||||
</script>
|
||||
|
||||
<div use:portal={{ target: '.svelte-flow__viewport-portal', domNode: $domNode }}>
|
||||
<div use:portal={{ target: '.svelte-flow__viewport-portal', domNode: store.domNode }}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user