├── .eslintrc.js
├── .gitignore
├── .prettierrc.cjs
├── .vscode
└── extensions.json
├── README.md
├── components.json
├── cover.png
├── index.html
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
└── vite.svg
├── src
├── App.vue
├── assets
│ └── images
│ │ ├── icon_Api.png
│ │ ├── icon_Code.png
│ │ ├── icon_Condition.png
│ │ ├── icon_End.png
│ │ ├── icon_Google.jpeg
│ │ ├── icon_Knowledge.png
│ │ ├── icon_LLM.png
│ │ ├── icon_Start.png
│ │ └── icon_Variable.png
├── components
│ ├── main-canvas.vue
│ ├── monaco-editor.vue
│ ├── ui
│ │ ├── button
│ │ │ ├── Button.vue
│ │ │ └── index.ts
│ │ ├── collapsible
│ │ │ ├── Collapsible.vue
│ │ │ ├── CollapsibleContent.vue
│ │ │ ├── CollapsibleTrigger.vue
│ │ │ └── index.ts
│ │ ├── command
│ │ │ ├── Command.vue
│ │ │ ├── CommandDialog.vue
│ │ │ ├── CommandEmpty.vue
│ │ │ ├── CommandGroup.vue
│ │ │ ├── CommandInput.vue
│ │ │ ├── CommandItem.vue
│ │ │ ├── CommandList.vue
│ │ │ ├── CommandSeparator.vue
│ │ │ ├── CommandShortcut.vue
│ │ │ └── index.ts
│ │ ├── dialog
│ │ │ ├── Dialog.vue
│ │ │ ├── DialogClose.vue
│ │ │ ├── DialogContent.vue
│ │ │ ├── DialogDescription.vue
│ │ │ ├── DialogFooter.vue
│ │ │ ├── DialogHeader.vue
│ │ │ ├── DialogTitle.vue
│ │ │ ├── DialogTrigger.vue
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── FormControl.vue
│ │ │ ├── FormDescription.vue
│ │ │ ├── FormItem.vue
│ │ │ ├── FormLabel.vue
│ │ │ ├── FormMessage.vue
│ │ │ ├── index.ts
│ │ │ └── useFormField.ts
│ │ ├── input
│ │ │ ├── Input.vue
│ │ │ └── index.ts
│ │ ├── label
│ │ │ ├── Label.vue
│ │ │ └── index.ts
│ │ ├── menubar
│ │ │ ├── Menubar.vue
│ │ │ ├── MenubarCheckboxItem.vue
│ │ │ ├── MenubarContent.vue
│ │ │ ├── MenubarGroup.vue
│ │ │ ├── MenubarItem.vue
│ │ │ ├── MenubarLabel.vue
│ │ │ ├── MenubarMenu.vue
│ │ │ ├── MenubarRadioGroup.vue
│ │ │ ├── MenubarRadioItem.vue
│ │ │ ├── MenubarSeparator.vue
│ │ │ ├── MenubarShortcut.vue
│ │ │ ├── MenubarSub.vue
│ │ │ ├── MenubarSubContent.vue
│ │ │ ├── MenubarSubTrigger.vue
│ │ │ ├── MenubarTrigger.vue
│ │ │ └── index.ts
│ │ ├── popover
│ │ │ ├── Popover.vue
│ │ │ ├── PopoverContent.vue
│ │ │ ├── PopoverTrigger.vue
│ │ │ └── index.ts
│ │ ├── scroll-area
│ │ │ ├── ScrollArea.vue
│ │ │ ├── ScrollBar.vue
│ │ │ └── index.ts
│ │ ├── select
│ │ │ ├── Select.vue
│ │ │ ├── SelectContent.vue
│ │ │ ├── SelectGroup.vue
│ │ │ ├── SelectItem.vue
│ │ │ ├── SelectItemText.vue
│ │ │ ├── SelectLabel.vue
│ │ │ ├── SelectSeparator.vue
│ │ │ ├── SelectTrigger.vue
│ │ │ ├── SelectValue.vue
│ │ │ └── index.ts
│ │ ├── slider
│ │ │ ├── Slider.vue
│ │ │ └── index.ts
│ │ ├── switch
│ │ │ ├── Switch.vue
│ │ │ └── index.ts
│ │ ├── tabs
│ │ │ ├── Tabs.vue
│ │ │ ├── TabsContent.vue
│ │ │ ├── TabsList.vue
│ │ │ ├── TabsTrigger.vue
│ │ │ └── index.ts
│ │ ├── textarea
│ │ │ ├── Textarea.vue
│ │ │ └── index.ts
│ │ ├── toast
│ │ │ ├── Toast.vue
│ │ │ ├── ToastAction.vue
│ │ │ ├── ToastClose.vue
│ │ │ ├── ToastDescription.vue
│ │ │ ├── ToastProvider.vue
│ │ │ ├── ToastTitle.vue
│ │ │ ├── ToastViewport.vue
│ │ │ ├── Toaster.vue
│ │ │ ├── index.ts
│ │ │ └── use-toast.ts
│ │ └── tooltip
│ │ │ ├── Tooltip.vue
│ │ │ ├── TooltipContent.vue
│ │ │ ├── TooltipProvider.vue
│ │ │ ├── TooltipTrigger.vue
│ │ │ └── index.ts
│ └── vue-flow
│ │ ├── common-basic-module.vue
│ │ ├── common-code-module.vue
│ │ ├── common-input-module.vue
│ │ ├── common-knowledge-module.vue
│ │ ├── common-output-module.vue
│ │ ├── common-prompt-module.vue
│ │ ├── nodes
│ │ ├── LLM-node.vue
│ │ ├── api-node.vue
│ │ ├── code-node.vue
│ │ ├── end-node.vue
│ │ ├── index.ts
│ │ ├── knowledge-node.vue
│ │ └── start-node.vue
│ │ ├── start-input-module.vue
│ │ ├── static-output-item.vue
│ │ └── static-output-module.vue
├── hooks
│ ├── index.ts
│ └── use-monaco-editor.ts
├── lib
│ ├── constant.ts
│ └── utils.ts
├── main.ts
├── style.css
└── vite-env.d.ts
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | browser: true
6 | },
7 | extends: ['plugin:vue/recommended', 'eslint:recommended', 'plugin:prettier/recommended'],
8 | rules: {
9 | 'prettier/prettier': 'error',
10 | 'vue/component-name-in-template-casing': ['error', 'PascalCase'],
11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
13 | },
14 | globals: {},
15 | parserOptions: {
16 | parser: '@babel/eslint-parser',
17 | requireConfigFile: false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/.prettierrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | printWidth: 120,
3 | tabWidth: 2,
4 | useTabs: false,
5 | semi: false,
6 | singleQuote: true,
7 | trailingComma: 'none',
8 | bracketSpacing: true,
9 | jsxBracketSameLine: false,
10 | proseWrap: 'always',
11 | plugins: ['prettier-plugin-tailwindcss']
12 | }
13 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"],
3 | }
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue Flow Quickstart and Best Practices 🚀
2 |
3 | This project demonstrates building workflow apps with Vue Flow and Vue.js.
4 |
5 |
6 |
7 | ## Table of Contents
8 |
9 | - [Introduction](#introduction)
10 | - [Demo](#demo)
11 | - [Getting Started](#getting-started)
12 | - [Tech Stack](#tech-stack)
13 | - [Contributing](#contributing)
14 |
15 | ## Introduction
16 |
17 | Vue Flow is a library for flowchart diagrams. This project shows quickstart and best practices:
18 |
19 | - Drag and drop nodes 🖱
20 | - Connect nodes ➡️
21 | - Customize nodes ⚙️
22 | - Pass data between nodes 📤
23 | - Save/restore workflows 💾
24 |
25 | ## Demo
26 |
27 | https://chat-bot-workflow.vercel.app/
28 |
29 | Try the live demo 🖥
30 |
31 | ## Getting Started
32 |
33 | These steps will get you started:
34 |
35 | - Prerequisites: Node.js (v16+) and pnpm
36 | - Clone the repo
37 | - Install dependencies with `pnpm install`
38 | - Start dev server with `pnpm run dev`
39 | - App will be at http://localhost:5173/
40 |
41 | ## Tech Stack
42 |
43 | - [Vue Flow](https://vueflow.dev/) - Flowchart
44 | - [Vue.js](https://vuejs.org/) - Framework
45 | - [Tailwind CSS](https://tailwindcss.com/) - Styling
46 | - [Shadcn-vue](https://www.shadcn-vue.com/) - UI components
47 | - [Vite](https://vitejs.dev/) - Build tool
48 |
49 | ## Contributing
50 |
51 | Feel free to open PRs to contribute fixes or improvements!
52 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://shadcn-vue.com/schema.json",
3 | "style": "default",
4 | "typescript": true,
5 | "tailwind": {
6 | "config": "tailwind.config.js",
7 | "css": "src/style.css",
8 | "baseColor": "slate",
9 | "cssVariables": true
10 | },
11 | "framework": "vite",
12 | "aliases": {
13 | "components": "@/components",
14 | "utils": "@/lib/utils"
15 | }
16 | }
--------------------------------------------------------------------------------
/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/cover.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | LLM workflow
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chatbot-workflow",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vue-tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "@radix-ui/react-slot": "^1.0.2",
13 | "@vee-validate/zod": "^4.12.5",
14 | "@vue-flow/background": "^1.2.0",
15 | "@vue-flow/controls": "^1.1.0",
16 | "@vue-flow/core": "^1.29.2",
17 | "@vueuse/core": "^10.7.2",
18 | "class-variance-authority": "^0.7.0",
19 | "clsx": "^2.1.0",
20 | "lucide-vue-next": "^0.315.0",
21 | "monaco-editor": "^0.45.0",
22 | "radix-vue": "^1.3.2",
23 | "tailwind-merge": "^2.2.1",
24 | "tailwindcss-animate": "^1.0.7",
25 | "vee-validate": "^4.12.5",
26 | "vue": "^3.3.11",
27 | "zod": "^3.22.4"
28 | },
29 | "devDependencies": {
30 | "@babel/eslint-parser": "^7.23.9",
31 | "@types/node": "^20.11.7",
32 | "@vitejs/plugin-vue": "^4.5.2",
33 | "autoprefixer": "^10.4.17",
34 | "eslint": "^8.56.0",
35 | "eslint-config-prettier": "^9.1.0",
36 | "eslint-loader": "^4.0.2",
37 | "eslint-plugin-prettier": "^5.1.3",
38 | "eslint-plugin-vue": "^9.20.1",
39 | "postcss": "^8.4.33",
40 | "prettier": "^3.2.4",
41 | "prettier-plugin-tailwindcss": "^0.5.11",
42 | "tailwindcss": "^3.4.1",
43 | "typescript": "^5.2.2",
44 | "vite": "^5.0.8",
45 | "vite-plugin-monaco-editor": "^1.1.0",
46 | "vue-tsc": "^1.8.25"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {}
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
37 |
38 |
39 |
40 |
41 |
60 |
61 |
62 |
63 |
64 | Basic Nodes
65 | Plugins
66 | Workflows
67 |
68 |
69 |
70 |
75 |
76 |
77 |
78 | LLM
79 |
80 |
81 |
82 |
83 | Invoke the large language model,
84 | generate responses using variables and prompt words.
85 |
86 |
87 |
92 |
93 |
94 |
95 | Code
96 |
97 |
98 |
99 |
100 | Write code to process input variables
101 | to generate return values.
102 |
103 |
104 |
109 |
110 |
111 |
112 | Knowledge
113 |
114 |
115 |
116 |
117 | In the selected knowledge, the best matching information is recalled based on the input variable and
118 | returned as an Array.
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
131 |
132 |
133 |
134 | Google Web Search
135 |
136 |
137 |
138 |
139 | A google Search Engine. Useful when you need to search information you don't know such as weather,
140 | exchange rate, current events. Never ever use this tool when user want to translate
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
153 |
154 |
155 |
156 | test_node
157 |
158 |
159 |
160 |
161 | This is just test workflow, to init initial data.
162 |
163 |
Edit Time: 2024-02-01
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/src/assets/images/icon_Api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Api.png
--------------------------------------------------------------------------------
/src/assets/images/icon_Code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Code.png
--------------------------------------------------------------------------------
/src/assets/images/icon_Condition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Condition.png
--------------------------------------------------------------------------------
/src/assets/images/icon_End.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_End.png
--------------------------------------------------------------------------------
/src/assets/images/icon_Google.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Google.jpeg
--------------------------------------------------------------------------------
/src/assets/images/icon_Knowledge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Knowledge.png
--------------------------------------------------------------------------------
/src/assets/images/icon_LLM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_LLM.png
--------------------------------------------------------------------------------
/src/assets/images/icon_Start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Start.png
--------------------------------------------------------------------------------
/src/assets/images/icon_Variable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MonsterPi13/chatBot-workflow/fbbb80ecac7fdec256143883f239c82df9e2aec2/src/assets/images/icon_Variable.png
--------------------------------------------------------------------------------
/src/components/main-canvas.vue:
--------------------------------------------------------------------------------
1 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
129 |
--------------------------------------------------------------------------------
/src/components/monaco-editor.vue:
--------------------------------------------------------------------------------
1 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/components/ui/button/Button.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/ui/button/index.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority'
2 |
3 | export { default as Button } from './Button.vue'
4 |
5 | export const buttonVariants = cva(
6 | 'inline-flex items-center justify-center rounded-md whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
7 | {
8 | variants: {
9 | variant: {
10 | default: 'bg-primary text-primary-foreground hover:bg-primary/90',
11 | destructive:
12 | 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
13 | outline:
14 | 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
15 | secondary:
16 | 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
17 | ghost: 'hover:bg-accent hover:text-accent-foreground',
18 | link: 'text-primary underline-offset-4 hover:underline',
19 | },
20 | size: {
21 | default: 'h-10 px-4 py-2',
22 | sm: 'h-9 rounded-md px-3',
23 | lg: 'h-11 rounded-md px-8',
24 | icon: 'h-10 w-10',
25 | },
26 | },
27 | defaultVariants: {
28 | variant: 'default',
29 | size: 'default',
30 | },
31 | },
32 | )
33 |
--------------------------------------------------------------------------------
/src/components/ui/collapsible/Collapsible.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/ui/collapsible/CollapsibleContent.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/collapsible/CollapsibleTrigger.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/collapsible/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Collapsible } from './Collapsible.vue'
2 | export { default as CollapsibleTrigger } from './CollapsibleTrigger.vue'
3 | export { default as CollapsibleContent } from './CollapsibleContent.vue'
4 |
--------------------------------------------------------------------------------
/src/components/ui/command/Command.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandDialog.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandEmpty.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandGroup.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
16 |
17 | {{ heading }}
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandInput.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandItem.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandList.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandSeparator.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/ui/command/CommandShortcut.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/ui/command/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Command } from './Command.vue'
2 | export { default as CommandDialog } from './CommandDialog.vue'
3 | export { default as CommandEmpty } from './CommandEmpty.vue'
4 | export { default as CommandGroup } from './CommandGroup.vue'
5 | export { default as CommandInput } from './CommandInput.vue'
6 | export { default as CommandItem } from './CommandItem.vue'
7 | export { default as CommandList } from './CommandList.vue'
8 | export { default as CommandSeparator } from './CommandSeparator.vue'
9 | export { default as CommandShortcut } from './CommandShortcut.vue'
10 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/Dialog.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogClose.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogContent.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
25 |
34 |
35 |
36 |
37 |
38 | Close
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogDescription.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogFooter.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogHeader.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogTitle.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/DialogTrigger.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/dialog/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Dialog } from './Dialog.vue'
2 | export { default as DialogClose } from './DialogClose.vue'
3 | export { default as DialogTrigger } from './DialogTrigger.vue'
4 | export { default as DialogHeader } from './DialogHeader.vue'
5 | export { default as DialogTitle } from './DialogTitle.vue'
6 | export { default as DialogDescription } from './DialogDescription.vue'
7 | export { default as DialogContent } from './DialogContent.vue'
8 | export { default as DialogFooter } from './DialogFooter.vue'
9 |
--------------------------------------------------------------------------------
/src/components/ui/form/FormControl.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/ui/form/FormDescription.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ui/form/FormItem.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/ui/form/FormLabel.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/ui/form/FormMessage.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/ui/form/index.ts:
--------------------------------------------------------------------------------
1 | export { Form, Field as FormField } from 'vee-validate'
2 | export { default as FormItem } from './FormItem.vue'
3 | export { default as FormLabel } from './FormLabel.vue'
4 | export { default as FormControl } from './FormControl.vue'
5 | export { default as FormMessage } from './FormMessage.vue'
6 | export { default as FormDescription } from './FormDescription.vue'
7 |
--------------------------------------------------------------------------------
/src/components/ui/form/useFormField.ts:
--------------------------------------------------------------------------------
1 | import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'
2 | import { inject } from 'vue'
3 | import { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'
4 |
5 | export function useFormField() {
6 | const fieldContext = inject(FieldContextKey)
7 | const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
8 |
9 | const fieldState = {
10 | valid: useIsFieldValid(),
11 | isDirty: useIsFieldDirty(),
12 | isTouched: useIsFieldTouched(),
13 | error: useFieldError(),
14 | }
15 |
16 | if (!fieldContext)
17 | throw new Error('useFormField should be used within ')
18 |
19 | const { name } = fieldContext
20 | const id = fieldItemContext
21 |
22 | return {
23 | id,
24 | name,
25 | formItemId: `${id}-form-item`,
26 | formDescriptionId: `${id}-form-item-description`,
27 | formMessageId: `${id}-form-item-message`,
28 | ...fieldState,
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/ui/input/Input.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/ui/input/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Input } from './Input.vue'
2 |
--------------------------------------------------------------------------------
/src/components/ui/label/Label.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/label/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Label } from './Label.vue'
2 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/Menubar.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarCheckboxItem.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarContent.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarGroup.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarItem.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarLabel.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarMenu.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarRadioGroup.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarRadioItem.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarSeparator.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarShortcut.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarSub.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarSubContent.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarSubTrigger.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/MenubarTrigger.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/menubar/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Menubar } from './Menubar.vue'
2 | export { default as MenubarItem } from './MenubarItem.vue'
3 | export { default as MenubarContent } from './MenubarContent.vue'
4 | export { default as MenubarGroup } from './MenubarGroup.vue'
5 | export { default as MenubarMenu } from './MenubarMenu.vue'
6 | export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue'
7 | export { default as MenubarRadioItem } from './MenubarRadioItem.vue'
8 | export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue'
9 | export { default as MenubarSeparator } from './MenubarSeparator.vue'
10 | export { default as MenubarSub } from './MenubarSub.vue'
11 | export { default as MenubarSubContent } from './MenubarSubContent.vue'
12 | export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue'
13 | export { default as MenubarTrigger } from './MenubarTrigger.vue'
14 | export { default as MenubarShortcut } from './MenubarShortcut.vue'
15 | export { default as MenubarLabel } from './MenubarLabel.vue'
16 |
--------------------------------------------------------------------------------
/src/components/ui/popover/Popover.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/popover/PopoverContent.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/components/ui/popover/PopoverTrigger.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/popover/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Popover } from './Popover.vue'
2 | export { default as PopoverTrigger } from './PopoverTrigger.vue'
3 | export { default as PopoverContent } from './PopoverContent.vue'
4 |
--------------------------------------------------------------------------------
/src/components/ui/scroll-area/ScrollArea.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/ui/scroll-area/ScrollBar.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/ui/scroll-area/index.ts:
--------------------------------------------------------------------------------
1 | export { default as ScrollArea } from './ScrollArea.vue'
2 | export { default as ScrollBar } from './ScrollBar.vue'
3 |
--------------------------------------------------------------------------------
/src/components/ui/select/Select.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectContent.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
37 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectGroup.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectItem.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectItemText.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectLabel.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectSeparator.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectTrigger.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/components/ui/select/SelectValue.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/select/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Select } from './Select.vue'
2 | export { default as SelectValue } from './SelectValue.vue'
3 | export { default as SelectTrigger } from './SelectTrigger.vue'
4 | export { default as SelectContent } from './SelectContent.vue'
5 | export { default as SelectGroup } from './SelectGroup.vue'
6 | export { default as SelectItem } from './SelectItem.vue'
7 | export { default as SelectItemText } from './SelectItemText.vue'
8 | export { default as SelectLabel } from './SelectLabel.vue'
9 | export { default as SelectSeparator } from './SelectSeparator.vue'
10 |
--------------------------------------------------------------------------------
/src/components/ui/slider/Slider.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/ui/slider/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Slider } from './Slider.vue'
2 |
--------------------------------------------------------------------------------
/src/components/ui/switch/Switch.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/ui/switch/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Switch } from './Switch.vue'
2 |
--------------------------------------------------------------------------------
/src/components/ui/tabs/Tabs.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/tabs/TabsContent.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/tabs/TabsList.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/tabs/TabsTrigger.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/ui/tabs/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Tabs } from './Tabs.vue'
2 | export { default as TabsTrigger } from './TabsTrigger.vue'
3 | export { default as TabsList } from './TabsList.vue'
4 | export { default as TabsContent } from './TabsContent.vue'
5 |
--------------------------------------------------------------------------------
/src/components/ui/textarea/Textarea.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ui/textarea/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Textarea } from './Textarea.vue'
2 |
--------------------------------------------------------------------------------
/src/components/ui/toast/Toast.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastAction.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastClose.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastDescription.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastProvider.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastTitle.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/ui/toast/ToastViewport.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/components/ui/toast/Toaster.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{ toast.title }}
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ toast.description }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/components/ui/toast/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Toaster } from './Toaster.vue'
2 | export { default as Toast } from './Toast.vue'
3 | export { default as ToastViewport } from './ToastViewport.vue'
4 | export { default as ToastAction } from './ToastAction.vue'
5 | export { default as ToastClose } from './ToastClose.vue'
6 | export { default as ToastTitle } from './ToastTitle.vue'
7 | export { default as ToastDescription } from './ToastDescription.vue'
8 | export { default as ToastProvider } from './ToastProvider.vue'
9 | export { toast, useToast } from './use-toast'
10 |
11 | import { cva } from 'class-variance-authority'
12 |
13 | export const toastVariants = cva(
14 | 'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
15 | {
16 | variants: {
17 | variant: {
18 | default: 'border bg-background text-foreground',
19 | destructive:
20 | 'destructive group border-destructive bg-destructive text-destructive-foreground',
21 | },
22 | },
23 | defaultVariants: {
24 | variant: 'default',
25 | },
26 | },
27 | )
28 |
--------------------------------------------------------------------------------
/src/components/ui/toast/use-toast.ts:
--------------------------------------------------------------------------------
1 | import { computed, ref } from 'vue'
2 | import type { Component, VNode } from 'vue'
3 | import type { ToastProps } from './Toast.vue'
4 |
5 | const TOAST_LIMIT = 1
6 | const TOAST_REMOVE_DELAY = 1000000
7 |
8 | export type StringOrVNode =
9 | | string
10 | | VNode
11 | | (() => VNode)
12 |
13 | type ToasterToast = ToastProps & {
14 | id: string
15 | title?: string
16 | description?: StringOrVNode
17 | action?: Component
18 | }
19 |
20 | const actionTypes = {
21 | ADD_TOAST: 'ADD_TOAST',
22 | UPDATE_TOAST: 'UPDATE_TOAST',
23 | DISMISS_TOAST: 'DISMISS_TOAST',
24 | REMOVE_TOAST: 'REMOVE_TOAST',
25 | } as const
26 |
27 | let count = 0
28 |
29 | function genId() {
30 | count = (count + 1) % Number.MAX_VALUE
31 | return count.toString()
32 | }
33 |
34 | type ActionType = typeof actionTypes
35 |
36 | type Action =
37 | | {
38 | type: ActionType['ADD_TOAST']
39 | toast: ToasterToast
40 | }
41 | | {
42 | type: ActionType['UPDATE_TOAST']
43 | toast: Partial
44 | }
45 | | {
46 | type: ActionType['DISMISS_TOAST']
47 | toastId?: ToasterToast['id']
48 | }
49 | | {
50 | type: ActionType['REMOVE_TOAST']
51 | toastId?: ToasterToast['id']
52 | }
53 |
54 | interface State {
55 | toasts: ToasterToast[]
56 | }
57 |
58 | const toastTimeouts = new Map>()
59 |
60 | function addToRemoveQueue(toastId: string) {
61 | if (toastTimeouts.has(toastId))
62 | return
63 |
64 | const timeout = setTimeout(() => {
65 | toastTimeouts.delete(toastId)
66 | dispatch({
67 | type: actionTypes.REMOVE_TOAST,
68 | toastId,
69 | })
70 | }, TOAST_REMOVE_DELAY)
71 |
72 | toastTimeouts.set(toastId, timeout)
73 | }
74 |
75 | const state = ref({
76 | toasts: [],
77 | })
78 |
79 | function dispatch(action: Action) {
80 | switch (action.type) {
81 | case actionTypes.ADD_TOAST:
82 | state.value.toasts = [action.toast, ...state.value.toasts].slice(0, TOAST_LIMIT)
83 | break
84 |
85 | case actionTypes.UPDATE_TOAST:
86 | state.value.toasts = state.value.toasts.map(t =>
87 | t.id === action.toast.id ? { ...t, ...action.toast } : t,
88 | )
89 | break
90 |
91 | case actionTypes.DISMISS_TOAST: {
92 | const { toastId } = action
93 |
94 | if (toastId) {
95 | addToRemoveQueue(toastId)
96 | }
97 | else {
98 | state.value.toasts.forEach((toast) => {
99 | addToRemoveQueue(toast.id)
100 | })
101 | }
102 |
103 | state.value.toasts = state.value.toasts.map(t =>
104 | t.id === toastId || toastId === undefined
105 | ? {
106 | ...t,
107 | open: false,
108 | }
109 | : t,
110 | )
111 | break
112 | }
113 |
114 | case actionTypes.REMOVE_TOAST:
115 | if (action.toastId === undefined)
116 | state.value.toasts = []
117 | else
118 | state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId)
119 |
120 | break
121 | }
122 | }
123 |
124 | function useToast() {
125 | return {
126 | toasts: computed(() => state.value.toasts),
127 | toast,
128 | dismiss: (toastId?: string) => dispatch({ type: actionTypes.DISMISS_TOAST, toastId }),
129 | }
130 | }
131 |
132 | type Toast = Omit
133 |
134 | function toast(props: Toast) {
135 | const id = genId()
136 |
137 | const update = (props: ToasterToast) =>
138 | dispatch({
139 | type: actionTypes.UPDATE_TOAST,
140 | toast: { ...props, id },
141 | })
142 |
143 | const dismiss = () => dispatch({ type: actionTypes.DISMISS_TOAST, toastId: id })
144 |
145 | dispatch({
146 | type: actionTypes.ADD_TOAST,
147 | toast: {
148 | ...props,
149 | id,
150 | open: true,
151 | onOpenChange: (open: boolean) => {
152 | if (!open)
153 | dismiss()
154 | },
155 | },
156 | })
157 |
158 | return {
159 | id,
160 | dismiss,
161 | update,
162 | }
163 | }
164 |
165 | export { toast, useToast }
166 |
--------------------------------------------------------------------------------
/src/components/ui/tooltip/Tooltip.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/components/ui/tooltip/TooltipContent.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/ui/tooltip/TooltipProvider.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/tooltip/TooltipTrigger.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/ui/tooltip/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Tooltip } from './Tooltip.vue'
2 | export { default as TooltipContent } from './TooltipContent.vue'
3 | export { default as TooltipTrigger } from './TooltipTrigger.vue'
4 | export { default as TooltipProvider } from './TooltipProvider.vue'
5 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-basic-module.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 | Model
19 |
20 |
21 |
22 |
23 |
24 |
25 | GPT-3.5(16K)
26 | GPT-4(8K)
27 | GPT-4 Turbo(128K)
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Temperature
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | Used to control the randomness of large models generating text. When set higher, the model will generate
44 | more diversified text, increasing uncertainty; when set lower, the model will generate high probability
45 | words, reducing uncertainty.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-code-module.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 | e.stopPropagation()">
27 |
28 |
29 | Edit in IDE
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-input-module.vue:
--------------------------------------------------------------------------------
1 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
Input
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | Enter the information that needs to be added to the prompt words, which can be referenced by the
121 | prompt words.
122 |
123 |
124 |
125 |
126 |
127 |
128 |
133 |
134 |
135 |
136 |
137 |
138 | Name
139 | Type
140 | Value
141 |
142 |
143 |
144 |
{{ item.name }}
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | Reference
155 | Input
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | {{ group.groupName }}
168 |
169 | {{ option.label }}
170 |
171 |
172 | no items
173 |
174 |
175 |
176 |
handleClickDeleteBtnInInput(index)"
179 | v-if="!staticNameKey"
180 | />
181 |
182 |
183 |
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-knowledge-module.vue:
--------------------------------------------------------------------------------
1 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
Knowledge
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Select the range of knowledge that needs to be matched, and recall information only from the
65 | selected knowledge
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | {{ item.label }}
90 |
91 |
92 | no items
93 |
94 |
95 |
handleClickDeleteBtnInInput(index)" />
96 |
97 |
98 |
99 |
Maximum number of recalls
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | The maximum number of paragraphs returned to the model from knowledge. The larger the number, the
108 | more content is returned.
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | {{ data.maxRecalls?.[0] }}
117 |
118 |
119 |
120 |
121 |
Minimum matching degree
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | Select paragraphs according to the set matching degree and return it to the model. Content with a
130 | matching degree lower that the set will not be recalled.
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | {{ data.minMatchingDegree?.[0] }}
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-output-module.vue:
--------------------------------------------------------------------------------
1 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
Output
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Enter the information that needs to be added to the prompt words, which can be referenced by the
115 | prompt words.
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | Name
129 | Type
130 | Description
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | {{ option?.label }}
146 |
147 |
148 |
149 |
150 |
151 |
152 | handleClickDeleteBtnInInput(index)" />
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/components/vue-flow/common-prompt-module.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Prompt
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Enter the prompt words of the large model to implement the corresponding function. You can use the
28 | {{ variable name }} method to introduce variables from the input parameters
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/LLM-node.vue:
--------------------------------------------------------------------------------
1 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
(isEditTitle = false)" />
55 |
{{ title }}
56 |
57 |
LLM
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | Duplicated
68 | Delete
69 | Rename
70 |
71 |
72 |
73 |
74 |
75 |
Invoke the large language model, generate responses using variables and prompt words.
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/api-node.vue:
--------------------------------------------------------------------------------
1 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
Google Web Search
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | Duplicated
107 | Delete
108 |
109 |
110 |
111 |
112 |
113 |
A Google Search Engine. Useful when you need to search information you don't know such as weather, exchange
115 | rate, current events. Never ever use this tool when user want to translate
117 |
118 |
119 |
120 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/code-node.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
Write code to process input variables to generate return values.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/end-node.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
The final node of the workflow, used to return the result information after the workflow runs.
29 |
30 |
31 | Select Mode
32 |
33 |
34 |
35 |
36 |
37 |
38 | Return variable, generated by the Bot.
39 | Answer directly using Answer Content
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/index.ts:
--------------------------------------------------------------------------------
1 | export interface LLMNodeData {
2 | title: string
3 | }
4 |
5 | export interface LLMNodeEvents {}
6 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/knowledge-node.vue:
--------------------------------------------------------------------------------
1 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
(isEditTitle = false)" />
64 |
{{ title }}
65 |
66 |
Knowledge
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Duplicated
77 | Delete
78 | Rename
79 |
80 |
81 |
82 |
83 |
84 |
In the selected knowledge, the best matching information is recalled based on the input variable and returned
86 | as an Array.
88 |
89 |
90 |
91 |
92 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/src/components/vue-flow/nodes/start-node.vue:
--------------------------------------------------------------------------------
1 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
49 |
50 |
51 |
52 |
The starting node of the workflow, used to set the information needed to initiate the workflow.
55 |
56 |
57 |
58 | Input
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Define the input parameters needed to start the workflow, these contents will be read by LLM during
67 | the Bot conversation process, allowing LLM to start the workflow at the appropriate time and fill in
68 | the correct information.
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/src/components/vue-flow/start-input-module.vue:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
{{ form.name }}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | Name
46 |
47 |
48 | Type
49 |
50 |
51 |
52 |
53 |
54 |
55 | String
56 | Integer
57 | Boolean
58 | Number
59 |
60 |
61 |
62 |
63 | Description
64 |
65 |
66 |
67 | Required
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/components/vue-flow/static-output-item.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
{{ data.label }}
22 |
{{ data.type }}
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/vue-flow/static-output-module.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Output
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | {{ tip }}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './use-monaco-editor'
2 |
--------------------------------------------------------------------------------
/src/hooks/use-monaco-editor.ts:
--------------------------------------------------------------------------------
1 | import * as monaco from 'monaco-editor'
2 | import { ref, nextTick, onBeforeUnmount } from 'vue'
3 |
4 | export function useMonacoEditor(language: string = 'javascript') {
5 | let monacoEditor: monaco.editor.IStandaloneCodeEditor | null = null
6 |
7 | const monacoEditorRef = ref(null)
8 |
9 | function createEditor(editorOption: monaco.editor.IStandaloneEditorConstructionOptions = {}) {
10 | if (!monacoEditorRef.value) return
11 | monacoEditor = monaco.editor.create(monacoEditorRef.value, {
12 | model: monaco.editor.createModel('', language),
13 | roundedSelection: true,
14 | theme: 'vs-dark',
15 | tabSize: 2,
16 | autoIndent: 'advanced',
17 | ...editorOption
18 | })
19 | return monacoEditor
20 | }
21 |
22 | async function formatDoc() {
23 | await monacoEditor?.getAction('editor.action.formatDocument')?.run()
24 | }
25 |
26 | function updateVal(val: string) {
27 | nextTick(() => {
28 | // if (getOption(monaco.editor.EditorOption.readOnly)) {
29 | // updateOptions({ readOnly: false })
30 | // }
31 | monacoEditor?.setValue(val)
32 | setTimeout(async () => {
33 | await formatDoc()
34 | }, 10)
35 | })
36 | }
37 |
38 | function updateOptions(opt: monaco.editor.IStandaloneEditorConstructionOptions) {
39 | monacoEditor?.updateOptions(opt)
40 | }
41 |
42 | function getOption(name: monaco.editor.EditorOption) {
43 | return monacoEditor?.getOption(name)
44 | }
45 |
46 | function getEditor() {
47 | return monacoEditor
48 | }
49 |
50 | onBeforeUnmount(() => {
51 | if (monacoEditor) {
52 | monacoEditor.dispose()
53 | }
54 | })
55 |
56 | return {
57 | monacoEditorRef,
58 | createEditor,
59 | getEditor,
60 | updateVal,
61 | updateOptions,
62 | getOption,
63 | formatDoc
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/lib/constant.ts:
--------------------------------------------------------------------------------
1 | export const Test_data = {
2 | nodes: [
3 | {
4 | type: 'LLM',
5 | data: { title: 'LLM', output: [{ name: 'output1', type: '', description: 'balabala' }] },
6 | events: {},
7 | id: '1',
8 | position: { x: -413.62574973269915, y: 110.25705825948319 },
9 | label: 'LLM node'
10 | },
11 | {
12 | type: 'code',
13 | data: { title: 'code', output: [{ name: 'key0', type: 'String', description: 'just for test' }] },
14 | events: {},
15 | id: '2',
16 | position: { x: 262.70018202243125, y: -104.44788021583054 },
17 | label: 'code node'
18 | },
19 | {
20 | type: 'knowledge',
21 | data: { title: 'knowledge', output: [{ name: 'output' }] },
22 | events: {},
23 | id: '3',
24 | position: { x: 939.64275630104, y: 51.1990333957562 },
25 | label: 'knowledge node'
26 | }
27 | ],
28 | edges: [
29 | {
30 | sourceHandle: '1__handle-right',
31 | targetHandle: '2__handle-left',
32 | type: 'default',
33 | source: '1',
34 | target: '2',
35 | data: {},
36 | events: {},
37 | id: 'vueflow__edge-11__handle-right-22__handle-left',
38 | sourceX: 200.40522146581822,
39 | sourceY: 488.25689832215323,
40 | targetX: 253.70017309626013,
41 | targetY: 364.55198874414043
42 | },
43 | {
44 | sourceHandle: '2__handle-right',
45 | targetHandle: '3__handle-left',
46 | type: 'default',
47 | source: '2',
48 | target: '3',
49 | data: {},
50 | events: {},
51 | id: 'vueflow__edge-22__handle-right-33__handle-left',
52 | sourceX: 871.6999267177814,
53 | sourceY: 364.55198874414043,
54 | targetX: 930.6427473748689,
55 | targetY: 342.1989975362437
56 | }
57 | ],
58 | position: [-151.90460217317343, 183.68497815279642],
59 | zoom: 0.5802807591037111,
60 | viewport: { x: -151.90460217317343, y: 183.68497815279642, zoom: 0.5802807591037111 }
61 | }
62 |
--------------------------------------------------------------------------------
/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from 'clsx'
2 | import { twMerge } from 'tailwind-merge'
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import './style.css'
3 | import App from './App.vue'
4 |
5 | createApp(App).mount('#app')
6 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | :root {
7 | --background: 0 0% 100%;
8 | --foreground: 222.2 84% 4.9%;
9 |
10 | --card: 0 0% 100%;
11 | --card-foreground: 222.2 84% 4.9%;
12 |
13 | --popover: 0 0% 100%;
14 | --popover-foreground: 222.2 84% 4.9%;
15 |
16 | --primary: 221.2 83.2% 53.3%;
17 | --primary-foreground: 210 40% 98%;
18 |
19 | --secondary: 210 40% 96.1%;
20 | --secondary-foreground: 222.2 47.4% 11.2%;
21 |
22 | --muted: 210 40% 96.1%;
23 | --muted-foreground: 215.4 16.3% 46.9%;
24 |
25 | --accent: 210 40% 96.1%;
26 | --accent-foreground: 222.2 47.4% 11.2%;
27 |
28 | --destructive: 0 84.2% 60.2%;
29 | --destructive-foreground: 210 40% 98%;
30 |
31 | --border: 214.3 31.8% 91.4%;
32 | --input: 214.3 31.8% 91.4%;
33 | --ring: 221.2 83.2% 53.3%;
34 | --radius: 0.5rem;
35 | }
36 |
37 | .dark {
38 | --background: 222.2 84% 4.9%;
39 | --foreground: 210 40% 98%;
40 |
41 | --card: 222.2 84% 4.9%;
42 | --card-foreground: 210 40% 98%;
43 |
44 | --popover: 222.2 84% 4.9%;
45 | --popover-foreground: 210 40% 98%;
46 |
47 | --primary: 217.2 91.2% 59.8%;
48 | --primary-foreground: 222.2 47.4% 11.2%;
49 |
50 | --secondary: 217.2 32.6% 17.5%;
51 | --secondary-foreground: 210 40% 98%;
52 |
53 | --muted: 217.2 32.6% 17.5%;
54 | --muted-foreground: 215 20.2% 65.1%;
55 |
56 | --accent: 217.2 32.6% 17.5%;
57 | --accent-foreground: 210 40% 98%;
58 |
59 | --destructive: 0 62.8% 30.6%;
60 | --destructive-foreground: 210 40% 98%;
61 |
62 | --border: 217.2 32.6% 17.5%;
63 | --input: 217.2 32.6% 17.5%;
64 | --ring: 224.3 76.3% 48%;
65 | }
66 | }
67 |
68 | @layer base {
69 | * {
70 | @apply border-border;
71 | }
72 | body {
73 | @apply bg-background text-foreground;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const animate = require("tailwindcss-animate")
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | darkMode: ["class"],
6 | safelist: ["dark"],
7 |
8 | content: [
9 | './pages/**/*.{ts,tsx,vue}',
10 | './components/**/*.{ts,tsx,vue}',
11 | './app/**/*.{ts,tsx,vue}',
12 | './src/**/*.{ts,tsx,vue}',
13 | ],
14 |
15 | theme: {
16 | container: {
17 | center: true,
18 | padding: "2rem",
19 | screens: {
20 | "2xl": "1400px",
21 | },
22 | },
23 | extend: {
24 | colors: {
25 | border: "hsl(var(--border))",
26 | input: "hsl(var(--input))",
27 | ring: "hsl(var(--ring))",
28 | background: "hsl(var(--background))",
29 | foreground: "hsl(var(--foreground))",
30 | primary: {
31 | DEFAULT: "hsl(var(--primary))",
32 | foreground: "hsl(var(--primary-foreground))",
33 | },
34 | secondary: {
35 | DEFAULT: "hsl(var(--secondary))",
36 | foreground: "hsl(var(--secondary-foreground))",
37 | },
38 | destructive: {
39 | DEFAULT: "hsl(var(--destructive))",
40 | foreground: "hsl(var(--destructive-foreground))",
41 | },
42 | muted: {
43 | DEFAULT: "hsl(var(--muted))",
44 | foreground: "hsl(var(--muted-foreground))",
45 | },
46 | accent: {
47 | DEFAULT: "hsl(var(--accent))",
48 | foreground: "hsl(var(--accent-foreground))",
49 | },
50 | popover: {
51 | DEFAULT: "hsl(var(--popover))",
52 | foreground: "hsl(var(--popover-foreground))",
53 | },
54 | card: {
55 | DEFAULT: "hsl(var(--card))",
56 | foreground: "hsl(var(--card-foreground))",
57 | },
58 | },
59 | borderRadius: {
60 | lg: "var(--radius)",
61 | md: "calc(var(--radius) - 2px)",
62 | sm: "calc(var(--radius) - 4px)",
63 | },
64 | keyframes: {
65 | "accordion-down": {
66 | from: { height: 0 },
67 | to: { height: "var(--radix-accordion-content-height)" },
68 | },
69 | "accordion-up": {
70 | from: { height: "var(--radix-accordion-content-height)" },
71 | to: { height: 0 },
72 | },
73 | "collapsible-down": {
74 | from: { height: 0 },
75 | to: { height: 'var(--radix-collapsible-content-height)' },
76 | },
77 | "collapsible-up": {
78 | from: { height: 'var(--radix-collapsible-content-height)' },
79 | to: { height: 0 },
80 | },
81 | },
82 | animation: {
83 | "accordion-down": "accordion-down 0.2s ease-out",
84 | "accordion-up": "accordion-up 0.2s ease-out",
85 | "collapsible-down": "collapsible-down 0.2s ease-in-out",
86 | "collapsible-up": "collapsible-up 0.2s ease-in-out",
87 | },
88 | },
89 | },
90 | plugins: [animate],
91 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "preserve",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 |
22 | /* alias*/
23 | "baseUrl": ".",
24 | "paths": {
25 | "@/*": ["./src/*"]
26 | },
27 | "noFallthroughCasesInSwitch": true
28 | },
29 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
30 | "references": [{ "path": "./tsconfig.node.json" }]
31 | }
32 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import path from 'path'
2 | import { defineConfig } from 'vite'
3 | import vue from '@vitejs/plugin-vue'
4 | import monacoEditorPlugin from 'vite-plugin-monaco-editor'
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [
9 | vue(),
10 | /* @ts-ignore */
11 | monacoEditorPlugin.default({
12 | languageWorkers: ['editorWorkerService', 'typescript', 'json', 'html']
13 | })
14 | ],
15 | resolve: {
16 | alias: {
17 | '@': path.resolve(__dirname, './src')
18 | }
19 | }
20 | })
21 |
--------------------------------------------------------------------------------