mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-11-17 18:52:06 +00:00
chore: use PrimeVue components
This commit is contained in:
@@ -8,7 +8,7 @@ type MinimalOutputChunk = Pick<OutputChunk, "type" | "fileName" | "code">;
|
||||
type MinimalOutputBundle = Record<string, MinimalOutputAsset | MinimalOutputChunk>;
|
||||
|
||||
function createVarName(fileName: string) {
|
||||
return fileName.replaceAll(".", "_").toUpperCase();
|
||||
return fileName.replaceAll(/[\.-]/g, "_").toUpperCase();
|
||||
}
|
||||
|
||||
function transformAsset(asset: MinimalOutputAsset) {
|
||||
|
||||
96
src/ModManUi/package-lock.json
generated
96
src/ModManUi/package-lock.json
generated
@@ -8,7 +8,10 @@
|
||||
"name": "openassettools",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"@primeuix/themes": "^1.2.5",
|
||||
"pinia": "3.0.3",
|
||||
"primevue": "^4.4.1",
|
||||
"vue": "3.5.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -1324,6 +1327,15 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/inter": {
|
||||
"version": "5.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.2.8.tgz",
|
||||
"integrity": "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
@@ -1829,6 +1841,74 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@primeuix/styled": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.7.4.tgz",
|
||||
"integrity": "sha512-QSO/NpOQg8e9BONWRBx9y8VGMCMYz0J/uKfNJEya/RGEu7ARx0oYW0ugI1N3/KB1AAvyGxzKBzGImbwg0KUiOQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/utils": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primeuix/styles": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/styles/-/styles-1.2.5.tgz",
|
||||
"integrity": "sha512-nypFRct/oaaBZqP4jinT0puW8ZIfs4u+l/vqUFmJEPU332fl5ePj6DoOpQgTLzo3OfmvSmz5a5/5b4OJJmmi7Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/styled": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@primeuix/themes": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/themes/-/themes-1.2.5.tgz",
|
||||
"integrity": "sha512-n3YkwJrHQaEESc/D/A/iD815sxp8cKnmzscA6a8Tm8YvMtYU32eCahwLLe6h5rywghVwxASWuG36XBgISYOIjQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/styled": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@primeuix/utils": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.6.1.tgz",
|
||||
"integrity": "sha512-tQL/ZOPgCdD+NTimlUmhyD0ey8J1XmpZE4hDHM+/fnuBicVVmlKOd5HpS748LcOVRUKbWjmEPdHX4hi5XZoC1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primevue/core": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.4.1.tgz",
|
||||
"integrity": "sha512-RG56iDKIJT//EtntjQzOiWOHZZJczw/qWWtdL5vFvw8/QDS9DPKn8HLpXK7N5Le6KK1MLXUsxoiGTZK+poUFUg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/styled": "^0.7.4",
|
||||
"@primeuix/utils": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primevue/icons": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.4.1.tgz",
|
||||
"integrity": "sha512-UfDimrIjVdY6EziwieyV4zPKzW6mnKHKhy4Dgyjv2oI6pNeuim+onbJo1ce22PEGXW78vfblG/3/JIzVHFweqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/utils": "^0.6.1",
|
||||
"@primevue/core": "4.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0-beta.29",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz",
|
||||
@@ -5369,6 +5449,22 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/primevue": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/primevue/-/primevue-4.4.1.tgz",
|
||||
"integrity": "sha512-JbHBa5k30pZ7mn/z4vYBOnyt5GrR15eM3X0wa3VanonxnFLYkTEx8OMh33aU6ndWeOfi7Ef57dOL3bTH+3f4hQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/styled": "^0.7.4",
|
||||
"@primeuix/styles": "^1.2.5",
|
||||
"@primeuix/utils": "^0.6.1",
|
||||
"@primevue/core": "4.4.1",
|
||||
"@primevue/icons": "4.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
"format": "prettier --write **/*.{js,ts,vue,html,json,yml,yaml,md}"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/inter": "^5.2.8",
|
||||
"@primeuix/themes": "^1.2.5",
|
||||
"pinia": "3.0.3",
|
||||
"primevue": "^4.4.1",
|
||||
"vue": "3.5.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import Button from "primevue/button";
|
||||
import { computed, ref } from "vue";
|
||||
import { webviewAddEventListener, webviewBinds } from "@/native";
|
||||
import { useZoneStore } from "@/stores/ZoneStore";
|
||||
import SpinningLoader from "@/components/SpinningLoader.vue";
|
||||
import ProgressBar from "primevue/progressbar";
|
||||
import ZoneSelector from "./components/ZoneSelector.vue";
|
||||
|
||||
const zoneStore = useZoneStore();
|
||||
const loadingFastFile = ref(false);
|
||||
const unlinkingFastFile = ref(false);
|
||||
const lastPercentage = ref<number>(0);
|
||||
|
||||
const performingAction = computed<boolean>(() => loadingFastFile.value || unlinkingFastFile.value);
|
||||
const progressBarWidth = computed<string>(() => `${lastPercentage.value * 100}%`);
|
||||
|
||||
async function openFastFileSelect() {
|
||||
return await webviewBinds.openFileDialog({ filters: [{ name: "Fastfiles", filter: "*.ff" }] });
|
||||
@@ -32,7 +31,7 @@ async function onOpenFastFileClick() {
|
||||
})
|
||||
.finally(() => {
|
||||
loadingFastFile.value = false;
|
||||
lastPercentage.value = 1;
|
||||
lastPercentage.value = 100;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,22 +64,16 @@ async function onUnlinkFastFileClick() {
|
||||
}
|
||||
} finally {
|
||||
unlinkingFastFile.value = false;
|
||||
lastPercentage.value = 1;
|
||||
lastPercentage.value = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function onUnloadClicked(zoneName: string) {
|
||||
webviewBinds.unloadZone(zoneName).catch((e: string) => {
|
||||
console.error("Failed to unload zone:", e);
|
||||
});
|
||||
}
|
||||
|
||||
webviewAddEventListener("zoneLoadProgress", (dto) => {
|
||||
lastPercentage.value = dto.percentage;
|
||||
lastPercentage.value = Math.floor(dto.percentage * 1000) / 10;
|
||||
});
|
||||
|
||||
webviewAddEventListener("zoneUnlinkProgress", (dto) => {
|
||||
lastPercentage.value = dto.percentage;
|
||||
lastPercentage.value = Math.floor(dto.percentage * 1000) / 10;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -90,33 +83,28 @@ webviewAddEventListener("zoneUnlinkProgress", (dto) => {
|
||||
<small>Nothing to see here yet, this is mainly for testing</small>
|
||||
|
||||
<div class="actions">
|
||||
<button :disabled="performingAction" @click="onOpenFastFileClick">
|
||||
<SpinningLoader v-if="loadingFastFile" class="loading" />
|
||||
<span>Load fastfile</span>
|
||||
</button>
|
||||
<button :disabled="performingAction" @click="onUnlinkFastFileClick">
|
||||
<SpinningLoader v-if="unlinkingFastFile" class="loading" />
|
||||
<span>Unlink fastfile</span>
|
||||
</button>
|
||||
<Button
|
||||
label="Load fastfile"
|
||||
:disabled="performingAction"
|
||||
:loading="loadingFastFile"
|
||||
@click="onOpenFastFileClick"
|
||||
/>
|
||||
<Button
|
||||
label="Unlink fastfile"
|
||||
:disabled="performingAction"
|
||||
:loading="unlinkingFastFile"
|
||||
@click="onUnlinkFastFileClick"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Loaded zones:</h3>
|
||||
<div class="zone-list">
|
||||
<div v-for="zone in zoneStore.loadedZones" :key="zone" class="zone">
|
||||
<span>{{ zone }}</span>
|
||||
<button :disabled="performingAction" @click="onUnloadClicked(zone)">Unload</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ZoneSelector />
|
||||
|
||||
<div class="progressbar-wrapper">
|
||||
<div
|
||||
class="progressbar"
|
||||
:class="{ visible: performingAction }"
|
||||
:style="{ width: progressBarWidth }"
|
||||
></div>
|
||||
</div>
|
||||
<ProgressBar
|
||||
v-if="performingAction"
|
||||
class="progressbar"
|
||||
:show-value="false"
|
||||
:value="lastPercentage"
|
||||
/>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -127,10 +115,6 @@ webviewAddEventListener("zoneUnlinkProgress", (dto) => {
|
||||
column-gap: 0.5em;
|
||||
}
|
||||
|
||||
.loading {
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
|
||||
.zone-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -141,23 +125,21 @@ webviewAddEventListener("zoneUnlinkProgress", (dto) => {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.progressbar-wrapper {
|
||||
@starting-style {
|
||||
.progressbar {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.progressbar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0.35rem 0.4rem;
|
||||
}
|
||||
|
||||
.progressbar {
|
||||
opacity: 0;
|
||||
height: 0.4rem;
|
||||
border-radius: 2.5rem;
|
||||
background-color: #b9772c;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
35
src/ModManUi/src/PrimeVue.ts
Normal file
35
src/ModManUi/src/PrimeVue.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { App } from "vue";
|
||||
import PrimeVue from "primevue/config";
|
||||
import Aura from "@primeuix/themes/aura";
|
||||
import { definePreset } from "@primeuix/themes";
|
||||
|
||||
const ModManTheme = definePreset(Aura, {
|
||||
semantic: {
|
||||
primary: {
|
||||
50: "{orange.50}",
|
||||
100: "{orange.100}",
|
||||
200: "{orange.200}",
|
||||
300: "{orange.300}",
|
||||
400: "{orange.400}",
|
||||
500: "{orange.500}",
|
||||
600: "{orange.600}",
|
||||
700: "{orange.700}",
|
||||
800: "{orange.800}",
|
||||
900: "{orange.900}",
|
||||
950: "{orange.950}",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export function configurePrimeVue(app: App) {
|
||||
app.use(PrimeVue, {
|
||||
theme: {
|
||||
preset: ModManTheme,
|
||||
options: {
|
||||
darkModeSelector: ".dark-mode",
|
||||
},
|
||||
},
|
||||
});
|
||||
// Always make dark mode for now
|
||||
document.documentElement.classList.add("dark-mode");
|
||||
}
|
||||
54
src/ModManUi/src/components/ZoneSelector.vue
Normal file
54
src/ModManUi/src/components/ZoneSelector.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
import Button from "primevue/button";
|
||||
import Listbox from "primevue/listbox";
|
||||
import { ref, watch } from "vue";
|
||||
import { useZoneStore } from "@/stores/ZoneStore";
|
||||
import { webviewBinds } from "@/native";
|
||||
|
||||
const zoneStore = useZoneStore();
|
||||
const selectedZone = ref<string | null>(null);
|
||||
|
||||
function onUnloadClicked() {
|
||||
if (!selectedZone.value) return;
|
||||
|
||||
webviewBinds.unloadZone(selectedZone.value).catch((e: string) => {
|
||||
console.error("Failed to unload zone:", e);
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => zoneStore.loadedZones,
|
||||
(newValue) => {
|
||||
// Reset selection if unloaded
|
||||
if (!selectedZone.value) return;
|
||||
if (newValue.indexOf(selectedZone.value) >= 0) return;
|
||||
selectedZone.value = null;
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="zone-selector">
|
||||
<div class="zone-list">
|
||||
<Listbox v-model="selectedZone" :options="zoneStore.loadedZones" class="zone" />
|
||||
</div>
|
||||
|
||||
<div class="zone-actions">
|
||||
<Button label="Unload" :disabled="!selectedZone" @click="onUnloadClicked" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.zone-selector {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
|
||||
& > * {
|
||||
width: 50%;
|
||||
padding: 1rem 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,11 +1,20 @@
|
||||
:root {
|
||||
@import "@fontsource/inter/latin-300.css";
|
||||
@import "@fontsource/inter/latin-300-italic.css";
|
||||
@import "@fontsource/inter/latin-400.css";
|
||||
@import "@fontsource/inter/latin-400-italic.css";
|
||||
@import "@fontsource/inter/latin-600.css";
|
||||
@import "@fontsource/inter/latin-600-italic.css";
|
||||
@import "@fontsource/inter/latin-700.css";
|
||||
@import "@fontsource/inter/latin-700-italic.css";
|
||||
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color: #0f0f0f;
|
||||
background-color: #f6f6f6;
|
||||
color: var(--p-text-color);
|
||||
background-color: var(--p-content-background);
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
@@ -33,92 +42,3 @@ body {
|
||||
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: 0.75s;
|
||||
}
|
||||
|
||||
.logo.tauri:hover {
|
||||
filter: drop-shadow(0 0 2em #24c8db);
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
color: #0f0f0f;
|
||||
background-color: #ffffff;
|
||||
transition: border-color 0.25s;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:not(:disabled):hover {
|
||||
border-color: #396cd8;
|
||||
}
|
||||
button:not(:disabled):active {
|
||||
border-color: #396cd8;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#greet-input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color: #f6f6f6;
|
||||
background-color: #2f2f2f;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #24c8db;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
color: #ffffff;
|
||||
background-color: #0f0f0f98;
|
||||
}
|
||||
button:not(:disabled):active {
|
||||
background-color: #0f0f0f69;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import "./main.scss";
|
||||
|
||||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import { configurePrimeVue } from "./PrimeVue.ts";
|
||||
|
||||
import App from "./App.vue";
|
||||
|
||||
@@ -10,4 +11,6 @@ const app = createApp(App);
|
||||
|
||||
app.use(createPinia());
|
||||
|
||||
configurePrimeVue(app);
|
||||
|
||||
app.mount("#app");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readonly, ref } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import { webviewAddEventListener } from "@/native";
|
||||
|
||||
@@ -16,5 +16,5 @@ export const useZoneStore = defineStore("zone", () => {
|
||||
}
|
||||
});
|
||||
|
||||
return { loadedZones: readonly(loadedZones) };
|
||||
return { loadedZones };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user