Initial commit
This commit is contained in:
parent
4bee7b73b5
commit
e53c007293
@ -1,8 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,4 +0,0 @@
|
||||
/.yarn/** linguist-vendored
|
||||
/.yarn/releases/* binary
|
||||
/.yarn/plugins/**/* binary
|
||||
/.pnp.* binary linguist-generated
|
||||
35
.gitignore
vendored
35
.gitignore
vendored
@ -1,17 +1,24 @@
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Whether you use PnP or not, the node_modules folder is often used to store
|
||||
# build artifacts that should be gitignored
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Swap the comments on the following lines if you wish to use zero-installs
|
||||
# In that case, don't forget to run `yarn config set enableGlobalCache false`!
|
||||
# Documentation here: https://yarnpkg.com/features/caching#zero-installs
|
||||
|
||||
#!.yarn/cache
|
||||
.pnp.*
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
@ -1 +1,5 @@
|
||||
# yjs-bpmn-frontend
|
||||
# Vue 3 + TypeScript + Vite
|
||||
|
||||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||
|
||||
Learn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).
|
||||
|
||||
17
eslint.config.js
Normal file
17
eslint.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default antfu({
|
||||
formatters: {
|
||||
css: true,
|
||||
},
|
||||
overrides: {
|
||||
vue: {
|
||||
'vue/block-order': ['error', {
|
||||
order: ['template', 'script', 'style'],
|
||||
}],
|
||||
},
|
||||
},
|
||||
globals: {
|
||||
definePage: 'readonly',
|
||||
},
|
||||
})
|
||||
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>yjs-bpmn-frontend</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
31
package.json
31
package.json
@ -1,4 +1,33 @@
|
||||
{
|
||||
"name": "yjs-bpmn-frontend",
|
||||
"packageManager": "yarn@4.11.0"
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue-flow/background": "^1.3.2",
|
||||
"@vue-flow/core": "^1.47.0",
|
||||
"@vueuse/core": "^14.0.0",
|
||||
"vue": "^3.5.24",
|
||||
"vue-router": "4",
|
||||
"y-websocket": "^3.0.0",
|
||||
"yjs": "^13.6.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^6.2.0",
|
||||
"@types/node": "^24.10.0",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-format": "^1.0.2",
|
||||
"sass-embedded": "^1.93.3",
|
||||
"typescript": "~5.9.3",
|
||||
"unplugin-vue-router": "^0.17.0",
|
||||
"vite": "^7.2.2",
|
||||
"vue-tsc": "^3.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
6
src/App.vue
Normal file
6
src/App.vue
Normal file
@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
1
src/assets/vue.svg
Normal file
1
src/assets/vue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 496 B |
64
src/components/Flowchart.vue
Normal file
64
src/components/Flowchart.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<VueFlow
|
||||
v-model:nodes="nodes"
|
||||
v-model:edges="edges"
|
||||
:apply-default="false"
|
||||
:connection-mode="ConnectionMode.Strict"
|
||||
:connection-line-type="ConnectionLineType.Step"
|
||||
>
|
||||
<Background />
|
||||
</VueFlow>
|
||||
|
||||
<div class="menu">
|
||||
<button @click="addRandomNode">
|
||||
Добавить
|
||||
</button>
|
||||
<button @click="reset">
|
||||
Сбросить
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Edge, Node } from '@vue-flow/core'
|
||||
import { Background } from '@vue-flow/background'
|
||||
import { ConnectionLineType, ConnectionMode, useVueFlow, VueFlow } from '@vue-flow/core'
|
||||
import { ref } from 'vue'
|
||||
import { useCollaborativeFlow } from '../composables/useCollaborativeFlow.js'
|
||||
|
||||
const props = defineProps<{
|
||||
diagramId: string
|
||||
}>()
|
||||
|
||||
const nodes = ref<Node[]>([])
|
||||
const edges = ref<Edge[]>([])
|
||||
|
||||
const { addNodes, onConnect, addEdges } = useVueFlow()
|
||||
|
||||
onConnect(addEdges)
|
||||
|
||||
const { reset } = useCollaborativeFlow(() => props.diagramId)
|
||||
|
||||
function addRandomNode() {
|
||||
addNodes({
|
||||
id: Math.random().toString(),
|
||||
position: { x: Math.random() * 500, y: Math.random() * 500 },
|
||||
label: 'Random Node',
|
||||
data: {
|
||||
hello: 'world',
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.menu {
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
width: 160px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
211
src/composables/useCollaborativeFlow.ts
Normal file
211
src/composables/useCollaborativeFlow.ts
Normal file
@ -0,0 +1,211 @@
|
||||
import type { Edge, Node } from '@vue-flow/core'
|
||||
import type { MaybeRefOrGetter } from 'vue'
|
||||
import type { YMapEvent } from 'yjs'
|
||||
import { useVueFlow } from '@vue-flow/core'
|
||||
import { onScopeDispose, shallowRef, toValue, watch } from 'vue'
|
||||
import { WebsocketProvider } from 'y-websocket'
|
||||
import * as Y from 'yjs'
|
||||
|
||||
export function useCollaborativeFlow(diagramId: MaybeRefOrGetter<string>) {
|
||||
const yDoc = new Y.Doc()
|
||||
|
||||
const provider = shallowRef<WebsocketProvider>()
|
||||
|
||||
const yNodes = yDoc.getMap<Node>('nodes')
|
||||
const yEdges = yDoc.getMap<Edge>('edges')
|
||||
|
||||
const {
|
||||
addNodes,
|
||||
addEdges,
|
||||
updateNode,
|
||||
onNodesChange,
|
||||
onEdgesChange,
|
||||
applyNodeChanges,
|
||||
applyEdgeChanges,
|
||||
removeNodes,
|
||||
removeEdges,
|
||||
} = useVueFlow()
|
||||
|
||||
let isApplyingFromY = false
|
||||
let isApplyingEdgesFromY = false
|
||||
|
||||
// ---------------------------
|
||||
// Yjs -> Vue Flow
|
||||
// ---------------------------
|
||||
const nodesObserver = (event: YMapEvent<Node>) => {
|
||||
console.log('nodesObserver', event)
|
||||
|
||||
isApplyingFromY = true
|
||||
|
||||
for (const [id, change] of event.changes.keys) {
|
||||
switch (change.action) {
|
||||
case 'add': {
|
||||
const node = yNodes.get(id)
|
||||
|
||||
if (!node)
|
||||
continue
|
||||
|
||||
addNodes(node)
|
||||
break
|
||||
}
|
||||
|
||||
case 'delete':
|
||||
removeNodes(id)
|
||||
break
|
||||
|
||||
case 'update': {
|
||||
const node = yNodes.get(id)
|
||||
|
||||
if (!node)
|
||||
continue
|
||||
|
||||
updateNode(id, { position: node.position })
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isApplyingFromY = false
|
||||
}
|
||||
|
||||
const edgesObserver = (event: YMapEvent<Edge>) => {
|
||||
console.log('edgesObserver', event)
|
||||
|
||||
isApplyingEdgesFromY = true
|
||||
|
||||
for (const [id, change] of event.changes.keys) {
|
||||
switch (change.action) {
|
||||
case 'add': {
|
||||
const edge = yEdges.get(id)
|
||||
|
||||
if (!edge)
|
||||
continue
|
||||
|
||||
addEdges(edge)
|
||||
break
|
||||
}
|
||||
|
||||
case 'delete':
|
||||
removeEdges(id)
|
||||
break
|
||||
|
||||
// case 'update':
|
||||
// updateEdgeData(id, data)
|
||||
// break
|
||||
}
|
||||
}
|
||||
|
||||
isApplyingEdgesFromY = false
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Vue Flow -> Yjs
|
||||
// ---------------------------
|
||||
onNodesChange((changes) => {
|
||||
console.log('onNodesChange', changes)
|
||||
|
||||
if (changes.length === 0)
|
||||
return
|
||||
|
||||
applyNodeChanges(changes)
|
||||
|
||||
if (isApplyingFromY)
|
||||
return
|
||||
|
||||
yDoc.transact(() => {
|
||||
for (const change of changes) {
|
||||
const { type } = change
|
||||
|
||||
switch (type) {
|
||||
case 'add': {
|
||||
yNodes.set(change.item.id, change.item)
|
||||
break
|
||||
}
|
||||
|
||||
case 'remove':
|
||||
yNodes.delete(change.id)
|
||||
break
|
||||
|
||||
case 'position': {
|
||||
const node = yNodes.get(change.id)
|
||||
|
||||
if (!node)
|
||||
return
|
||||
|
||||
if (change.position) {
|
||||
node.position = change.position
|
||||
}
|
||||
|
||||
yNodes.set(change.id, node)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onEdgesChange((changes) => {
|
||||
console.log('onEdgesChange', changes)
|
||||
|
||||
if (changes.length === 0)
|
||||
return
|
||||
|
||||
applyEdgeChanges(changes)
|
||||
|
||||
if (isApplyingEdgesFromY)
|
||||
return
|
||||
|
||||
yDoc.transact(() => {
|
||||
for (const change of changes) {
|
||||
const { type } = change
|
||||
|
||||
switch (type) {
|
||||
case 'add': {
|
||||
yEdges.set(change.item.id, change.item)
|
||||
break
|
||||
}
|
||||
|
||||
case 'remove':
|
||||
yEdges.delete(change.id)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
yNodes.observe(nodesObserver)
|
||||
yEdges.observe(edgesObserver)
|
||||
|
||||
watch(() => toValue(diagramId), (diagramId) => {
|
||||
provider.value?.destroy()
|
||||
|
||||
reset()
|
||||
|
||||
if (!diagramId)
|
||||
return
|
||||
|
||||
provider.value = new WebsocketProvider(
|
||||
'ws://localhost:1234',
|
||||
diagramId,
|
||||
yDoc,
|
||||
)
|
||||
}, { immediate: true })
|
||||
|
||||
onScopeDispose(() => {
|
||||
yNodes.unobserve(nodesObserver)
|
||||
yEdges.unobserve(edgesObserver)
|
||||
|
||||
provider.value?.destroy()
|
||||
})
|
||||
|
||||
function reset() {
|
||||
// yDoc.destroy()
|
||||
yNodes.clear()
|
||||
yEdges.clear()
|
||||
}
|
||||
|
||||
return {
|
||||
reset,
|
||||
}
|
||||
}
|
||||
8
src/main.ts
Normal file
8
src/main.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router.ts'
|
||||
import './style.css'
|
||||
|
||||
createApp(App)
|
||||
.use(router)
|
||||
.mount('#app')
|
||||
13
src/pages/[diagramId].vue
Normal file
13
src/pages/[diagramId].vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<Flowchart :diagram-id="diagramId" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import Flowchart from '../components/Flowchart.vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const diagramId = computed(() => route.params.diagramId as string)
|
||||
</script>
|
||||
31
src/pages/index.vue
Normal file
31
src/pages/index.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="index-page">
|
||||
<div class="index-page__content">
|
||||
<input v-model="diagramId" type="text" placeholder="Введите ID диаграммы">
|
||||
<button @click="$router.push(`/${diagramId}`)">
|
||||
Редактировать
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const diagramId = ref('')
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.index-page {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
||||
&__content {
|
||||
margin: auto;
|
||||
width: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
9
src/router.ts
Normal file
9
src/router.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { routes } from 'vue-router/auto-routes'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
export default router
|
||||
99
src/style.css
Normal file
99
src/style.css
Normal file
@ -0,0 +1,99 @@
|
||||
@import "@vue-flow/core/dist/style.css";
|
||||
@import "@vue-flow/core/dist/theme-default.css";
|
||||
|
||||
:root {
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
input {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
input:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
input:focus,
|
||||
input:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
||||
.vue-flow {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
16
tsconfig.app.json
Normal file
16
tsconfig.app.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"types": ["vite/client"],
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||
}
|
||||
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
26
tsconfig.node.json
Normal file
26
tsconfig.node.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"types": ["node"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
77
typed-router.d.ts
vendored
Normal file
77
typed-router.d.ts
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection ES6UnusedImports
|
||||
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
|
||||
// It's recommended to commit this file.
|
||||
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
|
||||
|
||||
declare module 'vue-router/auto-resolver' {
|
||||
export type ParamParserCustom = never
|
||||
}
|
||||
|
||||
declare module 'vue-router/auto-routes' {
|
||||
import type {
|
||||
RouteRecordInfo,
|
||||
ParamValue,
|
||||
ParamValueOneOrMore,
|
||||
ParamValueZeroOrMore,
|
||||
ParamValueZeroOrOne,
|
||||
} from 'vue-router'
|
||||
|
||||
/**
|
||||
* Route name map generated by unplugin-vue-router
|
||||
*/
|
||||
export interface RouteNamedMap {
|
||||
'/': RouteRecordInfo<
|
||||
'/',
|
||||
'/',
|
||||
Record<never, never>,
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/[diagramId]': RouteRecordInfo<
|
||||
'/[diagramId]',
|
||||
'/:diagramId',
|
||||
{ diagramId: ParamValue<true> },
|
||||
{ diagramId: ParamValue<false> },
|
||||
| never
|
||||
>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Route file to route info map by unplugin-vue-router.
|
||||
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
|
||||
*
|
||||
* Each key is a file path relative to the project root with 2 properties:
|
||||
* - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
|
||||
* - views: names of nested views (can be passed to <RouterView name="...">)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export interface _RouteFileInfoMap {
|
||||
'src/pages/index.vue': {
|
||||
routes:
|
||||
| '/'
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/pages/[diagramId].vue': {
|
||||
routes:
|
||||
| '/[diagramId]'
|
||||
views:
|
||||
| never
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a union of possible route names in a certain route component file.
|
||||
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export type _RouteNamesForFilePath<FilePath extends string> =
|
||||
_RouteFileInfoMap extends Record<FilePath, infer Info>
|
||||
? Info['routes']
|
||||
: keyof RouteNamedMap
|
||||
}
|
||||
17
vite.config.ts
Normal file
17
vite.config.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import VueRouter from 'unplugin-vue-router/vite'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
VueRouter({
|
||||
routesFolder: [
|
||||
{
|
||||
src: 'src/pages',
|
||||
path: '',
|
||||
},
|
||||
],
|
||||
}),
|
||||
vue(),
|
||||
],
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user