diff --git a/demo/index.html b/demo/index.html index 8de400a..cdaf757 100644 --- a/demo/index.html +++ b/demo/index.html @@ -21,6 +21,7 @@ diff --git a/demo/maps.html b/demo/maps.html new file mode 100644 index 0000000..2a65205 --- /dev/null +++ b/demo/maps.html @@ -0,0 +1,40 @@ + + + + + + Shapes - Collision + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index ef68b1b..fab9620 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,18 @@ { - "name": "spatial-canvas-primitives", + "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" + }, "devDependencies": { + "@types/leaflet": "^1.9.12", "@types/node": "^20.12.7", "typescript": "^5.0.0", "vite": "^5.0.0" @@ -592,6 +600,21 @@ "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", @@ -653,6 +676,11 @@ "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", diff --git a/package.json b/package.json index adc6ccd..dbadea5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,27 @@ { "name": "folk-canvas", "description": "", + "version": "0.1.0", + "type": "module", + "sideEffects": false, + "author": "Christopher Shank ", + "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", @@ -8,8 +29,12 @@ "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" } } diff --git a/src/elements/spatial-geometry.ts b/src/elements/spatial-geometry.ts index 7070cb9..bd781ec 100644 --- a/src/elements/spatial-geometry.ts +++ b/src/elements/spatial-geometry.ts @@ -32,13 +32,25 @@ styles.replaceSync(` :host { display: block; position: absolute; + padding: 20px 10px 10px; cursor: var(--fc-grab, grab); + content-visibility: auto; } -:host(:hover), :host(:focus-within){ +:host > div { + position: relative; + width: 100%; + height: 100%; +} + +:host(:focus-within) > div { outline: solid 1px hsl(214, 84%, 56%); } +:host(:hover) > div { + outline: solid 2px hsl(214, 84%, 56%); +} + :host(:state(moving)) { cursor: var(--fc-grabbing, grabbing); user-select: none; @@ -48,12 +60,13 @@ styles.replaceSync(` opacity: 0; } -:host(:focus-within) [resize-handler] { +[resize-handler] { display: block; position: absolute; box-sizing: border-box; padding: 0; background: hsl(210, 20%, 98%); + z-index: calc(infinity); /* should the handlers always show? */ &[resize-handler="top-left"], &[resize-handler="top-right"], @@ -64,7 +77,6 @@ styles.replaceSync(` transform: translate(-50%, -50%); border: 1.5px solid hsl(214, 84%, 56%); border-radius: 2px; - z-index: 3; } &[resize-handler="top-left"] { @@ -94,59 +106,9 @@ styles.replaceSync(` &[resize-handler="top-right"], &[resize-handler="bottom-left"] { cursor: var(--fc-nesw-resize, nesw-resize) } - - &[resize-handler="top"], - &[resize-handler="right"], - &[resize-handler="bottom"], - &[resize-handler="left"] { - background-color: hsl(214, 84%, 56%); - background-clip: content-box; - border: unset; - z-index: 2; - } - - &[resize-handler="top"] { - top: 0; - left: 0; - right: 0; - transform: translate(0, -50%); - } - - &[resize-handler="right"] { - top: 0; - bottom: 0; - right: 0; - transform: translate(50%, 0); - } - - &[resize-handler="bottom"] { - bottom:0; - left: 0; - right: 0; - transform: translate(0, 50%); - } - - &[resize-handler="left"] { - top: 0; - bottom: 0; - left: 0; - transform: translate(-50%, 0); - } - - &[resize-handler="top"], &[resize-handler="bottom"] { - height: 6px; - padding: 2px 0; - cursor: var(--fc-ns-resize, ns-resize) - } - - &[resize-handler="right"], &[resize-handler="left"] { - width: 6px; - padding: 0 2px; - cursor: var(--fc-ew-resize, ew-resize) - } } -:host(:focus-within) [rotation-handler] { +[rotation-handler] { display: block; position: absolute; box-sizing: border-box; @@ -163,7 +125,7 @@ styles.replaceSync(` cursor: url("data:image/svg+xml,") 16 16, pointer; } -:host(:focus-within) [rotation-handler]::before { +[rotation-handler]::before { box-sizing: border-box; display: block; position: absolute; @@ -172,8 +134,7 @@ styles.replaceSync(` border: 1px solid hsl(214, 84%, 56%); height: 50%; width: 1px; -} - `); +}`); // TODO: add z coordinate? export class SpatialGeometry extends HTMLElement { @@ -201,11 +162,14 @@ export class SpatialGeometry extends HTMLElement { // Maybe can add the first resize handler here, and lazily instantiate the rest when needed? // I can see it becoming important at scale shadowRoot.innerHTML = ` - - - - -`; +
+ + + + + + +
`; } #type: Shape = 'rectangle'; diff --git a/src/maps/index.ts b/src/maps/index.ts new file mode 100644 index 0000000..dce3de5 --- /dev/null +++ b/src/maps/index.ts @@ -0,0 +1,46 @@ +import { map, Map, tileLayer } from 'leaflet'; + +// @ts-ignore +// Vite specific import :( +import css from 'leaflet/dist/leaflet.css?inline'; +const styles = new CSSStyleSheet(); +styles.replaceSync(`${css} + :host { + display: block; + } + + :host > div { + height: 100%; + width: 100%; + } +`); + +export class LeafletMap extends HTMLElement { + static tagName = 'leaflet-map'; + + static register() { + customElements.define(this.tagName, this); + } + + #container = document.createElement('div'); + #map!: Map; + + constructor() { + super(); + + const shadow = this.attachShadow({ mode: 'open' }); + shadow.adoptedStyleSheets.push(styles); + shadow.appendChild(this.#container); + } + + connectedCallback() { + this.#map = map(this.#container); + this.#map.addLayer( + tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap', + }) + ); + this.#map.setView([52.09, 5.12], 13); + } +}