feat(spa): vite + tailwind + primevue scaffold

This commit is contained in:
DumiFlex
2026-04-26 19:30:45 +03:00
parent 82b6c6eb37
commit 7a4703546e
13 changed files with 781 additions and 56 deletions
-1
View File
@@ -14,7 +14,6 @@ pnpm-debug.log
# Build outputs
js/
web_dist/
web/*
!web/index.html
coverage/
+10 -1
View File
@@ -23,9 +23,18 @@
"prepare": "husky"
},
"dependencies": {
"vue": "^3.5.12"
"vue": "^3.5.12",
"vue-router": "^4.4.5",
"pinia": "^2.2.6",
"primevue": "^4.2.5",
"primeicons": "^7.0.0",
"@primevue/themes": "^4.2.5"
},
"devDependencies": {
"tailwindcss": "^3.4.14",
"postcss": "^8.4.47",
"autoprefixer": "^10.4.20",
"@primevue/forms": "^4.2.5",
"@comfyorg/comfyui-frontend-types": "^1.42.15",
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
+645 -35
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
+1
View File
@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Wildcard Pipeline Manager</title>
</head>
<body>
+1 -4
View File
@@ -1,4 +1 @@
const root = document.getElementById("app");
if (root) {
root.textContent = "Wildcard Pipeline Manager — placeholder (post-MVP)";
}
import "./manager/main";
+11
View File
@@ -0,0 +1,11 @@
<script setup lang="ts">
import Toast from "primevue/toast";
</script>
<template>
<div class="p-6 text-wp-text">
<h1 class="text-xl font-semibold">Wildcard Pipeline Manager</h1>
<p class="opacity-60 text-sm mt-2">Scaffold ready. Router + views ship in Task 2.</p>
</div>
<Toast position="bottom-right" />
</template>
+25
View File
@@ -0,0 +1,25 @@
import { createApp } from "vue";
import { createPinia } from "pinia";
import PrimeVue from "primevue/config";
import Aura from "@primevue/themes/aura";
import ToastService from "primevue/toastservice";
import ConfirmationService from "primevue/confirmationservice";
import "primeicons/primeicons.css";
import "./styles/theme.css";
import "./styles/tailwind.css";
import App from "./App.vue";
const app = createApp(App);
app.use(createPinia());
app.use(PrimeVue, {
theme: {
preset: Aura,
options: {
darkModeSelector: ":root",
cssLayer: { name: "primevue", order: "tailwind-base, primevue, tailwind-utilities" },
},
},
});
app.use(ToastService);
app.use(ConfirmationService);
app.mount("#app");
+3
View File
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+20
View File
@@ -0,0 +1,20 @@
/* Shared theme tokens — keep in sync with src/components/shared/theme.css. */
:root {
--wp-bg: #1e1e1e;
--wp-bg2: #262626;
--wp-bg3: #2e2e2e;
--wp-border: #3a3a3a;
--wp-text: #ddd;
--wp-text-dim: #999;
--wp-text-faint: #6e6e6e;
--wp-accent: #6366f1;
--wp-violet: #a970ff;
--wp-teal: #33d6c6;
--wp-green: #6bc96f;
--wp-amber: #fbbf24;
--wp-red: #f87171;
--wp-rose: #f472b6;
--wp-radius: 6px;
}
html, body { background: var(--wp-bg); color: var(--wp-text); margin: 0; }
+22
View File
@@ -0,0 +1,22 @@
/** @type {import('tailwindcss').Config} */
export default {
// Scope content scanning to the SPA only — extension code never sees Tailwind.
content: ["./src/manager/**/*.{vue,ts}", "./src/manager.html"],
theme: {
extend: {
colors: {
wp: {
bg: "var(--wp-bg)",
bg2: "var(--wp-bg2)",
bg3: "var(--wp-bg3)",
border: "var(--wp-border)",
text: "var(--wp-text)",
accent: "var(--wp-accent)",
violet: "var(--wp-violet)",
teal: "var(--wp-teal)",
},
},
},
},
plugins: [],
};
+26 -3
View File
@@ -2,6 +2,7 @@ import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
import { resolve } from "node:path";
import { copyFileSync, rmSync } from "node:fs";
// Two build targets controlled by --mode flag:
// pnpm build:extension → js/main.js (ComfyUI web extension, critical-path bundle)
@@ -69,16 +70,38 @@ export default defineConfig(({ mode }) => {
};
}
// Manager SPA — post-MVP, built as empty stub
// Manager SPA — Vue 3 + PrimeVue + Tailwind, served by aiohttp at /wp/
// The inline plugin renames src/manager.html → index.html so aiohttp's
// SPA fallback (which serves web/index.html) picks it up correctly.
// Post-write plugin: Vite preserves the input path for HTML outputs
// (src/manager.html → web/src/manager.html). After the write, promote it
// to web/index.html so aiohttp's SPA fallback can serve it.
const renameManagerHtml = {
name: "rename-manager-html",
closeBundle() {
const src = resolve(__dirname, "web/src/manager.html");
const dest = resolve(__dirname, "web/index.html");
copyFileSync(src, dest);
rmSync(resolve(__dirname, "web/src"), { recursive: true, force: true });
},
};
return {
...common,
base: "/wildcard-pipeline/",
base: "/wp/",
plugins: [...(common.plugins as []), renameManagerHtml],
build: {
outDir: "web_dist",
outDir: "web",
emptyOutDir: true,
rollupOptions: {
input: resolve(__dirname, "src/manager.html"),
},
},
test: {
environment: "jsdom",
globals: true,
include: ["src/**/*.test.ts", "src/manager/**/*.test.ts"],
setupFiles: ["./src/test-setup.ts"],
},
};
});
+11 -12
View File
@@ -1,14 +1,13 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Wildcard Pipeline Manager</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app">
<h1>Wildcard Pipeline Manager</h1>
<p>SPA scaffold not yet built. See Plan 2.</p>
</div>
</body>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Wildcard Pipeline Manager</title>
<script type="module" crossorigin src="/wp/assets/manager-BilMX2ww.js"></script>
<link rel="stylesheet" crossorigin href="/wp/assets/manager-C75BNoj2.css">
</head>
<body>
<div id="app"></div>
</body>
</html>