refactor(additional-components): move additional components into separate pkg

This commit is contained in:
braks
2022-10-08 23:25:34 +02:00
committed by Braks
parent 8567e3733b
commit c1bcc02797
82 changed files with 934 additions and 222 deletions
-1
View File
@@ -58,7 +58,6 @@
"unplugin-auto-import": "^0.11.2",
"vite": "^2.9.15",
"vite-plugin-vue-type-imports": "0.2.0",
"vite-svg-loader": "^3.6.0",
"vue-tsc": "^0.40.13"
},
"publishConfig": {
@@ -1,88 +0,0 @@
<script lang="ts" setup>
import { BackgroundVariant } from '../../types'
import { useVueFlow } from '../../composables'
import type { BackgroundProps } from '../../types/components'
const {
variant = 'dots' as BackgroundVariant,
gap = 10,
size = 0.4,
height = 100,
width = 100,
x = 0,
y = 0,
bgColor,
patternColor: initialPatternColor,
} = defineProps<BackgroundProps>()
const defaultColors: Record<BackgroundVariant, string> = {
[BackgroundVariant.Dots]: '#81818a',
[BackgroundVariant.Lines]: '#eee',
}
const { viewport } = $(useVueFlow())
const background = $computed(() => {
const scaledGap = gap && gap * viewport.zoom
const xOffset = scaledGap && viewport.x % scaledGap
const yOffset = scaledGap && viewport.y % scaledGap
const bgSize = size * viewport.zoom
return {
scaledGap,
xOffset,
yOffset,
size: bgSize,
}
})
// when there are multiple flows on a page we need to make sure that every background gets its own pattern.
const patternId = `pattern-${Math.floor(Math.random() * 100000)}`
const patternColor = computed(() => initialPatternColor || defaultColors[variant || BackgroundVariant.Dots])
const d = computed(
() => `M${background.scaledGap / 2} 0 V${background.scaledGap} M0 ${background.scaledGap / 2} H${background.scaledGap}`,
)
</script>
<script lang="ts">
export default {
name: 'Background',
}
</script>
<template>
<svg
class="vue-flow__background"
:style="{
height: `${height > 100 ? 100 : height}%`,
width: `${width > 100 ? 100 : width}%`,
}"
>
<slot :id="patternId" name="pattern-container">
<pattern
:id="patternId"
:x="background.xOffset"
:y="background.yOffset"
:width="background.scaledGap"
:height="background.scaledGap"
patternUnits="userSpaceOnUse"
>
<slot name="pattern">
<template v-if="variant === BackgroundVariant.Lines">
<path :stroke="patternColor" :stroke-width="size" :d="d" />
</template>
<template v-else-if="variant === BackgroundVariant.Dots">
<circle :cx="background.size" :cy="background.size" :r="background.size" :fill="patternColor" />
</template>
<svg v-if="bgColor" height="100" width="100">
<rect width="100%" height="100%" :fill="bgColor" />
</svg>
</slot>
</pattern>
</slot>
<rect :x="x" :y="y" width="100%" height="100%" :fill="`url(#${patternId})`" />
<slot :id="patternId" />
</svg>
</template>
@@ -1,11 +0,0 @@
<script lang="ts">
export default {
name: 'ControlButton',
}
</script>
<template>
<button class="vue-flow__controls-button">
<slot></slot>
</button>
</template>
@@ -1,93 +0,0 @@
<script lang="ts" setup>
import { useVueFlow } from '../../composables'
import type { ControlProps } from '../../types/components'
import ControlButton from './ControlButton.vue'
import PlusIcon from '~/assets/icons/plus.svg'
import MinusIcon from '~/assets/icons/minus.svg'
import FitView from '~/assets/icons/fitview.svg'
import Lock from '~/assets/icons/lock.svg'
import Unlock from '~/assets/icons/unlock.svg'
const { showZoom = true, showFitView = true, showInteractive = true, fitViewParams } = defineProps<ControlProps>()
const emit = defineEmits<{
(event: 'zoomIn'): void
(event: 'zoomOut'): void
(event: 'fitView'): void
(event: 'interactionChange', active: boolean): void
}>()
const { nodesDraggable, nodesConnectable, elementsSelectable, setInteractive, zoomIn, zoomOut, fitView } = $(useVueFlow())
const isInteractive = computed(() => nodesDraggable && nodesConnectable && elementsSelectable)
const onZoomInHandler = () => {
zoomIn()
emit('zoomIn')
}
const onZoomOutHandler = () => {
zoomOut()
emit('zoomOut')
}
const onFitViewHandler = () => {
fitView(fitViewParams)
emit('fitView')
}
const onInteractiveChangeHandler = () => {
setInteractive(!isInteractive.value)
emit('interactionChange', !isInteractive.value)
}
</script>
<script lang="ts">
export default {
name: 'Controls',
}
</script>
<template>
<div class="vue-flow__controls">
<slot name="top"></slot>
<template v-if="showZoom">
<slot name="control-zoom-in">
<ControlButton class="vue-flow__controls-zoomin" @click="onZoomInHandler">
<slot name="icon-zoom-in">
<PlusIcon />
</slot>
</ControlButton>
</slot>
<slot name="control-zoom-out">
<ControlButton class="vue-flow__controls-zoomout" @click="onZoomOutHandler">
<slot name="icon-zoom-out">
<MinusIcon />
</slot>
</ControlButton>
</slot>
</template>
<template v-if="showFitView">
<slot name="control-fit-view">
<ControlButton class="vue-flow__controls-fitview" @click="onFitViewHandler">
<slot name="icon-fit-view">
<FitView />
</slot>
</ControlButton>
</slot>
</template>
<template v-if="showInteractive">
<slot name="control-interactive">
<ControlButton v-if="showInteractive" class="vue-flow__controls-interactive" @click="onInteractiveChangeHandler">
<slot v-if="isInteractive" name="icon-unlock">
<Unlock />
</slot>
<slot v-if="!isInteractive" name="icon-lock">
<Lock />
</slot>
</ControlButton>
</slot>
</template>
<slot></slot>
</div>
</template>
@@ -1,170 +0,0 @@
<script lang="ts" setup>
import type { GraphNode, MiniMapNodeFunc, ShapeRendering } from '../../types'
import { useVueFlow, useWindow } from '../../composables'
import { getBoundsofRects, getConnectedEdges, getRectOfNodes } from '../../utils'
import type { MiniMapProps } from '../../types/components'
import MiniMapNode from './MiniMapNode'
const {
width,
height,
nodeStrokeColor = '#555',
nodeColor = '#fff',
nodeClassName,
nodeBorderRadius = 5,
nodeStrokeWidth = 2,
maskColor = 'rgb(240, 242, 243, 0.7)',
} = defineProps<MiniMapProps>()
const emit = defineEmits(['nodeClick', 'nodeDblclick', 'nodeMouseenter', 'nodeMousemove', 'nodeMouseleave'])
const attrs: Record<string, any> = useAttrs()
const window = useWindow()
const defaultWidth = 200
const defaultHeight = 150
const { edges, viewport, dimensions, emits, getNodes } = $(useVueFlow())
const elementWidth = $computed(() => width ?? attrs.style?.width ?? defaultWidth)
const elementHeight = $computed(() => height ?? attrs.style?.height ?? defaultHeight)
const nodeColorFunc: MiniMapNodeFunc = nodeColor instanceof Function ? nodeColor : () => nodeColor as string
const nodeStrokeColorFunc: MiniMapNodeFunc =
nodeStrokeColor instanceof Function ? nodeStrokeColor : () => nodeStrokeColor as string
const nodeClassNameFunc = nodeClassName instanceof Function ? nodeClassName : ((() => nodeClassName) as MiniMapNodeFunc)
const shapeRendering: ShapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision'
const bb = $computed(() => {
return getRectOfNodes(getNodes)
})
const viewBB = $computed(() => ({
x: -viewport.x / viewport.zoom,
y: -viewport.y / viewport.zoom,
width: dimensions.width / viewport.zoom,
height: dimensions.height / viewport.zoom,
}))
const viewBox = $(
controlledComputed($$(viewBB), () => {
const boundingRect = getNodes && getNodes.length ? getBoundsofRects(bb, viewBB) : viewBB
const scaledWidth = boundingRect.width / elementWidth
const scaledHeight = boundingRect.height / elementHeight
const viewScale = Math.max(scaledWidth, scaledHeight)
const viewWidth = viewScale * elementWidth
const viewHeight = viewScale * elementHeight
const offset = 5 * viewScale
return {
offset,
x: boundingRect.x - (viewWidth - boundingRect.width) / 2 - offset,
y: boundingRect.y - (viewHeight - boundingRect.height) / 2 - offset,
width: viewWidth + offset * 2,
height: viewHeight + offset * 2,
}
}),
)
const d = controlledComputed($$(viewBox), () => {
if (viewBox.x && viewBox.y) {
return `
M${viewBox.x - viewBox.offset},${viewBox.y - viewBox.offset}
h${viewBox.width + viewBox.offset * 2}
v${viewBox.height + viewBox.offset * 2}
h${-viewBox.width - viewBox.offset * 2}z
M${viewBB.x},${viewBB.y}
h${viewBB.width}
v${viewBB.height}
h${-viewBB.width}z`
} else {
return ''
}
})
const onNodeClick = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges) }
emits.miniMapNodeClick(param)
emit('nodeClick', param)
}
const onNodeDblClick = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges) }
emits.miniMapNodeDoubleClick(param)
emit('nodeDblclick', param)
}
const onNodeMouseEnter = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges) }
emits.miniMapNodeMouseEnter(param)
emit('nodeMouseenter', param)
}
const onNodeMouseMove = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges) }
emits.miniMapNodeMouseMove(param)
emit('nodeMousemove', param)
}
const onNodeMouseLeave = (event: MouseEvent, node: GraphNode) => {
const param = { event, node, connectedEdges: getConnectedEdges([node], edges) }
emits.miniMapNodeMouseLeave(param)
emit('nodeMouseleave', param)
}
</script>
<script lang="ts">
export default {
name: 'MiniMap',
}
</script>
<template>
<svg
:width="elementWidth"
:height="elementHeight"
:viewBox="[viewBox.x, viewBox.y, viewBox.width, viewBox.height].join(' ')"
class="vue-flow__minimap"
>
<MiniMapNode
v-for="node of getNodes"
:id="node.id"
:key="node.id"
:position="node.computedPosition"
:dimensions="node.dimensions"
:style="node.style"
:class="nodeClassNameFunc(node)"
:color="nodeColorFunc(node)"
:border-radius="nodeBorderRadius"
:stroke-color="nodeStrokeColorFunc(node)"
:stroke-width="nodeStrokeWidth"
:shape-rendering="shapeRendering"
@click="onNodeClick($event, node)"
@dblclick="onNodeDblClick($event, node)"
@mouseenter="onNodeMouseEnter($event, node)"
@mousemove="onNodeMouseMove($event, node)"
@mouseleave="onNodeMouseLeave($event, node)"
>
<slot
:id="node.id"
:name="`node-${node.type}`"
:parent-node="node.parentNode"
:selected="node.selected"
:position="node.computedPosition"
:dimensions="node.dimensions"
:style="node.style"
:class="nodeClassNameFunc(node)"
:color="nodeColorFunc(node)"
:border-radius="nodeBorderRadius"
:stroke-color="nodeStrokeColorFunc(node)"
:stroke-width="nodeStrokeWidth"
:shape-rendering="shapeRendering"
/>
</MiniMapNode>
<path class="vue-flow__minimap-mask" :d="d" :fill="maskColor" fill-rule="evenodd" />
</svg>
</template>
@@ -1,46 +0,0 @@
import type { CSSProperties, FunctionalComponent } from 'vue'
import type { MiniMapNodeProps } from '~/types'
const MiniMapNode: FunctionalComponent<MiniMapNodeProps> = function (
{
position: { x, y },
dimensions: { height, width },
strokeWidth,
strokeColor,
borderRadius,
color,
shapeRendering = 'geometricPrecision',
},
{ attrs, emit, slots },
) {
const style = (attrs.style ?? {}) as CSSProperties
return [
h('rect', {
class: ['vue-flow__minimap-node', attrs.class].join(' '),
style,
x,
y,
rx: borderRadius,
ry: borderRadius,
width,
height,
fill: color || (style.background as string) || style.backgroundColor,
stroke: strokeColor,
strokeWidth,
shapeRendering,
onClick: (e: MouseEvent) => emit('click', e),
onDblClick: (e: MouseEvent) => emit('dblclick', e),
onMouseenter: (e: MouseEvent) => emit('mouseenter', e),
onMousemove: (e: MouseEvent) => emit('mousemove', e),
onMouseleave: (e: MouseEvent) => emit('mouseleave', e),
}),
slots?.default?.(),
]
}
MiniMapNode.props = ['position', 'dimensions', 'strokeWidth', 'strokeColor', 'borderRadius', 'color', 'shapeRendering']
MiniMapNode.emits = ['click', 'dblclick', 'mouseenter', 'mousemove', 'mouseleave']
export default MiniMapNode
@@ -1,5 +0,0 @@
export { default as MiniMap } from './MiniMap/MiniMap.vue'
export { default as MiniMapNode } from './MiniMap/MiniMapNode'
export { default as Controls } from './Controls/Controls.vue'
export { default as ControlButton } from './Controls/ControlButton.vue'
export { default as Background } from './Background/Background.vue'
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 30">
<path d="M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" />
</svg>

