Every component is now two modules sharing a basename: - src/elements/leaflet-foo.ts -- `export default class LeafletFooElement extends WithProps(...)`, the class only, no customElements.define, no side effects. src/elements/index.ts is an order-free barrel. - src/components/leaflet-foo.ts -- three lines: import the class, define the tag, re-export. Importing this (or src/index.ts) registers the tag. Plugin authors can now import a class without triggering the built-in define, to subclass it or register it under a different tag name. Package subpath exports `leaflet-components/elements`, `leaflet-components/elements/leaflet-foo.js`, and `leaflet-components/components/leaflet-foo.js` map onto dist/; jsr.json gains an `./elements` entry. The load-bearing ordering moves from the export statements in src/index.ts to its `./components/*` side-effect imports (the elements barrel carries no define, so its order is free). Classes are renamed LeafletFoo -> LeafletFooElement, including in the HTMLElementTagNameMap augmentation. Docs (CLAUDE.md, docs/, README.md) updated for the new layout. |
2 weeks ago | |
|---|---|---|
| .. | ||
| 01-architecture.md | 2 weeks ago | |
| 02-props-and-attributes.md | 3 weeks ago | |
| 03-component-tree.md | 3 weeks ago | |
| 04-events.md | 2 weeks ago | |
| 05-special-cases.md | 2 weeks ago | |
| 06-load-order.md | 2 weeks ago | |
| 07-tooling-and-build.md | 2 weeks ago | |
| README.md | 2 weeks ago | |
README.md
Design docs
These describe how leaflet-components is built and why — the load-bearing
decisions, in their current form. They are not a usage guide (that's the
top-level README.md) and not a working cheat-sheet (that's
CLAUDE.md).
| Doc | Covers |
|---|---|
| 01 — Architecture | Element-per-Leaflet-object, the WithProps mixin, the lifecycle it owns |
| 02 — Props & attributes | The PropDef model, the codec factories, two-way attribute↔object sync |
| 03 — Component tree & registration | The leaflet-register bubbling protocol, attach modes, the other announcement events |
| 04 — Events | Re-emitting Leaflet events as leaflet:<type>, and how they're typed |
| 05 — Per-component special cases | Where a component does something the mixin can't express generically |
| 06 — Load order | Why the ./components/* import order in src/index.ts is load-bearing |
| 07 — Tooling & build | TypeScript 7, oxlint, oxfmt, Vitest, the no-bundle build, dual publish |
The one-paragraph version
Each leaflet-* custom element wraps exactly one Leaflet object. A mixin
(WithProps) generates the element class from a table of property
descriptors: it derives observedAttributes, builds the Leaflet options
object from the current attributes, calls the component's
createLeafletObject(), keeps attributes and the live object in sync in both
directions, and re-fires every Leaflet event on the element. Components join
each other through a DOM-event registration protocol that bubbles up to
<leaflet-map> at the root — no component ever reads another component's
state or queries the DOM for its relatives. The build is tsc with no
bundler; Leaflet is always external.