prevent passing of props to the div element as attributes

This commit is contained in:
peterkogo
2025-01-29 16:01:31 +01:00
parent 25db8d4e66
commit f481ee3953
5 changed files with 179 additions and 46 deletions

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { getContext, setContext, onDestroy } from 'svelte';
import type { DOMAttributes } from 'svelte/elements';
import { ConnectionLineType, PanOnScrollMode } from '@xyflow/system';
import { key, createStore } from '$lib/store';
@@ -15,10 +16,9 @@
import { Attribution } from '$lib/components/Attribution';
import type { SvelteFlowProps } from './types';
import { type ProviderContext, type StoreContext } from '$lib/store/types';
import Wrapper from './Wrapper.svelte';
let {
style,
class: className,
width,
height,
proOptions,
@@ -66,7 +66,7 @@
edges = $bindable([]),
viewport = $bindable(undefined),
...props
}: SvelteFlowProps = $props();
}: SvelteFlowProps & DOMAttributes<HTMLDivElement> = $props();
const store = createStore({
props,
@@ -111,17 +111,14 @@
});
</script>
<div
bind:this={store.domNode}
<Wrapper
bind:domNode={store.domNode}
bind:clientWidth={store.width}
bind:clientHeight={store.height}
style:width
style:height
{style}
class={['svelte-flow', className, store.colorMode]}
data-testid="svelte-flow__wrapper"
role="application"
{...props}
colorMode={store.colorMode}
{width}
{height}
rest={props}
>
<KeyHandler
{store}
@@ -195,31 +192,4 @@
</Zoom>
<Attribution {proOptions} position={attributionPosition} />
{@render children?.()}
</div>
<style>
.svelte-flow {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
z-index: 0;
background-color: var(--background-color, var(--background-color-default));
}
:root {
--background-color-default: #fff;
--background-pattern-color-default: #ddd;
--minimap-mask-color-default: rgb(240, 240, 240, 0.6);
--minimap-mask-stroke-color-default: none;
--minimap-mask-stroke-width-default: 1;
--controls-button-background-color-default: #fefefe;
--controls-button-background-color-hover-default: #f4f4f4;
--controls-button-color-default: inherit;
--controls-button-color-hover-default: inherit;
--controls-button-border-color-default: #eee;
}
</style>
</Wrapper>

View File

@@ -0,0 +1,115 @@
<script lang="ts">
import type { ClassValue, DOMAttributes } from 'svelte/elements';
import type { Snippet } from 'svelte';
import { type SvelteFlowRestProps } from '$lib/store/types';
let {
width,
height,
class: className,
colorMode,
domNode = $bindable(),
clientWidth = $bindable(),
clientHeight = $bindable(),
children,
rest
}: {
width?: number;
height?: number;
class?: ClassValue;
colorMode?: string;
domNode: HTMLDivElement | null;
clientWidth?: number;
clientHeight?: number;
children?: Snippet;
rest: SvelteFlowRestProps & DOMAttributes<HTMLDivElement>;
} = $props();
// Unfortunately we have to destructure the props here this way,
// so we don't pass all the props as attributes to the div element
let {
id,
nodeTypes,
edgeTypes,
colorMode: _colorMode,
isValidConnection,
onerror,
ondelete,
onbeforedelete,
onedgecreate,
onconnect,
onconnectstart,
onconnectend,
oninit,
fitView,
fitViewOptions,
nodeOrigin,
nodeDragThreshold,
minZoom,
maxZoom,
initialViewport,
connectionRadius,
connectionMode,
selectionMode,
selectNodesOnDrag,
snapGrid,
defaultMarkerColor,
nodesDraggable,
nodesConnectable,
elementsSelectable,
translateExtent,
nodeExtent,
onlyRenderVisibleElements,
autoPanOnConnect,
autoPanOnNodeDrag,
colorModeSSR,
style,
defaultEdgeOptions,
...divAttributes
} = $derived(rest);
type OnlyDivAttributes<T> = {
[K in keyof T]: K extends keyof DOMAttributes<HTMLDivElement> ? T[K] : never;
};
</script>
<div
bind:this={domNode}
bind:clientHeight
bind:clientWidth
style:width
style:height
class={['svelte-flow', 'svelte-flow-container', className, colorMode]}
data-testid="svelte-flow__wrapper"
role="application"
{...divAttributes satisfies OnlyDivAttributes<typeof divAttributes>}
>
{@render children?.()}
</div>
<style>
.svelte-flow {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
z-index: 0;
background-color: var(--background-color, var(--background-color-default));
}
:root {
--background-color-default: #fff;
--background-pattern-color-default: #ddd;
--minimap-mask-color-default: rgb(240, 240, 240, 0.6);
--minimap-mask-stroke-color-default: none;
--minimap-mask-stroke-width-default: 1;
--controls-button-background-color-default: #fefefe;
--controls-button-background-color-hover-default: #f4f4f4;
--controls-button-color-default: inherit;
--controls-button-color-hover-default: inherit;
--controls-button-border-color-default: #eee;
}
</style>

