Graduation
/
ui
/node_modules
/@xyflow
/svelte
/dist
/lib
/components
/NodeWrapper
/NodeWrapper.svelte
<svelte:options immutable /> | |
<script>import { setContext, onDestroy, createEventDispatcher } from 'svelte'; | |
import { get, writable } from 'svelte/store'; | |
import cc from 'classcat'; | |
import { errorMessages, Position } from '@xyflow/system'; | |
import drag from '../../actions/drag'; | |
import { useStore } from '../../store'; | |
import DefaultNode from '../nodes/DefaultNode.svelte'; | |
import { getNodeInlineStyleDimensions } from './utils'; | |
export let node; | |
export let id; | |
export let data = {}; | |
export let selected = false; | |
export let draggable = undefined; | |
export let selectable = undefined; | |
export let connectable = true; | |
export let deletable = true; | |
export let hidden = false; | |
export let dragging = false; | |
export let resizeObserver = null; | |
export let style = undefined; | |
export let type = 'default'; | |
export let isParent = false; | |
export let positionX; | |
export let positionY; | |
export let sourcePosition = undefined; | |
export let targetPosition = undefined; | |
export let zIndex; | |
export let measuredWidth = undefined; | |
export let measuredHeight = undefined; | |
export let initialWidth = undefined; | |
export let initialHeight = undefined; | |
export let width = undefined; | |
export let height = undefined; | |
export let dragHandle = undefined; | |
export let initialized = false; | |
export let parentId = undefined; | |
export let nodeClickDistance = undefined; | |
let className = ''; | |
export { className as class }; | |
const store = useStore(); | |
const { nodeTypes, nodeDragThreshold, selectNodesOnDrag, handleNodeSelection, updateNodeInternals } = store; | |
let nodeRef; | |
let prevNodeRef = null; | |
const dispatchNodeEvent = createEventDispatcher(); | |
const connectableStore = writable(connectable); | |
let prevType = undefined; | |
let prevSourcePosition = undefined; | |
let prevTargetPosition = undefined; | |
$: nodeType = type || 'default'; | |
$: nodeTypeValid = !!$nodeTypes[nodeType]; | |
$: nodeComponent = $nodeTypes[nodeType] || DefaultNode; | |
$: { | |
if (!nodeTypeValid) { | |
console.warn('003', errorMessages['error003'](type)); | |
} | |
} | |
$: inlineStyleDimensions = getNodeInlineStyleDimensions({ | |
width, | |
height, | |
initialWidth, | |
initialHeight, | |
measuredWidth, | |
measuredHeight | |
}); | |
$: { | |
connectableStore.set(!!connectable); | |
} | |
$: { | |
// if type, sourcePosition or targetPosition changes, | |
// we need to re-calculate the handle positions | |
const doUpdate = (prevType && nodeType !== prevType) || | |
(prevSourcePosition && sourcePosition !== prevSourcePosition) || | |
(prevTargetPosition && targetPosition !== prevTargetPosition); | |
if (doUpdate) { | |
requestAnimationFrame(() => updateNodeInternals(new Map([ | |
[ | |
id, | |
{ | |
id, | |
nodeElement: nodeRef, | |
force: true | |
} | |
] | |
]))); | |
} | |
prevType = nodeType; | |
prevSourcePosition = sourcePosition; | |
prevTargetPosition = targetPosition; | |
} | |
setContext('svelteflow__node_id', id); | |
setContext('svelteflow__node_connectable', connectableStore); | |
$: { | |
if (resizeObserver && (nodeRef !== prevNodeRef || !initialized)) { | |
prevNodeRef && resizeObserver.unobserve(prevNodeRef); | |
nodeRef && resizeObserver.observe(nodeRef); | |
prevNodeRef = nodeRef; | |
} | |
} | |
onDestroy(() => { | |
if (prevNodeRef) { | |
resizeObserver?.unobserve(prevNodeRef); | |
} | |
}); | |
function onSelectNodeHandler(event) { | |
if (selectable && (!get(selectNodesOnDrag) || !draggable || get(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); | |
} | |
dispatchNodeEvent('nodeclick', { node: node.internals.userNode, event }); | |
} | |
</script> | |
<!-- svelte-ignore a11y-click-events-have-key-events --> | |
<!-- svelte-ignore a11y-no-static-element-interactions --> | |
{#if !hidden} | |
<div | |
use:drag={{ | |
nodeId: id, | |
isSelectable: selectable, | |
disabled: false, | |
handleSelector: dragHandle, | |
noDragClass: 'nodrag', | |
nodeClickDistance, | |
onNodeMouseDown: handleNodeSelection, | |
onDrag: (event, _, targetNode, nodes) => { | |
dispatchNodeEvent('nodedrag', { event, targetNode, nodes }); | |
}, | |
onDragStart: (event, _, targetNode, nodes) => { | |
dispatchNodeEvent('nodedragstart', { event, targetNode, nodes }); | |
}, | |
onDragStop: (event, _, targetNode, nodes) => { | |
dispatchNodeEvent('nodedragstop', { event, targetNode, nodes }); | |
}, | |
store | |
}} | |
bind:this={nodeRef} | |
data-id={id} | |
class={cc(['svelte-flow__node', `svelte-flow__node-${nodeType}`, className])} | |
class:dragging | |
class:selected | |
class:draggable | |
class:connectable | |
class:selectable | |
class:nopan={draggable} | |
class:parent={isParent} | |
style:z-index={zIndex} | |
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 })} | |
> | |
<svelte:component | |
this={nodeComponent} | |
{data} | |
{id} | |
{selected} | |
{selectable} | |
{deletable} | |
{sourcePosition} | |
{targetPosition} | |
{zIndex} | |
{dragging} | |
{draggable} | |
{dragHandle} | |
{parentId} | |
type={nodeType} | |
isConnectable={$connectableStore} | |
positionAbsoluteX={positionX} | |
positionAbsoluteY={positionY} | |
{width} | |
{height} | |
/> | |
</div> | |
{/if} | |