Skip to content

Commit f28324a

Browse files
committed
feat: add node component
1 parent 4e5d245 commit f28324a

File tree

10 files changed

+163
-7
lines changed

10 files changed

+163
-7
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue'
3+
import Card from '@repo/shadcn-vue/components/ui/card/Card.vue'
4+
import { cn } from '@repo/shadcn-vue/lib/utils'
5+
import { Handle, Position } from '@vue-flow/core'
6+
import { reactiveOmit } from '@vueuse/core'
7+
8+
interface NodeHandles {
9+
target?: boolean
10+
source?: boolean
11+
}
12+
13+
interface NodeProps {
14+
class?: HTMLAttributes['class']
15+
handles?: NodeHandles
16+
}
17+
18+
const props = defineProps<NodeProps>()
19+
const delegatedProps = reactiveOmit(props, 'class')
20+
</script>
21+
22+
<template>
23+
<Card
24+
v-bind="delegatedProps"
25+
:class="cn('node-container relative size-full h-auto w-sm gap-0 rounded-md p-0', props.class)"
26+
>
27+
<Handle v-if="props.handles?.target" :position="Position.Left" type="target" />
28+
<Handle v-if="props.handles?.source" :position="Position.Right" type="source" />
29+
<slot />
30+
</Card>
31+
</template>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script setup lang="ts">
2+
import CardAction from '@repo/shadcn-vue/components/ui/card/CardAction.vue'
3+
</script>
4+
5+
<template>
6+
<CardAction>
7+
<slot />
8+
</CardAction>
9+
</template>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue'
3+
import CardContent from '@repo/shadcn-vue/components/ui/card/CardContent.vue'
4+
import { cn } from '@repo/shadcn-vue/lib/utils'
5+
6+
const props = defineProps<{
7+
class?: HTMLAttributes['class']
8+
}>()
9+
</script>
10+
11+
<template>
12+
<CardContent :class="cn('p-3', props.class)">
13+
<slot />
14+
</CardContent>
15+
</template>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script setup lang="ts">
2+
import CardDescription from '@repo/shadcn-vue/components/ui/card/CardDescription.vue'
3+
</script>
4+
5+
<template>
6+
<CardDescription>
7+
<slot />
8+
</CardDescription>
9+
</template>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue'
3+
import CardFooter from '@repo/shadcn-vue/components/ui/card/CardFooter.vue'
4+
import { cn } from '@repo/shadcn-vue/lib/utils'
5+
6+
const props = defineProps<{
7+
class?: HTMLAttributes['class']
8+
}>()
9+
</script>
10+
11+
<template>
12+
<CardFooter :class="cn('rounded-b-md border-t bg-secondary p-3!', props.class)">
13+
<slot />
14+
</CardFooter>
15+
</template>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
import type { HTMLAttributes } from 'vue'
3+
import CardHeader from '@repo/shadcn-vue/components/ui/card/CardHeader.vue'
4+
import { cn } from '@repo/shadcn-vue/lib/utils'
5+
6+
const props = defineProps<{
7+
class?: HTMLAttributes['class']
8+
}>()
9+
</script>
10+
11+
<template>
12+
<CardHeader :class="cn('gap-0.5 rounded-t-md border-b bg-secondary p-3!', props.class)">
13+
<slot />
14+
</CardHeader>
15+
</template>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script setup lang="ts">
2+
import CardTitle from '@repo/shadcn-vue/components/ui/card/CardTitle.vue'
3+
</script>
4+
5+
<template>
6+
<CardTitle>
7+
<slot />
8+
</CardTitle>
9+
</template>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export { default as Node } from './Node.vue'
2+
export { default as NodeAction } from './NodeAction.vue'
3+
export { default as NodeContent } from './NodeContent.vue'
4+
export { default as NodeDescription } from './NodeDescription.vue'
5+
export { default as NodeFooter } from './NodeFooter.vue'
6+
export { default as NodeHeader } from './NodeHeader.vue'
7+
export { default as NodeTitle } from './NodeTitle.vue'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<script setup lang="ts">
2+
import type { NodeProps } from '@vue-flow/core'
3+
import { Node, NodeContent, NodeDescription, NodeFooter, NodeHeader, NodeTitle } from '@repo/elements/node'
4+
5+
const props = defineProps<NodeProps>()
6+
</script>
7+
8+
<template>
9+
<Node :handles="props.data?.handles">
10+
<NodeHeader>
11+
<NodeTitle>{{ props.data?.label }}</NodeTitle>
12+
<NodeDescription>{{ props.data?.description }}</NodeDescription>
13+
</NodeHeader>
14+
15+
<NodeContent>
16+
<p class="text-sm">
17+
{{ props.data?.content }}
18+
</p>
19+
</NodeContent>
20+
21+
<NodeFooter>
22+
<p class="text-muted-foreground text-xs">
23+
{{ props.data?.footer }}
24+
</p>
25+
</NodeFooter>
26+
</Node>
27+
</template>

packages/examples/src/workflow.vue

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<script setup lang="ts">
2-
import type { Edge, Node } from '@vue-flow/core'
2+
import type { Edge, Node, NodeTypesObject } from '@vue-flow/core'
33
import { Canvas } from '@repo/elements/canvas'
44
import { Connection } from '@repo/elements/connection'
55
import { Controls } from '@repo/elements/controls'
66
import { Panel } from '@repo/elements/panel'
77
import { Button } from '@repo/shadcn-vue/components/ui/button'
88
import { nanoid } from 'nanoid'
9-
import { ref } from 'vue'
9+
import { markRaw, ref } from 'vue'
10+
import CustomNode from './custom-node.vue'
1011
1112
const nodeIds = {
1213
start: nanoid(),
@@ -16,13 +17,27 @@ const nodeIds = {
1617
const nodes = ref<Node[]>([
1718
{
1819
id: nodeIds.start,
19-
position: { x: 50, y: 50 },
20-
data: { label: 'Node 1' },
20+
type: 'custom',
21+
position: { x: 80, y: 80 },
22+
data: {
23+
label: 'start',
24+
description: 'test',
25+
content: 'test',
26+
footer: 'test',
27+
handles: { target: false, source: true },
28+
},
2129
},
2230
{
2331
id: nodeIds.process1,
24-
position: { x: 50, y: 250 },
25-
data: { label: 'Node 2' },
32+
type: 'custom',
33+
position: { x: 320, y: 260 },
34+
data: {
35+
label: 'process1',
36+
description: 'test',
37+
content: 'test',
38+
footer: 'test',
39+
handles: { target: true, source: true },
40+
},
2641
},
2742
])
2843
@@ -33,11 +48,15 @@ const edges = ref<Edge[]>([
3348
target: nodeIds.process1,
3449
},
3550
])
51+
52+
const nodeTypes: NodeTypesObject = {
53+
custom: markRaw(CustomNode),
54+
}
3655
</script>
3756

3857
<template>
3958
<div style="height: 400px">
40-
<Canvas :nodes="nodes" :edges="edges">
59+
<Canvas :nodes="nodes" :edges="edges" :node-types="nodeTypes">
4160
<template #connection-line="connectionLineProps">
4261
<Connection v-bind="connectionLineProps" />
4362
</template>

0 commit comments

Comments
 (0)