diff --git a/src/additional-components/Background/Background.vue b/src/additional-components/Background/Background.vue new file mode 100644 index 00000000..6bcc1256 --- /dev/null +++ b/src/additional-components/Background/Background.vue @@ -0,0 +1,59 @@ + + diff --git a/src/additional-components/Background/index.tsx b/src/additional-components/Background/index.tsx deleted file mode 100644 index 945010e0..00000000 --- a/src/additional-components/Background/index.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { BackgroundVariant, RevueFlowStore } from '../../types' -import { createGridDotsPath, createGridLinesPath } from './utils' -import { computed, defineComponent, HTMLAttributes, inject, PropType } from 'vue' - -export interface BackgroundProps extends HTMLAttributes { - variant?: BackgroundVariant - gap?: number - color?: string - size?: number -} - -const defaultColors = { - [BackgroundVariant.Dots]: '#81818a', - [BackgroundVariant.Lines]: '#eee' -} - -const Background = defineComponent({ - name: 'Background', - props: { - variant: { - type: String as PropType, - required: false, - default: BackgroundVariant.Dots - }, - gap: { - type: Number as PropType, - required: false, - default: 10 - }, - color: { - type: String as PropType, - required: false, - default: undefined - }, - size: { - type: Number as PropType, - required: false, - default: 0.4 - } - }, - setup(props) { - const store = inject('store')! - const transform = computed(() => store.transform) - // 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 bgClasses = ['revue-flow__background'] - const scaledGap = computed(() => props.gap && props.gap * transform.value[2]) - const xOffset = computed(() => scaledGap.value && transform.value[0] % scaledGap.value) - const yOffset = computed(() => scaledGap.value && transform.value[1] % scaledGap.value) - - const isLines = computed(() => props.variant === BackgroundVariant.Lines) - const bgColor = computed(() => (props.color ? props.color : defaultColors[props.variant || BackgroundVariant.Dots])) - const path = computed(() => - isLines.value - ? scaledGap.value && props.size && createGridLinesPath(scaledGap.value, props.size, bgColor.value) - : createGridDotsPath(props.size || 0.4 * transform.value[2], bgColor.value) - ) - - return () => ( - - - {path.value} - - - - ) - } -}) - -export default Background diff --git a/src/additional-components/Controls/ControlButton.vue b/src/additional-components/Controls/ControlButton.vue new file mode 100644 index 00000000..cc1893b4 --- /dev/null +++ b/src/additional-components/Controls/ControlButton.vue @@ -0,0 +1,10 @@ + + diff --git a/src/additional-components/Controls/Controls.vue b/src/additional-components/Controls/Controls.vue new file mode 100644 index 00000000..7e444603 --- /dev/null +++ b/src/additional-components/Controls/Controls.vue @@ -0,0 +1,76 @@ + + diff --git a/src/additional-components/Controls/index.tsx b/src/additional-components/Controls/index.tsx deleted file mode 100644 index 4f46086e..00000000 --- a/src/additional-components/Controls/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { defineComponent, HTMLAttributes, inject, onMounted, PropType, ref } from 'vue' -import useZoomPanHelper from '../../hooks/useZoomPanHelper' -import { FitViewParams, RevueFlowStore, ZoomPanHelperFunctions } from '../../types' -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' - -export interface ControlProps extends HTMLAttributes { - showZoom?: boolean - showFitView?: boolean - showInteractive?: boolean - fitViewParams?: FitViewParams - onZoomIn?: () => void - onZoomOut?: () => void - onFitView?: () => void - onInteractiveChange?: (interactiveStatus: boolean) => void -} - -export type ControlButtonProps = HTMLButtonElement - -export const ControlButton = defineComponent({ - props: { - disabled: { - type: Boolean as PropType, - required: false, - default: undefined - }, - onClick: { - type: Function as PropType<() => any>, - required: false, - default: undefined - } - }, - setup(props, { slots }) { - return () => ( - - ) - } -}) - -const Controls = defineComponent({ - name: 'Controls', - props: { - showZoom: { - type: Boolean as PropType, - required: false, - default: true - }, - showFitView: { - type: Boolean as PropType, - required: false, - default: true - }, - showInteractive: { - type: Boolean as PropType, - required: false, - default: true - }, - fitViewParams: { - type: Object as PropType, - required: false, - default: undefined - }, - onZoomIn: { - type: Function() as PropType, - required: false, - default: undefined - }, - onZoomOut: { - type: Function() as PropType, - required: false, - default: undefined - }, - onFitView: { - type: Function() as PropType, - required: false, - default: undefined - }, - onInteractiveChange: { - type: Function() as PropType, - required: false, - default: undefined - } - }, - setup(props, { slots }) { - const store = inject('store')! - const isVisible = ref(false) - const zoomHelper = ref() - const { onReady } = useZoomPanHelper() - - onReady((helper) => { - zoomHelper.value = helper - }) - - const isInteractive = store.nodesDraggable && store.nodesConnectable && store.elementsSelectable - const mapClasses = ['revue-flow__controls'] - - const onZoomInHandler = () => { - zoomHelper.value?.zoomIn?.() - props.onZoomIn?.() - } - - const onZoomOutHandler = () => { - zoomHelper.value?.zoomOut?.() - props.onZoomOut?.() - } - - const onFitViewHandler = () => { - zoomHelper.value?.fitView?.(props.fitViewParams) - props.onFitView?.() - } - - const onInteractiveChangeHandler = () => { - store.setInteractive?.(!isInteractive) - props.onInteractiveChange?.(!isInteractive) - } - - onMounted(() => { - isVisible.value = true - }) - - return () => ( -
- {props.showZoom && ( - <> - - - - - - - - )} - {props.showFitView && ( - - - - )} - {props.showInteractive && ( - - {isInteractive ? : } - - )} - {slots.default ? slots.default() : ''} -
- ) - } -}) - -export default Controls diff --git a/src/additional-components/MiniMap/MiniMap.vue b/src/additional-components/MiniMap/MiniMap.vue new file mode 100644 index 00000000..d0a60134 --- /dev/null +++ b/src/additional-components/MiniMap/MiniMap.vue @@ -0,0 +1,93 @@ + + diff --git a/src/additional-components/MiniMap/MiniMapNode.tsx b/src/additional-components/MiniMap/MiniMapNode.tsx deleted file mode 100644 index abb992c5..00000000 --- a/src/additional-components/MiniMap/MiniMapNode.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { computed, defineComponent, PropType } from 'vue' - -interface MiniMapNodeProps { - x: number - y: number - width: number - height: number - borderRadius: number - color: string - shapeRendering: string - strokeColor: string - strokeWidth: number -} - -const MiniMapNode = defineComponent({ - name: 'MiniMapNode', - props: { - x: { - type: Number as PropType, - required: false, - default: undefined - }, - y: { - type: Number as PropType, - required: false, - default: undefined - }, - width: { - type: Number as PropType, - required: false, - default: undefined - }, - height: { - type: Number as PropType, - required: false, - default: undefined - }, - borderRadius: { - type: Number as PropType, - required: false, - default: undefined - }, - color: { - type: String as PropType, - required: false, - default: undefined - }, - shapeRendering: { - type: String as PropType, - required: false, - default: undefined - }, - strokeColor: { - type: String as PropType, - required: false, - default: undefined - }, - strokeWidth: { - type: Number as PropType, - required: false, - default: undefined - } - }, - setup(props, { attrs }: { attrs: Record }) { - const styles = attrs.style || {} - const fill = computed(() => (props.color || styles.value.background || styles.value.backgroundColor) as string) - - return () => ( - - ) - } -}) - -export default MiniMapNode diff --git a/src/additional-components/MiniMap/MiniMapNode.vue b/src/additional-components/MiniMap/MiniMapNode.vue new file mode 100644 index 00000000..94648a56 --- /dev/null +++ b/src/additional-components/MiniMap/MiniMapNode.vue @@ -0,0 +1,35 @@ + + diff --git a/src/additional-components/MiniMap/index.tsx b/src/additional-components/MiniMap/index.tsx deleted file mode 100644 index 683d50d3..00000000 --- a/src/additional-components/MiniMap/index.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { getRectOfNodes, getBoundsofRects } from '../../utils/graph' -import { Node, Rect, RevueFlowStore } from '../../types' -import MiniMapNode from './MiniMapNode' -import { computed, defineComponent, HTMLAttributes, inject, PropType } from 'vue' - -type StringFunc = (node: Node) => string - -export interface MiniMapProps extends HTMLAttributes { - nodeColor?: string | StringFunc - nodeStrokeColor?: string | StringFunc - nodeClassName?: string | StringFunc - nodeBorderRadius?: number - nodeStrokeWidth?: number - maskColor?: string -} - -declare const window: any - -const defaultWidth = 200 -const defaultHeight = 150 - -const MiniMap = defineComponent({ - name: 'MiniMap', - props: { - nodeStrokeColor: { - type: [String, Function] as PropType, - required: false, - default: '#555' - }, - nodeColor: { - type: [String, Function] as PropType, - required: false, - default: '#fff' - }, - nodeClassName: { - type: [String, Function] as PropType, - required: false, - default: '' - }, - nodeBorderRadius: { - type: Number as PropType, - required: false, - default: 5 - }, - nodeStrokeWidth: { - type: Number as PropType, - required: false, - default: 2 - }, - maskColor: { - type: String as PropType, - required: false, - default: 'rgb(240, 242, 243, 0.7)' - } - }, - setup(props, { attrs }: { attrs: Record }) { - const store = inject('store')! - const transform = computed(() => store.transform) - const elementWidth = computed(() => (attrs.style?.width || defaultWidth)! as number) - const elementHeight = computed(() => (attrs.style?.height || defaultHeight)! as number) - const nodeColorFunc = computed( - () => (props.nodeColor instanceof Function ? props.nodeColor : () => props.nodeColor) as StringFunc - ) - const nodeStrokeColorFunc = computed( - () => (props.nodeStrokeColor instanceof Function ? props.nodeStrokeColor : () => props.nodeStrokeColor) as StringFunc - ) - const nodeClassNameFunc = computed( - () => (props.nodeClassName instanceof Function ? props.nodeClassName : () => props.nodeClassName) as StringFunc - ) - const hasNodes = computed(() => store.nodes && store.nodes.length) - const bb = computed(() => getRectOfNodes(store.nodes)) - const viewBB = computed(() => ({ - x: -transform.value[0] / transform.value[2], - y: -transform.value[1] / transform.value[2], - width: store.width / transform.value[2], - height: store.height / transform.value[2] - })) - const boundingRect = computed(() => (hasNodes.value ? getBoundsofRects(bb.value, viewBB.value) : viewBB.value)) - const scaledWidth = computed(() => boundingRect.value.width / elementWidth.value) - const scaledHeight = computed(() => boundingRect.value.height / elementHeight.value) - const viewScale = computed(() => Math.max(scaledWidth.value, scaledHeight.value)) - const viewWidth = computed(() => viewScale.value * elementWidth.value) - const viewHeight = computed(() => viewScale.value * elementHeight.value) - const offset = computed(() => 5 * viewScale.value) - const x = computed(() => boundingRect.value.x - (viewWidth.value - boundingRect.value.width) / 2 - offset.value) - const y = computed(() => boundingRect.value.y - (viewHeight.value - boundingRect.value.height) / 2 - offset.value) - const width = computed(() => viewWidth.value + offset.value * 2) - const height = computed(() => viewHeight.value + offset.value * 2) - const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision' - - return () => ( - - {store.nodes - .filter((node) => !node.isHidden) - .map((node) => ( - - ))} - - - ) - } -}) - -export default MiniMap diff --git a/src/additional-components/index.ts b/src/additional-components/index.ts index dc21be20..b24608ed 100644 --- a/src/additional-components/index.ts +++ b/src/additional-components/index.ts @@ -1,6 +1,6 @@ // These components are not used by revue Flow directly // but the user can add them as children of a revue Flow component -export { default as MiniMap } from './MiniMap' -export { default as Controls, ControlButton } from './Controls' -export { default as Background } from './Background' +export { default as MiniMap } from './MiniMap/MiniMap.vue' +export { default as Controls } from './Controls/Controls.vue' +export { default as Background } from './Background/Background.vue' diff --git a/src/components/ConnectionLine/ConnectionLine.vue b/src/components/ConnectionLine/ConnectionLine.vue index 344e15f0..62f13140 100644 --- a/src/components/ConnectionLine/ConnectionLine.vue +++ b/src/components/ConnectionLine/ConnectionLine.vue @@ -1,6 +1,6 @@