Merge branch 'dev' into main

This commit is contained in:
Alexis
2023-10-13 18:10:04 +02:00
17 changed files with 1141 additions and 259 deletions

View File

@@ -1,4 +1,8 @@
import { defineConfig } from 'astro/config';
import vue from "@astrojs/vue";
// https://astro.build/config
export default defineConfig({});
export default defineConfig({
integrations: [vue()]
});

538
package-lock.json generated
View File

@@ -8,8 +8,13 @@
"name": "leim-maps",
"version": "0.0.1",
"dependencies": {
"@astrojs/vue": "^3.0.1",
"@nanostores/vue": "^0.10.0",
"@types/leaflet": "^1.9.6",
"astro": "^3.2.0"
"@vueuse/core": "^10.5.0",
"astro": "^3.2.0",
"nanostores": "^0.9.3",
"vue": "^3.3.4"
},
"devDependencies": {
"sass": "^1.68.0"
@@ -33,14 +38,14 @@
"integrity": "sha512-Mp+qrNhly+27bL/Zq8lGeUY+YrdoU0eDfIlAeGIPrzt0PnI/jGpvPUdCaugv4zbCrDkOUScFfcbeEiYumrdJnw=="
},
"node_modules/@astrojs/internal-helpers": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.2.0.tgz",
"integrity": "sha512-NQ4ppp1CM0HNkKbJNM4saVSfmUYzGlRalF6wx7F6T/MYHYSWGuojY89/oFTy4t8VlOGUCUijlsVNNeziWaUo5g=="
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.2.1.tgz",
"integrity": "sha512-06DD2ZnItMwUnH81LBLco3tWjcZ1lGU9rLCCBaeUCGYe9cI0wKyY2W3kDyoW1I6GmcWgt1fu+D1CTvz+FIKf8A=="
},
"node_modules/@astrojs/markdown-remark": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-3.2.0.tgz",
"integrity": "sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-3.2.1.tgz",
"integrity": "sha512-Z4YNMRtgFZeHhB29uCZl0B9MbMZddW9ZKCNucapoysbvygbDFF1gGtqpVnf+Lyv3rUBHwM/J5qWB2MSZuTuz1g==",
"dependencies": {
"@astrojs/prism": "^3.0.0",
"github-slugger": "^2.0.0",
@@ -58,7 +63,7 @@
"vfile": "^5.3.7"
},
"peerDependencies": {
"astro": "^3.1.0"
"astro": "^3.2.3"
}
},
"node_modules/@astrojs/prism": {
@@ -73,9 +78,9 @@
}
},
"node_modules/@astrojs/telemetry": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.2.tgz",
"integrity": "sha512-ef+jqCkqopCzjGfsMsr+8p56Nj6F9ZzouWcWZt+dKsqbRccI3c8K3jfkLcdq4AyfFZtKBDB6N4ZuI68g33oiOg==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.3.tgz",
"integrity": "sha512-j19Cf5mfyLt9hxgJ9W/FMdAA5Lovfp7/CINNB/7V71GqvygnL7KXhRC3TzfB+PsVQcBtgWZzCXhUWRbmJ64Raw==",
"dependencies": {
"ci-info": "^3.8.0",
"debug": "^4.3.4",
@@ -83,13 +88,30 @@
"dset": "^3.1.2",
"is-docker": "^3.0.0",
"is-wsl": "^3.0.0",
"undici": "^5.23.0",
"which-pm-runs": "^1.1.0"
},
"engines": {
"node": ">=18.14.1"
}
},
"node_modules/@astrojs/vue": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@astrojs/vue/-/vue-3.0.1.tgz",
"integrity": "sha512-qXn99sQ60zUPoHsMXGt43IySMKN5VXZz5VJlTKqkXG+CFV9DOWw0+syj/5iYKZSouH3nyNNb5a9uAkdz+X6Cew==",
"dependencies": {
"@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vue/babel-plugin-jsx": "^1.1.5",
"@vue/compiler-sfc": "^3.3.4"
},
"engines": {
"node": ">=18.14.1"
},
"peerDependencies": {
"astro": "^3.2.3",
"vue": "^3.2.30"
}
},
"node_modules/@babel/code-frame": {
"version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
@@ -195,6 +217,36 @@
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
"integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-member-expression-to-functions": "^7.22.15",
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-replace-supers": "^7.22.9",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-environment-visitor": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
@@ -226,6 +278,17 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
"integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
"dependencies": {
"@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
@@ -255,6 +318,17 @@
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-optimise-call-expression": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
"integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
"dependencies": {
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
@@ -263,6 +337,22 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-replace-supers": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz",
"integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==",
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-member-expression-to-functions": "^7.22.15",
"@babel/helper-optimise-call-expression": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-simple-access": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
@@ -274,6 +364,17 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
"integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
"dependencies": {
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
@@ -360,6 +461,20 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-syntax-typescript": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz",
"integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-react-jsx": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz",
@@ -378,6 +493,23 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-typescript": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz",
"integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-create-class-features-plugin": "^7.22.15",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-typescript": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/template": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
@@ -754,14 +886,6 @@
"node": ">=12"
}
},
"node_modules/@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
"engines": {
"node": ">=14"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
@@ -805,6 +929,28 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@nanostores/vue": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@nanostores/vue/-/vue-0.10.0.tgz",
"integrity": "sha512-832RAUbzRfHPs1CdqVEwfvgB2+RD/INji4Zo8bUSEfRO2pQRMMeq479gydnohGpRaa0oNwlfKo7TGFXCghq/1g==",
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"peerDependencies": {
"@nanostores/logger": ">=0.2.3",
"@vue/devtools-api": ">=6.5.0",
"nanostores": ">=0.9.2",
"vue": ">=3.3.1"
},
"peerDependenciesMeta": {
"@nanostores/logger": {
"optional": true
},
"@vue/devtools-api": {
"optional": true
}
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -959,6 +1105,275 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz",
"integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w=="
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.18",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.18.tgz",
"integrity": "sha512-v/ZHEj9xh82usl8LMR3GarzFY1IrbXJw5L4QfQhokjRV91q+SelFqxQWSep1ucXEZ22+dSTwLFkXeur25sPIbw=="
},
"node_modules/@vitejs/plugin-vue": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz",
"integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==",
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"peerDependencies": {
"vite": "^4.0.0",
"vue": "^3.2.25"
}
},
"node_modules/@vitejs/plugin-vue-jsx": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-3.0.2.tgz",
"integrity": "sha512-obF26P2Z4Ogy3cPp07B4VaW6rpiu0ue4OT2Y15UxT5BZZ76haUY9guOsZV3uWh/I6xc+VeiW+ZVabRE82FyzWw==",
"dependencies": {
"@babel/core": "^7.22.10",
"@babel/plugin-transform-typescript": "^7.22.10",
"@vue/babel-plugin-jsx": "^1.1.5"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"peerDependencies": {
"vite": "^4.0.0",
"vue": "^3.0.0"
}
},
"node_modules/@vue/babel-helper-vue-transform-on": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz",
"integrity": "sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w=="
},
"node_modules/@vue/babel-plugin-jsx": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.5.tgz",
"integrity": "sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==",
"dependencies": {
"@babel/helper-module-imports": "^7.22.5",
"@babel/plugin-syntax-jsx": "^7.22.5",
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/types": "^7.22.5",
"@vue/babel-helper-vue-transform-on": "^1.1.5",
"camelcase": "^6.3.0",
"html-tags": "^3.3.1",
"svg-tags": "^1.0.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@vue/babel-plugin-jsx/node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
"integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-core/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
"integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-ssr": "3.3.4",
"@vue/reactivity-transform": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0",
"postcss": "^8.1.10",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
"integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
"integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
"dependencies": {
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity-transform": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
"integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0"
}
},
"node_modules/@vue/reactivity-transform/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/@vue/runtime-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
"integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
"dependencies": {
"@vue/reactivity": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
"integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
"dependencies": {
"@vue/runtime-core": "3.3.4",
"@vue/shared": "3.3.4",
"csstype": "^3.1.1"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
"dependencies": {
"@vue/compiler-ssr": "3.3.4",
"@vue/shared": "3.3.4"
},
"peerDependencies": {
"vue": "3.3.4"
}
},
"node_modules/@vue/shared": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vueuse/core": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.5.0.tgz",
"integrity": "sha512-z/tI2eSvxwLRjOhDm0h/SXAjNm8N5ld6/SC/JQs6o6kpJ6Ya50LnEL8g5hoYu005i28L0zqB5L5yAl8Jl26K3A==",
"dependencies": {
"@types/web-bluetooth": "^0.0.18",
"@vueuse/metadata": "10.5.0",
"@vueuse/shared": "10.5.0",
"vue-demi": ">=0.14.6"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.5.0.tgz",
"integrity": "sha512-fEbElR+MaIYyCkeM0SzWkdoMtOpIwO72x8WsZHRE7IggiOlILttqttM69AS13nrDxosnDBYdyy3C5mR1LCxHsw==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.5.0.tgz",
"integrity": "sha512-18iyxbbHYLst9MqU1X1QNdMHIjks6wC7XTVf0KNOv5es/Ms6gjVFCAAWTVP2JStuGqydg3DT+ExpFORUEi9yhg==",
"dependencies": {
"vue-demi": ">=0.14.6"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/acorn": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
@@ -1069,14 +1484,14 @@
}
},
"node_modules/astro": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/astro/-/astro-3.2.0.tgz",
"integrity": "sha512-sDQnSFV46ZzNkVU6co5f8wilZFmGiWsqnIVoMhd5/XPU76iZdA40WqFyBOhGaji7hGuqbcjN8MGobMg53lsoUg==",
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/astro/-/astro-3.2.4.tgz",
"integrity": "sha512-e95Yz6tYG6Q2SEOCzujqCHq9/HOB2z085KP1K36kGuGtu0qaa3mmnz3R9FpKM/W5SbmrNgUv4QaP207EUkMp5Q==",
"dependencies": {
"@astrojs/compiler": "^2.1.0",
"@astrojs/internal-helpers": "0.2.0",
"@astrojs/markdown-remark": "3.2.0",
"@astrojs/telemetry": "3.0.2",
"@astrojs/internal-helpers": "0.2.1",
"@astrojs/markdown-remark": "3.2.1",
"@astrojs/telemetry": "3.0.3",
"@babel/core": "^7.22.10",
"@babel/generator": "^7.22.10",
"@babel/parser": "^7.22.10",
@@ -1121,7 +1536,6 @@
"string-width": "^6.1.0",
"strip-ansi": "^7.1.0",
"tsconfig-resolver": "^3.0.1",
"undici": "^5.23.0",
"unist-util-visit": "^4.1.2",
"vfile": "^5.3.7",
"vite": "^4.4.9",
@@ -1423,9 +1837,9 @@
"optional": true
},
"node_modules/ci-info": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
"integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
"integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
"funding": [
{
"type": "github",
@@ -1574,6 +1988,11 @@
"node": ">= 8"
}
},
"node_modules/csstype": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -2143,6 +2562,17 @@
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
"integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="
},
"node_modules/html-tags": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
"integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
@@ -3640,6 +4070,20 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/nanostores": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/nanostores/-/nanostores-0.9.3.tgz",
"integrity": "sha512-KobZjcVyNndNrb5DAjfs0WG0lRcZu5Q1BOrfTOxokFLi25zFrWPjg+joXC6kuDqNfSt9fQwppyjUBkRPtsL+8w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"engines": {
"node": "^16.0.0 || ^18.0.0 || >=20.0.0"
}
},
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
@@ -4710,9 +5154,9 @@
}
},
"node_modules/shiki": {
"version": "0.14.4",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz",
"integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==",
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
"integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==",
"dependencies": {
"ansi-sequence-parser": "^1.1.0",
"jsonc-parser": "^3.2.0",
@@ -4966,6 +5410,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
"integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA=="
},
"node_modules/tar-fs": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz",
@@ -5075,17 +5524,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/undici": {
"version": "5.25.3",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.25.3.tgz",
"integrity": "sha512-7lmhlz3K1+IKB6IUjkdzV2l0jKY8/0KguEMdEpzzXCug5pEGIp3DxUg0DEN65DrVoxHiRKpPORC/qzX+UglSkQ==",
"dependencies": {
"@fastify/busboy": "^2.0.0"
},
"engines": {
"node": ">=14.0"
}
},
"node_modules/unherit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",
@@ -5800,6 +6238,18 @@
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg=="
},
"node_modules/vue": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-sfc": "3.3.4",
"@vue/runtime-dom": "3.3.4",
"@vue/server-renderer": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",

