Merge branch 'next' into svelte-on-init
This commit is contained in:
@@ -1,19 +1,29 @@
|
||||
# @xyflow/react
|
||||
|
||||
## 12.0.0-next.6
|
||||
## 12.0.0-next.8
|
||||
|
||||
### Patch changes
|
||||
|
||||
- fix `OnNodeDrag` type
|
||||
- refactor(handles): do not use fallback handle if an id is being used #3409
|
||||
|
||||
## 12.0.0-next.7
|
||||
|
||||
## Minor changes
|
||||
|
||||
- pass Node/Edge types to changes thanks @FelipeEmos
|
||||
- use position instead of positionAbsolute for `getNodesBounds`
|
||||
- add second option param to `screenToFlowPosition` for configuring if `snapToGrid` should be used
|
||||
|
||||
### Patch changes
|
||||
|
||||
- pass `Node`/ `Edge` types to changes thanks @FelipeEmos
|
||||
- use position instead of positionAbsolute for `getNodesBounds`
|
||||
- infer types for `getIncomers`, `getOutgoers`, `updateEdge`, `addEdge` and `getConnectedEdges` thanks @joeyballentine
|
||||
- refactor handles: prefix with flow id for handling nested flows
|
||||
- add comments for types like `ReactFlowProps` or `Node` for a better developer experience
|
||||
|
||||
## 12.0.0-next.6
|
||||
|
||||
### Minor changes
|
||||
### Patch changes
|
||||
|
||||
- fix `deleteElements`
|
||||
- refactor internal `applyChanges`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xyflow/react",
|
||||
"version": "12.0.0-next.6",
|
||||
"version": "12.0.0-next.7",
|
||||
"description": "React Flow - A highly customizable React library for building node-based editors and interactive flow charts.",
|
||||
"keywords": [
|
||||
"react",
|
||||
|
||||
@@ -186,6 +186,7 @@ export function EdgeWrapper({
|
||||
animated: edge.animated,
|
||||
inactive: !isSelectable && !onClick,
|
||||
updating: updateHover,
|
||||
selectable: isSelectable,
|
||||
},
|
||||
])}
|
||||
onClick={onEdgeClick}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useStore, useStoreApi } from '../../hooks/useStore';
|
||||
import { useNodeId } from '../../contexts/NodeIdContext';
|
||||
import { type ReactFlowState } from '../../types';
|
||||
|
||||
export type HandleComponentProps = HandleProps & Omit<HTMLAttributes<HTMLDivElement>, 'id'>;
|
||||
export interface HandleComponentProps extends HandleProps, Omit<HTMLAttributes<HTMLDivElement>, 'id'> {}
|
||||
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
connectOnClick: s.connectOnClick,
|
||||
@@ -221,4 +221,7 @@ const HandleComponent = forwardRef<HTMLDivElement, HandleComponentProps>(
|
||||
|
||||
HandleComponent.displayName = 'Handle';
|
||||
|
||||
/**
|
||||
* The Handle component is the part of a node that can be used to connect nodes.
|
||||
*/
|
||||
export const Handle = memo(HandleComponent);
|
||||
|
||||
@@ -203,7 +203,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
||||
const node = isRect ? null : (store.getState().nodeLookup.get(nodeOrRect.id) as NodeType);
|
||||
|
||||
if (!isRect && !node) {
|
||||
[null, null, isRect];
|
||||
return [null, null, isRect];
|
||||
}
|
||||
|
||||
const nodeRect = isRect ? nodeOrRect : nodeToRect(node!);
|
||||
|
||||
@@ -67,7 +67,6 @@ export {
|
||||
type OnError,
|
||||
type NodeProps,
|
||||
type NodeOrigin,
|
||||
type OnNodeDrag,
|
||||
type OnSelectionDrag,
|
||||
Position,
|
||||
type XYPosition,
|
||||
@@ -80,7 +79,6 @@ export {
|
||||
type ColorMode,
|
||||
type ColorModeClass,
|
||||
type HandleType,
|
||||
type OnBeforeDelete,
|
||||
type ShouldResize,
|
||||
type OnResizeStart,
|
||||
type OnResize,
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
/* this will be exported as base.css and can be used for a basic styling */
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/base.css';
|
||||
|
||||
.react-flow {
|
||||
--edge-label-background-color-default: #ffffff;
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.react-flow.dark {
|
||||
--edge-label-background-color-default: #141414;
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: var(--edge-label-background-color, var(--edge-label-background-color-default));
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
fill: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -3,20 +3,10 @@
|
||||
@import '../../../system/src/styles/style.css';
|
||||
@import '../../../system/src/styles/node-resizer.css';
|
||||
|
||||
.react-flow {
|
||||
--edge-label-background-color-default: #ffffff;
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.react-flow.dark {
|
||||
--edge-label-background-color-default: #141414;
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: var(--edge-label-background-color, var(--edge-label-background-color-default));
|
||||
fill: var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default));
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
fill: var(--edge-label-color, var(--edge-label-color-default));
|
||||
fill: var(--xy-edge-label-color, var(--xy-edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import type {
|
||||
IsValidConnection,
|
||||
ColorMode,
|
||||
SnapGrid,
|
||||
OnBeforeDelete,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -40,17 +39,18 @@ import type {
|
||||
OnDelete,
|
||||
OnNodesChange,
|
||||
OnEdgesChange,
|
||||
NodeDragHandler,
|
||||
NodeMouseHandler,
|
||||
SelectionDragHandler,
|
||||
EdgeMouseHandler,
|
||||
OnNodeDrag,
|
||||
OnBeforeDelete,
|
||||
} from '.';
|
||||
|
||||
/**
|
||||
* ReactFlow component props.
|
||||
* @public
|
||||
*/
|
||||
export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
|
||||
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onError'> {
|
||||
/** An array of nodes to render in a controlled flow.
|
||||
* @example
|
||||
* const nodes = [
|
||||
@@ -111,11 +111,11 @@ export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
|
||||
/** This event handler is called when a user right clicks on a node */
|
||||
onNodeContextMenu?: NodeMouseHandler;
|
||||
/** This event handler is called when a user starts to drag a node */
|
||||
onNodeDragStart?: NodeDragHandler;
|
||||
onNodeDragStart?: OnNodeDrag;
|
||||
/** This event handler is called when a user drags a node */
|
||||
onNodeDrag?: NodeDragHandler;
|
||||
onNodeDrag?: OnNodeDrag;
|
||||
/** This event handler is called when a user stops dragging a node */
|
||||
onNodeDragStop?: NodeDragHandler;
|
||||
onNodeDragStop?: OnNodeDrag;
|
||||
/** This event handler is called when a user clicks on an edge */
|
||||
onEdgeClick?: (event: ReactMouseEvent, edge: Edge) => void;
|
||||
/** This event handler is called when a user right clicks on an edge */
|
||||
@@ -502,6 +502,6 @@ export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
|
||||
* @example 'system' | 'light' | 'dark'
|
||||
*/
|
||||
colorMode?: ColorMode;
|
||||
};
|
||||
}
|
||||
|
||||
export type ReactFlowRefType = HTMLDivElement;
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
FitBounds,
|
||||
XYPosition,
|
||||
NodeProps,
|
||||
OnBeforeDeleteBase,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps } from '.';
|
||||
@@ -19,7 +20,7 @@ import { ComponentType } from 'react';
|
||||
export type OnNodesChange<NodeType extends Node = Node> = (changes: NodeChange<NodeType>[]) => void;
|
||||
export type OnEdgesChange<EdgeType extends Edge = Edge> = (changes: EdgeChange<EdgeType>[]) => void;
|
||||
|
||||
export type OnNodesDelete = (nodes: Node[]) => void;
|
||||
export type OnNodesDelete<NodeType extends Node = Node> = (nodes: NodeType[]) => void;
|
||||
export type OnEdgesDelete = (edges: Edge[]) => void;
|
||||
export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void;
|
||||
|
||||
@@ -59,3 +60,8 @@ export type ViewportHelperFunctions = {
|
||||
flowToScreenPosition: (position: XYPosition) => XYPosition;
|
||||
viewportInitialized: boolean;
|
||||
};
|
||||
|
||||
export type OnBeforeDelete<NodeType extends Node = Node, EdgeType extends Edge = Edge> = OnBeforeDeleteBase<
|
||||
NodeType,
|
||||
EdgeType
|
||||
>;
|
||||
|
||||
@@ -3,11 +3,11 @@ import type { CoordinateExtent, NodeBase, NodeOrigin, OnError } from '@xyflow/sy
|
||||
|
||||
import { NodeTypes } from './general';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
/**
|
||||
* The node data structure that gets used for the nodes prop.
|
||||
* @public
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Node<NodeData = any, NodeType extends string | undefined = string | undefined> = NodeBase<
|
||||
NodeData,
|
||||
NodeType
|
||||
@@ -18,9 +18,13 @@ export type Node<NodeData = any, NodeType extends string | undefined = string |
|
||||
focusable?: boolean;
|
||||
};
|
||||
|
||||
export type NodeMouseHandler = (event: ReactMouseEvent, node: Node) => void;
|
||||
export type NodeDragHandler = (event: ReactMouseEvent, node: Node, nodes: Node[]) => void;
|
||||
export type SelectionDragHandler = (event: ReactMouseEvent, nodes: Node[]) => void;
|
||||
export type NodeMouseHandler<NodeType extends Node = Node> = (event: ReactMouseEvent, node: NodeType) => void;
|
||||
export type SelectionDragHandler<NodeType extends Node = Node> = (event: ReactMouseEvent, nodes: NodeType[]) => void;
|
||||
export type OnNodeDrag<NodeType extends Node = Node> = (
|
||||
event: ReactMouseEvent,
|
||||
node: NodeType,
|
||||
nodes: NodeType[]
|
||||
) => void;
|
||||
|
||||
export type NodeWrapperProps = {
|
||||
id: string;
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
type PanBy,
|
||||
type OnConnectStart,
|
||||
type OnConnectEnd,
|
||||
type OnNodeDrag,
|
||||
type OnSelectionDrag,
|
||||
type OnMoveStart,
|
||||
type OnMove,
|
||||
@@ -27,7 +26,6 @@ import {
|
||||
type EdgeLookup,
|
||||
type ConnectionLookup,
|
||||
type NodeLookup,
|
||||
OnBeforeDelete,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -43,6 +41,8 @@ import type {
|
||||
OnSelectionChangeFunc,
|
||||
UnselectNodesAndEdgesParams,
|
||||
OnDelete,
|
||||
OnNodeDrag,
|
||||
OnBeforeDelete,
|
||||
} from '.';
|
||||
|
||||
export type ReactFlowStore = {
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
# @xyflow/svelte
|
||||
|
||||
## 0.0.35
|
||||
|
||||
## Minor changes
|
||||
|
||||
- add `getNode`, `getNodes`, `getEdge` and `getEdges` to `useSvelteFlow`
|
||||
|
||||
## Patch changes
|
||||
|
||||
- Edge label has a default background and is clickable
|
||||
- refactor(handles): do not use fallback handle if an id is being used #3409
|
||||
|
||||
## 0.0.34
|
||||
|
||||
## Minor changes
|
||||
|
||||
- add second option param to `screenToFlowPosition` for configuring if `snapToGrid` should be used
|
||||
- add slot to `Controls`
|
||||
|
||||
## Patch changes
|
||||
|
||||
- cleanup `ControlButton` types
|
||||
- infer types for `getIncomers`, `getOutgoers`, `updateEdge`, `addEdge` and `getConnectedEdges` thanks @joeyballentine
|
||||
- refactor handles: prefix with flow id for handling nested flows
|
||||
@@ -42,7 +56,7 @@
|
||||
- add `onbeforedelete` handler to prevent/ manage deletions
|
||||
- TSDocs for hooks and some types
|
||||
|
||||
### Minor changes
|
||||
### Patch changes
|
||||
|
||||
- new nodeDragThreshold default is 1
|
||||
- refactor/simplify edge rendering
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xyflow/svelte",
|
||||
"version": "0.0.33",
|
||||
"version": "0.0.34",
|
||||
"description": "Svelte Flow - A highly customizable Svelte library for building node-based editors, workflow systems, diagrams and more.",
|
||||
"keywords": [
|
||||
"svelte",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import cc from 'classcat';
|
||||
import { EdgeLabelRenderer } from '$lib/components/EdgeLabelRenderer';
|
||||
import type { BaseEdgeProps } from './types';
|
||||
import EdgeLabel from '../EdgeLabel/EdgeLabel.svelte';
|
||||
|
||||
type $$Props = BaseEdgeProps;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
let className: $$Props['class'] = undefined;
|
||||
export { className as class };
|
||||
|
||||
// @todo, why is interactionWidth undefined after first re-render?
|
||||
let interactionWidthValue = interactionWidth === undefined ? 20 : interactionWidth;
|
||||
</script>
|
||||
|
||||
@@ -43,13 +42,7 @@
|
||||
{/if}
|
||||
|
||||
{#if label}
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="svelte-flow__edge-label"
|
||||
style:transform="translate(-50%, -50%) translate({labelX}px,{labelY}px)"
|
||||
style={labelStyle}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
<EdgeLabel x={labelX} y={labelY} style={labelStyle}>
|
||||
{label}
|
||||
</EdgeLabel>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { getContext } 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;
|
||||
|
||||
const handleEdgeSelect = useHandleEdgeSelect();
|
||||
|
||||
const id = getContext<string>('svelteflow__edge_id');
|
||||
</script>
|
||||
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="svelte-flow__edge-label"
|
||||
style:transform="translate(-50%, -50%) translate({x}px,{y}px)"
|
||||
style={'pointer-events: all;' + style}
|
||||
on:click={() => {
|
||||
if (id) handleEdgeSelect(id);
|
||||
}}
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</EdgeLabelRenderer>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as EdgeLabel } from './EdgeLabel.svelte';
|
||||
@@ -1,14 +1,14 @@
|
||||
<svelte:options immutable />
|
||||
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, setContext } from 'svelte';
|
||||
import cc from 'classcat';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { errorMessages, getMarkerId } from '@xyflow/system';
|
||||
import { getMarkerId } from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
import { BezierEdgeInternal } from '$lib/components/edges';
|
||||
import type { EdgeLayouted, Edge } from '$lib/types';
|
||||
import { get } from 'svelte/store';
|
||||
import { useHandleEdgeSelect } from '$lib/hooks/useHandleEdgeSelect';
|
||||
|
||||
type $$Props = EdgeLayouted;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
export let animated: $$Props['animated'] = false;
|
||||
export let selected: $$Props['selected'] = false;
|
||||
export let selectable: $$Props['selectable'] = true;
|
||||
export let hidden: $$Props['hidden'] = false;
|
||||
export let label: $$Props['label'] = undefined;
|
||||
export let labelStyle: $$Props['labelStyle'] = undefined;
|
||||
@@ -43,16 +42,9 @@
|
||||
let className: string = '';
|
||||
export { className as class };
|
||||
|
||||
const {
|
||||
edges,
|
||||
edgeTypes,
|
||||
flowId,
|
||||
selectionRect,
|
||||
selectionRectMode,
|
||||
multiselectionKeyPressed,
|
||||
addSelectedEdges,
|
||||
unselectNodesAndEdges
|
||||
} = useStore();
|
||||
setContext('svelteflow__edge_id', id);
|
||||
|
||||
const { edgeLookup, edgeTypes, flowId } = useStore();
|
||||
const dispatch = createEventDispatcher<{
|
||||
edgeclick: { edge: Edge; event: MouseEvent | TouchEvent };
|
||||
edgecontextmenu: { edge: Edge; event: MouseEvent };
|
||||
@@ -62,30 +54,19 @@
|
||||
$: markerStartUrl = markerStart ? `url(#${getMarkerId(markerStart, $flowId)})` : undefined;
|
||||
$: markerEndUrl = markerEnd ? `url(#${getMarkerId(markerEnd, $flowId)})` : undefined;
|
||||
|
||||
const handleEdgeSelect = useHandleEdgeSelect();
|
||||
|
||||
function onClick(event: MouseEvent | TouchEvent) {
|
||||
const edge = $edges.find((e) => e.id === id);
|
||||
const edge = $edgeLookup.get(id);
|
||||
|
||||
if (!edge) {
|
||||
console.warn('012', errorMessages['error012'](id));
|
||||
return;
|
||||
if (edge) {
|
||||
handleEdgeSelect(id);
|
||||
dispatch('edgeclick', { event, edge });
|
||||
}
|
||||
|
||||
if (selectable) {
|
||||
selectionRect.set(null);
|
||||
selectionRectMode.set(null);
|
||||
|
||||
if (!edge.selected) {
|
||||
addSelectedEdges([id]);
|
||||
} else if (edge.selected && get(multiselectionKeyPressed)) {
|
||||
unselectNodesAndEdges({ nodes: [], edges: [edge] });
|
||||
}
|
||||
}
|
||||
|
||||
dispatch('edgeclick', { event, edge });
|
||||
}
|
||||
|
||||
function onContextMenu(event: MouseEvent) {
|
||||
const edge = $edges.find((e) => e.id === id);
|
||||
const edge = $edgeLookup.get(id);
|
||||
|
||||
if (edge) {
|
||||
dispatch('edgecontextmenu', { event, edge });
|
||||
|
||||
@@ -126,6 +126,10 @@
|
||||
// @todo implement connectablestart, connectableend
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@component
|
||||
The Handle component is the part of a node that can be used to connect nodes.
|
||||
-->
|
||||
<div
|
||||
data-handleid={handleId}
|
||||
data-nodeid={nodeId}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
export let defaultEdgeOptions: DefaultEdgeOptions | undefined;
|
||||
|
||||
const {
|
||||
elementsSelectable,
|
||||
visibleEdges,
|
||||
edgesInitialized,
|
||||
edges: { setDefaultOptions }
|
||||
@@ -26,11 +25,6 @@
|
||||
</svg>
|
||||
|
||||
{#each $visibleEdges as edge (edge.id)}
|
||||
{@const edgeType = edge.type || 'default'}
|
||||
{@const selectable = !!(
|
||||
edge.selectable ||
|
||||
($elementsSelectable && typeof edge.selectable === 'undefined')
|
||||
)}
|
||||
<EdgeWrapper
|
||||
id={edge.id}
|
||||
source={edge.source}
|
||||
@@ -55,9 +49,8 @@
|
||||
ariaLabel={edge.ariaLabel}
|
||||
interactionWidth={edge.interactionWidth}
|
||||
class={edge.class}
|
||||
type={edgeType}
|
||||
type={edge.type || 'default'}
|
||||
zIndex={edge.zIndex}
|
||||
{selectable}
|
||||
on:edgeclick
|
||||
on:edgecontextmenu
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { get } from 'svelte/store';
|
||||
import { errorMessages } from '@xyflow/system';
|
||||
|
||||
import { useStore } from '$lib/store';
|
||||
|
||||
export function useHandleEdgeSelect() {
|
||||
const {
|
||||
edgeLookup,
|
||||
selectionRect,
|
||||
selectionRectMode,
|
||||
multiselectionKeyPressed,
|
||||
addSelectedEdges,
|
||||
unselectNodesAndEdges,
|
||||
elementsSelectable
|
||||
} = useStore();
|
||||
|
||||
return (id: string) => {
|
||||
const edge = get(edgeLookup).get(id);
|
||||
|
||||
if (!edge) {
|
||||
console.warn('012', errorMessages['error012'](id));
|
||||
return;
|
||||
}
|
||||
|
||||
const selectable =
|
||||
edge.selectable || (get(elementsSelectable) && typeof edge.selectable === 'undefined');
|
||||
|
||||
if (selectable) {
|
||||
selectionRect.set(null);
|
||||
selectionRectMode.set(null);
|
||||
|
||||
if (!edge.selected) {
|
||||
addSelectedEdges([id]);
|
||||
} else if (edge.selected && get(multiselectionKeyPressed)) {
|
||||
unselectNodesAndEdges({ nodes: [], edges: [edge] });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -29,6 +29,10 @@ import { isNode } from '$lib/utils';
|
||||
export function useSvelteFlow(): {
|
||||
zoomIn: ZoomInOut;
|
||||
zoomOut: ZoomInOut;
|
||||
getNode: (id: string) => Node | undefined;
|
||||
getNodes: (ids?: string[]) => Node[];
|
||||
getEdge: (id: string) => Edge | undefined;
|
||||
getEdges: (ids?: string[]) => Edge[];
|
||||
setZoom: (zoomLevel: number, options?: ViewportHelperFunctionOptions) => void;
|
||||
getZoom: () => number;
|
||||
setCenter: (x: number, y: number, options?: SetCenterOptions) => void;
|
||||
@@ -82,7 +86,9 @@ export function useSvelteFlow(): {
|
||||
panZoom,
|
||||
nodes,
|
||||
edges,
|
||||
domNode
|
||||
domNode,
|
||||
nodeLookup,
|
||||
edgeLookup
|
||||
} = useStore();
|
||||
|
||||
const getNodeRect = (
|
||||
@@ -121,6 +127,10 @@ export function useSvelteFlow(): {
|
||||
return {
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
getNode: (id) => get(nodeLookup).get(id),
|
||||
getNodes: (ids) => (ids === undefined ? get(nodes) : getElements(get(nodeLookup), ids)),
|
||||
getEdge: (id) => get(edgeLookup).get(id),
|
||||
getEdges: (ids) => (ids === undefined ? get(edges) : getElements(get(edgeLookup), ids)),
|
||||
setZoom: (zoomLevel, options) => {
|
||||
get(panZoom)?.scaleTo(zoomLevel, { duration: options?.duration });
|
||||
},
|
||||
@@ -295,3 +305,17 @@ export function useSvelteFlow(): {
|
||||
viewport
|
||||
};
|
||||
}
|
||||
|
||||
function getElements<EdgeOrNode>(lookup: Map<string, EdgeOrNode>, ids: string[]) {
|
||||
const result = [];
|
||||
|
||||
for (const id of ids) {
|
||||
const element = lookup.get(id);
|
||||
|
||||
if (element) {
|
||||
result.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ export {
|
||||
type OnError,
|
||||
type NodeProps,
|
||||
type NodeOrigin,
|
||||
type OnNodeDrag,
|
||||
type OnSelectionDrag,
|
||||
Position,
|
||||
type XYPosition,
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
type XYPosition,
|
||||
type CoordinateExtent,
|
||||
type UpdateConnection,
|
||||
type NodeBase,
|
||||
type NodeDragItem,
|
||||
errorMessages
|
||||
} from '@xyflow/system';
|
||||
@@ -67,7 +66,7 @@ export function createStore({
|
||||
const updateNodePositions: UpdateNodePositions = (nodeDragItems, dragging = false) => {
|
||||
store.nodes.update((nds) => {
|
||||
return nds.map((node) => {
|
||||
const nodeDragItem = (nodeDragItems as Array<NodeBase | NodeDragItem>).find(
|
||||
const nodeDragItem = (nodeDragItems as Array<Node | NodeDragItem>).find(
|
||||
(ndi) => ndi.id === node.id
|
||||
);
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
type OnConnectStart,
|
||||
type OnConnectEnd,
|
||||
type NodeLookup,
|
||||
type OnBeforeDelete,
|
||||
type EdgeLookup
|
||||
} from '@xyflow/system';
|
||||
|
||||
@@ -47,7 +46,8 @@ import type {
|
||||
Edge,
|
||||
FitViewOptions,
|
||||
OnDelete,
|
||||
OnEdgeCreate
|
||||
OnEdgeCreate,
|
||||
OnBeforeDelete
|
||||
} from '$lib/types';
|
||||
import { createNodesStore, createEdgesStore } from './utils';
|
||||
import { initConnectionProps, type ConnectionProps } from './derived-connection-props';
|
||||
|
||||
@@ -5,7 +5,8 @@ import type {
|
||||
Position,
|
||||
XYPosition,
|
||||
ConnectingHandle,
|
||||
Connection
|
||||
Connection,
|
||||
OnBeforeDeleteBase
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type { Node } from './nodes';
|
||||
@@ -52,3 +53,7 @@ export type FitViewOptions = FitViewOptionsBase<Node>;
|
||||
|
||||
export type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void;
|
||||
export type OnEdgeCreate = (connection: Connection) => Edge | Connection | void;
|
||||
export type OnBeforeDelete<
|
||||
NodeType extends Node = Node,
|
||||
EdgeType extends Edge = Edge
|
||||
> = OnBeforeDeleteBase<NodeType, EdgeType>;
|
||||
|
||||
@@ -2,16 +2,7 @@
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/base.css';
|
||||
|
||||
.svelte-flow {
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.svelte-flow.dark {
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.svelte-flow__edge-label {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
color: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -3,19 +3,14 @@
|
||||
@import '../../../system/src/styles/style.css';
|
||||
@import '../../../system/src/styles/node-resizer.css';
|
||||
|
||||
.svelte-flow {
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.svelte-flow.dark {
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.svelte-flow__edge-label {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
padding: 2px;
|
||||
font-size: 10px;
|
||||
color: var(--edge-label-color, var(--edge-label-color-default));
|
||||
cursor: pointer;
|
||||
color: var(--xy-edge-label-color, var(--xy-edge-label-color-default));
|
||||
background: var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default));
|
||||
}
|
||||
|
||||
.svelte-flow__nodes {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xyflow/system",
|
||||
"version": "0.0.14",
|
||||
"version": "0.0.15",
|
||||
"description": "xyflow core system that powers React Flow and Svelte Flow.",
|
||||
"keywords": [
|
||||
"node-based UI",
|
||||
|
||||
@@ -139,8 +139,8 @@
|
||||
}
|
||||
|
||||
&.selected .xy-flow__edge-path,
|
||||
&:focus .xy-flow__edge-path,
|
||||
&:focus-visible .xy-flow__edge-path {
|
||||
&.selectable:focus .xy-flow__edge-path,
|
||||
&.selectable:focus-visible .xy-flow__edge-path {
|
||||
stroke: var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
--xy-controls-button-color-hover-default: inherit;
|
||||
--xy-controls-button-border-color-default: #eee;
|
||||
--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
|
||||
--xy-edge-label-background-color-default: #ffffff;
|
||||
--xy-edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.xy-flow.dark {
|
||||
@@ -41,6 +44,9 @@
|
||||
--xy-controls-button-color-hover-default: #fff;
|
||||
--xy-controls-button-border-color-default: #5b5b5b;
|
||||
--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
|
||||
--xy-edge-label-background-color-default: #141414;
|
||||
--xy-edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.xy-flow__edge {
|
||||
|
||||
@@ -142,7 +142,7 @@ export type ColorMode = ColorModeClass | 'system';
|
||||
|
||||
export type ConnectionLookup = Map<string, Map<string, Connection>>;
|
||||
|
||||
export type OnBeforeDelete = <NodeType extends NodeBase = NodeBase, EdgeType extends EdgeBase = EdgeBase>({
|
||||
export type OnBeforeDeleteBase<NodeType extends NodeBase = NodeBase, EdgeType extends EdgeBase = EdgeBase> = ({
|
||||
nodes,
|
||||
edges,
|
||||
}: {
|
||||
|
||||
@@ -94,9 +94,9 @@ export type NodeProps<T = any> = {
|
||||
positionAbsoluteY: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
dragging: boolean;
|
||||
targetPosition?: Position;
|
||||
sourcePosition?: Position;
|
||||
dragging: NodeBase['dragging'];
|
||||
sourcePosition?: NodeBase['sourcePosition'];
|
||||
targetPosition?: NodeBase['targetPosition'];
|
||||
};
|
||||
|
||||
export type NodeHandleBounds = {
|
||||
@@ -134,8 +134,6 @@ export type NodeDragItem = {
|
||||
|
||||
export type NodeOrigin = [number, number];
|
||||
|
||||
export type OnNodeDrag = (event: MouseEvent, node: NodeBase, nodes: NodeBase[]) => void;
|
||||
|
||||
export type OnSelectionDrag = (event: MouseEvent, nodes: NodeBase[]) => void;
|
||||
|
||||
export type NodeHandle = Optional<HandleElement, 'width' | 'height'>;
|
||||
|
||||
@@ -114,11 +114,6 @@ function getHandle(bounds: HandleElement[], handleId?: string | null): HandleEle
|
||||
return null;
|
||||
}
|
||||
|
||||
if (bounds.length === 1 || !handleId) {
|
||||
return bounds[0];
|
||||
} else if (handleId) {
|
||||
return bounds.find((d) => d.id === handleId) || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
// if no handleId is given, we use the first handle, otherwise we check for the id
|
||||
return (!handleId ? bounds[0] : bounds.find((d) => d.id === handleId)) || null;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
NodeDragItem,
|
||||
CoordinateExtent,
|
||||
OnError,
|
||||
OnBeforeDelete,
|
||||
OnBeforeDeleteBase,
|
||||
} from '../types';
|
||||
import { errorMessages } from '../constants';
|
||||
|
||||
@@ -347,7 +347,7 @@ export async function getElementsToRemove<NodeType extends NodeBase = NodeBase,
|
||||
edgesToRemove: Partial<EdgeType>[];
|
||||
nodes: NodeType[];
|
||||
edges: EdgeType[];
|
||||
onBeforeDelete?: OnBeforeDelete;
|
||||
onBeforeDelete?: OnBeforeDeleteBase<NodeType, EdgeType>;
|
||||
}): Promise<{
|
||||
nodes: NodeType[];
|
||||
edges: EdgeType[];
|
||||
|
||||
@@ -23,7 +23,6 @@ import type {
|
||||
SnapGrid,
|
||||
Transform,
|
||||
PanBy,
|
||||
OnNodeDrag,
|
||||
OnSelectionDrag,
|
||||
UpdateNodePositions,
|
||||
Box,
|
||||
@@ -31,7 +30,7 @@ import type {
|
||||
|
||||
export type OnDrag = (event: MouseEvent, dragItems: NodeDragItem[], node: NodeBase, nodes: NodeBase[]) => void;
|
||||
|
||||
type StoreItems = {
|
||||
type StoreItems<OnNodeDrag> = {
|
||||
nodes: NodeBase[];
|
||||
nodeLookup: Map<string, NodeBase>;
|
||||
edges: EdgeBase[];
|
||||
@@ -58,9 +57,9 @@ type StoreItems = {
|
||||
updateNodePositions: UpdateNodePositions;
|
||||
};
|
||||
|
||||
export type XYDragParams = {
|
||||
export type XYDragParams<OnNodeDrag> = {
|
||||
domNode: Element;
|
||||
getStoreItems: () => StoreItems;
|
||||
getStoreItems: () => StoreItems<OnNodeDrag>;
|
||||
onDragStart?: OnDrag;
|
||||
onDrag?: OnDrag;
|
||||
onDragStop?: OnDrag;
|
||||
@@ -80,14 +79,15 @@ export type DragUpdateParams = {
|
||||
domNode: Element;
|
||||
};
|
||||
|
||||
export function XYDrag({
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function XYDrag<OnNodeDrag extends (e: any, nodes: any, node: any) => void | undefined>({
|
||||
domNode,
|
||||
onNodeMouseDown,
|
||||
getStoreItems,
|
||||
onDragStart,
|
||||
onDrag,
|
||||
onDragStop,
|
||||
}: XYDragParams): XYDragInstance {
|
||||
}: XYDragParams<OnNodeDrag>): XYDragInstance {
|
||||
let lastPos: { x: number | null; y: number | null } = { x: null, y: null };
|
||||
let autoPanId = 0;
|
||||
let dragItems: NodeDragItem[] = [];
|
||||
|
||||
Reference in New Issue
Block a user