docs: document leaflet-control-layers component and active attribute

main
Buddy 3 months ago
parent f85e67547d
commit 0855851504

@ -407,6 +407,38 @@ Content comes from `innerHTML`, not an attribute.
| `imperial` | — | Show imperial scale (mi/ft) | | `imperial` | — | Show imperial scale (mi/ft) |
| `update-when-idle` | — | Update only when the map stops moving | | `update-when-idle` | — | Update only when the map stops moving |
### `<leaflet-control-layers>`
The built-in Leaflet layer switcher. Children with `type="base"` appear as radio buttons; children with `type="overlay"` (or no `type`) appear as checkboxes.
```html
<leaflet-map>
<leaflet-control-layers position="topright" collapsed>
<leaflet-tile-layer type="base" name="Streets" active url="..."></leaflet-tile-layer>
<leaflet-tile-layer type="base" name="Satellite" url="..."></leaflet-tile-layer>
<leaflet-marker type="overlay" name="Cities" active lat="51.5" lng="-0.09"></leaflet-marker>
</leaflet-control-layers>
</leaflet-map>
```
| Attribute | Default | Description |
|---|---|---|
| `position` | `'topright'` | Corner position |
| `collapsed` | `true` (toggle with `collapsed="false"`) | Collapse into an icon until hovered |
| `auto-z-index` | `true` | Assign increasing z-indexes to layers |
| `hide-single-base` | — | Hide the base layers section when only one base layer exists |
| `sort-layers` | — | Sort layers alphabetically |
Each child layer inside `<leaflet-control-layers>` may carry:
| Attribute | Description |
|---|---|
| `type="base"` | Show as a radio button (base layer). Omit or set `type="overlay"` for a checkbox. |
| `name` | Human-readable label displayed in the control. |
| `active` | Add the layer to the map immediately so it starts visible. Internally, the control dispatches a `leaflet-add-layer` event that the map handles. Layers without `active` are removed from the map before the control renders, so they correctly appear unchecked. |
The control intercepts child `leaflet-register` events and stops propagation — layers inside `<leaflet-control-layers>` are managed by the layers control, not added directly to the map.
## Path style ## Path style
The following attributes apply to `<leaflet-circle>`, `<leaflet-circle-marker>`, `<leaflet-polyline>`, `<leaflet-polygon>`, `<leaflet-rectangle>`, and `<leaflet-geojson>`. The following attributes apply to `<leaflet-circle>`, `<leaflet-circle-marker>`, `<leaflet-polyline>`, `<leaflet-polygon>`, `<leaflet-rectangle>`, and `<leaflet-geojson>`.
@ -431,6 +463,7 @@ The following attributes apply to `<leaflet-circle>`, `<leaflet-circle-marker>`,
- **Layer as child of a group** → added via `addLayer`. - **Layer as child of a group** → added via `addLayer`.
- **Any layer as child of `leaflet-map`** → added to the map directly. - **Any layer as child of `leaflet-map`** → added to the map directly.
- **`leaflet-polygon` / `leaflet-polyline`** take their coordinates from `<leaflet-line>` children, not from attributes. - **`leaflet-polygon` / `leaflet-polyline`** take their coordinates from `<leaflet-line>` children, not from attributes.
- **Layer as child of `<leaflet-control-layers>`** → intercepted by the control and registered as a base or overlay entry. The control stops propagation so the layer doesn't reach the map directly. Use `active` to start the layer visible.
## Development ## Development

@ -18,7 +18,7 @@
<leaflet-tile-layer <leaflet-tile-layer
type="base" type="base"
name="OpenStreetMap" name="OpenStreetMap"
checked active
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="&copy; OpenStreetMap" attribution="&copy; OpenStreetMap"
></leaflet-tile-layer> ></leaflet-tile-layer>

@ -13,19 +13,19 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
connectedCallback() { connectedCallback() {
const baseLayers: Record<string, Layer> = {}; const baseLayers: Record<string, Layer> = {};
const overlays: Record<string, Layer> = {}; const overlays: Record<string, Layer> = {};
const uncheckedLayers: Layer[] = []; const inactiveLayers: Layer[] = [];
for (const child of this.querySelectorAll(':scope > *')) { for (const child of this.querySelectorAll(':scope > *')) {
const layer = (child as unknown as { leafletObject?: Layer }).leafletObject; const layer = (child as unknown as { leafletObject?: Layer }).leafletObject;
const name = child.getAttribute('name'); const name = child.getAttribute('name');
if (!name || !layer) continue; if (!name || !layer) continue;
const base = child.getAttribute('type') === 'base'; const base = child.getAttribute('type') === 'base';
const checked = child.hasAttribute('checked'); const active = child.hasAttribute('active');
(base ? baseLayers : overlays)[name] = layer; (base ? baseLayers : overlays)[name] = layer;
if (!checked) uncheckedLayers.push(layer); if (!active) inactiveLayers.push(layer);
} }
for (const layer of uncheckedLayers) { for (const layer of inactiveLayers) {
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('leaflet-remove-layer', { bubbles: true, detail: { layer } }), new CustomEvent('leaflet-remove-layer', { bubbles: true, detail: { layer } }),
); );
@ -67,10 +67,10 @@ export class LeafletControlLayers extends WithProps(HTMLElement, PROPS) {
const name = el.getAttribute('name'); const name = el.getAttribute('name');
if (!name || !layer) return; if (!name || !layer) return;
const base = el.getAttribute('type') === 'base'; const base = el.getAttribute('type') === 'base';
const checked = el.hasAttribute('checked'); const active = el.hasAttribute('active');
if (base) this.#obj!.addBaseLayer(layer, name); if (base) this.#obj!.addBaseLayer(layer, name);
else this.#obj!.addOverlay(layer, name); else this.#obj!.addOverlay(layer, name);
if (checked) { if (active) {
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('leaflet-add-layer', { bubbles: true, detail: { layer } }), new CustomEvent('leaflet-add-layer', { bubbles: true, detail: { layer } }),
); );

Loading…
Cancel
Save