View File

@@ -10,8 +10,13 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/vue": "^3.0.1",
"@nanostores/vue": "^0.10.0",
"@types/leaflet": "^1.9.6",
"astro": "^3.2.0"
"@vueuse/core": "^10.5.0",
"astro": "^3.2.0",
"nanostores": "^0.9.3",
"vue": "^3.3.4"
},
"devDependencies": {
"sass": "^1.68.0"

View File

@@ -5,7 +5,7 @@
width: 100%;
max-width: 100%;
max-height: 100%;
background: #98bcd0 !important;
background: #f1f5f9;
.leaflet-map-pane {
.leaflet-tooltip-pane {

101
src/assets/scss/_reset.scss Normal file
View File

@@ -0,0 +1,101 @@
@charset "utf-8";
/***
The new CSS reset - version 1.8.5 (last updated 14.6.2023)
GitHub page: https://github.com/elad2412/the-new-css-reset
***/
/*
Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
- The "symbol *" part is to solve Firefox SVG sprite bug
- The "html" attribute is exclud, because otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36)
*/
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
all: unset;
display: revert;
}
/* Preferred box-sizing value */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Reapply the pointer cursor for anchor tags */
a, button {
cursor: revert;
}
/* Remove list styles (bullets/numbers) */
ol, ul, menu {
list-style: none;
}
/* For images to not be able to exceed their container */
img {
max-inline-size: 100%;
max-block-size: 100%;
}
/* removes spacing between cells in tables */
table {
border-collapse: collapse;
}
/* Safari - solving issue when using user-select:none on the <body> text input doesn't working */
input, textarea {
-webkit-user-select: auto;
}
/* revert the 'white-space' property for textarea elements on Safari */
textarea {
white-space: revert;
}
/* minimum style to allow to style meter element */
meter {
-webkit-appearance: revert;
appearance: revert;
}
/* preformatted text - use only for this feature */
:where(pre) {
all: revert;
}
/* reset default text opacity of input placeholder */
::placeholder {
color: unset;
}
/* remove default dot (•) sign */
::marker {
content: initial;
}
/* fix the feature of 'hidden' attribute.
display:revert; revert to element instead of attribute */
:where([hidden]) {
display: none;
}
/* revert for bug in Chromium browsers
- fix for the content editable attribute will work properly.
- webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */
:where([contenteditable]:not([contenteditable="false"])) {
-moz-user-modify: read-write;
-webkit-user-modify: read-write;
overflow-wrap: break-word;
-webkit-line-break: after-white-space;
-webkit-user-select: auto;
}
/* apply back the draggable feature - exist only in Chromium and Safari */
:where([draggable="true"]) {
-webkit-user-drag: element;
}
/* Revert Modal native behavior */
:where(dialog:modal) {
all: revert;
}

View File

@@ -1,5 +1,22 @@
@use './leaflet';
@use 'reset';
@use 'leaflet';
:root {
--slate-50: #f8fafc;
--slate-100: #f1f5f9;
--slate-200: #e2e8f0;
--slate-300: #cbd5e1;
--slate-400: #94a3b8;
--slate-500: #64748b;
--slate-600: #475569;
--slate-700: #334155;
--slate-800: #1e293b;
--slate-900: #0f172a;
--slate-950: #020617;
}
html {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
color: var(--slate-900);
}

View File

@@ -1,195 +0,0 @@
---
import type { MapMarker } from '@/types/Leaflet';
interface Props {
markers: MapMarker[];
players?: MapMarker;
}
const { markers, players } = Astro.props
---
<div id="map"></div>
<script lang="ts" define:vars={{ markers, players }}>
const mapHeight = 15168;
const mapWidth = 14658;
const map = L.map('map', {
crs: L.CRS.Simple,
maxZoom: 12,
minZoom: 2.5,
zoom: 2.5,
zoomSnap: 0,
});
// Layers
const layer = L.tileLayer.zoomify('/zoomify/alliance-kaldelienne/{g}/{z}-{x}-{y}.jpg', {
width: mapWidth,
height: mapHeight,
}).addTo(map);
const layerGroups = {
players: L.layerGroup(),
capitals: L.layerGroup(),
cities: L.layerGroup(),
towns: L.layerGroup(),
landmarks: L.layerGroup(),
};
/**
* Build all markers and their related info
*/
for (let i = 0; i < markers.length; i++) {
const m = markers[i];
const coords = [m.markerCoords.y, m.markerCoords.x];
let markerIcon
switch (m.group) {
case "capitals":
markerIcon = L.icon({
iconUrl: `icons/castle.png`,
shadowUrl: `icons/castle-shadow.png`,
iconSize: [25, 25],
shadowSize: [35, 30],
iconAnchor: [12.5, 8],
shadowAnchor: [11, 12]
});
break;
case "cities":
markerIcon = L.icon({
iconUrl: `icons/circle.png`,
iconSize: [12, 12],
});
break;
case "landmarks":
markerIcon = L.icon({
iconUrl: `icons/monument.png`,
shadowUrl: `icons/monument-shadow.png`,
iconSize: [18, 18],
shadowSize: [32, 14],
iconAnchor: [12.5, 8],
shadowAnchor: [15, 6]
});
break;
case "towns":
default:
iconKey = "house"
break;
}
const marker = L.marker(coords, { icon: markerIcon }).addTo(map);
const popupContent = `
<b>
<a href="${m.link}" target="_blank">
${m.title}
</a>
</b>
<br>
${m.description}
`;
marker.bindPopup(popupContent).openPopup();
const displayTooltip = m.group === 'capitals';
if (displayTooltip) {
L.tooltip({ permanent: true, direction: 'top', offset: [0, 2], content: m.title, className: "capital-name", opacity: 1 }).setLatLng(coords).addTo(map);
}
marker.addTo(layerGroups[m.group])
}
/**
* Add player's position marker
*/
if ( players ) {
const playersPosition = [players.markerCoords.y, players.markerCoords.x];
const playerIcon = L.icon({
iconUrl: `icons/location-pin.png`,
shadowUrl: `icons/location-pin-shadow.png`,
iconSize: [18, 24],
shadowSize: [20, 16],
iconAnchor: [11, 8],
shadowAnchor: [3, 0],
});
const playerMarker = L.marker(playersPosition, { icon: playerIcon }).addTo(map)
playerMarker.addTo(layerGroups['players'])
console.log(map)
}
map.fitBounds(layer.getBounds());
// L.control.layers({ "base": layer }, layerGroups).addTo(map);
/**
* RULER
*/
/**
* Workaround specific to leaflet version
* See https://github.com/ljagis/leaflet-measure/issues/171 for details
*/
L.Control.Measure.include({
// set icon on the capture marker
_setCaptureMarkerIcon: function () {
// disable autopan
this._captureMarker.options.autoPanOnFocus = false;
// default function
this._captureMarker.setIcon(
L.divIcon({
iconSize: this._map.getSize().multiplyBy(2)
})
);
},
});
const rulerOptions = {
position: 'topleft',
primaryLengthUnit: 'kilometers',
secondaryLengthUnit: 'days',
primaryAreaUnit: 'hectares',
units: {
kilometers: {
factor: 0.00013,
display: 'Kilomètres',
},
days: {
factor: 0.000002,
display: 'Jours de marche',
decimals: 1
}
}
};
const measureControl = L.control.measure(rulerOptions);
measureControl.addTo(map);
/**
* DEBUGS
*/
map.addEventListener('click', (event) => {
let lat = Math.round(event.latlng.lat * 100000) / 100000;
let lng = Math.round(event.latlng.lng * 100000) / 100000;
console.log(lat, lng);
})
</script>
<style lang="scss">
html,
body {
height: 100vh;
margin: 0;
}
.leaflet-container {
aspect-ratio: 1551 / 1605;
}
</style>

View File

@@ -0,0 +1,212 @@
---
import { allTasks } from 'nanostores';
import { $world } from './worldStore';
$world.listen(() => {})
await allTasks()
const { markers, players } = $world.get()
---
<div class="world-wrapper">
<div id="world"></div>
</div>
<script lang="ts" define:vars={{ markers, players }}>
const mapHeight = 15168;
const mapWidth = 14658;
const map = L.map('world', {
crs: L.CRS.Simple,
maxZoom: 12,
minZoom: 2.5,
zoom: 2.5,
zoomSnap: 0,
zoomControl: false
});
L.control.zoom({
position: 'bottomright',
}).addTo(map);
// Layers
const layer = L.tileLayer.zoomify('/zoomify/alliance-kaldelienne/{g}/{z}-{x}-{y}.jpg', {
width: mapWidth,
height: mapHeight,
}).addTo(map);
const layerGroups = {
players: L.layerGroup(),
capitals: L.layerGroup(),
cities: L.layerGroup(),
towns: L.layerGroup(),
landmarks: L.layerGroup(),
};
/**
* Build all markers and their related info
*/
for (let i = 0; i < markers.length; i++) {
const m = markers[i];
const coords = [m.markerCoords.y, m.markerCoords.x];
let markerIcon
switch (m.group) {
case "capitals":
markerIcon = L.icon({
iconUrl: `icons/castle.png`,
shadowUrl: `icons/castle-shadow.png`,
iconSize: [25, 25],
shadowSize: [35, 30],
iconAnchor: [12.5, 8],
shadowAnchor: [11, 12]
});
break;
case "cities":
markerIcon = L.icon({
iconUrl: `icons/circle.png`,
iconSize: [12, 12],
});
break;
case "landmarks":
markerIcon = L.icon({
iconUrl: `icons/monument.png`,
shadowUrl: `icons/monument-shadow.png`,
iconSize: [18, 18],
shadowSize: [32, 14],
iconAnchor: [12.5, 8],
shadowAnchor: [15, 6]
});
break;
case "towns":
default:
iconKey = "house"
break;
}
const marker = L.marker(coords, { icon: markerIcon }).addTo(map);
const popupContent = `
<b>
<a href="${m.link}" target="_blank">
${m.title}
</a>
</b>
<br>
${m.description}
`;
marker.bindPopup(popupContent).openPopup();
const displayTooltip = m.group === 'capitals';
if (displayTooltip) {
L.tooltip({ permanent: true, direction: 'top', offset: [0, 2], content: m.title, className: "capital-name", opacity: 1 }).setLatLng(coords).addTo(map);
}
marker.addTo(layerGroups[m.group])
}
/**
* Add player's position marker
*/
if ( players ) {
const playersPosition = [players.markerCoords.y, players.markerCoords.x];
const playerIcon = L.icon({
iconUrl: `icons/location-pin.png`,
shadowUrl: `icons/location-pin-shadow.png`,
iconSize: [18, 24],
shadowSize: [20, 16],
iconAnchor: [11, 8],
shadowAnchor: [3, 0],
});
const playerMarker = L.marker(playersPosition, { icon: playerIcon }).addTo(map)
playerMarker.addTo(layerGroups['players'])
}
map.fitBounds(layer.getBounds());
// L.control.layers({ "base": layer }, layerGroups).addTo(map);
/**
* RULER
*/
/**
* Workaround specific to leaflet version
* See https://github.com/ljagis/leaflet-measure/issues/171 for details
*/
L.Control.Measure.include({
// set icon on the capture marker
_setCaptureMarkerIcon: function () {
// disable autopan
this._captureMarker.options.autoPanOnFocus = false;
// default function
this._captureMarker.setIcon(
L.divIcon({
iconSize: this._map.getSize().multiplyBy(2)
})
);
},
});
const rulerOptions = {
position: 'topright',
primaryLengthUnit: 'kilometers',
secondaryLengthUnit: 'days',
primaryAreaUnit: 'hectares',
units: {
kilometers: {
factor: 0.00013,
display: 'Kilomètres',
},
days: {
factor: 0.000002,
display: 'Jours de marche',
decimals: 1
}
}
};
const measureControl = L.control.measure(rulerOptions);
measureControl.addTo(map);
/**
* Flying to points of interests
*/
document.addEventListener('fly-to', (e) => {
const targetCoords = e.detail
map.flyTo([targetCoords.y, targetCoords.x], 5)
})
/**
* DEBUGS
*/
map.addEventListener('click', (event) => {
let lat = Math.round(event.latlng.lat * 100000) / 100000;
let lng = Math.round(event.latlng.lng * 100000) / 100000;
console.log(lat, lng);
})
</script>
<style lang="scss">
html,
body {
height: 100vh;
margin: 0;
position: relative;
}
.world-wrapper {
position: fixed;
inset: 0;
}
.leaflet-container {
aspect-ratio: 1551 / 1605;
}
</style>

View File

@@ -0,0 +1,31 @@
---
import { allTasks } from 'nanostores';
import { $world } from './worldStore';
import SearchMarkers from "./overlay/SearchMarkers.vue";
$world.listen(() => {})
await allTasks()
const { markers, players } = $world.get()
---
<div class="world-overlay">
<SearchMarkers markers={markers} players={players} client:visible />
</div>
<script>
</script>
<style lang="scss">
.world-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
z-index: 10;
padding: 10px;
pointer-events: none;
}
</style>

View File

@@ -0,0 +1,231 @@
<script setup lang="ts">
import { allTasks } from 'nanostores';
import { useStore } from '@nanostores/vue'
import { $world } from '../worldStore';
import { useFocus, useMagicKeys, whenever } from '@vueuse/core';
import { computed, onMounted, ref, onUpdated } from 'vue';
$world.listen(() => {})
await allTasks()
const { markers, players } = useStore($world).value
// Search functions
const qInput = ref()
const { focused: isFocused } = useFocus(qInput)
onMounted(() => {
isFocused.value = true
})
const shouldBeActive = computed(() => {
if (q.value.length > 0) {
return isFocused
}
})
const q = ref<string>("")
const filteredMarkers = computed(() => {
return markers?.filter(m => {
const unifier = new RegExp(/[^a-zA-Z0-9\-\'']/g)
const queryString = new String(q.value).replace(unifier, "").toLocaleLowerCase()
const hitTitle = m.title.replace(unifier, "").toLocaleLowerCase().includes(queryString)
const hitDesc = m.description?.replace(unifier, "").toLocaleLowerCase().includes(queryString)
return hitTitle || hitDesc
})
})
// Key Combos
const keys = useMagicKeys()
const shortcutKeyCombo = keys['Shift+Period']
const eraseKeyCombo = keys['Escape']
whenever(shortcutKeyCombo, () => {
isFocused.value = true
})
whenever(eraseKeyCombo, () => {
q.value = ""
})
/**
* Player geolocation
* Uses native JS to avoid changing leaflet library
*/
onMounted(() => {
const playerBtnRef = document.querySelector('[data-to-players]')
const flyToPlayers = new CustomEvent('fly-to', { bubbles: true, detail: players.markerCoords })
playerBtnRef?.addEventListener('click', () => {
playerBtnRef.dispatchEvent(flyToPlayers)
})
})
/**
* Marker geolocation
* We need to use onUpdated hook because the list is not always rendered, and it often rebuilt.
*/
onUpdated(() => {
const markerBtnRefs = document.querySelectorAll('[data-to-marker]')
markerBtnRefs.forEach((btn) => {
const { toMarker } = (btn as HTMLButtonElement).dataset
if (!toMarker) return
const rawCoords = toMarker?.split(',')
const detail = {
x: rawCoords[0],
y: rawCoords[1]
}
const flyToMarker = new CustomEvent('fly-to', { bubbles: true, detail })
btn.addEventListener('click', () => btn.dispatchEvent(flyToMarker))
})
})
</script>
<template>
<div ref="searchBar" class="search-w" :data-focused="shouldBeActive">
<div class="input-w">
<i class="search-icon ph-fill ph-magnifying-glass"></i>
<input ref="qInput" type="text" v-model="q">
<button data-to-players class="player-btn" tabindex="1">
<i class="pin-icon ph-fill ph-map-pin"></i>
</button>
</div>
<ul class="search-results" v-if="shouldBeActive">
<li v-for="m in filteredMarkers?.slice(0, 10)" :key="m.title">
<button class="search-item" :data-to-marker="`${m.markerCoords.x},${m.markerCoords.y}`" tabindex="0">
<span class="title">{{ m.title }}</span>
<span class="desc">{{ m.description }}</span>
</button>
</li>
</ul>
</div>
</template>
<style lang="scss" scoped>
.search-w {
margin-bottom: 1em;
padding: .5rem 1.2rem;
width: 25%;
min-width: 20rem;
background: #fff;
border: 1px solid var(--slate-400);
border-radius: 25px;
pointer-events: all;
.input-w {
$search-items-gap: .5rem;
$search-icon-size: 1.2em;
position: relative;
padding-block: .2rem;
display: flex;
align-items: center;
gap: $search-items-gap;
input {
display: block;
min-width: 10rem;
padding-inline-start: calc($search-icon-size + $search-items-gap);
flex-grow: 1;
}
.search-icon {
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
font-size: $search-icon-size;
color: var(--slate-400);
pointer-events: none;
}
.player-btn {
aspect-ratio: 1 / 1;
line-height: 1;
font-size: 1.5em;
color: #dc2626;
border-radius: 50%;
cursor: pointer;
}
}
.search-results {
max-height: 50vh;
overflow-y: auto;
scrollbar-gutter: stable;
&::-webkit-scrollbar,
&::-webkit-scrollbar-thumb {
width: 26px;
border-radius: 13px;
background-clip: padding-box;
border: 10px solid transparent;
}
&::-webkit-scrollbar-thumb {
background-color: var(--slate-300);
}
> * + * {
margin-bottom: .33rem;
}
.search-item {
cursor: pointer;
padding: .4rem .25em;
width: 100%;
outline-offset: -1px;
&:hover {
background-color: var(--slate-100);
.title {
text-decoration: underline;
}
}
&:focus-visible {
outline: 1px dotted var(--slate-500);
outline: 4px auto var(--slate-900);
.title {
text-decoration: underline;
}
}
.title,
.desc {
display: block;
font-size: .85em;
}
.title {
font-weight: 500;
text-underline-offset: 2px;
}
.desc {
color: var(--slate-500);
}
}
}
&[data-focused="true"] {
.input-w {
border-bottom: 1px solid var(--slate-200);
margin-bottom: .5rem;
padding-bottom: .5rem;
input {
padding-block-start: .2rem;
}
}
}
}
</style>

View File

@@ -0,0 +1,21 @@
import { deepMap, onMount, task, action } from 'nanostores'
import type { MapCoords, MapMarker } from '../../types/Leaflet';
export const $world = deepMap({
markers: [] as MapMarker[],
players: {} as MapMarker,
})
// Fetch initial data
onMount($world, () => {
// Fetch all markers
task(async () => {
const m = await fetch('http://localhost:4321/api/markers.json')
$world.setKey('markers', await m.json())
})
// Fetch all player data
task(async () => {
const p = await fetch('http://localhost:4321/api/players.json')
$world.setKey('players', await p.json())
})
})

View File

@@ -23,6 +23,8 @@ const { title } = Astro.props;
<meta name="msapplication-TileColor" content="#00aba9">
<meta name="theme-color" content="#a9d1eb">
<script is:inline src="https://unpkg.com/@phosphor-icons/web"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<script is:inline src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="">
</script>

View File

@@ -1,6 +1,6 @@
import type { MapMarker } from "@/types/Leaflet";
export const allianceMarkers: MapMarker[] = [
export const worldMarkers: MapMarker[] = [
{
group: "capitals",
title: "Ambrose",

View File

@@ -1,8 +1,8 @@
import type { APIRoute } from "astro";
import { allianceMarkers } from "./data/alliance.markers";
import { worldMarkers } from "./data/world.markers";
export const GET: APIRoute = ({ params, request }) => {
return new Response(
JSON.stringify(allianceMarkers)
JSON.stringify(worldMarkers)
)
}

View File

@@ -1,6 +1,7 @@
---
import Layout from '../layouts/Layout.astro';
import AllianceKaldelienne from '../components/maps/AllianceKaldelienne.astro'
import WorldMap from '../components/maps/WorldMap.astro'
import WorldMapOverlay from '../components/maps/WorldMapOverlay.astro'
const fetchLandMarkers = await fetch('http://localhost:4321/api/markers.json');
const fetchPlayersPosition = await fetch('http://localhost:4321/api/players.json');
@@ -9,5 +10,6 @@ const playerCoords = await fetchPlayersPosition.json();
---
<Layout title="Cartographie">
<AllianceKaldelienne markers={landData} players={playerCoords} />
<WorldMapOverlay markers={landData} players={playerCoords} />
<WorldMap markers={landData} players={playerCoords} />
</Layout>

View File

@@ -1,11 +1,12 @@
export type MapMarkerGroup = "capitals" | "cities" | "towns" | "landmarks";
export type MapMarker = {
title: string,
markerCoords: {
export type MapCoords = {
x: number,
y: number,
}
export type MapMarker = {
title: string,
markerCoords: MapCoords,
description?: string,
link?: string,
group?: MapMarkerGroup,
@@ -13,10 +14,7 @@ export type MapMarker = {
export type PlayerMarker = {
title: string,
markerCoords: {
x: number,
y: number,
}
markerCoords: MapCoords,
description?: string,
link?: string,
}

View File

@@ -3,7 +3,10 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
}
"@/*": [
"src/*"
]
},
"jsx": "preserve"
}
}