View File

@@ -1,4 +1,4 @@
import type { ClassValue, DOMAttributes } from 'svelte/elements';
import type { ClassValue } from 'svelte/elements';
import type {
ConnectionLineType,
NodeOrigin,
@@ -41,8 +41,7 @@ import type { EdgeEvents, NodeEvents, NodeSelectionEvents, PaneEvents } from '$l
export type SvelteFlowProps = NodeEvents &
NodeSelectionEvents &
EdgeEvents &
PaneEvents &
DOMAttributes<HTMLDivElement> & {
PaneEvents & {
/** The id of the flow
*
* This is necessary if you want to render multiple flows.

View File

@@ -21,8 +21,6 @@ import {
import type { EdgeTypes, NodeTypes, Node, Edge, FitViewOptions } from '$lib/types';
import { initialEdgeTypes, initialNodeTypes, getInitialStore } from './initial-store.svelte';
import { type StoreSignals, type SvelteFlowStore, type SvelteFlowStoreActions } from './types';
// import { getVisibleEdges } from './visible-edges';
// import { getVisibleNodes } from './visible-nodes';
export const key = Symbol();

View File

@@ -37,8 +37,59 @@ export type SvelteFlowStoreActions = {
reset(): void;
};
export type SvelteFlowRestProps = Omit<
SvelteFlowProps,
| 'width'
| 'height'
| 'class'
| 'proOptions'
| 'selectionKey'
| 'deleteKey'
| 'panActivationKey'
| 'multiSelectionKey'
| 'zoomActivationKey'
| 'paneClickDistance'
| 'nodeClickDistance'
| 'onMoveStart'
| 'onMoveEnd'
| 'onMove'
| 'onnodeclick'
| 'onnodecontextmenu'
| 'onnodedrag'
| 'onnodedragstart'
| 'onnodedragstop'
| 'onnodepointerenter'
| 'onnodepointermove'
| 'onnodepointerleave'
| 'onselectionclick'
| 'onselectioncontextmenu'
| 'onedgeclick'
| 'onedgecontextmenu'
| 'onedgepointerenter'
| 'onedgepointerleave'
| 'onpaneclick'
| 'onpanecontextmenu'
| 'panOnScrollMode'
| 'preventScrolling'
| 'zoomOnScroll'
| 'zoomOnDoubleClick'
| 'zoomOnPinch'
| 'panOnScroll'
| 'panOnDrag'
| 'selectionOnDrag'
| 'connectionLineComponent'
| 'connectionLineStyle'
| 'connectionLineContainerStyle'
| 'connectionLineType'
| 'attributionPosition'
| 'children'
| 'nodes'
| 'edges'
| 'viewport'
>;
export type StoreSignals = {
props: Partial<SvelteFlowProps>;
props: SvelteFlowRestProps;
width?: number;
height?: number;
nodes: Node[];