diff --git a/index.html b/index.html
index a888544..a77cf6f 100644
--- a/index.html
+++ b/index.html
@@ -1,10 +1,10 @@
-
+
-
-
-
- Vite App
+
+
+
+ OSM Filter
diff --git a/package-lock.json b/package-lock.json
index cf432ab..57ba261 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,9 @@
"dependencies": {
"@vuestic/tailwind": "^0.1.5",
"pinia": "^2.1.7",
+ "pinia-plugin-persistedstate": "^3.2.1",
"vue": "^3.4.21",
+ "vue-i18n": "^9.13.1",
"vue-router": "^4.3.0",
"vuestic-ui": "^1.9.9"
},
@@ -615,6 +617,47 @@
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true
},
+ "node_modules/@intlify/core-base": {
+ "version": "9.13.1",
+ "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.13.1.tgz",
+ "integrity": "sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==",
+ "dependencies": {
+ "@intlify/message-compiler": "9.13.1",
+ "@intlify/shared": "9.13.1"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/message-compiler": {
+ "version": "9.13.1",
+ "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.13.1.tgz",
+ "integrity": "sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==",
+ "dependencies": {
+ "@intlify/shared": "9.13.1",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
+ "node_modules/@intlify/shared": {
+ "version": "9.13.1",
+ "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.13.1.tgz",
+ "integrity": "sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -3126,6 +3169,14 @@
}
}
},
+ "node_modules/pinia-plugin-persistedstate": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz",
+ "integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==",
+ "peerDependencies": {
+ "pinia": "^2.0.0"
+ }
+ },
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
@@ -4104,6 +4155,25 @@
"eslint": ">=6.0.0"
}
},
+ "node_modules/vue-i18n": {
+ "version": "9.13.1",
+ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.13.1.tgz",
+ "integrity": "sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==",
+ "dependencies": {
+ "@intlify/core-base": "9.13.1",
+ "@intlify/shared": "9.13.1",
+ "@vue/devtools-api": "^6.5.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/kazupon"
+ },
+ "peerDependencies": {
+ "vue": "^3.0.0"
+ }
+ },
"node_modules/vue-router": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz",
diff --git a/package.json b/package.json
index c26a561..7a65506 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,9 @@
"dependencies": {
"@vuestic/tailwind": "^0.1.5",
"pinia": "^2.1.7",
+ "pinia-plugin-persistedstate": "^3.2.1",
"vue": "^3.4.21",
+ "vue-i18n": "^9.13.1",
"vue-router": "^4.3.0",
"vuestic-ui": "^1.9.9"
},
diff --git a/src/App.vue b/src/App.vue
index 20d10c7..51ea0e7 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,29 +1,119 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ menuStore.click(0)"
+ >{{ menuStore.items[0].text }}
+ menuStore.click(1)"
+ >{{ menuStore.items[1].text }}
+ menuStore.click(2)"
+ >{{ menuStore.items[2].text }}
+ menuStore.click(3)"
+ >{{ menuStore.items[3].text }}
+ menuStore.click(4)"
+ >{{ menuStore.items[4].text }}
+
+
+
+
+
+
+
+ LOGO
+
+
+
+
+
+
+ Home
+ Home
+ filter
+ Home
+
+
+
+
+
+
+
diff --git a/src/assets/main.css b/src/assets/main.css
index d47b6c0..dd1345d 100644
--- a/src/assets/main.css
+++ b/src/assets/main.css
@@ -4,3 +4,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+body {
+ background-color: var(--va-background-primary);
+ color: var(--va-text-primary);
+}
diff --git a/src/components/TheWelcome.vue b/src/components/TheWelcome.vue
index 0143747..cf377f3 100644
--- a/src/components/TheWelcome.vue
+++ b/src/components/TheWelcome.vue
@@ -5,6 +5,21 @@ import ToolingIcon from './icons/IconTooling.vue';
import EcosystemIcon from './icons/IconEcosystem.vue';
import CommunityIcon from './icons/IconCommunity.vue';
import SupportIcon from './icons/IconSupport.vue';
+import { useAdditionalMenu } from '@/stores/menu';
+import { computed, ref } from 'vue';
+
+const toggle = ref(false);
+
+const menu = computed(() => {
+ return [
+ {
+ text: toggle.value ? 'option 1 select' : 'option 1 unselect',
+ onClick: () => (toggle.value = !toggle.value)
+ },
+ { text: 'option 2' }
+ ];
+});
+useAdditionalMenu(menu);
@@ -118,4 +133,28 @@ import SupportIcon from './icons/IconSupport.vue';
>becoming a sponsor.
+
+
+
+
+ Support Vue
+
+ As an independent project, Vue relies on community backing for its
+ sustainability. You can help us by
+ becoming a sponsor.
+
+
+
+
+
+ Support Vue
+
+ As an independent project, Vue relies on community backing for its
+ sustainability. You can help us by
+ becoming a sponsor.
+
diff --git a/src/i18n.ts b/src/i18n.ts
new file mode 100644
index 0000000..5adb2fd
--- /dev/null
+++ b/src/i18n.ts
@@ -0,0 +1,16 @@
+import { createI18n } from 'vue-i18n';
+import en from './locales/en.json';
+import de from './locales/de.json';
+
+export const SUPPORT_LOCALES = [{ code: 'en' }, { code: 'de' }];
+
+export const i18n = createI18n({
+ legacy: false,
+ locale: 'en',
+ fallbackLocale: 'en',
+ messages: {
+ en,
+ de
+ },
+ availableLocales: SUPPORT_LOCALES.map((l) => l.code)
+});
diff --git a/src/locales/de.json b/src/locales/de.json
new file mode 100644
index 0000000..4f174da
--- /dev/null
+++ b/src/locales/de.json
@@ -0,0 +1,7 @@
+{
+ "text": "Hallo",
+ "locales": {
+ "en": "Englisch",
+ "de": "Deutsch"
+ }
+}
diff --git a/src/locales/en.json b/src/locales/en.json
new file mode 100644
index 0000000..879ded8
--- /dev/null
+++ b/src/locales/en.json
@@ -0,0 +1,7 @@
+{
+ "text": "Hello",
+ "locales": {
+ "en": "English",
+ "de": "German"
+ }
+}
diff --git a/src/main.ts b/src/main.ts
index 67595c4..f58dc6d 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -2,11 +2,18 @@ import './assets/main.css';
import { createApp } from 'vue';
import { createPinia } from 'pinia';
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
import App from './App.vue';
import router from './router';
import { createVuestic } from 'vuestic-ui';
+import { i18n } from '@/i18n';
const app = createApp(App);
-app.use(createPinia()).use(router).use(createVuestic()).mount('#app');
+app
+ .use(i18n)
+ .use(createPinia().use(piniaPluginPersistedstate))
+ .use(router)
+ .use(createVuestic())
+ .mount('#app');
diff --git a/src/stores/menu.ts b/src/stores/menu.ts
new file mode 100644
index 0000000..f927a16
--- /dev/null
+++ b/src/stores/menu.ts
@@ -0,0 +1,47 @@
+import { acceptHMRUpdate, defineStore } from 'pinia';
+import { onMounted, onUnmounted, type Ref, ref, toRef, watch } from 'vue';
+
+type MenuOption = {
+ icon?: string;
+ rightIcon?: string;
+ text: string;
+ onClick?: () => void;
+};
+export const useMenuStore = defineStore(
+ 'menu',
+ () => {
+ const items = ref>([]);
+
+ function click(index: number) {
+ if (items.value.length <= index) {
+ return;
+ }
+ console.log('menu', `selected ${index}`, items.value[index]);
+ items.value[index].onClick?.();
+ }
+
+ return { items, click };
+ },
+ { persist: false }
+);
+
+export function useAdditionalMenu(
+ items: Ref> | Array
+) {
+ const store = useMenuStore();
+ onMounted(() => {
+ store.items.splice(0);
+ store.items.push(...toRef(items).value);
+ });
+ onUnmounted(() => {
+ store.items.splice(0);
+ });
+ watch(toRef(items), (newItems) => {
+ store.items.splice(0);
+ store.items.push(...newItems);
+ });
+}
+
+if (import.meta.hot) {
+ import.meta.hot.accept(acceptHMRUpdate(useMenuStore, import.meta.hot));
+}
diff --git a/src/stores/theme.ts b/src/stores/theme.ts
new file mode 100644
index 0000000..365de3c
--- /dev/null
+++ b/src/stores/theme.ts
@@ -0,0 +1,45 @@
+import { ref, watch } from 'vue';
+import { acceptHMRUpdate, defineStore } from 'pinia';
+import { useColors } from 'vuestic-ui';
+import { i18n, SUPPORT_LOCALES } from '@/i18n';
+
+export const useThemeStore = defineStore(
+ 'theme',
+ () => {
+ const { applyPreset, currentPresetName } = useColors();
+ const mode = ref(currentPresetName.value);
+ const h = document.querySelector('html');
+ watch(mode, (newMode, oldMode) => {
+ applyPreset(newMode);
+ console.log(newMode);
+ if (h?.classList.replace(oldMode, newMode) === false) {
+ h?.classList.add(newMode);
+ }
+ });
+
+ console.log(navigator.language);
+ const lang = ref(
+ SUPPORT_LOCALES.find((l) =>
+ navigator.language.toLowerCase().startsWith(l.code)
+ )?.code || SUPPORT_LOCALES[0].code
+ );
+ watch(lang, (l) => {
+ console.log(l);
+ i18n.global.locale.value = l as any;
+ document.querySelector('html')?.setAttribute('lang', l);
+ });
+
+ return { mode, lang };
+ },
+ {
+ persist: {
+ afterRestore: (ctx) => {
+ i18n.global.locale.value = ctx.store.lang as any;
+ document.querySelector('html')?.setAttribute('lang', ctx.store.lang);
+ }
+ }
+ }
+);
+if (import.meta.hot) {
+ import.meta.hot.accept(acceptHMRUpdate(useThemeStore, import.meta.hot));
+}
diff --git a/tailwind.config.js b/tailwind.config.js
index 35d66ec..cd76ec9 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */
export default {
+ darkMode: 'class',
content: ['./index.html', './src/**/*.{vue,js,ts}'],
theme: {
extend: {