# 06 — Load order ## The rule **Export order in `src/index.ts` is load-bearing.** A component that listens for a bubbling announcement from another tag must be exported — and therefore `customElements.define()`d — **before** that other tag. ## Why `customElements.define(name, Class)` upgrades every matching element already in the document **immediately and synchronously**, running `connectedCallback` right then for elements that are already connected. On a real static-HTML page the markup is fully parsed before the deferred module script runs, so at `define()` time the elements already exist. The first `define()` for a given tag wins the race: - If a **child** tag is defined before its listening **parent** tag, every instance of that child in the page upgrades and fires its one-shot connect-time announcement (`leaflet-register`, `icon-changed`, `leaflet-line-sync`, `leaflet-crs-changed`) into a parent element that has no listener attached yet — because the parent class isn't defined, so its `connectedCallback` hasn't run. - That announcement is **gone for good**: `connectedCallback` does not fire again for an element that stays connected. So parents must be defined first. ## The ordering in `src/index.ts` Root to leaf (this is the comment at the top of the file, kept in sync): ``` LeafletMap ← nothing can register before the root exists LeafletControlLayers, LeafletLayerGroup, LeafletFeatureGroup ← listen for leaflet-register from arbitrary layers every concrete layer type (Marker, Circle, Polygon, TileLayer, …) LeafletLine ← child of Polygon/Polyline LeafletPopup, LeafletTooltip ← child of any layer LeafletIcon, LeafletDivIcon ← child of Marker ``` Standalone controls (`LeafletControlZoom`, `LeafletControlAttribution`, `LeafletControlScale`) have no such relationship and can go anywhere. The core re-exports (`register.ts`, `props.ts`, `with-props.ts`, `shared-props.ts`, `event-types.ts`) come first and carry no `customElements.define`, so their order is free. ## The `HTMLElementTagNameMap` augmentation At the bottom of `src/index.ts`. Because `export { X } from '…'` re-exports `X` without binding it locally, the tag map needs its **own** `import type` of every component class alongside the re-export. Those imports are type-only, erased at build, back no `define()` — their order doesn't matter. ## The test that guards this `test/load-order.test.ts` is structurally unlike every other test file **on purpose**: it never statically imports a component module, so nothing is `customElements.define`d until it dynamically `import()`s `src/index.ts` partway through — _after_ building a DOM tree out of plain, undefined elements. That's the only test reproducing a real page's actual order (markup first, module script second). Every other test file imports components up front, so components are already defined before any element is created — they **structurally cannot** catch an ordering regression. If you add a component with a "parent listens for a child's announcement" relationship, extend `load-order.test.ts`.