mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-17 22:40:51 +01:00
switch to nuxt layers
This commit is contained in:
@ -1,7 +0,0 @@
|
|||||||
// ~/app.config.ts
|
|
||||||
export default defineAppConfig({
|
|
||||||
icon: {
|
|
||||||
mode: "css",
|
|
||||||
cssLayer: "base",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@ -2,19 +2,11 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: "2024-11-01",
|
extends: [
|
||||||
|
"github:haexhub/haex-base-ui"
|
||||||
modules: [
|
|
||||||
"nuxt-zod-i18n",
|
|
||||||
"@nuxtjs/i18n",
|
|
||||||
"@pinia/nuxt",
|
|
||||||
"@vueuse/nuxt",
|
|
||||||
"@nuxt/icon",
|
|
||||||
"nuxt-snackbar",
|
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
compatibilityDate: "2024-11-01",
|
||||||
|
|
||||||
|
|
||||||
imports: {
|
imports: {
|
||||||
@ -39,14 +31,7 @@ export default defineNuxtConfig({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* i18n: {
|
||||||
|
|
||||||
/* svgo: {
|
|
||||||
autoImportPath: '~/assets/svg/',
|
|
||||||
dts: true,
|
|
||||||
}, */
|
|
||||||
|
|
||||||
i18n: {
|
|
||||||
strategy: "prefix_and_default",
|
strategy: "prefix_and_default",
|
||||||
defaultLocale: "de",
|
defaultLocale: "de",
|
||||||
vueI18n: "~/i18n/i18n.config.ts",
|
vueI18n: "~/i18n/i18n.config.ts",
|
||||||
@ -65,14 +50,9 @@ export default defineNuxtConfig({
|
|||||||
bundle: {
|
bundle: {
|
||||||
optimizeTranslationDirective: false,
|
optimizeTranslationDirective: false,
|
||||||
},
|
},
|
||||||
},
|
}, */
|
||||||
|
|
||||||
|
|
||||||
zodI18n: {
|
|
||||||
localeCodesMapping: {
|
|
||||||
"en-GB": "en",
|
|
||||||
"de-DE": "de",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
public: {
|
public: {
|
||||||
@ -83,8 +63,6 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
css: ["~/assets/css/main.css"],
|
|
||||||
|
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
|
|
||||||
srcDir: "./src",
|
srcDir: "./src",
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
"nuxt-zod-i18n": "^1.11.5",
|
"nuxt-zod-i18n": "^1.11.5",
|
||||||
"tailwindcss": "^4.1.7",
|
"tailwindcss": "^4.1.7",
|
||||||
"vue": "^3.5.14",
|
"vue": "^3.5.14",
|
||||||
|
"vue-router": "^4.5.1",
|
||||||
"zod": "^3.25.4"
|
"zod": "^3.25.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@ -86,6 +86,9 @@ importers:
|
|||||||
vue:
|
vue:
|
||||||
specifier: ^3.5.14
|
specifier: ^3.5.14
|
||||||
version: 3.5.14(typescript@5.8.3)
|
version: 3.5.14(typescript@5.8.3)
|
||||||
|
vue-router:
|
||||||
|
specifier: ^4.5.1
|
||||||
|
version: 4.5.1(vue@3.5.14(typescript@5.8.3))
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.25.4
|
specifier: ^3.25.4
|
||||||
version: 3.25.4
|
version: 3.25.4
|
||||||
@ -3307,7 +3310,6 @@ packages:
|
|||||||
|
|
||||||
libsql@0.5.10:
|
libsql@0.5.10:
|
||||||
resolution: {integrity: sha512-lQu5RLqDLFuo6H5SuR3CnEstGVph77Jd8lm3fdW64p6tUjOC0X8Z9PlfAdZYxWyirYLH9uwcEZUrABsNKYwOiQ==}
|
resolution: {integrity: sha512-lQu5RLqDLFuo6H5SuR3CnEstGVph77Jd8lm3fdW64p6tUjOC0X8Z9PlfAdZYxWyirYLH9uwcEZUrABsNKYwOiQ==}
|
||||||
cpu: [x64, arm64, wasm32, arm]
|
|
||||||
os: [darwin, linux, win32]
|
os: [darwin, linux, win32]
|
||||||
|
|
||||||
lightningcss-darwin-arm64@1.30.1:
|
lightningcss-darwin-arm64@1.30.1:
|
||||||
|
|||||||
@ -19,17 +19,18 @@
|
|||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
"csp": {
|
"csp": {
|
||||||
"default-src": "'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost; default-src 'self' asset: http://asset.localhost",
|
"default-src": ["'self'", "ipc: http://ipc.localhost", "blob:"],
|
||||||
"script-src": ["'self'", "haex-extension:"],
|
"media-src": [
|
||||||
"style-src": ["'self'", "haex-extension:"],
|
"'self'",
|
||||||
"connect-src": ["'self'", "haex-extension:"],
|
"asset:",
|
||||||
"img-src": ["'self'", "haex-extension:", "data:"],
|
"http://asset.localhost",
|
||||||
"font-src": ["'self'", "haex-extension:", "data:"],
|
"blob:",
|
||||||
"media-src": "'self' haex-extension: data: blob: asset:"
|
"asset: http://asset.localhost"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"assetProtocol": {
|
"assetProtocol": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"scope": ["$RESOURCE/**", "$APPDATA/**"]
|
"scope": ["*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
@import "tailwindcss";
|
|
||||||
@import "flyonui/variants.css";
|
|
||||||
|
|
||||||
@plugin "@iconify/tailwind4";
|
|
||||||
@plugin "flyonui" {
|
|
||||||
themes: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
@source "../../node_modules/flyonui/flyonui.js";
|
|
||||||
@ -39,15 +39,4 @@ const isActive = computed(() => {
|
|||||||
const linkRef = useTemplateRef('linkRef')
|
const linkRef = useTemplateRef('linkRef')
|
||||||
|
|
||||||
const triggerNavigate = () => linkRef.value?.$el.click()
|
const triggerNavigate = () => linkRef.value?.$el.click()
|
||||||
|
|
||||||
/* computed(() => {
|
|
||||||
const found = useRouter()
|
|
||||||
.getRoutes()
|
|
||||||
.find((route) => route.name === useLocaleRoute()(props.to)?.name);
|
|
||||||
console.log('found route', found, useRoute());
|
|
||||||
return (
|
|
||||||
found?.name === useRoute().name ||
|
|
||||||
found?.children.some((child) => child.name === useRoute().name)
|
|
||||||
);
|
|
||||||
}); */
|
|
||||||
</script>
|
</script>
|
||||||
@ -1,43 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="accordion divide-neutral/20 divide-y">
|
|
||||||
<div class="accordion-item active" :id="itemId" ref="accordionRef">
|
|
||||||
<button
|
|
||||||
class="accordion-toggle inline-flex items-center gap-x-4 text-start"
|
|
||||||
:aria-controls="collapseId"
|
|
||||||
aria-expanded="true"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="icon-[tabler--chevron-right] accordion-item-active:rotate-90 size-5 shrink-0 transition-transform duration-300 rtl:rotate-180"
|
|
||||||
></span>
|
|
||||||
<slot name="title" />
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
:id="collapseId"
|
|
||||||
class="accordion-content w-full overflow-hidden transition-[height] duration-300"
|
|
||||||
:aria-labelledby="itemId"
|
|
||||||
role="region"
|
|
||||||
>
|
|
||||||
<div class="px-5 pb-4">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { HSAccordion } from "flyonui/flyonui";
|
|
||||||
|
|
||||||
const itemId = useId();
|
|
||||||
const collapseId = useId();
|
|
||||||
|
|
||||||
const accordionRef = useTemplateRef("accordionRef");
|
|
||||||
const accordion = ref<HSAccordion>();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (accordionRef.value) {
|
|
||||||
accordion.value = new HSAccordion(accordionRef.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="fixed z-10">
|
|
||||||
<div
|
|
||||||
class="dropdown relative inline-flex [--placement:top] [--strategy:absolute]"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
:id
|
|
||||||
class="dropdown-toggle btn btn-primary btn-lg btn-square dropdown-open:rotate-45"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Menu"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
:name="icon"
|
|
||||||
size="46"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="dropdown-menu dropdown-open:opacity-100 hidden min-w-60 rtl:left-0 bg-transparent"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
:aria-labelledby="id"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
class="dropdown-open:ease-in dropdown-open:translate-x-0 -translate-x-1 rtl:translate-x-1 transition duration-300 ease-out"
|
|
||||||
data-dropdown-transition
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
v-for="link in menu"
|
|
||||||
class="dropdown-item hover:bg-transparent"
|
|
||||||
>
|
|
||||||
<NuxtLinkLocale
|
|
||||||
v-if="link.to"
|
|
||||||
:to="link.to"
|
|
||||||
class="btn btn-primary flex items-center no-underline rounded-lg flex-nowrap"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
v-if="link.icon"
|
|
||||||
:name="link.icon"
|
|
||||||
class="me-3"
|
|
||||||
/>
|
|
||||||
{{ link.label }}
|
|
||||||
</NuxtLinkLocale>
|
|
||||||
|
|
||||||
<button
|
|
||||||
v-else
|
|
||||||
@click="link.action"
|
|
||||||
class="link hover:link-primary flex items-center no-underline w-full"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
v-if="link.icon"
|
|
||||||
:name="link.icon"
|
|
||||||
class="me-3"
|
|
||||||
/>
|
|
||||||
{{ link.label }}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import type { IActionMenuItem } from './types';
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
menu: {
|
|
||||||
type: Array as PropType<IActionMenuItem[]>,
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
type: String,
|
|
||||||
default: 'mdi:plus',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const id = useId();
|
|
||||||
</script>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<button class="btn join-item" :type>
|
|
||||||
<slot />
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineProps({
|
|
||||||
type: {
|
|
||||||
type: String as PropType<"reset" | "submit" | "button">,
|
|
||||||
default: "button",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
8
src/components/ui/button/types.d.ts
vendored
8
src/components/ui/button/types.d.ts
vendored
@ -1,8 +0,0 @@
|
|||||||
import type { RouteLocationRaw } from 'vue-router';
|
|
||||||
|
|
||||||
export interface IActionMenuItem {
|
|
||||||
label: string;
|
|
||||||
icon?: string;
|
|
||||||
action?: () => Promise<unknown>;
|
|
||||||
to?: RouteLocationRaw;
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
<template>
|
|
||||||
<slot name="trigger" :id> </slot>
|
|
||||||
|
|
||||||
<div
|
|
||||||
:id
|
|
||||||
class="overlay modal overlay-open:opacity-100 hidden modal-middle [--tab-accessibility-limited:false] overflow-scroll p-0 sm:p-4"
|
|
||||||
role="dialog"
|
|
||||||
ref="modalRef"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="overlay-animation-target overlay-open:mt-4 overlay-open:duration-500 mt-12 transition-all ease-out modal-dialog overlay-open:opacity-100"
|
|
||||||
>
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<slot name="title">
|
|
||||||
<h3 v-if="title" class="modal-title text-base sm:text-lg">
|
|
||||||
{{ title }}
|
|
||||||
</h3>
|
|
||||||
</slot>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-text btn-circle btn-sm absolute end-3 top-3"
|
|
||||||
:aria-label="t('close')"
|
|
||||||
@click="open = false"
|
|
||||||
tabindex="1"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:close" size="18" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body text-sm sm:text-base py-1">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer flex-wrap">
|
|
||||||
<slot name="buttons" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { HSOverlay } from "flyonui/flyonui";
|
|
||||||
|
|
||||||
export interface IDom {
|
|
||||||
class?: String;
|
|
||||||
text: String;
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = useId();
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const open = defineModel<boolean>("open", { default: false });
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const modalRef = useTemplateRef("modalRef");
|
|
||||||
const modal = ref<HSOverlay>();
|
|
||||||
|
|
||||||
watch(open, async () => {
|
|
||||||
console.log("open modal", open.value);
|
|
||||||
if (open.value) {
|
|
||||||
await modal.value?.open();
|
|
||||||
} else {
|
|
||||||
await modal.value?.close(true);
|
|
||||||
console.log("close dialog");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (!modalRef.value) return;
|
|
||||||
modal.value = new HSOverlay(modalRef.value, { isClosePrev: true });
|
|
||||||
|
|
||||||
modal.value.on("close", () => {
|
|
||||||
console.log("close it from event", open.value);
|
|
||||||
open.value = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="json">
|
|
||||||
{
|
|
||||||
"de": {
|
|
||||||
"close": "Schließen"
|
|
||||||
},
|
|
||||||
"en": {
|
|
||||||
"close": "Close"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</i18n>
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
<template>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-primary"
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-controls="basic-modal"
|
|
||||||
data-overlay="#basic-modal"
|
|
||||||
>
|
|
||||||
Open modal
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div
|
|
||||||
id="basic-modal"
|
|
||||||
class="overlay modal overlay-open:opacity-100 hidden"
|
|
||||||
role="dialog"
|
|
||||||
tabindex="-1"
|
|
||||||
>
|
|
||||||
<div class="modal-dialog overlay-open:opacity-100">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h3 class="modal-title">Dialog Title</h3>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-text btn-circle btn-sm absolute end-3 top-3"
|
|
||||||
aria-label="Close"
|
|
||||||
data-overlay="#basic-modal"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--x] size-4"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
This is some placeholder content to show the scrolling behavior for
|
|
||||||
modals. Instead of repeating the text in the modal, we use an inline
|
|
||||||
style to set a minimum height, thereby extending the length of the
|
|
||||||
overall modal and demonstrating the overflow scrolling. When content
|
|
||||||
becomes longer than the height of the viewport, scrolling will move
|
|
||||||
the modal as needed.
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-soft btn-secondary"
|
|
||||||
data-overlay="#basic-modal"
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-primary"
|
|
||||||
>
|
|
||||||
Save changes
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h3 class="modal-title">
|
|
||||||
<slot />
|
|
||||||
</h3>
|
|
||||||
</template>
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="dropdown relative inline-flex" :class="dropdownClass">
|
|
||||||
<button
|
|
||||||
:id
|
|
||||||
class="dropdown-toggle"
|
|
||||||
:class="activatorClass"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-expanded="false"
|
|
||||||
:aria-label="label"
|
|
||||||
>
|
|
||||||
<slot name="activator">
|
|
||||||
<slot name="label">
|
|
||||||
{{ label }}
|
|
||||||
</slot>
|
|
||||||
<span
|
|
||||||
class="icon-[tabler--chevron-down] dropdown-open:rotate-180 size-4"
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
</slot>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<slot name="items" :items>
|
|
||||||
<ul
|
|
||||||
class="dropdown-menu dropdown-open:opacity-100 hidden min-w-28"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
:aria-labelledby="id"
|
|
||||||
>
|
|
||||||
<component
|
|
||||||
:is="itemIs"
|
|
||||||
class="dropdown-item"
|
|
||||||
v-for="item in items"
|
|
||||||
@click="$emit('select', item)"
|
|
||||||
>
|
|
||||||
<slot name="item" :item>
|
|
||||||
{{ item }}
|
|
||||||
</slot>
|
|
||||||
</component>
|
|
||||||
</ul>
|
|
||||||
</slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts" generic="T">
|
|
||||||
const { itemIs = 'li' } = defineProps<{
|
|
||||||
label?: string
|
|
||||||
items?: T[]
|
|
||||||
itemIs?: string
|
|
||||||
activatorClass?: string
|
|
||||||
dropdownClass?: string
|
|
||||||
}>()
|
|
||||||
|
|
||||||
defineEmits<{ select: [T] }>()
|
|
||||||
const id = useId()
|
|
||||||
</script>
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
<template>
|
|
||||||
<UiDropdown
|
|
||||||
:items="availableLocales"
|
|
||||||
@select="(locale) => $emit('select', locale)"
|
|
||||||
activator-class="btn btn-primary"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<Icon :name="flags[locale]" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #item="{ item }">
|
|
||||||
<div class="flex gap-2 justify-center">
|
|
||||||
<Icon :name="flags[item]" class="my-auto" />
|
|
||||||
<p>
|
|
||||||
{{ item }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</UiDropdown>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { type Locale } from 'vue-i18n'
|
|
||||||
|
|
||||||
const flags = {
|
|
||||||
de: 'emojione:flag-for-germany',
|
|
||||||
en: 'emojione:flag-for-united-kingdom',
|
|
||||||
}
|
|
||||||
|
|
||||||
const { availableLocales, locale } = useI18n()
|
|
||||||
|
|
||||||
defineEmits<{ select: [Locale] }>()
|
|
||||||
</script>
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
<template>
|
|
||||||
<UiDropdown
|
|
||||||
:items="availableThemes"
|
|
||||||
@select="(theme) => $emit('select', theme)"
|
|
||||||
activator-class="btn btn-primary"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<Icon :name="currentTheme.icon" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #item="{ item }">
|
|
||||||
<div class="flex gap-2 justify-center">
|
|
||||||
<Icon :name="item.icon" class="my-auto" />
|
|
||||||
<p>
|
|
||||||
{{ item.name }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</UiDropdown>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const { availableThemes, currentTheme } = storeToRefs(useUiStore())
|
|
||||||
|
|
||||||
defineEmits<{ select: [ITheme] }>()
|
|
||||||
</script>
|
|
||||||
@ -1,147 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<fieldset class="join w-full pt-0.5">
|
|
||||||
<slot name="prepend" />
|
|
||||||
|
|
||||||
<div class="input join-item">
|
|
||||||
<Icon v-if="prependIcon" :name="prependIcon" class="my-auto shrink-0" />
|
|
||||||
|
|
||||||
<div class="input-floating grow">
|
|
||||||
<input
|
|
||||||
:id
|
|
||||||
:name="name ?? id"
|
|
||||||
:placeholder="placeholder || label"
|
|
||||||
:type
|
|
||||||
:autofocus
|
|
||||||
class="ps-3"
|
|
||||||
v-bind="$attrs"
|
|
||||||
v-model="input"
|
|
||||||
ref="inputRef"
|
|
||||||
:readonly="read_only"
|
|
||||||
/>
|
|
||||||
<label class="input-floating-label" :for="id">{{ label }}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Icon v-if="appendIcon" :name="appendIcon" class="my-auto shrink-0" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<slot name="append" class="h-auto" />
|
|
||||||
|
|
||||||
<UiButton
|
|
||||||
v-if="withCopyButton"
|
|
||||||
class="btn-outline btn-accent btn-square join-item h-auto"
|
|
||||||
@click="copy(`${input}`)"
|
|
||||||
>
|
|
||||||
<Icon :name="copied ? 'mdi:check' : 'mdi:content-copy'" />
|
|
||||||
</UiButton>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<span class="flex flex-col px-2 pt-0.5" v-show="errors">
|
|
||||||
<span v-for="error in errors" class="label-text-alt text-error">
|
|
||||||
{{ error }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { type ZodSchema } from 'zod'
|
|
||||||
|
|
||||||
const inputRef = useTemplateRef('inputRef')
|
|
||||||
defineExpose({ inputRef })
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
inheritAttrs: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String as PropType<
|
|
||||||
| 'button'
|
|
||||||
| 'checkbox'
|
|
||||||
| 'color'
|
|
||||||
| 'date'
|
|
||||||
| 'datetime-local'
|
|
||||||
| 'email'
|
|
||||||
| 'file'
|
|
||||||
| 'hidden'
|
|
||||||
| 'image'
|
|
||||||
| 'month'
|
|
||||||
| 'number'
|
|
||||||
| 'password'
|
|
||||||
| 'radio'
|
|
||||||
| 'range'
|
|
||||||
| 'reset'
|
|
||||||
| 'search'
|
|
||||||
| 'submit'
|
|
||||||
| 'tel'
|
|
||||||
| 'text'
|
|
||||||
| 'time'
|
|
||||||
| 'url'
|
|
||||||
| 'week'
|
|
||||||
>,
|
|
||||||
default: 'text',
|
|
||||||
},
|
|
||||||
label: String,
|
|
||||||
name: String,
|
|
||||||
prependIcon: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
prependLabel: String,
|
|
||||||
appendIcon: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
appendLabel: String,
|
|
||||||
rules: Object as PropType<ZodSchema>,
|
|
||||||
checkInput: Boolean,
|
|
||||||
withCopyButton: Boolean,
|
|
||||||
autofocus: Boolean,
|
|
||||||
read_only: Boolean,
|
|
||||||
})
|
|
||||||
|
|
||||||
const input = defineModel<string | number | undefined | null>({
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const { currentScreenSize } = storeToRefs(useUiStore())
|
|
||||||
onMounted(() => {
|
|
||||||
if (props.autofocus && inputRef.value) inputRef.value.focus()
|
|
||||||
})
|
|
||||||
|
|
||||||
const errors = defineModel<string[] | undefined>('errors')
|
|
||||||
|
|
||||||
const id = useId()
|
|
||||||
|
|
||||||
watch(input, () => checkInput())
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.checkInput,
|
|
||||||
() => {
|
|
||||||
checkInput()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const emit = defineEmits(['error'])
|
|
||||||
|
|
||||||
const checkInput = () => {
|
|
||||||
if (props.rules) {
|
|
||||||
const result = props.rules.safeParse(input.value)
|
|
||||||
//console.log('check result', result.error, props.rules);
|
|
||||||
if (!result.success) {
|
|
||||||
errors.value = result.error.errors.map((error) => error.message)
|
|
||||||
emit('error', errors.value)
|
|
||||||
} else {
|
|
||||||
errors.value = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { copy, copied } = useClipboard()
|
|
||||||
</script>
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
<template>
|
|
||||||
<UiInput
|
|
||||||
:check-input
|
|
||||||
:label="label || t('password')"
|
|
||||||
:placeholder="placeholder || t('password')"
|
|
||||||
:rules
|
|
||||||
:type="type"
|
|
||||||
:autofocus
|
|
||||||
v-model="value"
|
|
||||||
>
|
|
||||||
<template #append>
|
|
||||||
<UiButton
|
|
||||||
class="btn-outline btn-accent btn-square h-auto"
|
|
||||||
@click="tooglePasswordType"
|
|
||||||
>
|
|
||||||
<Icon :name="type === 'password' ? 'mdi:eye-off' : 'mdi:eye'" />
|
|
||||||
</UiButton>
|
|
||||||
</template>
|
|
||||||
</UiInput>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import type { ZodSchema } from 'zod'
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
|
|
||||||
const value = defineModel<string | number | null | undefined>()
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
label: String,
|
|
||||||
placeholder: String,
|
|
||||||
checkInput: Boolean,
|
|
||||||
rules: Object as PropType<ZodSchema>,
|
|
||||||
autofocus: Boolean,
|
|
||||||
})
|
|
||||||
|
|
||||||
const type = ref<'password' | 'text'>('password')
|
|
||||||
|
|
||||||
const tooglePasswordType = () => {
|
|
||||||
type.value = type.value === 'password' ? 'text' : 'password'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="json">
|
|
||||||
{
|
|
||||||
"de": {
|
|
||||||
"password": "Passwort"
|
|
||||||
},
|
|
||||||
"en": {
|
|
||||||
"password": "Password"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</i18n>
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
<template>
|
|
||||||
<UiInput
|
|
||||||
:autofocus
|
|
||||||
:check-input="checkInput"
|
|
||||||
:label="label || t('url')"
|
|
||||||
:placeholder="placeholder || t('url')"
|
|
||||||
:read_only
|
|
||||||
:rules
|
|
||||||
:with-copy-button
|
|
||||||
v-model.trim="value"
|
|
||||||
>
|
|
||||||
<template #append>
|
|
||||||
<UiButton
|
|
||||||
v-if="read_only"
|
|
||||||
@click="openUrl(`${value}`)"
|
|
||||||
class="btn-outline btn-accent h-auto"
|
|
||||||
:class="{
|
|
||||||
disabled: !value?.length,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<Icon name="streamline:web" />
|
|
||||||
</UiButton>
|
|
||||||
</template>
|
|
||||||
</UiInput>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import type { ZodSchema } from 'zod';
|
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const { currentScreenSize } = storeToRefs(useUiStore());
|
|
||||||
|
|
||||||
const value = defineModel<string | null | undefined>();
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
label: String,
|
|
||||||
placeholder: String,
|
|
||||||
checkInput: Boolean,
|
|
||||||
rules: Object as PropType<ZodSchema>,
|
|
||||||
autofocus: Boolean,
|
|
||||||
withCopyButton: Boolean,
|
|
||||||
read_only: Boolean,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="json">
|
|
||||||
{
|
|
||||||
"de": {
|
|
||||||
"url": "Url"
|
|
||||||
},
|
|
||||||
"en": {
|
|
||||||
"url": "Url"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</i18n>
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
<template>
|
|
||||||
<svg
|
|
||||||
id="logo"
|
|
||||||
class="fill-current stroke-current w-[160px]"
|
|
||||||
version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
x="0px"
|
|
||||||
y="0px"
|
|
||||||
viewBox="0 0 286.3 85"
|
|
||||||
xml:space="preserve"
|
|
||||||
>
|
|
||||||
<switch>
|
|
||||||
<g>
|
|
||||||
<g class="logo-imagesss">
|
|
||||||
<circle
|
|
||||||
fill="white"
|
|
||||||
cx="42.5"
|
|
||||||
cy="42.5"
|
|
||||||
r="40"
|
|
||||||
></circle>
|
|
||||||
<path
|
|
||||||
d="M42.3,83.4c-22.6,0-40.9-18.4-40.9-40.9c0-22.6,18.4-40.9,40.9-40.9c22.6,0,40.9,18.4,40.9,40.9
|
|
||||||
C83.3,65.1,64.9,83.4,42.3,83.4z M42.3,5.8C22.1,5.8,5.7,22.3,5.7,42.5s16.5,36.7,36.7,36.7S79,62.7,79,42.5S62.6,5.8,42.3,5.8z
|
|
||||||
"
|
|
||||||
></path>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polygon
|
|
||||||
points="38.8,69.8 38.8,31.7 22.3,31.7 22.3,38.5 29.8,38.5 29.8,69.8 "
|
|
||||||
></polygon>
|
|
||||||
<path
|
|
||||||
d="M34.1,13.2c-3.3,0-6,2.6-6,5.9c0,3.3,2.6,6,5.9,6c3.3,0,6-2.6,6-6
|
|
||||||
C39.9,15.9,37.3,13.2,34.1,13.2z"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon
|
|
||||||
points="45.9,69.8 45.9,31.7 62.4,31.7 62.4,38.5 54.9,38.5 54.9,69.8 "
|
|
||||||
></polygon>
|
|
||||||
<path
|
|
||||||
d="M50.6,13.2c3.3,0,6,2.6,6,5.9c0,3.3-2.6,6-5.9,6c-3.3,0-6-2.6-6-6
|
|
||||||
C44.8,15.9,47.4,13.2,50.6,13.2z"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g class="logo-textsss">
|
|
||||||
<path
|
|
||||||
d="M136.1,63.6c-4,0-5.3-2.6-5.3-6V38.5h10.6v-6.7h-10.6v-6.7h-9c0,7,0,29.1,0,32.7
|
|
||||||
c0,4.2,1.6,7.5,3.8,9.7c2.3,2.2,5.6,3.3,9.8,3.3c5.1,0,8.4-1.8,10.6-4.2l-4.7-6C140.2,62.1,138.5,63.6,136.1,63.6z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
d="M217.7,30.7c-4.9,0-8.2,1.6-10.4,3.8c-2.2-2.2-5.5-3.8-10.4-3.8c-15,0-14.9,12.1-14.9,15
|
|
||||||
s0,24.1,0,24.1h9V45.7c0-8.5,4.9-8.3,5.9-8.3c1,0,5.9-0.3,5.9,8.3v24.1h0h9h0V45.7c0-8.5,4.9-8.3,5.9-8.3c1,0,5.9-0.3,5.9,8.3
|
|
||||||
v24.1h9c0,0,0-21.2,0-24.1C232.6,42.8,232.7,30.7,217.7,30.7z"
|
|
||||||
></path>
|
|
||||||
<path
|
|
||||||
d="M273.2,46.4c-4.3-1.4-6-2.5-6-5.2c0-2,1.1-3.8,4.3-3.8c3.2,0,4.5,3.3,5.1,4.8
|
|
||||||
c2.7-1.5,5.3-2.9,6.6-3.6c-2.5-6-6.3-7.9-12-7.9c-8,0-11.7,5.5-11.7,10.6c0,6.5,2.9,9.8,11.2,12.2c6,1.8,6.5,4.7,6.2,6.2
|
|
||||||
c-0.3,1.7-1.6,3.6-5.3,3.6c-3.6,0-5.8-3.8-6.8-5.4c-1.8,1.1-3.4,2.1-6.4,3.8c2.1,5,6.8,9.1,13.5,9.1c7.9,0,12.9-5.1,12.9-12.1
|
|
||||||
C284.9,51,279.6,48.5,273.2,46.4z"
|
|
||||||
></path>
|
|
||||||
<g>
|
|
||||||
<polygon
|
|
||||||
points="239.7,69.8 239.7,31.7 256.2,31.7 256.2,38.5 248.7,38.5 248.7,69.8 "
|
|
||||||
></polygon>
|
|
||||||
<path
|
|
||||||
d="M244.4,13.2c3.3,0,6,2.6,6,5.9c0,3.3-2.6,6-5.9,6c-3.3,0-6-2.6-6-6
|
|
||||||
C238.6,15.9,241.2,13.2,244.4,13.2z"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon
|
|
||||||
points="114.7,69.8 114.7,31.7 98.1,31.7 98.1,38.5 105.7,38.5 105.7,69.8 "
|
|
||||||
></polygon>
|
|
||||||
<path
|
|
||||||
d="M110,13.2c-3.3,0-6,2.6-6,5.9c0,3.3,2.6,6,5.9,6c3.3,0,6-2.6,6-6C115.8,15.9,113.2,13.2,110,13.2
|
|
||||||
z"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
d="M176.4,52.4v-3.7c0-12.3-4.7-18-14.8-18c-9.3,0-14.7,6.6-14.7,18v4c0,11.5,5.8,18.2,15.8,18.2
|
|
||||||
c6.6,0,10.8-3.7,12.7-7.9c-2.2-1.4-4.6-2.8-6.1-3.8c-1,1.7-2.9,4.4-6.7,4.4c-5.8,0-7-5.9-7-10.9v-0.2H176.4z M155.7,45.7
|
|
||||||
c0.2-7.1,3.3-8.2,6-8.2c2.6,0,5.9,1,6,8.2H155.7z"
|
|
||||||
></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</switch>
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
<template>
|
|
||||||
<UiTooltip
|
|
||||||
:tooltip="tooltip ?? label"
|
|
||||||
direction="right-end"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="link flex items-center justify-center py-3 hover:text-primary tooltip-toogle bg w-full"
|
|
||||||
@click="$emit('click')"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
:name="icon"
|
|
||||||
class="size-8"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</UiTooltip>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
defineProps<{
|
|
||||||
label: string;
|
|
||||||
tooltip?: string;
|
|
||||||
icon: string;
|
|
||||||
}>();
|
|
||||||
</script>
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
<template>
|
|
||||||
<aside
|
|
||||||
class="flex shrink-0 transition-[width] ease-in duration-300 z-30 h-full overflow-hidden fixed sm:relative left-0 shadow border-r border-base-300/90"
|
|
||||||
>
|
|
||||||
<div class="sm:flex flex-col w-14 bg-base-200 shrink-0 h-full hidden">
|
|
||||||
<img src="/logo.svg" class="bg-primary p-3 size-16" />
|
|
||||||
|
|
||||||
<div class="flex flex-col justify-between h-full overflow-y-scroll z-10">
|
|
||||||
<div class="flex flex-col space-y-2 text-base-content/90"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div class="bg-base-100 flex flex-col w-full overflow-clip">
|
|
||||||
<div
|
|
||||||
class="h-16 flex items-center sm:justify-center justify-end md:justify-start bg-base-300 shrink-0"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="top-3 left-2 absolute z-30 duration-1000 btn btn-square btn-primary transition-opacity btn-outline sm:hidden"
|
|
||||||
@click="show = !show"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name="mdi:menu"
|
|
||||||
size="28"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<span
|
|
||||||
class="px-4 font-semibold text-base-content shrink-0 sm:bg-transparent bg-primary h-full flex items-center rounded-l-lg"
|
|
||||||
>
|
|
||||||
<p>Haex Vault</p>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<img
|
|
||||||
src="/logo.svg"
|
|
||||||
class="bg-primary p-3 size-16 shrink-0 sm:hidden rounded-r-lg"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn btn-square btn-primary btn-outline mr-2 ml-auto hidden sm:flex"
|
|
||||||
@click="show = false"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name="mdi:close"
|
|
||||||
size="28"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="overflow-scroll flex pb-4 relative">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</aside>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
defineProps({
|
|
||||||
menu: {
|
|
||||||
type: Object as PropType<ISidebarItem>,
|
|
||||||
default: () => {},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@ -1,268 +0,0 @@
|
|||||||
<template>
|
|
||||||
<nav
|
|
||||||
class="navbar bg-base-100 max-sm:rounded-box max-sm:shadow sm:border-b border-base-content/25 sm:z-[1] relative"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-text max-sm:btn-square sm:hidden me-2"
|
|
||||||
aria-haspopup="dialog"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-controls="sidebar"
|
|
||||||
data-overlay="#sidebar"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--menu-2] size-5"></span>
|
|
||||||
</button>
|
|
||||||
<div class="flex flex-1 items-center">
|
|
||||||
<a
|
|
||||||
class="link text-base-content link-neutral text-xl font-semibold no-underline"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<UiTextGradient>Haex Hub</UiTextGradient>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-end flex items-center gap-4">
|
|
||||||
<div
|
|
||||||
class="dropdown relative inline-flex [--auto-close:inside] [--offset:8] [--placement:bottom-end]"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
id="dropdown-scrollable"
|
|
||||||
type="button"
|
|
||||||
class="dropdown-toggle btn btn-text btn-circle dropdown-open:bg-base-content/10 size-10"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Dropdown"
|
|
||||||
>
|
|
||||||
<div class="indicator">
|
|
||||||
<span
|
|
||||||
v-show="notifications.length"
|
|
||||||
class="indicator-item bg-error size-2 rounded-full text-sm"
|
|
||||||
></span>
|
|
||||||
<span
|
|
||||||
class="icon-[tabler--bell] text-base-content size-[1.375rem]"
|
|
||||||
></span>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
class="dropdown-menu dropdown-open:opacity-100 hidden"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="dropdown-scrollable"
|
|
||||||
>
|
|
||||||
<div class="dropdown-header justify-center">
|
|
||||||
<h6 class="text-base-content text-base">
|
|
||||||
{{ t('notifications.label') }}
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="vertical-scrollbar horizontal-scrollbar rounded-scrollbar text-base-content/80 max-h-56 overflow-auto max-md:max-w-60"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="dropdown-item"
|
|
||||||
v-for="notification in notifications"
|
|
||||||
>
|
|
||||||
<div class="avatar">
|
|
||||||
<div class="w-10 rounded-full">
|
|
||||||
<img
|
|
||||||
v-if="notification.image"
|
|
||||||
:src="notification.image"
|
|
||||||
:alt="notification.alt ?? 'notification avatar'"
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
v-else-if="notification.icon"
|
|
||||||
:name="notification.icon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-60">
|
|
||||||
<h6 class="truncate text-base">
|
|
||||||
{{ notification.title }}
|
|
||||||
</h6>
|
|
||||||
<small class="text-base-content/50 truncate">
|
|
||||||
{{ notification.description }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
class="dropdown-footer justify-center gap-1"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--eye] size-4"></span>
|
|
||||||
{{ t('notifications.view_all') }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="dropdown relative inline-flex [--auto-close:inside] [--offset:8] [--placement:bottom-end]"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
id="dropdown-scrollable"
|
|
||||||
type="button"
|
|
||||||
class="dropdown-toggle flex items-center"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Dropdown"
|
|
||||||
>
|
|
||||||
<div class="avatar">
|
|
||||||
<div class="size-9.5 rounded-full">
|
|
||||||
<img
|
|
||||||
src="https://cdn.flyonui.com/fy-assets/avatar/avatar-1.png"
|
|
||||||
alt="avatar 1"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<ul
|
|
||||||
class="dropdown-menu dropdown-open:opacity-100 hidden min-w-60"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="dropdown-avatar"
|
|
||||||
>
|
|
||||||
<li class="dropdown-header gap-2">
|
|
||||||
<div class="avatar">
|
|
||||||
<div class="w-10 rounded-full">
|
|
||||||
<img
|
|
||||||
src="https://cdn.flyonui.com/fy-assets/avatar/avatar-1.png"
|
|
||||||
alt="avatar"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h6 class="text-base-content text-base font-semibold">
|
|
||||||
John Doe
|
|
||||||
</h6>
|
|
||||||
<small class="text-base-content/50">Admin</small>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--user]"></span>
|
|
||||||
My Profile
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--settings]"></span>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--receipt-rupee]"></span>
|
|
||||||
Billing
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="dropdown-item"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--help-triangle]"></span>
|
|
||||||
FAQs
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="dropdown-footer gap-2">
|
|
||||||
<a
|
|
||||||
class="btn btn-error btn-soft btn-block"
|
|
||||||
href="#"
|
|
||||||
>
|
|
||||||
<span class="icon-[tabler--logout]"></span>
|
|
||||||
Sign out
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<aside
|
|
||||||
id="sidebar"
|
|
||||||
class="overlay sm:shadow-none overlay-open:translate-x-0 drawer drawer-start hidden max-w-64 sm:absolute sm:z-0 sm:flex sm:translate-x-0 pt-16"
|
|
||||||
role="dialog"
|
|
||||||
tabindex="-1"
|
|
||||||
>
|
|
||||||
<div class="drawer-body px-2 pt-4">
|
|
||||||
<ul class="menu p-0">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li v-for="item in menu">
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--home] size-5"></span>
|
|
||||||
Home
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--user] size-5"></span>
|
|
||||||
Account
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--message] size-5"></span>
|
|
||||||
Notifications
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--mail] size-5"></span>
|
|
||||||
Email
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--calendar] size-5"></span>
|
|
||||||
Calendar
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--shopping-bag] size-5"></span>
|
|
||||||
Product
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--login] size-5"></span>
|
|
||||||
Sign In
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<span class="icon-[tabler--logout-2] size-5"></span>
|
|
||||||
Sign Out
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const { notifications } = storeToRefs(useNotificationStore());
|
|
||||||
|
|
||||||
const { menu } = storeToRefs(useSidebarStore());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<i18n lang="yaml">
|
|
||||||
de:
|
|
||||||
notifications:
|
|
||||||
label: Benachrichtigungen
|
|
||||||
view_all: Alle ansehen
|
|
||||||
en:
|
|
||||||
notifications:
|
|
||||||
label: Notifications
|
|
||||||
view_all: View all
|
|
||||||
</i18n>
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
<template>
|
|
||||||
<p
|
|
||||||
class="bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent font-black"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="tooltip [--prevent-popper:false]">
|
|
||||||
<div
|
|
||||||
class="tooltip-toggle"
|
|
||||||
aria-label="Tooltip"
|
|
||||||
>
|
|
||||||
<slot>
|
|
||||||
<button class="btn btn-square">
|
|
||||||
<Icon name="mdi:chevron-up-box-outline" />
|
|
||||||
</button>
|
|
||||||
</slot>
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="tooltip-content tooltip-shown:opacity-100 tooltip-shown:visible z-40"
|
|
||||||
role="tooltip"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="tooltip-body"
|
|
||||||
v-bind="$attrs"
|
|
||||||
>
|
|
||||||
{{ tooltip }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import type { PropType } from 'vue';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
direction: {
|
|
||||||
type: String as PropType<
|
|
||||||
| 'top'
|
|
||||||
| 'top-start'
|
|
||||||
| 'top-end'
|
|
||||||
| 'bottom'
|
|
||||||
| 'bottom-start'
|
|
||||||
| 'bottom-end'
|
|
||||||
| 'right'
|
|
||||||
| 'right-start'
|
|
||||||
| 'right-end'
|
|
||||||
| 'left'
|
|
||||||
| 'left-start'
|
|
||||||
| 'left-end'
|
|
||||||
>,
|
|
||||||
default: 'top',
|
|
||||||
},
|
|
||||||
|
|
||||||
tooltip: String,
|
|
||||||
|
|
||||||
trigger: {
|
|
||||||
type: String as PropType<'focus' | 'hover' | 'click'>,
|
|
||||||
default: 'hover',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
inheritAttrs: false,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@ -1,13 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<UiDialog :title="t('title')" v-model:open="open">
|
<UiDialog
|
||||||
<template #trigger="{ id }">
|
:title="t('title')"
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-outline shadow-md md:btn-lg shrink-0 flex-1 whitespace-nowrap flex-nowrap"
|
class="btn btn-primary btn-outline shadow-md md:btn-lg shrink-0 flex-1 whitespace-nowrap flex-nowrap"
|
||||||
@click="open = true"
|
|
||||||
>
|
>
|
||||||
|
<template #trigger>
|
||||||
<Icon name="mdi:plus" />
|
<Icon name="mdi:plus" />
|
||||||
{{ t('database.create') }}
|
{{ t('database.create') }}
|
||||||
</button>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<form class="flex flex-col gap-4" @submit="onCreateAsync">
|
<form class="flex flex-col gap-4" @submit="onCreateAsync">
|
||||||
|
|||||||
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<UiDialog v-model:open="isOpen">
|
<UiDialog
|
||||||
<!-- @close="initDatabase" -->
|
|
||||||
<template #trigger>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-outline shadow-md md:btn-lg shrink-0 flex-1"
|
class="btn btn-primary btn-outline shadow-md md:btn-lg shrink-0 flex-1"
|
||||||
|
v-model:open="isOpen"
|
||||||
@click="onLoadDatabase"
|
@click="onLoadDatabase"
|
||||||
>
|
>
|
||||||
|
<!-- @close="initDatabase" -->
|
||||||
|
<template #trigger>
|
||||||
|
<!-- <button
|
||||||
|
class="btn btn-primary btn-outline shadow-md md:btn-lg shrink-0 flex-1"
|
||||||
|
@click="onLoadDatabase"
|
||||||
|
> -->
|
||||||
|
|
||||||
<Icon name="mdi:folder-open-outline" />
|
<Icon name="mdi:folder-open-outline" />
|
||||||
{{ t('database.open') }}
|
{{ t('database.open') }}
|
||||||
</button>
|
<!-- </button> -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<UiInputPassword
|
<UiInputPassword
|
||||||
|
|||||||
@ -1,115 +0,0 @@
|
|||||||
export const bytesToBase64DataUrlAsync = async (
|
|
||||||
bytes: Uint8Array,
|
|
||||||
type = "application/octet-stream"
|
|
||||||
) => {
|
|
||||||
return await new Promise((resolve, reject) => {
|
|
||||||
const reader = Object.assign(new FileReader(), {
|
|
||||||
onload: () => resolve(reader.result),
|
|
||||||
onerror: () => reject(reader.error),
|
|
||||||
});
|
|
||||||
reader.readAsDataURL(new File([new Blob([bytes])], "", { type }));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const blobToImageAsync = (blob: Blob): Promise<HTMLImageElement> => {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
console.log("transform blob", blob);
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
let img = new Image();
|
|
||||||
img.onload = () => {
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
resolve(img);
|
|
||||||
};
|
|
||||||
img.src = url;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deepToRaw = <T extends Record<string, any>>(sourceObj: T): T => {
|
|
||||||
const objectIterator = (input: any): any => {
|
|
||||||
if (Array.isArray(input)) {
|
|
||||||
return input.map((item) => objectIterator(item));
|
|
||||||
}
|
|
||||||
if (isRef(input) || isReactive(input) || isProxy(input)) {
|
|
||||||
return objectIterator(toRaw(input));
|
|
||||||
}
|
|
||||||
if (input && typeof input === "object") {
|
|
||||||
return Object.keys(input).reduce((acc, key) => {
|
|
||||||
acc[key as keyof typeof acc] = objectIterator(input[key]);
|
|
||||||
return acc;
|
|
||||||
}, {} as T);
|
|
||||||
}
|
|
||||||
return input;
|
|
||||||
};
|
|
||||||
|
|
||||||
return objectIterator(sourceObj);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const readableFileSize = (sizeInByte: number | string = 0) => {
|
|
||||||
if (!sizeInByte) {
|
|
||||||
return "0 KB";
|
|
||||||
}
|
|
||||||
const size = typeof sizeInByte === "string" ? parseInt(sizeInByte) : sizeInByte;
|
|
||||||
const sizeInKb = size / 1024;
|
|
||||||
const sizeInMb = sizeInKb / 1024;
|
|
||||||
const sizeInGb = sizeInMb / 1024;
|
|
||||||
const sizeInTb = sizeInGb / 1024;
|
|
||||||
|
|
||||||
if (sizeInTb > 1) return `${sizeInTb.toFixed(2)} TB`;
|
|
||||||
if (sizeInGb > 1) return `${sizeInGb.toFixed(2)} GB`;
|
|
||||||
if (sizeInMb > 1) return `${sizeInMb.toFixed(2)} MB`;
|
|
||||||
|
|
||||||
return `${sizeInKb.toFixed(2)} KB`;
|
|
||||||
};
|
|
||||||
|
|
||||||
import type { LocationQueryValue, RouteLocationRawI18n } from "vue-router";
|
|
||||||
|
|
||||||
export const getSingleRouteParam = (
|
|
||||||
param: string | string[] | LocationQueryValue | LocationQueryValue[]
|
|
||||||
): string => {
|
|
||||||
const _param = Array.isArray(param) ? param.at(0) ?? "" : param ?? "";
|
|
||||||
//console.log('found param', _param, param);
|
|
||||||
return decodeURIComponent(_param);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isRouteActive = (to: RouteLocationRawI18n, exact: boolean = false) =>
|
|
||||||
computed(() => {
|
|
||||||
const found = useRouter()
|
|
||||||
.getRoutes()
|
|
||||||
.find((route) => route.name === useLocaleRoute()(to)?.name);
|
|
||||||
//console.log('found route', found, useRouter().currentRoute.value, to);
|
|
||||||
return exact
|
|
||||||
? found?.name === useRouter().currentRoute.value.name
|
|
||||||
: found?.name === useRouter().currentRoute.value.name ||
|
|
||||||
found?.children.some((child) => child.name === useRouter().currentRoute.value.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const isKey = <T extends object>(x: T, k: PropertyKey): k is keyof T => {
|
|
||||||
return k in x;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const filterAsync = async <T>(
|
|
||||||
arr: T[],
|
|
||||||
predicate: (value: T, index: number, array: T[]) => Promise<boolean>
|
|
||||||
) => {
|
|
||||||
// 1. Mappe jedes Element auf ein Promise, das zu true/false auflöst
|
|
||||||
const results = await Promise.all(arr.map(predicate));
|
|
||||||
|
|
||||||
// 2. Filtere das ursprüngliche Array basierend auf den Ergebnissen
|
|
||||||
return arr.filter((_value, index) => results[index]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const stringToHex = (str: string) =>
|
|
||||||
str
|
|
||||||
.split("")
|
|
||||||
.map((char) => char.charCodeAt(0).toString(16).padStart(2, "0"))
|
|
||||||
.join(""); // Join array into a single string
|
|
||||||
|
|
||||||
export const hexToString = (hex: string) => {
|
|
||||||
if (!hex) return "";
|
|
||||||
const parsedValue = hex
|
|
||||||
.match(/.{1,2}/g) // Split hex into pairs
|
|
||||||
?.map((byte) => String.fromCharCode(parseInt(byte, 16))) // Convert hex to char
|
|
||||||
.join(""); // Join array into a single string
|
|
||||||
|
|
||||||
return parsedValue ? parsedValue : "";
|
|
||||||
};
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
/* import de from '@/stores/sidebar/de.json';
|
|
||||||
import en from '@/stores/sidebar/en.json'; */
|
|
||||||
|
|
||||||
export default defineI18nConfig(() => {
|
|
||||||
return {
|
|
||||||
legacy: false,
|
|
||||||
messages: {
|
|
||||||
de: {
|
|
||||||
//sidebar: de,
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
//sidebar: en,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@ -116,8 +116,12 @@
|
|||||||
>
|
>
|
||||||
<div class="drawer-body h-full">
|
<div class="drawer-body h-full">
|
||||||
<ul class="menu p-0 h-full rounded-none">
|
<ul class="menu p-0 h-full rounded-none">
|
||||||
<UiSidebarLink v-bind="item" v-for="item in menu" :key="item.id" />
|
<HaexSidebarLink
|
||||||
<UiSidebarLink
|
v-bind="item"
|
||||||
|
v-for="item in menu"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
|
<HaexSidebarLink
|
||||||
v-for="item in extensionLinks"
|
v-for="item in extensionLinks"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
v-bind="item"
|
v-bind="item"
|
||||||
|
|||||||
@ -26,6 +26,64 @@
|
|||||||
v-model:isOpen="passwordPromptOpen"
|
v-model:isOpen="passwordPromptOpen"
|
||||||
:path="vaultPath"
|
:path="vaultPath"
|
||||||
/>
|
/>
|
||||||
|
<UiDialogTest />
|
||||||
|
|
||||||
|
<UiDialog> aaaaaa </UiDialog>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-primary"
|
||||||
|
aria-haspopup="dialog"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="basic-modal"
|
||||||
|
data-overlay="#basic-modal1"
|
||||||
|
>
|
||||||
|
Open modal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="basic-modal1"
|
||||||
|
class="overlay modal overlay-open:opacity-100 hidden overlay-open:duration-300"
|
||||||
|
role="dialog"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="modal-dialog overlay-open:opacity-100 overlay-open:duration-300"
|
||||||
|
>
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title">Dialog Title</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-text btn-circle btn-sm absolute end-3 top-3"
|
||||||
|
aria-label="Close"
|
||||||
|
data-overlay="#basic-modal1"
|
||||||
|
>
|
||||||
|
<span class="icon-[tabler--x] size-4"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
This is some placeholder content to show the scrolling behavior
|
||||||
|
for modals. Instead of repeating the text in the modal, we use
|
||||||
|
an inline style to set a minimum height, thereby extending the
|
||||||
|
length of the overall modal and demonstrating the overflow
|
||||||
|
scrolling. When content becomes longer than the height of the
|
||||||
|
viewport, scrolling will move the modal as needed.
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-soft btn-secondary"
|
||||||
|
data-overlay="#basic-modal1"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary">
|
||||||
|
Save changes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="lastVaults.length" class="w-full">
|
<div v-show="lastVaults.length" class="w-full">
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import 'flyonui/flyonui';
|
|
||||||
import { type IStaticMethods } from 'flyonui/flyonui';
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
HSStaticMethods: IStaticMethods;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
|
||||||
nuxtApp.hook('page:finish', () => {
|
|
||||||
window.HSStaticMethods.autoInit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"light": "Hell",
|
|
||||||
"dark": "Dunkel",
|
|
||||||
"soft": "Soft",
|
|
||||||
"corporate": "Corporate"
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"light": "Light",
|
|
||||||
"dark": "Dark",
|
|
||||||
"soft": "Soft",
|
|
||||||
"corporate": "Corporate"
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
|
|
||||||
import de from './de.json';
|
|
||||||
import en from './en.json';
|
|
||||||
|
|
||||||
export interface ITheme {
|
|
||||||
value: string,
|
|
||||||
name: string,
|
|
||||||
icon: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useUiStore = defineStore('uiStore', () => {
|
|
||||||
const breakpoints = useBreakpoints(breakpointsTailwind);
|
|
||||||
|
|
||||||
const currentScreenSize = computed(() =>
|
|
||||||
breakpoints.active().value.length > 0 ? breakpoints.active().value : 'xs'
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useI18n({
|
|
||||||
messages: {
|
|
||||||
de: { ui: de },
|
|
||||||
en: { ui: en },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const availableThemes = ref([
|
|
||||||
{
|
|
||||||
value: 'dark',
|
|
||||||
name: t('ui.dark'),
|
|
||||||
icon: 'line-md:moon-rising-alt-loop',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'light',
|
|
||||||
name: t('ui.light'),
|
|
||||||
icon: 'line-md:moon-to-sunny-outline-loop-transition',
|
|
||||||
},
|
|
||||||
{ value: 'soft', name: t('ui.soft'), icon: 'line-md:paint-drop' },
|
|
||||||
{
|
|
||||||
value: 'corporate',
|
|
||||||
name: t('ui.corporate'),
|
|
||||||
icon: 'hugeicons:corporate',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const defaultTheme = ref(availableThemes.value[0])
|
|
||||||
|
|
||||||
const currentTheme = ref(defaultTheme);
|
|
||||||
|
|
||||||
return {
|
|
||||||
availableThemes,
|
|
||||||
breakpoints,
|
|
||||||
currentScreenSize,
|
|
||||||
currentTheme,
|
|
||||||
defaultTheme,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user