docs: update README and CLAUDE.md for current build and architecture
Remove stale JSR reference, add import-options section (formats, deep imports, leaflet as external dep), fix build command (esbuild -> Rollup). Rewrite CLAUDE.md architecture to reflect withProps mixin, register.ts helpers, feature-group, and the full rollup output.
This commit is contained in:
parent
5d0d15fba1
commit
edecb44533
32
CLAUDE.md
32
CLAUDE.md
@ -5,7 +5,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
npm run build # Type-check + emit .d.ts via tsc, then bundle to dist/index.js via esbuild
|
||||
npm run build # tsc emits individual ESM modules, then Rollup bundles ESM/CJS/UMD
|
||||
npm run typecheck # tsc --noEmit
|
||||
npm run lint # ESLint over src/**/*.{ts,js}
|
||||
npm run format # Prettier formatting
|
||||
```
|
||||
@ -16,35 +17,38 @@ There are no tests in this project. To preview components locally, open `index.h
|
||||
|
||||
This library wraps [Leaflet.js](https://leafletjs.com/) as native Web Components (Custom Elements). Each HTML element maps 1:1 to a Leaflet object.
|
||||
|
||||
### Core base class: `src/core/LeafletElement.ts`
|
||||
### `withProps` mixin: `src/core/with-props.ts`
|
||||
|
||||
`LeafletElement` (extends `HTMLElement`) is the abstract base for all components except `leaflet-map`. Subclasses must implement `createLeafletObject()` returning an `L.Layer`. The base class:
|
||||
The `withProps(Base, PROPS)` mixin factory replaces the old `LeafletElement` base class. Each component defines a `PROPS` table (a const record mapping kebab-case attribute names to `PropDef` descriptors), then extends `withProps(HTMLElement, PROPS)`. The mixin handles:
|
||||
|
||||
- Reads `observedAttributes` to auto-populate `this.options` via `initOptions()` on connect, converting kebab-case attribute names to camelCase for Leaflet options.
|
||||
- Parses attribute values to booleans, numbers, or JSON automatically (`parseAttributeValue`).
|
||||
- On `attributeChangedCallback`, calls `updateLeafletObject()` which by default invokes the matching Leaflet setter (e.g. `setOpacity`, `setRadius`). Subclasses override this for attributes needing custom logic (e.g. lat/lng pairs).
|
||||
- Uses a custom `leaflet-register` bubbling event to wire children into parents. When a child connects, it dispatches this event upward; each parent intercepts and either calls `addLayer`, `bindPopup`, or `bindTooltip` depending on the child's type.
|
||||
- `observedAttributes` getter derived from the PROPS table keys.
|
||||
- `definePropAccessors` — property getters/setters on the prototype that sync attributes.
|
||||
- `parseAttributeValue` for boolean, number, and JSON coersion in `attributeChangedCallback`.
|
||||
- On connect, `initOptions()` builds a Leaflet options object from current attributes + PROPS defaults, then calls `createLeafletObject()`.
|
||||
- On attribute change, `updateLeafletObject()` by default dispatches to the matching Leaflet setter (e.g. `setOpacity`, `setRadius`). Components override this for custom attribute handling (e.g. lat/lng pairs).
|
||||
|
||||
### `leaflet-map`: `src/components/leaflet-map.ts`
|
||||
|
||||
`LeafletMap` does **not** extend `LeafletElement` — it extends `HTMLElement` directly and uses Shadow DOM. It is the root of the component tree and terminates all bubbling `leaflet-register` events by calling `layer.addTo(this.map)`.
|
||||
`LeafletMap` extends `HTMLElement` directly and uses Shadow DOM. It is the root of the component tree and terminates all bubbling `leaflet-register` events by calling `layer.addTo(this.map)`. Uses a `ResizeObserver` on the host element to call `map.invalidateSize()` automatically.
|
||||
|
||||
### Child component pattern
|
||||
|
||||
All other components extend `LeafletElement`. To add a new component:
|
||||
All non-map components extend `withProps(HTMLElement, PROPS)`. To add a new component:
|
||||
|
||||
1. Extend `LeafletElement`, implement `createLeafletObject()`.
|
||||
2. Declare `static get observedAttributes()` listing HTML attributes (kebab-case).
|
||||
3. Override `updateLeafletObject()` only if the default setter-based update won't work (common for coordinate pairs).
|
||||
1. Define a `PROPS = {...}` const table mapping kebab-case attributes to `PropDef` entries.
|
||||
2. Declare `class LeafletFoo extends withProps(HTMLElement, PROPS)` implementing `createLeafletObject(): L.Layer`.
|
||||
3. Override `updateLeafletObject(name, val)` only if the default setter-based update won't work (common for coordinate pairs).
|
||||
4. Call `customElements.define('leaflet-foo', LeafletFoo)` at the bottom.
|
||||
5. Export from `src/index.ts`.
|
||||
|
||||
For components that accept children (layers, popups, tooltips), use the `registerChildren`/`unregisterChildren`/`getChildren` WeakMap-backed helpers from `src/core/register.ts` in `connectedCallback`/`disconnectedCallback` instead of maintaining private fields.
|
||||
|
||||
### Special cases
|
||||
|
||||
- **`leaflet-polygon`** uses `<leaflet-line>` children for vertices. The polygon collects lat/lng from child `leaflet-line` elements rather than having them as direct attributes.
|
||||
- **`leaflet-popup`** / **`leaflet-tooltip`**: content comes from `innerHTML`, not attributes. `leaflet-popup` watches for DOM mutations to keep Leaflet in sync.
|
||||
- **`leaflet-layer-group`**: a passthrough container; children register themselves into it via the standard bubble mechanism.
|
||||
- **`leaflet-layer-group`** / **`leaflet-feature-group`**: passthrough containers extending `HTMLElement` directly (not via `withProps`). Children register themselves into them via the standard bubble mechanism.
|
||||
|
||||
### Output
|
||||
|
||||
`tsc` compiles `src/` → `dist/` with `.js` files and `.d.ts` declarations. Imports within the source use `.js` extensions (required for ESM `"moduleResolution": "bundler"`).
|
||||
`tsc` compiles `src/` → `dist/` as individual ESM modules (`.js` + `.d.ts` + `.d.ts.map`), then `rollup -c` bundles `dist/index.js` (ESM), `dist/index.cjs` (CJS), and `dist/index.umd.js` (UMD) — each with minified variants. Leaflet is always external (never bundled). Imports within source use `.js` extensions (required for ESM `"moduleResolution": "bundler"`).
|
||||
|
||||
26
README.md
26
README.md
@ -8,7 +8,28 @@
|
||||
npm install leaflet-components
|
||||
```
|
||||
|
||||
Available on JSR as `@buddy/leaflet-components`.
|
||||
## Import options
|
||||
|
||||
The package ships multiple bundle formats and supports deep imports for tree-shaking.
|
||||
|
||||
```js
|
||||
// Default ESM bundle (recommended) — registers all components
|
||||
import 'leaflet-components';
|
||||
|
||||
// Minified ESM bundle
|
||||
import 'leaflet-components/dist/index.min.js';
|
||||
|
||||
// CommonJS
|
||||
const lc = require('leaflet-components');
|
||||
|
||||
// Deep import — register only one component
|
||||
import 'leaflet-components/dist/components/leaflet-marker.js';
|
||||
|
||||
// UMD (for script tags, expects Leaflet as window.L)
|
||||
// <script src="node_modules/leaflet-components/dist/index.umd.js"></script>
|
||||
```
|
||||
|
||||
`leaflet` is always an external dependency — you must install it yourself.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -400,7 +421,8 @@ The following attributes apply to `<leaflet-circle>`, `<leaflet-circle-marker>`,
|
||||
## Development
|
||||
|
||||
```bash
|
||||
npm run build # type-check + emit .d.ts via tsc, then bundle to dist/index.js via esbuild
|
||||
npm run build # tsc emits individual ESM modules; Rollup bundles ESM, CJS + UMD (minified/unminified)
|
||||
npm run typecheck # tsc --noEmit
|
||||
npm run lint # ESLint
|
||||
npm run format # Prettier
|
||||
# serve the project root with any static-file server and open index.html
|
||||
|
||||
Loading…
Reference in New Issue
Block a user