Before

Width:  |  Height:  |  Size: 463 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" />
</svg>

Before

Width:  |  Height:  |  Size: 530 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 5">
<path d="M0 0h32v4.2H0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 96 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path d="M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"/>
</svg>

Before

Width:  |  Height:  |  Size: 152 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" />
</svg>

Before

Width:  |  Height:  |  Size: 472 B

-3
View File
@@ -1,5 +1,2 @@
declare const __VUE_FLOW_VERSION__: string
declare const __ENV__: string
declare interface Window {
chrome?: any
}
-1
View File
@@ -1,5 +1,4 @@
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />
/// <reference types="vue/macros-global" />
declare module '*.vue' {
+1 -2
View File
@@ -26,6 +26,7 @@ export {
graphPosToZoomedPos,
getNodesInside,
getMarkerId,
getBoundsofRects,
} from './utils/graph'
/**
@@ -48,6 +49,4 @@ export { default as useNode } from './composables/useNode'
export { default as useEdge } from './composables/useEdge'
export * from './additional-components'
export * from './types'
+1 -76
View File
@@ -1,8 +1,6 @@
import type { CSSProperties, Component, DefineComponent, SVGAttributes, VNode } from 'vue'
import type { BackgroundVariant, Dimensions, XYPosition } from './flow'
import type { GraphNode, NodeProps } from './node'
import type { NodeProps } from './node'
import type { EdgeProps } from './edge'
import type { FitViewParams } from './zoom'
/** Global component names are components registered to the vue instance and are "autoloaded" by their string name */
type GlobalComponentName = string
@@ -20,79 +18,6 @@ export type EdgeComponent = Component<EdgeProps> | DefineComponent<EdgeProps, an
export type DefaultEdgeTypes = { [key in 'default' | 'straight' | 'smoothstep' | 'step' | 'simplebezier']: EdgeComponent }
export type DefaultNodeTypes = { [key in 'input' | 'output' | 'default']: NodeComponent }
export interface BackgroundProps {
/** The background pattern variant, {@link BackgroundVariant} */
variant?: BackgroundVariant
/** Background pattern gap */
gap?: number
/** Background pattern size */
size?: number
/** Background pattern color */
patternColor?: string
/** Background color */
bgColor?: string
/** Background height */
height?: number
/** Background width */
width?: number
/** Background x-coordinate (offset x) */
x?: number
/** Background y-coordinate (offset y) */
y?: number
}
export interface ControlProps {
/** Show the zoom icon */
showZoom?: boolean
/** Show the fit-view icon */
showFitView?: boolean
/** Show the interactive icon */
showInteractive?: boolean
/** Params to use on fitView */
fitViewParams?: FitViewParams
}
/** expects a node and returns a color value */
export type MiniMapNodeFunc = (node: GraphNode) => string
// hack for vue-type imports
type MiniMapNodeFunc2 = (node: GraphNode) => string
type MiniMapNodeFunc3 = (node: GraphNode) => string
export type ShapeRendering = CSSProperties['shapeRendering']
export interface MiniMapProps {
/** Node color, can be either a string or a string func that receives the current node */
nodeColor?: string | MiniMapNodeFunc
/** Node stroke color, can be either a string or a string func that receives the current node */
nodeStrokeColor?: string | MiniMapNodeFunc2
/** Additional node class name, can be either a string or a string func that receives the current node */
nodeClassName?: string | MiniMapNodeFunc3
/** Node border radius */
nodeBorderRadius?: number
/** Node stroke width */
nodeStrokeWidth?: number
/** Background color of minimap */
maskColor?: string
width?: number
height?: number
}
/** these props are passed to mini map node slots */
export interface MiniMapNodeProps {
id: string
parentNode?: string
selected?: boolean
dragging?: boolean
position: XYPosition
dimensions: Dimensions
borderRadius?: number
color?: string
shapeRendering?: ShapeRendering
strokeColor?: string
strokeWidth?: number
}
/** these props are passed to edge texts */
export interface EdgeTextProps extends SVGAttributes {
x: number
-5
View File
@@ -58,11 +58,6 @@ export interface Rect extends Dimensions, XYPosition {}
export type SnapGrid = [number, number]
export enum BackgroundVariant {
Lines = 'lines',
Dots = 'dots',
}
export interface SelectionRect extends Rect {
startX: number
startY: number
-2
View File
@@ -2,7 +2,6 @@ import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueTypes from 'vite-plugin-vue-type-imports'
import svgLoader from 'vite-svg-loader'
import AutoImport from 'unplugin-auto-import/vite'
import replace from '@rollup/plugin-replace'
import pkg from './package.json'
@@ -43,7 +42,6 @@ export default defineConfig({
reactivityTransform: true,
}),
vueTypes(),
svgLoader(),
AutoImport({
imports: ['vue', '@vueuse/core', 'vue/macros'],
dts: 'src/auto-imports.d.ts',