Front stack primary updates and improvements (#757)

* (fix) index.html formating for prettier

* (add) proper icon management
- on-demand icons auto importing
- handle all available icon sets (https://icones.js.org)

* (fix) proper css management

* (add) front stack improvement:
- implement vue router
- prepare for App.vue simplification
- proper management of views and layouts
- fix Tailwind CSS and prepare for overall css cleaning

* (fix) move back user.css to public dir

* (fix) remove user.css import from main.ts
This commit is contained in:
ArtificialLab
2024-09-11 03:53:54 +04:00
committed by GitHub
parent 90abf9744c
commit 05b3ad2f59
12 changed files with 655 additions and 125 deletions

1
.gitignore vendored
View File

@@ -23,6 +23,7 @@ dist-ssr
*.njsproj
*.sln
*.sw?
components.d.ts
# Ignore test data.
tests-ui/data/*

View File

@@ -1,55 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ComfyUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<!-- Browser Test Fonts -->
<!-- <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<style>
* {
font-family: 'Roboto Mono', 'Noto Color Emoji';
}
</style> -->
<script type="module" src="node_modules/reflect-metadata/Reflect.js"></script>
<script type="module">
import 'reflect-metadata';
window["__COMFYUI_FRONTEND_VERSION__"] = __COMFYUI_FRONTEND_VERSION__;
console.log("ComfyUI Front-end version:", __COMFYUI_FRONTEND_VERSION__);
</script>
<script type="module" src="src/main.ts"></script>
<link rel="stylesheet" type="text/css" href="user.css" />
<link rel="stylesheet" type="text/css" href="materialdesignicons.min.css" />
</head>
<body class="litegraph">
<div id="vue-app"></div>
<div id="comfy-user-selection" class="comfy-user-selection" style="display: none;">
<main class="comfy-user-selection-inner">
<h1>ComfyUI</h1>
<form>
<section>
<label>New user:
<input placeholder="Enter a username" />
</label>
</section>
<div class="comfy-user-existing">
<span class="or-separator">OR</span>
<section>
<label>
Existing user:
<select>
<option hidden disabled selected value> Select a user </option>
</select>
</label>
</section>
</div>
<footer>
<span class="comfy-user-error">&nbsp;</span>
<button class="comfy-btn comfy-user-button-next">Next</button>
</footer>
</form>
</main>
</div>
</body>
<head>
<meta charset="UTF-8">
<title>ComfyUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<!-- Browser Test Fonts -->
<!-- <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<style>
* {
font-family: 'Roboto Mono', 'Noto Color Emoji';
}
</style> -->
<script type="module" src="node_modules/reflect-metadata/Reflect.js"></script>
<script type="module">
import 'reflect-metadata';
window["__COMFYUI_FRONTEND_VERSION__"] = __COMFYUI_FRONTEND_VERSION__;
console.log("ComfyUI Front-end version:", __COMFYUI_FRONTEND_VERSION__);
</script>
<script type="module" src="src/main.ts"></script>
<link rel="stylesheet" type="text/css" href="user.css" />
<link rel="stylesheet" type="text/css" href="materialdesignicons.min.css" />
</head>
<body class="litegraph">
<div id="vue-app"></div>
<div id="comfy-user-selection" class="comfy-user-selection" style="display: none;">
<main class="comfy-user-selection-inner">
<h1>ComfyUI</h1>
<form>
<section>
<label>New user:
<input placeholder="Enter a username" />
</label>
</section>
<div class="comfy-user-existing">
<span class="or-separator">OR</span>
<section>
<label>
Existing user:
<select>
<option hidden disabled selected value> Select a user </option>
</select>
</label>
</section>
</div>
<footer>
<span class="comfy-user-error">&nbsp;</span>
<button class="comfy-btn comfy-user-button-next">Next</button>
</footer>
</form>
</main>
</div>
</body>
</html>

320
package-lock.json generated
View File

@@ -24,6 +24,7 @@
"reflect-metadata": "^0.2.2",
"vue": "^3.4.31",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.3",
"zod": "^3.23.8",
"zod-validation-error": "^3.3.0"
},
@@ -31,6 +32,7 @@
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.22.20",
"@eslint/js": "^9.8.0",
"@iconify/json": "^2.2.245",
"@playwright/test": "^1.44.1",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.6",
@@ -59,6 +61,8 @@
"tsx": "^4.15.6",
"typescript": "^5.4.5",
"typescript-eslint": "^8.0.0",
"unplugin-icons": "^0.19.3",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.2.0",
"vite-plugin-static-copy": "^1.0.5",
"vitest": "^2.0.5",
@@ -112,6 +116,28 @@
"node": ">=6.0.0"
}
},
"node_modules/@antfu/install-pkg": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz",
"integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==",
"dev": true,
"dependencies": {
"package-manager-detector": "^0.2.0",
"tinyexec": "^0.3.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@antfu/utils": {
"version": "0.7.10",
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz",
"integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@atlaskit/pragmatic-drag-and-drop": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@atlaskit/pragmatic-drag-and-drop/-/pragmatic-drag-and-drop-1.2.1.tgz",
@@ -2414,6 +2440,37 @@
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@iconify/json": {
"version": "2.2.245",
"resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.245.tgz",
"integrity": "sha512-JbruddbGKghBe6fE1mzuo5hhUkisIW4mAdQGAyx0Q6sI52ukeQJHakolc2RQD/yWC3xp7rARNXMzWSXJynJ1vw==",
"dev": true,
"dependencies": {
"@iconify/types": "*",
"pathe": "^1.1.2"
}
},
"node_modules/@iconify/types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
"dev": true
},
"node_modules/@iconify/utils": {
"version": "2.1.32",
"resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.32.tgz",
"integrity": "sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==",
"dev": true,
"dependencies": {
"@antfu/install-pkg": "^0.4.0",
"@antfu/utils": "^0.7.10",
"@iconify/types": "^2.0.0",
"debug": "^4.3.6",
"kolorist": "^1.8.0",
"local-pkg": "^0.5.0",
"mlly": "^1.7.1"
}
},
"node_modules/@intlify/core-base": {
"version": "9.13.1",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.13.1.tgz",
@@ -3237,9 +3294,9 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
@@ -3380,6 +3437,28 @@
"node": ">=12.11.0"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz",
@@ -5327,6 +5406,12 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"node_modules/confbox": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz",
"integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==",
"dev": true
},
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
@@ -5544,12 +5629,12 @@
}
},
"node_modules/debug": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -9024,6 +9109,12 @@
"node": ">=6"
}
},
"node_modules/kolorist": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
"dev": true
},
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -9252,6 +9343,22 @@
"node": ">=18.0.0"
}
},
"node_modules/local-pkg": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
"integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
"dev": true,
"dependencies": {
"mlly": "^1.4.2",
"pkg-types": "^1.0.3"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -9409,11 +9516,11 @@
}
},
"node_modules/magic-string": {
"version": "0.30.10",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
"version": "0.30.11",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz",
"integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/make-dir": {
@@ -9542,10 +9649,22 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mlly": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz",
"integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==",
"dev": true,
"dependencies": {
"acorn": "^8.11.3",
"pathe": "^1.1.2",
"pkg-types": "^1.1.1",
"ufo": "^1.5.3"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/mz": {
@@ -9776,6 +9895,12 @@
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"dev": true
},
"node_modules/package-manager-detector": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.0.tgz",
"integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==",
"dev": true
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -10019,6 +10144,17 @@
"node": ">=8"
}
},
"node_modules/pkg-types": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz",
"integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==",
"dev": true,
"dependencies": {
"confbox": "^0.1.7",
"mlly": "^1.7.1",
"pathe": "^1.1.2"
}
},
"node_modules/playwright": {
"version": "1.45.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz",
@@ -11207,6 +11343,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/tinyexec": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz",
"integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==",
"dev": true
},
"node_modules/tinypool": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz",
@@ -11541,6 +11683,12 @@
}
}
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"dev": true
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
@@ -11596,6 +11744,130 @@
"node": ">= 4.0.0"
}
},
"node_modules/unplugin": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.13.1.tgz",
"integrity": "sha512-6Kq1iSSwg7KyjcThRUks9LuqDAKvtnioxbL9iEtB9ctTyBA5OmrB8gZd/d225VJu1w3UpUsKV7eGrvf59J7+VA==",
"dev": true,
"dependencies": {
"acorn": "^8.12.1",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"webpack-sources": "^3"
},
"peerDependenciesMeta": {
"webpack-sources": {
"optional": true
}
}
},
"node_modules/unplugin-icons": {
"version": "0.19.3",
"resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-0.19.3.tgz",
"integrity": "sha512-EUegRmsAI6+rrYr0vXjFlIP+lg4fSC4zb62zAZKx8FGXlWAGgEGBCa3JDe27aRAXhistObLPbBPhwa/0jYLFkQ==",
"dev": true,
"dependencies": {
"@antfu/install-pkg": "^0.4.1",
"@antfu/utils": "^0.7.10",
"@iconify/utils": "^2.1.29",
"debug": "^4.3.6",
"kolorist": "^1.8.0",
"local-pkg": "^0.5.0",
"unplugin": "^1.12.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@svgr/core": ">=7.0.0",
"@svgx/core": "^1.0.1",
"@vue/compiler-sfc": "^3.0.2 || ^2.7.0",
"vue-template-compiler": "^2.6.12",
"vue-template-es2015-compiler": "^1.9.0"
},
"peerDependenciesMeta": {
"@svgr/core": {
"optional": true
},
"@svgx/core": {
"optional": true
},
"@vue/compiler-sfc": {
"optional": true
},
"vue-template-compiler": {
"optional": true
},
"vue-template-es2015-compiler": {
"optional": true
}
}
},
"node_modules/unplugin-vue-components": {
"version": "0.27.4",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.27.4.tgz",
"integrity": "sha512-1XVl5iXG7P1UrOMnaj2ogYa5YTq8aoh5jwDPQhemwO/OrXW+lPQKDXd1hMz15qxQPxgb/XXlbgo3HQ2rLEbmXQ==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.7.10",
"@rollup/pluginutils": "^5.1.0",
"chokidar": "^3.6.0",
"debug": "^4.3.6",
"fast-glob": "^3.3.2",
"local-pkg": "^0.5.0",
"magic-string": "^0.30.11",
"minimatch": "^9.0.5",
"mlly": "^1.7.1",
"unplugin": "^1.12.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",
"vue": "2 || 3"
},
"peerDependenciesMeta": {
"@babel/parser": {
"optional": true
},
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/unplugin-vue-components/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/unplugin-vue-components/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
@@ -12108,6 +12380,20 @@
"vue": "^3.0.0"
}
},
"node_modules/vue-router": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.3.tgz",
"integrity": "sha512-sv6wmNKx2j3aqJQDMxLFzs/u/mjA9Z5LCgy6BE0f7yFWMjrPLnS/sPNn8ARY/FXw6byV18EFutn5lTO6+UsV5A==",
"dependencies": {
"@vue/devtools-api": "^6.6.3"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@@ -12138,6 +12424,12 @@
"node": ">=12"
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",

View File

@@ -24,6 +24,7 @@
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.22.20",
"@eslint/js": "^9.8.0",
"@iconify/json": "^2.2.245",
"@playwright/test": "^1.44.1",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.6",
@@ -52,6 +53,8 @@
"tsx": "^4.15.6",
"typescript": "^5.4.5",
"typescript-eslint": "^8.0.0",
"unplugin-icons": "^0.19.3",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.2.0",
"vite-plugin-static-copy": "^1.0.5",
"vitest": "^2.0.5",
@@ -74,6 +77,7 @@
"reflect-metadata": "^0.2.2",
"vue": "^3.4.31",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.3",
"zod": "^3.23.8",
"zod-validation-error": "^3.3.0"
},

View File

@@ -1,10 +1,10 @@
<template>
<router-view />
<ProgressSpinner v-if="isLoading" class="spinner"></ProgressSpinner>
<BlockUI full-screen :blocked="isLoading" />
<GlobalDialog />
<GlobalToast />
<UnloadWindowConfirmDialog />
<GraphCanvas />
</template>
<script setup lang="ts">
@@ -18,7 +18,6 @@ import {
} from 'vue'
import BlockUI from 'primevue/blockui'
import ProgressSpinner from 'primevue/progressspinner'
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
import QueueSidebarTab from '@/components/sidebar/tabs/QueueSidebarTab.vue'
import { app } from './scripts/app'
import { useSettingStore } from './stores/settingStore'

View File

@@ -1,15 +1,18 @@
import App from './App.vue'
import router from '@/router'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { i18n } from './i18n'
import PrimeVue from 'primevue/config'
import Aura from '@primevue/themes/aura'
import { definePreset } from '@primevue/themes'
import ConfirmationService from 'primevue/confirmationservice'
import ToastService from 'primevue/toastservice'
import Tooltip from 'primevue/tooltip'
import 'primeicons/primeicons.css'
import App from './App.vue'
import { createPinia } from 'pinia'
import { i18n } from './i18n'
import '@comfyorg/litegraph/style.css'
import '@/assets/css/style.css'
import 'primeicons/primeicons.css'
const ComfyUIPreset = definePreset(Aura, {
semantic: {
@@ -21,6 +24,7 @@ const app = createApp(App)
const pinia = createPinia()
app.directive('tooltip', Tooltip)
app
.use(router)
.use(PrimeVue, {
theme: {
preset: ComfyUIPreset,

28
src/router.ts Normal file
View File

@@ -0,0 +1,28 @@
import { createRouter, createWebHistory } from 'vue-router'
import LayoutDefault from '@/views/layouts/LayoutDefault.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: LayoutDefault,
children: [
{
path: '',
component: () => import('@/views/GraphView.vue')
}
]
}
],
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
})
export default router

View File

@@ -29,13 +29,10 @@ import {
LGraphCanvas,
LGraph,
LGraphNode,
LiteGraph
LiteGraph,
LGraphGroup
} from '@comfyorg/litegraph'
import { StorageLocation } from '@/types/settingTypes'
// CSS imports. style.css must be imported later as it overwrites some litegraph styles.
import '@comfyorg/litegraph/style.css'
import '../assets/css/style.css'
import { ExtensionManager } from '@/types/extensionTypes'
import {
ComfyNodeDefImpl,
@@ -54,7 +51,6 @@ import { useToastStore } from '@/stores/toastStore'
import { ModelStore, useModelStore } from '@/stores/modelStore'
import type { ToastMessageOptions } from 'primevue/toast'
import { useWorkspaceStore } from '@/stores/workspaceStateStore'
import { LGraphGroup } from '@comfyorg/litegraph'
export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview'

7
src/views/GraphView.vue Normal file
View File

@@ -0,0 +1,7 @@
<template>
<GraphCanvas />
</template>
<script setup lang="ts">
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
</script>

View File

@@ -0,0 +1,5 @@
<template>
<main class="w-full min-h-screen overflow-hidden relative">
<router-view />
</main>
</template>

View File

@@ -1,11 +1,182 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
corePlugins: {
preflight: false // This disables Tailwind's base styles
},
theme: {
extend: {}
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
'6xl': '4rem'
},
screens: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px',
'3xl': '1800px',
'4xl': '2500px',
'5xl': '3200px'
},
spacing: {
px: '1px',
0: '0px',
0.5: '0.125rem',
1: '0.25rem',
1.5: '0.375rem',
2: '0.5rem',
2.5: '0.625rem',
3: '0.75rem',
3.5: '0.875rem',
4: '1rem',
4.5: '1.125rem',
5: '1.25rem',
6: '1.5rem',
7: '1.75rem',
8: '2rem',
9: '2.25rem',
10: '2.5rem',
11: '2.75rem',
12: '3rem',
14: '3.5rem',
16: '4rem',
18: '4.5rem',
20: '5rem',
24: '6rem',
28: '7rem',
32: '8rem',
36: '9rem',
40: '10rem',
44: '11rem',
48: '12rem',
52: '13rem',
56: '14rem',
60: '15rem',
64: '16rem',
72: '18rem',
80: '20rem',
84: '22rem',
90: '24rem',
96: '26rem',
100: '28rem',
110: '32rem'
},
extend: {
colors: {
zinc: {
50: '#fafafa',
100: '#f4f4f5',
200: '#e4e4e7',
300: '#d4d4d8',
400: '#a1a1aa',
500: '#71717a',
600: '#52525b',
700: '#3f3f46',
800: '#27272a',
900: '#18181b',
950: '#09090b'
},
gray: {
50: '#f8fbfc',
100: '#f3f6fa',
200: '#edf2f7',
300: '#e2e8f0',
400: '#cbd5e0',
500: '#a0aec0',
600: '#718096',
700: '#4a5568',
800: '#2d3748',
900: '#1a202c',
950: '#0a1016'
},
teal: {
50: '#f0fdfa',
100: '#e0fcff',
200: '#bef8fd',
300: '#87eaf2',
400: '#54d1db',
500: '#38bec9',
600: '#2cb1bc',
700: '#14919b',
800: '#0e7c86',
900: '#005860',
950: '#022c28'
},
blue: {
50: '#eff6ff',
100: '#ebf8ff',
200: '#bee3f8',
300: '#90cdf4',
400: '#63b3ed',
500: '#4299e1',
600: '#3182ce',
700: '#2b6cb0',
800: '#2c5282',
900: '#2a4365',
950: '#172554'
},
green: {
50: '#fcfff5',
100: '#fafff3',
200: '#eaf9c9',
300: '#d1efa0',
400: '#b2e16e',
500: '#96ce4c',
600: '#7bb53d',
700: '#649934',
800: '#507b2e',
900: '#456829',
950: '#355819'
},
fuchsia: {
50: '#fdf4ff',
100: '#fae8ff',
200: '#f5d0fe',
300: '#f0abfc',
400: '#e879f9',
500: '#d946ef',
600: '#c026d3',
700: '#a21caf',
800: '#86198f',
900: '#701a75',
950: '#4a044e'
},
orange: {
50: '#fff7ed',
100: '#ffedd5',
200: '#fedbb8',
300: '#fbd38d',
400: '#f6ad55',
500: '#ed8936',
600: '#dd6b20',
700: '#c05621',
800: '#9c4221',
900: '#7b341e',
950: '#431407'
}
}
}
},
plugins: []
}

View File

@@ -1,92 +1,95 @@
import { defineConfig, Plugin } from 'vite';
import type { UserConfigExport } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import dotenv from "dotenv";
dotenv.config();
import { defineConfig, Plugin } from 'vite'
import type { UserConfigExport } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import dotenv from "dotenv"
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'
const IS_DEV = process.env.NODE_ENV === 'development';
const SHOULD_MINIFY = process.env.ENABLE_MINIFY === 'true';
dotenv.config()
const IS_DEV = process.env.NODE_ENV === 'development'
const SHOULD_MINIFY = process.env.ENABLE_MINIFY === 'true'
interface ShimResult {
code: string;
exports: string[];
code: string
exports: string[]
}
function isLegacyFile(id: string): boolean {
return id.endsWith('.ts') && (
id.includes("src/extensions/core") ||
id.includes("src/scripts")
);
)
}
function comfyAPIPlugin(): Plugin {
return {
name: 'comfy-api-plugin',
transform(code: string, id: string) {
if (IS_DEV)
return null;
if (IS_DEV) return null
if (isLegacyFile(id)) {
const result = transformExports(code, id);
const result = transformExports(code, id)
if (result.exports.length > 0) {
const projectRoot = process.cwd();
const relativePath = path.relative(path.join(projectRoot, 'src'), id);
const shimFileName = relativePath.replace(/\.ts$/, '.js');
const projectRoot = process.cwd()
const relativePath = path.relative(path.join(projectRoot, 'src'), id)
const shimFileName = relativePath.replace(/\.ts$/, '.js')
const shimComment = `// Shim for ${relativePath}\n`;
const shimComment = `// Shim for ${relativePath}\n`
this.emitFile({
type: "asset",
fileName: shimFileName,
source: shimComment + result.exports.join(""),
});
source: shimComment + result.exports.join("")
})
}
return {
code: result.code,
map: null // If you're not modifying the source map, return null
};
}
}
}
};
}
}
function transformExports(code: string, id: string): ShimResult {
const moduleName = getModuleName(id);
const exports: string[] = [];
let newCode = code;
const moduleName = getModuleName(id)
const exports: string[] = []
let newCode = code
// Regex to match different types of exports
const regex = /export\s+(const|let|var|function|class|async function)\s+([a-zA-Z$_][a-zA-Z\d$_]*)(\s|\()/g;
let match;
const regex = /export\s+(const|let|var|function|class|async function)\s+([a-zA-Z$_][a-zA-Z\d$_]*)(\s|\()/g
let match
while ((match = regex.exec(code)) !== null) {
const name = match[2];
const name = match[2]
// All exports should be bind to the window object as new API endpoint.
if (exports.length == 0) {
newCode += `\nwindow.comfyAPI = window.comfyAPI || {};`;
newCode += `\nwindow.comfyAPI.${moduleName} = window.comfyAPI.${moduleName} || {};`;
newCode += `\nwindow.comfyAPI = window.comfyAPI || {};`
newCode += `\nwindow.comfyAPI.${moduleName} = window.comfyAPI.${moduleName} || {};`
}
newCode += `\nwindow.comfyAPI.${moduleName}.${name} = ${name};`;
exports.push(`export const ${name} = window.comfyAPI.${moduleName}.${name};\n`);
newCode += `\nwindow.comfyAPI.${moduleName}.${name} = ${name};`
exports.push(`export const ${name} = window.comfyAPI.${moduleName}.${name};\n`)
}
return {
code: newCode,
exports,
};
exports
}
}
function getModuleName(id: string): string {
// Simple example to derive a module name from the file path
const parts = id.split('/');
const fileName = parts[parts.length - 1];
return fileName.replace(/\.\w+$/, ''); // Remove file extension
const parts = id.split('/')
const fileName = parts[parts.length - 1]
return fileName.replace(/\.\w+$/, '') // Remove file extension
}
const DEV_SERVER_COMFYUI_URL = process.env.DEV_SERVER_COMFYUI_URL || 'http://127.0.0.1:8188';
const DEV_SERVER_COMFYUI_URL = process.env.DEV_SERVER_COMFYUI_URL || 'http://127.0.0.1:8188'
export default defineConfig({
base: '',
@@ -95,27 +98,43 @@ export default defineConfig({
'/internal': {
target: DEV_SERVER_COMFYUI_URL,
},
'/api': {
target: DEV_SERVER_COMFYUI_URL,
// Return empty array for extensions API as these modules
// are not on vite's dev server.
bypass: (req, res, options) => {
if (req.url === '/api/extensions') {
res.end(JSON.stringify([]));
res.end(JSON.stringify([]))
}
return null;
return null
},
},
'/ws': {
target: DEV_SERVER_COMFYUI_URL,
ws: true,
},
ws: true
}
}
},
plugins: [
vue(),
comfyAPIPlugin(),
Icons({
'compiler': 'vue3'
}),
Components({
dts: true,
resolvers: [IconsResolver()],
dirs: ['src/components', 'src/layout', 'src/views'],
deep: true,
extensions: ['vue']
})
],
build: {
minify: SHOULD_MINIFY ? 'esbuild' : false,
target: 'es2022',
@@ -126,23 +145,27 @@ export default defineConfig({
treeshake: false
}
},
esbuild: {
minifyIdentifiers: false,
keepNames: true,
minifySyntax: SHOULD_MINIFY,
minifyWhitespace: SHOULD_MINIFY,
minifyWhitespace: SHOULD_MINIFY
},
test: {
globals: true,
environment: 'happy-dom',
setupFiles: ['./vitest.setup.ts'],
setupFiles: ['./vitest.setup.ts']
},
define: {
'__COMFYUI_FRONTEND_VERSION__': JSON.stringify(process.env.npm_package_version),
'__COMFYUI_FRONTEND_VERSION__': JSON.stringify(process.env.npm_package_version)
},
resolve: {
alias: {
'@': '/src'
}
}
}) as UserConfigExport;
}) as UserConfigExport