partial migration to Deno
This commit is contained in:
parent
862174a8bb
commit
f5df5841bc
|
|
@ -0,0 +1,38 @@
|
|||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
# Make sure that you set these permissions
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Setup repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Deno
|
||||
uses: denoland/setup-deno@v1
|
||||
|
||||
- name: Build
|
||||
run: deno task build
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: "./demo/dist"
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
dist
|
||||
.vite
|
||||
node_modules
|
||||
dist
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
11
README.md
11
README.md
|
|
@ -10,6 +10,17 @@
|
|||
- How can we compose together live and visual programming notations?
|
||||
- Can we have lightweight visual and live scripting for web pages?
|
||||
|
||||
## Development
|
||||
|
||||
1. Install [Deno](https://docs.deno.com/runtime/getting_started/installation/)
|
||||
|
||||
```bash
|
||||
deno i
|
||||
# then
|
||||
deno task dev
|
||||
```
|
||||
All config is in `deno.json`.
|
||||
|
||||
## Primitives
|
||||
|
||||
- `<fc-geometry>`: Manipulate HTML elements in space.
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { FolkGeometry } from '../../src/canvas/fc-geometry.ts';
|
||||
import { FolkConnection } from '../../src/arrows/fc-connection.ts';
|
||||
import { FileSaver } from '../../src/persistence/file.ts';
|
||||
import { FolkGeometry } from "../../src/canvas/fc-geometry.ts";
|
||||
import { FolkConnection } from "../../src/arrows/fc-connection.ts";
|
||||
import { FileSaver } from "../../src/persistence/file.ts";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'fc-thought': FolkThought;
|
||||
"fc-thought": FolkThought;
|
||||
}
|
||||
}
|
||||
|
||||
class FolkThought extends HTMLElement {
|
||||
static tagName = 'fc-thought';
|
||||
static tagName = "fc-thought";
|
||||
|
||||
static register() {
|
||||
customElements.define(this.tagName, this);
|
||||
|
|
@ -25,7 +25,7 @@ class FolkThought extends HTMLElement {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.addEventListener('click', this);
|
||||
this.addEventListener("click", this);
|
||||
}
|
||||
|
||||
get text() {
|
||||
|
|
@ -33,7 +33,7 @@ class FolkThought extends HTMLElement {
|
|||
}
|
||||
|
||||
handleEvent(event: PointerEvent): void {
|
||||
if (event.type === 'click' && event.target === this.#deleteButton) {
|
||||
if (event.type === "click" && event.target === this.#deleteButton) {
|
||||
this.#geometry.remove();
|
||||
|
||||
document
|
||||
|
|
@ -91,14 +91,14 @@ function renderConnection({ sourceId, targetId }: Connection) {
|
|||
}
|
||||
|
||||
function renderChainOfThought({ thoughts, connections }: ChainOfThought) {
|
||||
return html`${thoughts.map(renderThought).join('')}${connections
|
||||
return html`${thoughts.map(renderThought).join("")}${connections
|
||||
.map(renderConnection)
|
||||
.join('')}`;
|
||||
.join("")}`;
|
||||
}
|
||||
|
||||
function parseChainOfThought(): ChainOfThought {
|
||||
return {
|
||||
thoughts: Array.from(document.querySelectorAll('fc-geometry')).map(
|
||||
thoughts: Array.from(document.querySelectorAll("fc-geometry")).map(
|
||||
(el) => ({
|
||||
id: el.id,
|
||||
text: (el.firstElementChild as FolkThought).text,
|
||||
|
|
@ -106,7 +106,7 @@ function parseChainOfThought(): ChainOfThought {
|
|||
y: el.y,
|
||||
})
|
||||
),
|
||||
connections: Array.from(document.querySelectorAll('fc-connection')).map(
|
||||
connections: Array.from(document.querySelectorAll("fc-connection")).map(
|
||||
(el) => ({
|
||||
sourceId: (el.sourceElement as FolkGeometry).id,
|
||||
targetId: (el.targetElement as FolkGeometry).id,
|
||||
|
|
@ -118,20 +118,20 @@ function parseChainOfThought(): ChainOfThought {
|
|||
const openButton = document.querySelector('button[name="open"]')!;
|
||||
const saveButton = document.querySelector('button[name="save"]')!;
|
||||
const saveAsButton = document.querySelector('button[name="save-as"]')!;
|
||||
const main = document.querySelector('main')!;
|
||||
const main = document.querySelector("main")!;
|
||||
const fileSaver = new FileSaver(
|
||||
'chains-of-thought',
|
||||
'json',
|
||||
'application/json'
|
||||
"chains-of-thought",
|
||||
"json",
|
||||
"application/json"
|
||||
);
|
||||
|
||||
main.addEventListener('dblclick', (e) => {
|
||||
main.addEventListener("dblclick", (e) => {
|
||||
if (e.target === main) {
|
||||
main.appendChild(
|
||||
parseHTML(
|
||||
renderThought({
|
||||
id: String(document.querySelectorAll('fc-thought').length + 1),
|
||||
text: '',
|
||||
id: String(document.querySelectorAll("fc-thought").length + 1),
|
||||
text: "",
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
})
|
||||
|
|
@ -151,20 +151,20 @@ async function openFile(showPicker = true) {
|
|||
}
|
||||
}
|
||||
|
||||
async function saveFile(promptNewFile = false) {
|
||||
function saveFile(promptNewFile = false) {
|
||||
const file = JSON.stringify(parseChainOfThought(), null, 2);
|
||||
fileSaver.save(file, promptNewFile);
|
||||
}
|
||||
|
||||
openButton.addEventListener('click', () => {
|
||||
openButton.addEventListener("click", () => {
|
||||
openFile();
|
||||
});
|
||||
|
||||
saveButton.addEventListener('click', () => {
|
||||
saveButton.addEventListener("click", () => {
|
||||
saveFile();
|
||||
});
|
||||
|
||||
saveAsButton.addEventListener('click', () => {
|
||||
saveAsButton.addEventListener("click", () => {
|
||||
saveFile(true);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import { resolve } from 'node:path';
|
||||
import { readdirSync } from 'node:fs';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
target: 'esnext',
|
||||
rollupOptions: {
|
||||
input: readdirSync(__dirname)
|
||||
.filter((file) => file.endsWith('.html'))
|
||||
.reduce((acc, file) => {
|
||||
acc[file.replace('.html', '')] = resolve(__dirname, file);
|
||||
return acc;
|
||||
}, {} as Record<string, string>),
|
||||
// input: {
|
||||
// thoughts: resolve(__dirname, 'chains-of-thought/index.html'),
|
||||
// },
|
||||
},
|
||||
modulePreload: {
|
||||
polyfill: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"tasks": {
|
||||
"dev": "vite demo",
|
||||
"build": "vite build demo --outDir dist"
|
||||
},
|
||||
"imports": {
|
||||
"perfect-arrows": "npm:perfect-arrows@^0.3.7",
|
||||
"perfect-freehand": "npm:perfect-freehand@^1.2.2",
|
||||
"leaflet": "npm:leaflet@^1.9.4",
|
||||
"vite": "npm:vite@^5.4.10"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"dom.asynciterable",
|
||||
"deno.ns"
|
||||
]
|
||||
},
|
||||
"nodeModulesDir": "auto"
|
||||
}
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
{
|
||||
"version": "4",
|
||||
"specifiers": {
|
||||
"npm:leaflet@^1.9.4": "1.9.4",
|
||||
"npm:perfect-arrows@~0.3.7": "0.3.7",
|
||||
"npm:perfect-freehand@^1.2.2": "1.2.2",
|
||||
"npm:vite@5.4.10": "5.4.10",
|
||||
"npm:vite@^5.4.10": "5.4.10"
|
||||
},
|
||||
"npm": {
|
||||
"@esbuild/aix-ppc64@0.21.5": {
|
||||
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="
|
||||
},
|
||||
"@esbuild/android-arm64@0.21.5": {
|
||||
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="
|
||||
},
|
||||
"@esbuild/android-arm@0.21.5": {
|
||||
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="
|
||||
},
|
||||
"@esbuild/android-x64@0.21.5": {
|
||||
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="
|
||||
},
|
||||
"@esbuild/darwin-arm64@0.21.5": {
|
||||
"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="
|
||||
},
|
||||
"@esbuild/darwin-x64@0.21.5": {
|
||||
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="
|
||||
},
|
||||
"@esbuild/freebsd-arm64@0.21.5": {
|
||||
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="
|
||||
},
|
||||
"@esbuild/freebsd-x64@0.21.5": {
|
||||
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="
|
||||
},
|
||||
"@esbuild/linux-arm64@0.21.5": {
|
||||
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="
|
||||
},
|
||||
"@esbuild/linux-arm@0.21.5": {
|
||||
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="
|
||||
},
|
||||
"@esbuild/linux-ia32@0.21.5": {
|
||||
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="
|
||||
},
|
||||
"@esbuild/linux-loong64@0.21.5": {
|
||||
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="
|
||||
},
|
||||
"@esbuild/linux-mips64el@0.21.5": {
|
||||
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="
|
||||
},
|
||||
"@esbuild/linux-ppc64@0.21.5": {
|
||||
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="
|
||||
},
|
||||
"@esbuild/linux-riscv64@0.21.5": {
|
||||
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="
|
||||
},
|
||||
"@esbuild/linux-s390x@0.21.5": {
|
||||
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="
|
||||
},
|
||||
"@esbuild/linux-x64@0.21.5": {
|
||||
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="
|
||||
},
|
||||
"@esbuild/netbsd-x64@0.21.5": {
|
||||
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="
|
||||
},
|
||||
"@esbuild/openbsd-x64@0.21.5": {
|
||||
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="
|
||||
},
|
||||
"@esbuild/sunos-x64@0.21.5": {
|
||||
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="
|
||||
},
|
||||
"@esbuild/win32-arm64@0.21.5": {
|
||||
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="
|
||||
},
|
||||
"@esbuild/win32-ia32@0.21.5": {
|
||||
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="
|
||||
},
|
||||
"@esbuild/win32-x64@0.21.5": {
|
||||
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="
|
||||
},
|
||||
"@rollup/rollup-android-arm-eabi@4.24.3": {
|
||||
"integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ=="
|
||||
},
|
||||
"@rollup/rollup-android-arm64@4.24.3": {
|
||||
"integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q=="
|
||||
},
|
||||
"@rollup/rollup-darwin-arm64@4.24.3": {
|
||||
"integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w=="
|
||||
},
|
||||
"@rollup/rollup-darwin-x64@4.24.3": {
|
||||
"integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow=="
|
||||
},
|
||||
"@rollup/rollup-freebsd-arm64@4.24.3": {
|
||||
"integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A=="
|
||||
},
|
||||
"@rollup/rollup-freebsd-x64@4.24.3": {
|
||||
"integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg=="
|
||||
},
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.24.3": {
|
||||
"integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A=="
|
||||
},
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.24.3": {
|
||||
"integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw=="
|
||||
},
|
||||
"@rollup/rollup-linux-arm64-gnu@4.24.3": {
|
||||
"integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ=="
|
||||
},
|
||||
"@rollup/rollup-linux-arm64-musl@4.24.3": {
|
||||
"integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw=="
|
||||
},
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.24.3": {
|
||||
"integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g=="
|
||||
},
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.24.3": {
|
||||
"integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA=="
|
||||
},
|
||||
"@rollup/rollup-linux-s390x-gnu@4.24.3": {
|
||||
"integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw=="
|
||||
},
|
||||
"@rollup/rollup-linux-x64-gnu@4.24.3": {
|
||||
"integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ=="
|
||||
},
|
||||
"@rollup/rollup-linux-x64-musl@4.24.3": {
|
||||
"integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw=="
|
||||
},
|
||||
"@rollup/rollup-win32-arm64-msvc@4.24.3": {
|
||||
"integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA=="
|
||||
},
|
||||
"@rollup/rollup-win32-ia32-msvc@4.24.3": {
|
||||
"integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ=="
|
||||
},
|
||||
"@rollup/rollup-win32-x64-msvc@4.24.3": {
|
||||
"integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ=="
|
||||
},
|
||||
"@types/estree@1.0.6": {
|
||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
||||
},
|
||||
"esbuild@0.21.5": {
|
||||
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
||||
"dependencies": [
|
||||
"@esbuild/aix-ppc64",
|
||||
"@esbuild/android-arm",
|
||||
"@esbuild/android-arm64",
|
||||
"@esbuild/android-x64",
|
||||
"@esbuild/darwin-arm64",
|
||||
"@esbuild/darwin-x64",
|
||||
"@esbuild/freebsd-arm64",
|
||||
"@esbuild/freebsd-x64",
|
||||
"@esbuild/linux-arm",
|
||||
"@esbuild/linux-arm64",
|
||||
"@esbuild/linux-ia32",
|
||||
"@esbuild/linux-loong64",
|
||||
"@esbuild/linux-mips64el",
|
||||
"@esbuild/linux-ppc64",
|
||||
"@esbuild/linux-riscv64",
|
||||
"@esbuild/linux-s390x",
|
||||
"@esbuild/linux-x64",
|
||||
"@esbuild/netbsd-x64",
|
||||
"@esbuild/openbsd-x64",
|
||||
"@esbuild/sunos-x64",
|
||||
"@esbuild/win32-arm64",
|
||||
"@esbuild/win32-ia32",
|
||||
"@esbuild/win32-x64"
|
||||
]
|
||||
},
|
||||
"fsevents@2.3.3": {
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="
|
||||
},
|
||||
"leaflet@1.9.4": {
|
||||
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||
},
|
||||
"nanoid@3.3.7": {
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
|
||||
},
|
||||
"perfect-arrows@0.3.7": {
|
||||
"integrity": "sha512-wEN2gerTPVWl3yqoFEF8OeGbg3aRe2sxNUi9rnyYrCsL4JcI6K2tBDezRtqVrYG0BNtsWLdYiiTrYm+X//8yLQ=="
|
||||
},
|
||||
"perfect-freehand@1.2.2": {
|
||||
"integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ=="
|
||||
},
|
||||
"picocolors@1.1.0": {
|
||||
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw=="
|
||||
},
|
||||
"postcss@8.4.47": {
|
||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||
"dependencies": [
|
||||
"nanoid",
|
||||
"picocolors",
|
||||
"source-map-js"
|
||||
]
|
||||
},
|
||||
"rollup@4.24.3": {
|
||||
"integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==",
|
||||
"dependencies": [
|
||||
"@rollup/rollup-android-arm-eabi",
|
||||
"@rollup/rollup-android-arm64",
|
||||
"@rollup/rollup-darwin-arm64",
|
||||
"@rollup/rollup-darwin-x64",
|
||||
"@rollup/rollup-freebsd-arm64",
|
||||
"@rollup/rollup-freebsd-x64",
|
||||
"@rollup/rollup-linux-arm-gnueabihf",
|
||||
"@rollup/rollup-linux-arm-musleabihf",
|
||||
"@rollup/rollup-linux-arm64-gnu",
|
||||
"@rollup/rollup-linux-arm64-musl",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu",
|
||||
"@rollup/rollup-linux-riscv64-gnu",
|
||||
"@rollup/rollup-linux-s390x-gnu",
|
||||
"@rollup/rollup-linux-x64-gnu",
|
||||
"@rollup/rollup-linux-x64-musl",
|
||||
"@rollup/rollup-win32-arm64-msvc",
|
||||
"@rollup/rollup-win32-ia32-msvc",
|
||||
"@rollup/rollup-win32-x64-msvc",
|
||||
"@types/estree",
|
||||
"fsevents"
|
||||
]
|
||||
},
|
||||
"source-map-js@1.2.1": {
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
|
||||
},
|
||||
"vite@5.4.10": {
|
||||
"integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==",
|
||||
"dependencies": [
|
||||
"esbuild",
|
||||
"fsevents",
|
||||
"postcss",
|
||||
"rollup"
|
||||
]
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"npm:leaflet@^1.9.4",
|
||||
"npm:perfect-arrows@~0.3.7",
|
||||
"npm:perfect-freehand@^1.2.2",
|
||||
"npm:vite@^5.4.10"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,874 +0,0 @@
|
|||
{
|
||||
"name": "folk-canvas",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "folk-canvas",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"leaflet": "^1.9.4",
|
||||
"perfect-arrows": "^0.3.7",
|
||||
"perfect-freehand": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/leaflet": "^1.9.12",
|
||||
"@types/node": "^20.12.7",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||
"integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
|
||||
"integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
|
||||
"integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
|
||||
"integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
|
||||
"integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
|
||||
"integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
|
||||
"integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
|
||||
"integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
|
||||
"integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
|
||||
"integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
|
||||
"integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
|
||||
"integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
|
||||
"integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz",
|
||||
"integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz",
|
||||
"integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz",
|
||||
"integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz",
|
||||
"integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz",
|
||||
"integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz",
|
||||
"integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz",
|
||||
"integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz",
|
||||
"integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz",
|
||||
"integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz",
|
||||
"integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz",
|
||||
"integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz",
|
||||
"integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz",
|
||||
"integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz",
|
||||
"integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz",
|
||||
"integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/geojson": {
|
||||
"version": "7946.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
|
||||
"integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/leaflet": {
|
||||
"version": "1.9.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz",
|
||||
"integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.15.0.tgz",
|
||||
"integrity": "sha512-eQf4OkH6gA9v1W0iEpht/neozCsZKMTK+C4cU6/fv7wtJCCL8LEQ4hie2Ln8ZP/0YYM2xGj7//f8xyqItkJ6QA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.21.5",
|
||||
"@esbuild/android-arm": "0.21.5",
|
||||
"@esbuild/android-arm64": "0.21.5",
|
||||
"@esbuild/android-x64": "0.21.5",
|
||||
"@esbuild/darwin-arm64": "0.21.5",
|
||||
"@esbuild/darwin-x64": "0.21.5",
|
||||
"@esbuild/freebsd-arm64": "0.21.5",
|
||||
"@esbuild/freebsd-x64": "0.21.5",
|
||||
"@esbuild/linux-arm": "0.21.5",
|
||||
"@esbuild/linux-arm64": "0.21.5",
|
||||
"@esbuild/linux-ia32": "0.21.5",
|
||||
"@esbuild/linux-loong64": "0.21.5",
|
||||
"@esbuild/linux-mips64el": "0.21.5",
|
||||
"@esbuild/linux-ppc64": "0.21.5",
|
||||
"@esbuild/linux-riscv64": "0.21.5",
|
||||
"@esbuild/linux-s390x": "0.21.5",
|
||||
"@esbuild/linux-x64": "0.21.5",
|
||||
"@esbuild/netbsd-x64": "0.21.5",
|
||||
"@esbuild/openbsd-x64": "0.21.5",
|
||||
"@esbuild/sunos-x64": "0.21.5",
|
||||
"@esbuild/win32-arm64": "0.21.5",
|
||||
"@esbuild/win32-ia32": "0.21.5",
|
||||
"@esbuild/win32-x64": "0.21.5"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/leaflet": {
|
||||
"version": "1.9.4",
|
||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/perfect-arrows": {
|
||||
"version": "0.3.7",
|
||||
"resolved": "https://registry.npmjs.org/perfect-arrows/-/perfect-arrows-0.3.7.tgz",
|
||||
"integrity": "sha512-wEN2gerTPVWl3yqoFEF8OeGbg3aRe2sxNUi9rnyYrCsL4JcI6K2tBDezRtqVrYG0BNtsWLdYiiTrYm+X//8yLQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/perfect-freehand": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/perfect-freehand/-/perfect-freehand-1.2.2.tgz",
|
||||
"integrity": "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ=="
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
|
||||
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.47",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
|
||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.1.0",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.22.4",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz",
|
||||
"integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.22.4",
|
||||
"@rollup/rollup-android-arm64": "4.22.4",
|
||||
"@rollup/rollup-darwin-arm64": "4.22.4",
|
||||
"@rollup/rollup-darwin-x64": "4.22.4",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.22.4",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.22.4",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.22.4",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.22.4",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.22.4",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.22.4",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.22.4",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.22.4",
|
||||
"@rollup/rollup-linux-x64-musl": "4.22.4",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.22.4",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.22.4",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.22.4",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.5.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
|
||||
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz",
|
||||
"integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.6",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz",
|
||||
"integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
"rollup": "^4.20.0"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/vitejs/vite?sponsor=1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^18.0.0 || >=20.0.0",
|
||||
"less": "*",
|
||||
"lightningcss": "^1.21.0",
|
||||
"sass": "*",
|
||||
"sass-embedded": "*",
|
||||
"stylus": "*",
|
||||
"sugarss": "*",
|
||||
"terser": "^5.4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
},
|
||||
"less": {
|
||||
"optional": true
|
||||
},
|
||||
"lightningcss": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass-embedded": {
|
||||
"optional": true
|
||||
},
|
||||
"stylus": {
|
||||
"optional": true
|
||||
},
|
||||
"sugarss": {
|
||||
"optional": true
|
||||
},
|
||||
"terser": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
package.json
42
package.json
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"name": "folk-canvas",
|
||||
"description": "",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"author": "Christopher Shank <chris.shank.23@gmail.com>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ChrisShank/folk-canvas.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ChrisShank/folk-canvas/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ChrisShank/folk-canvas#readme",
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"keywords": [
|
||||
"spatial canvas",
|
||||
"custom elements"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc --build",
|
||||
"dev": "vite demo",
|
||||
"demo:build": "vite build demo",
|
||||
"demo:preview": "pnpm demo:build && vite preview demo"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/leaflet": "^1.9.12",
|
||||
"@types/node": "^20.12.7",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"leaflet": "^1.9.4",
|
||||
"perfect-arrows": "^0.3.7",
|
||||
"perfect-freehand": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { FolkConnection } from './fc-connection';
|
||||
import { FolkConnection } from "./fc-connection.ts";
|
||||
|
||||
export class EventPropagator extends FolkConnection {
|
||||
static tagName = 'event-propagator';
|
||||
static override tagName = "event-propagator";
|
||||
|
||||
#triggers = (this.getAttribute('triggers') || '').split(',');
|
||||
#triggers = (this.getAttribute("triggers") || "").split(",");
|
||||
get triggers() {
|
||||
return this.#triggers;
|
||||
}
|
||||
|
|
@ -11,23 +11,23 @@ export class EventPropagator extends FolkConnection {
|
|||
this.#triggers = triggers;
|
||||
}
|
||||
|
||||
#expression = '';
|
||||
#expression = "";
|
||||
#function = new Function();
|
||||
get expression() {
|
||||
return this.#expression;
|
||||
}
|
||||
set expression(expression) {
|
||||
this.#expression = expression;
|
||||
this.#function = new Function('$source', '$target', '$event', expression);
|
||||
this.#function = new Function("$source", "$target", "$event", expression);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.expression = this.getAttribute('expression') || '';
|
||||
this.expression = this.getAttribute("expression") || "";
|
||||
}
|
||||
|
||||
observeSource() {
|
||||
override observeSource() {
|
||||
super.observeSource();
|
||||
|
||||
for (const trigger of this.#triggers) {
|
||||
|
|
@ -38,7 +38,7 @@ export class EventPropagator extends FolkConnection {
|
|||
this.evaluateExpression();
|
||||
}
|
||||
|
||||
unobserveSource() {
|
||||
override unobserveSource() {
|
||||
super.unobserveSource();
|
||||
|
||||
for (const trigger of this.#triggers) {
|
||||
|
|
@ -47,12 +47,12 @@ export class EventPropagator extends FolkConnection {
|
|||
}
|
||||
}
|
||||
|
||||
observeTarget() {
|
||||
override observeTarget() {
|
||||
super.observeTarget();
|
||||
this.evaluateExpression();
|
||||
}
|
||||
|
||||
unobserveTarget() {
|
||||
override unobserveTarget() {
|
||||
super.unobserveTarget();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { getBoxToBoxArrow } from 'perfect-arrows';
|
||||
import { AbstractArrow } from './abstract-arrow';
|
||||
import { pointsOnBezierCurves } from './points-on-path';
|
||||
import getStroke, { StrokeOptions } from 'perfect-freehand';
|
||||
import { getBoxToBoxArrow } from "perfect-arrows";
|
||||
import { AbstractArrow } from "./abstract-arrow.ts";
|
||||
import { pointsOnBezierCurves } from "./points-on-path.ts";
|
||||
import { getStroke, StrokeOptions } from "perfect-freehand";
|
||||
|
||||
export type Arrow = [
|
||||
/** The x position of the (padded) starting point. */
|
||||
|
|
@ -26,12 +26,12 @@ export type Arrow = [
|
|||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'fc-connection': FolkConnection;
|
||||
"fc-connection": FolkConnection;
|
||||
}
|
||||
}
|
||||
|
||||
export class FolkConnection extends AbstractArrow {
|
||||
static tagName = 'fc-connection';
|
||||
static override tagName = "fc-connection";
|
||||
|
||||
#options: StrokeOptions = {
|
||||
size: 7,
|
||||
|
|
@ -53,7 +53,7 @@ export class FolkConnection extends AbstractArrow {
|
|||
},
|
||||
};
|
||||
|
||||
render() {
|
||||
override render() {
|
||||
const { sourceRect, targetRect } = this;
|
||||
|
||||
const [sx, sy, cx, cy, ex, ey] = getBoxToBoxArrow(
|
||||
|
|
@ -77,12 +77,12 @@ export class FolkConnection extends AbstractArrow {
|
|||
const stroke = getStroke(points, this.#options);
|
||||
const path = getSvgPathFromStroke(stroke);
|
||||
this.style.clipPath = `path('${path}')`;
|
||||
this.style.backgroundColor = 'black';
|
||||
this.style.backgroundColor = "black";
|
||||
}
|
||||
}
|
||||
|
||||
function getSvgPathFromStroke(stroke: number[][]): string {
|
||||
if (stroke.length === 0) return '';
|
||||
if (stroke.length === 0) return "";
|
||||
|
||||
for (const point of stroke) {
|
||||
point[0] = Math.round(point[0] * 100) / 100;
|
||||
|
|
@ -95,9 +95,9 @@ function getSvgPathFromStroke(stroke: number[][]): string {
|
|||
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
|
||||
return acc;
|
||||
},
|
||||
['M', ...stroke[0], 'Q']
|
||||
["M", ...stroke[0], "Q"]
|
||||
);
|
||||
|
||||
d.push('Z');
|
||||
return d.join(' ');
|
||||
d.push("Z");
|
||||
return d.join(" ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class ResizeObserverManager {
|
|||
}
|
||||
|
||||
unobserve(target: Element, callback: ResizeObserverEntryCallback): void {
|
||||
let callbacks = this.#elementMap.get(target);
|
||||
const callbacks = this.#elementMap.get(target);
|
||||
|
||||
if (callbacks === undefined) return;
|
||||
|
||||
|
|
@ -45,13 +45,13 @@ class ResizeObserverManager {
|
|||
|
||||
const resizeObserver = new ResizeObserverManager();
|
||||
|
||||
export type Shape = 'rectangle' | 'circle' | 'triangle';
|
||||
export type Shape = "rectangle" | "circle" | "triangle";
|
||||
|
||||
export type MoveEventDetail = { movementX: number; movementY: number };
|
||||
|
||||
export class MoveEvent extends CustomEvent<MoveEventDetail> {
|
||||
constructor(detail: MoveEventDetail) {
|
||||
super('move', { detail, cancelable: true, bubbles: true });
|
||||
super("move", { detail, cancelable: true, bubbles: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ export type ResizeEventDetail = { movementX: number; movementY: number };
|
|||
|
||||
export class ResizeEvent extends CustomEvent<MoveEventDetail> {
|
||||
constructor(detail: MoveEventDetail) {
|
||||
super('resize', { detail, cancelable: true, bubbles: true });
|
||||
super("resize", { detail, cancelable: true, bubbles: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,11 +67,11 @@ export type RotateEventDetail = { rotate: number };
|
|||
|
||||
export class RotateEvent extends CustomEvent<RotateEventDetail> {
|
||||
constructor(detail: RotateEventDetail) {
|
||||
super('rotate', { detail, cancelable: true, bubbles: true });
|
||||
super("rotate", { detail, cancelable: true, bubbles: true });
|
||||
}
|
||||
}
|
||||
|
||||
export type Dimension = number | 'auto';
|
||||
export type Dimension = number | "auto";
|
||||
|
||||
const styles = new CSSStyleSheet();
|
||||
styles.replaceSync(`
|
||||
|
|
@ -180,13 +180,13 @@ styles.replaceSync(`
|
|||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'fc-geometry': FolkGeometry;
|
||||
"fc-geometry": FolkGeometry;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add z coordinate?
|
||||
export class FolkGeometry extends HTMLElement {
|
||||
static tagName = 'fc-geometry';
|
||||
static tagName = "fc-geometry";
|
||||
|
||||
static register() {
|
||||
customElements.define(this.tagName, this);
|
||||
|
|
@ -194,17 +194,17 @@ export class FolkGeometry extends HTMLElement {
|
|||
|
||||
#internals = this.attachInternals();
|
||||
|
||||
#type = (this.getAttribute('type') || 'rectangle') as Shape;
|
||||
#type = (this.getAttribute("type") || "rectangle") as Shape;
|
||||
get type(): Shape {
|
||||
return this.#type;
|
||||
}
|
||||
|
||||
set type(type: Shape) {
|
||||
this.setAttribute('type', type);
|
||||
this.setAttribute("type", type);
|
||||
}
|
||||
|
||||
#previousX = 0;
|
||||
#x = Number(this.getAttribute('x')) || 0;
|
||||
#x = Number(this.getAttribute("x")) || 0;
|
||||
get x() {
|
||||
return this.#x;
|
||||
}
|
||||
|
|
@ -212,11 +212,11 @@ export class FolkGeometry extends HTMLElement {
|
|||
set x(x) {
|
||||
this.#previousX = this.#x;
|
||||
this.#x = x;
|
||||
this.#requestUpdate('x');
|
||||
this.#requestUpdate("x");
|
||||
}
|
||||
|
||||
#previousY = 0;
|
||||
#y = Number(this.getAttribute('y')) || 0;
|
||||
#y = Number(this.getAttribute("y")) || 0;
|
||||
get y() {
|
||||
return this.#y;
|
||||
}
|
||||
|
|
@ -224,7 +224,7 @@ export class FolkGeometry extends HTMLElement {
|
|||
set y(y) {
|
||||
this.#previousY = this.#y;
|
||||
this.#y = y;
|
||||
this.#requestUpdate('y');
|
||||
this.#requestUpdate("y");
|
||||
}
|
||||
|
||||
#autoContentRect = this.getBoundingClientRect();
|
||||
|
|
@ -232,48 +232,48 @@ export class FolkGeometry extends HTMLElement {
|
|||
#previousWidth: Dimension = 0;
|
||||
#width: Dimension = 0;
|
||||
get width(): number {
|
||||
if (this.#width === 'auto') {
|
||||
if (this.#width === "auto") {
|
||||
return this.#autoContentRect.width;
|
||||
}
|
||||
return this.#width;
|
||||
}
|
||||
|
||||
set width(width: Dimension) {
|
||||
if (width === 'auto') {
|
||||
if (width === "auto") {
|
||||
resizeObserver.observe(this, this.#onResize);
|
||||
} else if (this.#width === 'auto' && this.#height !== 'auto') {
|
||||
} else if (this.#width === "auto" && this.#height !== "auto") {
|
||||
resizeObserver.unobserve(this, this.#onResize);
|
||||
}
|
||||
this.#previousWidth = this.#width;
|
||||
this.#width = width;
|
||||
this.#requestUpdate('width');
|
||||
this.#requestUpdate("width");
|
||||
}
|
||||
|
||||
#previousHeight: Dimension = 0;
|
||||
#height: Dimension = 0;
|
||||
get height(): number {
|
||||
if (this.#height === 'auto') {
|
||||
if (this.#height === "auto") {
|
||||
return this.#autoContentRect.height;
|
||||
}
|
||||
return this.#height;
|
||||
}
|
||||
|
||||
set height(height: Dimension) {
|
||||
if (height === 'auto') {
|
||||
if (height === "auto") {
|
||||
resizeObserver.observe(this, this.#onResize);
|
||||
} else if (this.#height === 'auto' && this.#width !== 'auto') {
|
||||
} else if (this.#height === "auto" && this.#width !== "auto") {
|
||||
resizeObserver.unobserve(this, this.#onResize);
|
||||
}
|
||||
|
||||
this.#previousHeight = this.#height;
|
||||
this.#height = height;
|
||||
this.#requestUpdate('height');
|
||||
this.#requestUpdate("height");
|
||||
}
|
||||
|
||||
#initialRotation = 0;
|
||||
#startAngle = 0;
|
||||
#previousRotate = 0;
|
||||
#rotate = Number(this.getAttribute('rotate')) || 0;
|
||||
#rotate = Number(this.getAttribute("rotate")) || 0;
|
||||
get rotate(): number {
|
||||
return this.#rotate;
|
||||
}
|
||||
|
|
@ -281,16 +281,16 @@ export class FolkGeometry extends HTMLElement {
|
|||
set rotate(rotate: number) {
|
||||
this.#previousRotate = this.#rotate;
|
||||
this.#rotate = rotate;
|
||||
this.#requestUpdate('rotate');
|
||||
this.#requestUpdate("rotate");
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addEventListener('pointerdown', this);
|
||||
this.addEventListener("pointerdown", this);
|
||||
|
||||
const shadowRoot = this.attachShadow({
|
||||
mode: 'open',
|
||||
mode: "open",
|
||||
delegatesFocus: true,
|
||||
});
|
||||
shadowRoot.adoptedStyleSheets.push(styles);
|
||||
|
|
@ -305,12 +305,12 @@ export class FolkGeometry extends HTMLElement {
|
|||
<button part="resize-sw"></button>
|
||||
<slot></slot>`;
|
||||
|
||||
this.height = Number(this.getAttribute('height')) || 'auto';
|
||||
this.width = Number(this.getAttribute('width')) || 'auto';
|
||||
this.height = Number(this.getAttribute("height")) || "auto";
|
||||
this.width = Number(this.getAttribute("width")) || "auto";
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.#update(new Set(['type', 'x', 'y', 'height', 'width', 'rotate']));
|
||||
this.#update(new Set(["type", "x", "y", "height", "width", "rotate"]));
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
|
|
@ -319,7 +319,7 @@ export class FolkGeometry extends HTMLElement {
|
|||
|
||||
// Similar to `Element.getClientBoundingRect()`, but returns an SVG path that precisely outlines the shape.
|
||||
getBoundingPath(): string {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
// We might also want some kind of utility function that maps a path into an approximate set of vertices.
|
||||
|
|
@ -329,13 +329,13 @@ export class FolkGeometry extends HTMLElement {
|
|||
|
||||
handleEvent(event: PointerEvent) {
|
||||
switch (event.type) {
|
||||
case 'pointerdown': {
|
||||
case "pointerdown": {
|
||||
if (event.button !== 0 || event.ctrlKey) return;
|
||||
|
||||
const target = event.composedPath()[0] as HTMLElement;
|
||||
|
||||
// Store initial angle on rotation start
|
||||
if (target.getAttribute('part') === 'rotate') {
|
||||
if (target.getAttribute("part") === "rotate") {
|
||||
// We need to store initial rotation/angle somewhere.
|
||||
// This is a little awkward as we'll want to do *quite a lot* of this kind of thing.
|
||||
// Might be an argument for making elements dumber (i.e. not have them manage their own state) and do this from the outside.
|
||||
|
|
@ -351,19 +351,19 @@ export class FolkGeometry extends HTMLElement {
|
|||
}
|
||||
|
||||
// ignore interactions from slotted elements.
|
||||
if (target !== this && !target.hasAttribute('part')) return;
|
||||
if (target !== this && !target.hasAttribute("part")) return;
|
||||
|
||||
target.addEventListener('pointermove', this);
|
||||
this.addEventListener('lostpointercapture', this);
|
||||
target.addEventListener("pointermove", this);
|
||||
this.addEventListener("lostpointercapture", this);
|
||||
target.setPointerCapture(event.pointerId);
|
||||
|
||||
const interaction = target.getAttribute('part') || 'move';
|
||||
const interaction = target.getAttribute("part") || "move";
|
||||
this.#internals.states.add(interaction);
|
||||
|
||||
this.focus();
|
||||
return;
|
||||
}
|
||||
case 'pointermove': {
|
||||
case "pointermove": {
|
||||
const target = event.target as HTMLElement;
|
||||
|
||||
if (target === null) return;
|
||||
|
|
@ -374,33 +374,33 @@ export class FolkGeometry extends HTMLElement {
|
|||
return;
|
||||
}
|
||||
|
||||
const part = target.getAttribute('part');
|
||||
const part = target.getAttribute("part");
|
||||
|
||||
if (part === null) return;
|
||||
|
||||
if (part.includes('resize')) {
|
||||
if (part.includes("resize")) {
|
||||
// This triggers a move and resize event :(
|
||||
if (part.includes('-n')) {
|
||||
if (part.includes("-n")) {
|
||||
this.y += event.movementY;
|
||||
this.height -= event.movementY;
|
||||
}
|
||||
|
||||
if (part.endsWith('e')) {
|
||||
if (part.endsWith("e")) {
|
||||
this.width += event.movementX;
|
||||
}
|
||||
|
||||
if (part.includes('-s')) {
|
||||
if (part.includes("-s")) {
|
||||
this.height += event.movementY;
|
||||
}
|
||||
|
||||
if (part.endsWith('w')) {
|
||||
if (part.endsWith("w")) {
|
||||
this.x += event.movementX;
|
||||
this.width -= event.movementX;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (part === 'rotate') {
|
||||
if (part === "rotate") {
|
||||
const centerX = this.#x + this.width / 2;
|
||||
const centerY = this.#y + this.height / 2;
|
||||
const currentAngle = Math.atan2(
|
||||
|
|
@ -415,12 +415,12 @@ export class FolkGeometry extends HTMLElement {
|
|||
|
||||
return;
|
||||
}
|
||||
case 'lostpointercapture': {
|
||||
case "lostpointercapture": {
|
||||
const target = event.composedPath()[0] as HTMLElement;
|
||||
const interaction = target.getAttribute('part') || 'move';
|
||||
const interaction = target.getAttribute("part") || "move";
|
||||
this.#internals.states.delete(interaction);
|
||||
target.removeEventListener('pointermove', this);
|
||||
this.removeEventListener('lostpointercapture', this);
|
||||
target.removeEventListener("pointermove", this);
|
||||
this.removeEventListener("lostpointercapture", this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -446,14 +446,14 @@ export class FolkGeometry extends HTMLElement {
|
|||
|
||||
// Any updates that should be batched should happen here like updating the DOM or emitting events should be executed here.
|
||||
#update(updatedProperties: Set<string>) {
|
||||
if (updatedProperties.has('type')) {
|
||||
if (updatedProperties.has("type")) {
|
||||
// TODO: Update shape styles. For many shapes, we could just use clip-path to style the shape.
|
||||
// If we use relative values in `clip-path: polygon()`, then no JS is needed to style the shape
|
||||
// If `clip-path: path()` is used then we need to update the path in JS.
|
||||
// See https://www.smashingmagazine.com/2024/05/modern-guide-making-css-shapes/
|
||||
}
|
||||
|
||||
if (updatedProperties.has('x') || updatedProperties.has('y')) {
|
||||
if (updatedProperties.has("x") || updatedProperties.has("y")) {
|
||||
// Although the change in movement isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics
|
||||
const notCancelled = this.dispatchEvent(
|
||||
new MoveEvent({
|
||||
|
|
@ -463,12 +463,12 @@ export class FolkGeometry extends HTMLElement {
|
|||
);
|
||||
|
||||
if (notCancelled) {
|
||||
if (updatedProperties.has('x')) {
|
||||
if (updatedProperties.has("x")) {
|
||||
// In the future, when CSS `attr()` is supported we could define this x/y projection in CSS.
|
||||
this.style.left = `${this.#x}px`;
|
||||
}
|
||||
|
||||
if (updatedProperties.has('y')) {
|
||||
if (updatedProperties.has("y")) {
|
||||
this.style.top = `${this.#y}px`;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -477,26 +477,26 @@ export class FolkGeometry extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
if (updatedProperties.has('width') || updatedProperties.has('height')) {
|
||||
if (updatedProperties.has("width") || updatedProperties.has("height")) {
|
||||
// Although the change in resize isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics
|
||||
const notCancelled = this.dispatchEvent(
|
||||
new ResizeEvent({
|
||||
movementX:
|
||||
this.width -
|
||||
(this.#previousWidth === 'auto' ? 0 : this.#previousWidth),
|
||||
(this.#previousWidth === "auto" ? 0 : this.#previousWidth),
|
||||
movementY:
|
||||
this.height -
|
||||
(this.#previousHeight === 'auto' ? 0 : this.#previousHeight),
|
||||
(this.#previousHeight === "auto" ? 0 : this.#previousHeight),
|
||||
})
|
||||
);
|
||||
if (notCancelled) {
|
||||
if (updatedProperties.has('width')) {
|
||||
this.style.width = this.#width === 'auto' ? '' : `${this.#width}px`;
|
||||
if (updatedProperties.has("width")) {
|
||||
this.style.width = this.#width === "auto" ? "" : `${this.#width}px`;
|
||||
}
|
||||
|
||||
if (updatedProperties.has('height')) {
|
||||
if (updatedProperties.has("height")) {
|
||||
this.style.height =
|
||||
this.#height === 'auto' ? '' : `${this.#height}px`;
|
||||
this.#height === "auto" ? "" : `${this.#height}px`;
|
||||
}
|
||||
} else {
|
||||
// TODO: Revert changes to position too
|
||||
|
|
@ -505,14 +505,14 @@ export class FolkGeometry extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
if (updatedProperties.has('rotate')) {
|
||||
if (updatedProperties.has("rotate")) {
|
||||
// Although the change in resize isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics
|
||||
const notCancelled = this.dispatchEvent(
|
||||
new RotateEvent({ rotate: this.#rotate - this.#previousRotate })
|
||||
);
|
||||
|
||||
if (notCancelled) {
|
||||
if (updatedProperties.has('rotate')) {
|
||||
if (updatedProperties.has("rotate")) {
|
||||
this.style.rotate = `${this.#rotate}deg`;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -529,23 +529,23 @@ export class FolkGeometry extends HTMLElement {
|
|||
new ResizeEvent({
|
||||
movementX:
|
||||
this.width -
|
||||
(this.#previousWidth === 'auto'
|
||||
(this.#previousWidth === "auto"
|
||||
? previousRect.width
|
||||
: this.#previousWidth),
|
||||
movementY:
|
||||
this.height -
|
||||
(this.#previousHeight === 'auto'
|
||||
(this.#previousHeight === "auto"
|
||||
? previousRect.height
|
||||
: this.#previousHeight),
|
||||
})
|
||||
);
|
||||
|
||||
if (!notCancelled) {
|
||||
if (this.#height === 'auto') {
|
||||
if (this.#height === "auto") {
|
||||
this.height = previousRect?.height || 0;
|
||||
}
|
||||
|
||||
if (this.#width === 'auto') {
|
||||
if (this.#width === "auto") {
|
||||
this.width = previousRect?.width || 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import getStroke, { StrokeOptions } from 'perfect-freehand';
|
||||
import { getStroke, StrokeOptions } from "perfect-freehand";
|
||||
|
||||
export type Point = [x: number, y: number, pressure: number];
|
||||
|
||||
|
|
@ -25,12 +25,12 @@ styles.replaceSync(`
|
|||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'fc-ink': FolkInk;
|
||||
"fc-ink": FolkInk;
|
||||
}
|
||||
}
|
||||
|
||||
export class FolkInk extends HTMLElement {
|
||||
static tagName = 'fc-ink';
|
||||
static tagName = "fc-ink";
|
||||
|
||||
static register() {
|
||||
customElements.define(this.tagName, this);
|
||||
|
|
@ -38,10 +38,10 @@ export class FolkInk extends HTMLElement {
|
|||
|
||||
#internals = this.attachInternals();
|
||||
|
||||
#svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
#path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||
#svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
#path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||
|
||||
#size = Number(this.getAttribute('size') || 16);
|
||||
#size = Number(this.getAttribute("size") || 16);
|
||||
|
||||
get size() {
|
||||
return this.#size;
|
||||
|
|
@ -51,7 +51,7 @@ export class FolkInk extends HTMLElement {
|
|||
this.#update();
|
||||
}
|
||||
|
||||
#thinning = Number(this.getAttribute('thinning') || 0.5);
|
||||
#thinning = Number(this.getAttribute("thinning") || 0.5);
|
||||
|
||||
get thinning() {
|
||||
return this.#thinning;
|
||||
|
|
@ -61,7 +61,7 @@ export class FolkInk extends HTMLElement {
|
|||
this.#update();
|
||||
}
|
||||
|
||||
#smoothing = Number(this.getAttribute('smoothing') || 0.5);
|
||||
#smoothing = Number(this.getAttribute("smoothing") || 0.5);
|
||||
|
||||
get smoothing() {
|
||||
return this.#smoothing;
|
||||
|
|
@ -71,7 +71,7 @@ export class FolkInk extends HTMLElement {
|
|||
this.#update();
|
||||
}
|
||||
|
||||
#streamline = Number(this.getAttribute('streamline') || 0.5);
|
||||
#streamline = Number(this.getAttribute("streamline") || 0.5);
|
||||
|
||||
get streamline() {
|
||||
return this.#streamline;
|
||||
|
|
@ -82,7 +82,7 @@ export class FolkInk extends HTMLElement {
|
|||
}
|
||||
|
||||
#simulatePressure =
|
||||
this.getAttribute('streamline') === 'false' ? false : true;
|
||||
this.getAttribute("streamline") === "false" ? false : true;
|
||||
|
||||
get simulatePressure() {
|
||||
return this.#simulatePressure;
|
||||
|
|
@ -92,7 +92,7 @@ export class FolkInk extends HTMLElement {
|
|||
this.#update();
|
||||
}
|
||||
|
||||
#points: Point[] = JSON.parse(this.getAttribute('points') || '[]');
|
||||
#points: Point[] = JSON.parse(this.getAttribute("points") || "[]");
|
||||
|
||||
get points() {
|
||||
return this.#points;
|
||||
|
|
@ -106,7 +106,7 @@ export class FolkInk extends HTMLElement {
|
|||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({
|
||||
mode: 'open',
|
||||
mode: "open",
|
||||
delegatesFocus: true,
|
||||
});
|
||||
shadowRoot.adoptedStyleSheets.push(styles);
|
||||
|
|
@ -130,10 +130,10 @@ export class FolkInk extends HTMLElement {
|
|||
|
||||
// TODO: cancel trace?
|
||||
draw(event?: PointerEvent) {
|
||||
if (event?.type === 'pointerdown') {
|
||||
if (event?.type === "pointerdown") {
|
||||
this.handleEvent(event);
|
||||
} else {
|
||||
this.addEventListener('pointerdown', this);
|
||||
this.addEventListener("pointerdown", this);
|
||||
}
|
||||
this.#tracingPromise = Promise.withResolvers();
|
||||
return this.#tracingPromise.promise;
|
||||
|
|
@ -146,26 +146,26 @@ export class FolkInk extends HTMLElement {
|
|||
|
||||
handleEvent(event: PointerEvent) {
|
||||
switch (event.type) {
|
||||
case 'pointerdown': {
|
||||
case "pointerdown": {
|
||||
if (event.button !== 0 || event.ctrlKey) return;
|
||||
|
||||
this.points = [];
|
||||
this.addPoint([event.offsetX, event.offsetY, event.pressure]);
|
||||
this.addEventListener('lostpointercapture', this);
|
||||
this.addEventListener('pointermove', this);
|
||||
this.addEventListener("lostpointercapture", this);
|
||||
this.addEventListener("pointermove", this);
|
||||
this.setPointerCapture(event.pointerId);
|
||||
this.#internals.states.add('drawing');
|
||||
this.#internals.states.add("drawing");
|
||||
return;
|
||||
}
|
||||
case 'pointermove': {
|
||||
case "pointermove": {
|
||||
this.addPoint([event.offsetX, event.offsetY, event.pressure]);
|
||||
return;
|
||||
}
|
||||
case 'lostpointercapture': {
|
||||
this.removeEventListener('pointerdown', this);
|
||||
this.removeEventListener('pointermove', this);
|
||||
this.removeEventListener('lostpointercapture', this);
|
||||
this.#internals.states.delete('drawing');
|
||||
case "lostpointercapture": {
|
||||
this.removeEventListener("pointerdown", this);
|
||||
this.removeEventListener("pointermove", this);
|
||||
this.removeEventListener("lostpointercapture", this);
|
||||
this.#internals.states.delete("drawing");
|
||||
this.#tracingPromise?.resolve();
|
||||
this.#tracingPromise = null;
|
||||
return;
|
||||
|
|
@ -194,13 +194,13 @@ export class FolkInk extends HTMLElement {
|
|||
},
|
||||
};
|
||||
this.#path.setAttribute(
|
||||
'd',
|
||||
"d",
|
||||
this.#getSvgPathFromStroke(getStroke(this.#points, options))
|
||||
);
|
||||
}
|
||||
|
||||
#getSvgPathFromStroke(stroke: Stroke): string {
|
||||
if (stroke.length === 0) return '';
|
||||
if (stroke.length === 0) return "";
|
||||
|
||||
const d = stroke.reduce(
|
||||
(acc, [x0, y0], i, arr) => {
|
||||
|
|
@ -208,10 +208,10 @@ export class FolkInk extends HTMLElement {
|
|||
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
|
||||
return acc;
|
||||
},
|
||||
['M', ...stroke[0], 'Q']
|
||||
["M", ...stroke[0], "Q"]
|
||||
);
|
||||
|
||||
d.push('Z');
|
||||
return d.join(' ');
|
||||
d.push("Z");
|
||||
return d.join(" ");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
import { LatLng, LatLngExpression, LeafletEvent, map, Map, tileLayer } from 'leaflet';
|
||||
import {
|
||||
LatLng,
|
||||
LatLngExpression,
|
||||
LeafletEvent,
|
||||
map,
|
||||
Map,
|
||||
tileLayer,
|
||||
} from "leaflet";
|
||||
|
||||
// @ts-ignore
|
||||
// Vite specific import :(
|
||||
import css from 'leaflet/dist/leaflet.css?inline';
|
||||
import css from "leaflet/dist/leaflet.css?inline";
|
||||
const styles = new CSSStyleSheet();
|
||||
styles.replaceSync(`${css}
|
||||
:host {
|
||||
|
|
@ -17,24 +24,24 @@ styles.replaceSync(`${css}
|
|||
|
||||
export class RecenterEvent extends CustomEvent<LatLng> {
|
||||
constructor(detail: LatLng) {
|
||||
super('recenter', { detail, bubbles: true });
|
||||
super("recenter", { detail, bubbles: true });
|
||||
}
|
||||
}
|
||||
|
||||
export class LeafletMap extends HTMLElement {
|
||||
static tagName = 'leaflet-map';
|
||||
static tagName = "leaflet-map";
|
||||
|
||||
static register() {
|
||||
customElements.define(this.tagName, this);
|
||||
}
|
||||
|
||||
#container = document.createElement('div');
|
||||
#container = document.createElement("div");
|
||||
#map!: Map;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.handleEvent = this.handleEvent.bind(this);
|
||||
const shadow = this.attachShadow({ mode: 'open' });
|
||||
const shadow = this.attachShadow({ mode: "open" });
|
||||
shadow.adoptedStyleSheets.push(styles);
|
||||
shadow.appendChild(this.#container);
|
||||
}
|
||||
|
|
@ -42,25 +49,26 @@ export class LeafletMap extends HTMLElement {
|
|||
connectedCallback() {
|
||||
this.#map = map(this.#container);
|
||||
this.#map.addLayer(
|
||||
tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
attribution:
|
||||
'© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
})
|
||||
);
|
||||
const coordinates = (this.getAttribute('coordinates')
|
||||
?.split(',')
|
||||
const coordinates = (this.getAttribute("coordinates")
|
||||
?.split(",")
|
||||
.map((str) => Number(str)) || [0, 0]) as LatLngExpression;
|
||||
const zoom = Number(this.getAttribute('zoom') || 13);
|
||||
const zoom = Number(this.getAttribute("zoom") || 13);
|
||||
this.#map.setView(coordinates, zoom);
|
||||
|
||||
this.#map.on('zoom', this.handleEvent);
|
||||
this.#map.on('moveend', this.handleEvent);
|
||||
this.#map.on("zoom", this.handleEvent);
|
||||
this.#map.on("moveend", this.handleEvent);
|
||||
}
|
||||
|
||||
handleEvent(event: LeafletEvent) {
|
||||
switch (event.type) {
|
||||
case 'zoom':
|
||||
case 'moveend': {
|
||||
case "zoom":
|
||||
case "moveend": {
|
||||
this.dispatchEvent(new RecenterEvent(this.#map.getCenter()));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": false,
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"declaration": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"experimentalDecorators": true,
|
||||
|
||||
/* Transpile */
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Loading…
Reference in New Issue