@aceshooting/lyra-ui 11.2.0 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +407 -0
- package/README.md +11 -8
- package/custom-elements.json +1 -1
- package/dist/all.d.ts +1 -0
- package/dist/all.js +1 -1
- package/dist/autoloader.js +1 -1
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +0 -1
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +1 -1
- package/dist/components/charts/chart/chart.class.d.ts +13 -1
- package/dist/components/charts/chart/histogram-bin.d.ts +0 -1
- package/dist/components/charts/chart/histogram-bin.js +1 -1
- package/dist/components/charts/chart/lite-chart.class.d.ts +22 -9
- package/dist/components/charts/chart/lite-chart.class.js +6 -6
- package/dist/components/conversation/code-block/code-block-shared.d.ts +4 -54
- package/dist/components/conversation/code-block/code-block-shared.js +1 -1
- package/dist/components/conversation/code-block/shiki-types.d.ts +2 -1
- package/dist/components/conversation/generation-metrics/generation-metrics.class.js +1 -1
- package/dist/components/conversation/model-select/model-select.class.d.ts +0 -3
- package/dist/components/conversation/model-select/model-select.class.js +1 -1
- package/dist/components/conversation/selection-toolbar/selection-toolbar.class.js +1 -1
- package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +0 -1
- package/dist/components/conversation/voice-picker/voice-picker.class.js +1 -1
- package/dist/components/data/data-grid/data-grid.class.js +1 -1
- package/dist/components/data/funnel/funnel.class.d.ts +92 -0
- package/dist/components/data/funnel/funnel.class.js +25 -0
- package/dist/components/data/funnel/funnel.d.ts +1 -0
- package/dist/components/data/funnel/funnel.js +1 -0
- package/dist/components/data/funnel/funnel.styles.d.ts +1 -0
- package/dist/components/data/funnel/funnel.styles.js +127 -0
- package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +0 -1
- package/dist/components/data/graph-query-builder/graph-query-builder.class.js +1 -1
- package/dist/components/data/heatmap/heatmap.class.d.ts +199 -14
- package/dist/components/data/heatmap/heatmap.class.js +30 -22
- package/dist/components/data/heatmap/heatmap.styles.js +36 -0
- package/dist/components/data/index.d.ts +1 -0
- package/dist/components/data/index.js +1 -1
- package/dist/components/data/table/table.class.d.ts +18 -4
- package/dist/components/data/table/table.class.js +2 -2
- package/dist/components/data/table/table.styles.js +2 -1
- package/dist/components/data/timeline/timeline-cluster.d.ts +1 -0
- package/dist/components/data/timeline/timeline-cluster.js +1 -0
- package/dist/components/data/timeline/timeline-item.class.d.ts +17 -2
- package/dist/components/data/timeline/timeline-item.class.js +13 -2
- package/dist/components/data/timeline/timeline-item.styles.js +65 -0
- package/dist/components/data/timeline/timeline.class.d.ts +83 -27
- package/dist/components/data/timeline/timeline.class.js +3 -3
- package/dist/components/data/timeline/timeline.d.ts +1 -0
- package/dist/components/data/timeline/timeline.js +1 -1
- package/dist/components/data/timeline/timeline.styles.js +14 -0
- package/dist/components/forms/button/button.class.js +1 -1
- package/dist/components/forms/checkbox/checkbox.class.d.ts +0 -1
- package/dist/components/forms/checkbox/checkbox.class.js +1 -1
- package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +0 -1
- package/dist/components/forms/checkbox-group/checkbox-group.class.js +1 -1
- package/dist/components/forms/code-editor/code-editor.class.js +1 -1
- package/dist/components/forms/color-picker/color-picker.class.js +1 -1
- package/dist/components/forms/combobox/combobox.class.d.ts +7 -1
- package/dist/components/forms/combobox/combobox.class.js +3 -2
- package/dist/components/forms/combobox/combobox.styles.js +1 -1
- package/dist/components/forms/date-picker/date-input.class.d.ts +23 -0
- package/dist/components/forms/date-picker/date-input.class.js +1 -1
- package/dist/components/forms/emoji-picker/emoji-data-loader.d.ts +0 -1
- package/dist/components/forms/input/native-time-input.class.js +1 -1
- package/dist/components/forms/input/time-input-shared.d.ts +2 -1
- package/dist/components/forms/input/time-input.class.js +1 -1
- package/dist/components/forms/locale-picker/locale-picker.class.d.ts +0 -1
- package/dist/components/forms/locale-picker/locale-picker.class.js +1 -1
- package/dist/components/forms/radio/radio-button.styles.d.ts +0 -1
- package/dist/components/forms/radio/radio-button.styles.js +1 -1
- package/dist/components/forms/radio/radio-group.class.d.ts +0 -1
- package/dist/components/forms/radio/radio-group.class.js +1 -1
- package/dist/components/forms/radio/radio.class.d.ts +0 -1
- package/dist/components/forms/radio/radio.class.js +1 -1
- package/dist/components/forms/rubric-form/rubric-form.class.d.ts +0 -1
- package/dist/components/forms/rubric-form/rubric-form.class.js +1 -1
- package/dist/components/forms/select/select.class.d.ts +0 -1
- package/dist/components/forms/select/select.class.js +1 -1
- package/dist/components/forms/slider/slider.class.d.ts +0 -1
- package/dist/components/forms/slider/slider.class.js +1 -1
- package/dist/components/forms/switch/switch.class.d.ts +0 -1
- package/dist/components/forms/switch/switch.class.js +1 -1
- package/dist/components/forms/time-range/time-range.class.d.ts +0 -1
- package/dist/components/forms/time-range/time-range.class.js +1 -1
- package/dist/components/forms/token-input/token-input.class.d.ts +0 -1
- package/dist/components/forms/token-input/token-input.class.js +1 -1
- package/dist/components/layout/app-rail/app-rail-item.class.d.ts +16 -0
- package/dist/components/layout/app-rail/app-rail-item.class.js +4 -4
- package/dist/components/layout/dashboard-grid/layout-internal.d.ts +0 -1
- package/dist/components/layout/dashboard-grid/layout-internal.js +1 -1
- package/dist/components/layout/details/accordion-owner.d.ts +1 -1
- package/dist/components/layout/filter-bar/filter-bar.class.d.ts +32 -3
- package/dist/components/layout/filter-bar/filter-bar.class.js +2 -1
- package/dist/components/layout/menu/menu-item.class.js +1 -1
- package/dist/components/layout/virtual-list/virtual-list.class.js +1 -1
- package/dist/components/layout/widget/widget.class.d.ts +16 -0
- package/dist/components/layout/widget/widget.class.js +2 -2
- package/dist/components/lr-funnel.d.ts +1 -0
- package/dist/components/lr-funnel.js +1 -0
- package/dist/components/media/av-player/av-metadata.d.ts +0 -2
- package/dist/components/media/av-player/av-metadata.js +1 -1
- package/dist/components/media/file-input/file-input.class.d.ts +0 -1
- package/dist/components/media/file-input/file-input.class.js +1 -1
- package/dist/components/media/flag/flag-peer-bulk-standard.d.ts +25 -0
- package/dist/components/media/flag/flag-peer-bulk-standard.js +1 -0
- package/dist/components/media/flag/flag.class.d.ts +8 -0
- package/dist/components/media/flag/flag.class.js +1 -1
- package/dist/components/media/map/map-loader.d.ts +4 -1
- package/dist/components/media/map/map.class.d.ts +242 -23
- package/dist/components/media/map/map.class.js +2 -2
- package/dist/components/overlays/chip/chip-group.class.d.ts +16 -0
- package/dist/components/overlays/chip/chip-group.class.js +10 -3
- package/dist/components/overlays/overlay/popover.class.d.ts +7 -1
- package/dist/components/overlays/overlay/popover.class.js +1 -1
- package/dist/components/overlays/overlay/tooltip.class.d.ts +1 -0
- package/dist/components/overlays/overlay/tooltip.class.js +1 -1
- package/dist/components/overlays/progress/progress-shared.d.ts +0 -2
- package/dist/components/overlays/progress/progress-shared.js +1 -1
- package/dist/components/overlays/rating/rating.class.js +1 -1
- package/dist/components/retrieval/graph/graph-canvas.d.ts +10 -9
- package/dist/components/retrieval/mind-map/mind-map-layout.d.ts +0 -4
- package/dist/components/retrieval/mind-map/mind-map-layout.js +1 -1
- package/dist/components/utility/format/format-options.d.ts +0 -2
- package/dist/components/utility/format/format-options.js +1 -1
- package/dist/components/utility/icon/icon-resource.d.ts +0 -2
- package/dist/components/utility/icon/icon-resource.js +1 -1
- package/dist/components/viewers/archive-viewer/zip-resource-guard.d.ts +2 -1
- package/dist/components/viewers/docx-viewer/docx-resource-guard.d.ts +0 -3
- package/dist/components/viewers/docx-viewer/docx-resource-guard.js +1 -1
- package/dist/components/viewers/ebook-viewer/ebook-loader.d.ts +2 -1
- package/dist/components/viewers/ebook-viewer/epub-resource-guard.d.ts +0 -3
- package/dist/components/viewers/ebook-viewer/epub-resource-guard.js +1 -1
- package/dist/components/viewers/pdf-viewer/pdf-loader.d.ts +2 -2
- package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +2 -2
- package/dist/components/viewers/pptx-viewer/pptx-resource-guard.d.ts +0 -2
- package/dist/components/viewers/pptx-viewer/pptx-resource-guard.js +1 -1
- package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.d.ts +0 -5
- package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.js +1 -1
- package/dist/custom-elements-jsx.d.ts +16 -8
- package/dist/events.d.ts +15 -0
- package/dist/internal/accessibility-visibility.d.ts +1 -1
- package/dist/internal/anchor-target.d.ts +1 -3
- package/dist/internal/anchor-target.js +2 -2
- package/dist/internal/anchored-overlay-runtime.d.ts +7 -0
- package/dist/internal/anchored-overlay-runtime.js +1 -0
- package/dist/internal/announcement-text.d.ts +1 -1
- package/dist/internal/ansi.d.ts +0 -4
- package/dist/internal/ansi.js +1 -1
- package/dist/internal/aria-ownership.d.ts +2 -1
- package/dist/internal/autoloader-manifest.js +1 -1
- package/dist/internal/autoloader-tags.d.ts +1 -1
- package/dist/internal/autoloader-tags.js +1 -1
- package/dist/internal/default-strings.generated.d.ts +1 -0
- package/dist/internal/default-strings.generated.js +1 -1
- package/dist/internal/focus-navigation.d.ts +3 -2
- package/dist/internal/form-associated.d.ts +0 -1
- package/dist/internal/form-associated.js +1 -1
- package/dist/internal/form-control-labels.d.ts +0 -3
- package/dist/internal/form-control-labels.js +1 -1
- package/dist/internal/localization-runtime.js +1 -1
- package/dist/internal/localization-types.d.ts +1 -1
- package/dist/internal/localization.js +1 -1
- package/dist/internal/lyra-element.d.ts +7 -14
- package/dist/internal/lyra-element.js +1 -1
- package/dist/internal/nonmodal-overlay-manager.d.ts +9 -0
- package/dist/internal/nonmodal-overlay-manager.js +1 -0
- package/dist/internal/overlay-manager.d.ts +4 -20
- package/dist/internal/overlay-manager.js +1 -1
- package/dist/internal/overlay-stack.d.ts +66 -0
- package/dist/internal/overlay-stack.js +1 -0
- package/dist/internal/package-metadata.d.ts +1 -1
- package/dist/internal/package-metadata.js +1 -1
- package/dist/internal/positioner.js +1 -1
- package/dist/internal/root-registration-allowlist.d.ts +1 -1
- package/dist/internal/root-registration-allowlist.js +1 -1
- package/dist/internal/text-quote.d.ts +1 -1
- package/dist/lyra.d.ts +5 -4
- package/dist/lyra.js +1 -1
- package/dist/ssr/all.d.ts +1 -0
- package/dist/ssr/all.js +1 -1
- package/dist/ssr.d.ts +4 -4
- package/dist/styles/tokens-root.css +488 -0
- package/dist/svelte.d.ts +17 -8
- package/dist/translations/ar.js +1 -1
- package/dist/translations/de.js +1 -1
- package/dist/translations/es.js +1 -1
- package/dist/translations/fa.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/he.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/translations/pt-BR.js +1 -1
- package/dist/translations/ru.js +1 -1
- package/dist/translations/zh-CN.js +1 -1
- package/dist/utilities/localization.js +1 -1
- package/dist/vue.d.ts +16 -8
- package/llms/components/lr-app-rail-item.md +8 -1
- package/llms/components/lr-app-rail.md +6 -0
- package/llms/components/lr-chip-group.md +7 -0
- package/llms/components/lr-chip.md +7 -0
- package/llms/components/lr-combobox.md +42 -0
- package/llms/components/lr-date-input.md +19 -1
- package/llms/components/lr-date-picker.md +19 -1
- package/llms/components/lr-filter-bar.md +50 -1
- package/llms/components/lr-flag.md +14 -0
- package/llms/components/lr-funnel.md +122 -0
- package/llms/components/lr-heatmap.md +55 -8
- package/llms/components/lr-lite-chart.md +20 -8
- package/llms/components/lr-map.md +109 -22
- package/llms/components/lr-option.md +42 -0
- package/llms/components/lr-popover.md +39 -0
- package/llms/components/lr-table.md +7 -3
- package/llms/components/lr-timeline-item.md +49 -24
- package/llms/components/lr-timeline.md +49 -24
- package/llms/components/lr-widget.md +7 -1
- package/llms/index.md +3 -2
- package/llms/peers.md +1 -1
- package/llms/shared.md +110 -1
- package/llms-full.txt +681 -67
- package/llms.txt +1 -1
- package/package.json +26 -8
- package/vscode-css-data.json +63 -0
- package/vscode-html-data.json +108 -23
- package/web-types.json +32738 -310
|
@@ -75,9 +75,89 @@ export interface LyraMapChoroplethLayer {
|
|
|
75
75
|
* gradient legend) but could not express this one.
|
|
76
76
|
*/
|
|
77
77
|
export type LyraMapChoroplethInterpolation = 'linear' | 'logarithmic' | 'step';
|
|
78
|
+
/**
|
|
79
|
+
* What a `dataLayers` entry renders.
|
|
80
|
+
*
|
|
81
|
+
* `'auto'` (the default, and the only previous behavior) splits the source by geometry into the
|
|
82
|
+
* fill/line/circle layers below. `'heatmap'` replaces that split with MapLibre's own first-class
|
|
83
|
+
* `heatmap` layer — a density surface, which the geometry split cannot express at all: thousands of
|
|
84
|
+
* overlapping circles read as one opaque blob, not as where the data is concentrated.
|
|
85
|
+
*/
|
|
86
|
+
export type LyraMapDataLayerKind = 'auto' | 'heatmap';
|
|
87
|
+
/**
|
|
88
|
+
* Native MapLibre marker clustering for one `dataLayers` entry.
|
|
89
|
+
*
|
|
90
|
+
* Clustering is a *source* option plus layers, not new rendering machinery: setting this adds
|
|
91
|
+
* `cluster`/`clusterRadius`/`clusterMaxZoom` to the entry's GeoJSON source and swaps its geometry
|
|
92
|
+
* split for a `${sourceId}-cluster` circle, a `${sourceId}-cluster-count` label, and a
|
|
93
|
+
* `${sourceId}-circle` layer for the points that stayed unclustered. It is the answer to a
|
|
94
|
+
* thousands-of-pins map, which `markers` cannot be: `markers` mints one real DOM element per entry,
|
|
95
|
+
* which is correct for tens of pins and unreadable (and expensive) for thousands.
|
|
96
|
+
*
|
|
97
|
+
* A clustered source carries points only — MapLibre drops non-point geometry when clustering — so no
|
|
98
|
+
* fill/line layer is created for a clustered entry.
|
|
99
|
+
*/
|
|
100
|
+
export interface LyraMapClusterOptions {
|
|
101
|
+
/** Cluster radius in pixels at each zoom level. Defaults to 50, MapLibre's own default. */
|
|
102
|
+
readonly radius?: number;
|
|
103
|
+
/** Zoom past which points stop being clustered. Defaults to 14. */
|
|
104
|
+
readonly maxZoom?: number;
|
|
105
|
+
/**
|
|
106
|
+
* `[pointCount, radiusPx]` breaks for the cluster circle, in the same ascending `[value, output]`
|
|
107
|
+
* shape as `choropleth.stops` and with the same `['step', …]` semantics: the first entry's output
|
|
108
|
+
* is also the base, so counts below the first threshold use it.
|
|
109
|
+
*/
|
|
110
|
+
readonly radiusSteps?: readonly (readonly [number, number])[];
|
|
111
|
+
/**
|
|
112
|
+
* `[pointCount, color]` breaks for the cluster circle. Same vocabulary as `choropleth.stops`,
|
|
113
|
+
* including color resolution: a `var(--lr-…)` reference is resolved against the host before it
|
|
114
|
+
* reaches MapLibre, which paints to a WebGL canvas and never sees the CSS cascade.
|
|
115
|
+
*/
|
|
116
|
+
readonly colorSteps?: readonly (readonly [number, string])[];
|
|
117
|
+
/**
|
|
118
|
+
* Font stack for the cluster count label, which must exist in the style's own glyph source.
|
|
119
|
+
* Defaults to MapLibre's spec default; supply the names your style actually ships when that
|
|
120
|
+
* default is absent. The count label is skipped entirely when the style declares no `glyphs`,
|
|
121
|
+
* since a text layer without one paints nothing and only emits peer errors.
|
|
122
|
+
*/
|
|
123
|
+
readonly countFont?: readonly string[];
|
|
124
|
+
}
|
|
125
|
+
/** A heatmap paint value expressed either as one constant or bounded `[zoom, value]` stops. */
|
|
126
|
+
export type LyraMapHeatmapZoomValue = number | readonly (readonly [zoom: number, value: number])[];
|
|
127
|
+
/** Paint configuration for a `kind: 'heatmap'` data layer. */
|
|
128
|
+
export interface LyraMapHeatmapOptions {
|
|
129
|
+
/** Feature property weighting each point. Omitted, every point weighs 1 (MapLibre's default). */
|
|
130
|
+
readonly weightField?: string;
|
|
131
|
+
/**
|
|
132
|
+
* `[min, max]` of `weightField` in the data's own units, mapped onto MapLibre's 0–1 weight. Without
|
|
133
|
+
* it the raw property value is used, which saturates the surface for any quantity above ~1.
|
|
134
|
+
*/
|
|
135
|
+
readonly weightRange?: readonly [number, number];
|
|
136
|
+
/**
|
|
137
|
+
* `[density, color]` ramp stops, density in `[0, 1]` — the same `[value, color]` vocabulary
|
|
138
|
+
* `choropleth.stops` and `legendGradient` already share, `var(--lr-…)` references included. A ramp
|
|
139
|
+
* that does not start at density 0 gets a fully transparent stop prepended, because a colored zero
|
|
140
|
+
* tints the entire map.
|
|
141
|
+
*
|
|
142
|
+
* One stop is therefore enough, as long as it sits above density 0: `[[1, hot]]` is spelled
|
|
143
|
+
* exactly the way it reads, transparent to hot. The only ramp that cannot be honored is a lone
|
|
144
|
+
* stop AT density 0, which is a flat color rather than a gradient; that one falls back to the
|
|
145
|
+
* default ramp.
|
|
146
|
+
*/
|
|
147
|
+
readonly stops?: readonly (readonly [number, string])[];
|
|
148
|
+
/** Kernel radius in pixels, or linear `[zoom, radius]` stops. Zooms clamp to `[0, 24]`, radii
|
|
149
|
+
* to `[1, 200]`, and a scalar/default remains 30. */
|
|
150
|
+
readonly radius?: LyraMapHeatmapZoomValue;
|
|
151
|
+
/** Global intensity multiplier, or linear `[zoom, intensity]` stops. Zooms clamp to `[0, 24]`,
|
|
152
|
+
* intensity to `[0, 100]`, and a scalar/default remains 1. */
|
|
153
|
+
readonly intensity?: LyraMapHeatmapZoomValue;
|
|
154
|
+
/** Whole-layer opacity in `[0, 1]`. Omitted, MapLibre's own default remains in force. */
|
|
155
|
+
readonly opacity?: number;
|
|
156
|
+
}
|
|
78
157
|
/** One GeoJSON source rendered as three layers (`${sourceId}-fill` for polygons, `${sourceId}-line`
|
|
79
|
-
* for lines/outlines, `${sourceId}-circle` for points)
|
|
80
|
-
*
|
|
158
|
+
* for lines/outlines, `${sourceId}-circle` for points), or — under `cluster`/`kind` — as the
|
|
159
|
+
* cluster or heatmap layers those describe. Colors resolve from `--lr-*` tokens at apply time,
|
|
160
|
+
* defaulting to `accent`. */
|
|
81
161
|
export interface LyraMapGeoJsonDataLayer {
|
|
82
162
|
/** Trimmed nonempty business identity. A collection retains the first occurrence and ignores
|
|
83
163
|
* blank or later duplicate `sourceId` records. */
|
|
@@ -102,6 +182,20 @@ export interface LyraMapGeoJsonDataLayer {
|
|
|
102
182
|
* to `color`, then to `tone`. See `color` for why these are separable.
|
|
103
183
|
*/
|
|
104
184
|
readonly strokeColor?: string;
|
|
185
|
+
/** What this entry renders. Defaults to `'auto'` — today's geometry split, unchanged. */
|
|
186
|
+
readonly kind?: LyraMapDataLayerKind;
|
|
187
|
+
/**
|
|
188
|
+
* Paint configuration for `kind: 'heatmap'`. Ignored under any other kind, so it can be carried
|
|
189
|
+
* beside an `'auto'` entry without effect.
|
|
190
|
+
*/
|
|
191
|
+
readonly heatmap?: LyraMapHeatmapOptions;
|
|
192
|
+
/**
|
|
193
|
+
* Enables native MapLibre clustering for this entry. `cluster: {}` accepts every default.
|
|
194
|
+
*
|
|
195
|
+
* Ignored when `kind` is `'heatmap'`: a heatmap already aggregates density, and clustering its
|
|
196
|
+
* input would feed it one weighted point per cluster instead of the real distribution.
|
|
197
|
+
*/
|
|
198
|
+
readonly cluster?: LyraMapClusterOptions;
|
|
105
199
|
}
|
|
106
200
|
export interface LyraMapMarker {
|
|
107
201
|
/** Optional explicit business identity. Explicit IDs are trimmed and must be nonempty; the
|
|
@@ -122,6 +216,19 @@ export interface LyraMapMarker {
|
|
|
122
216
|
*/
|
|
123
217
|
readonly unsafeHtml?: string;
|
|
124
218
|
}
|
|
219
|
+
/** Input path that activated a declarative map marker. */
|
|
220
|
+
export type LyraMapMarkerActivationSource = 'pointer' | 'keyboard';
|
|
221
|
+
/** Immutable payload emitted when a declarative marker is activated. */
|
|
222
|
+
export interface LyraMapMarkerActivationDetail {
|
|
223
|
+
/** Trimmed explicit marker identity, or `undefined` for an idless marker. */
|
|
224
|
+
readonly id: string | undefined;
|
|
225
|
+
/** Validated marker position as `[longitude, latitude]`. */
|
|
226
|
+
readonly lngLat: readonly [number, number];
|
|
227
|
+
/** The accepted declarative marker snapshot. */
|
|
228
|
+
readonly marker: LyraMapMarker;
|
|
229
|
+
/** Whether activation came through click/pointer semantics or the keyboard contract. */
|
|
230
|
+
readonly source: LyraMapMarkerActivationSource;
|
|
231
|
+
}
|
|
125
232
|
/** Peer-neutral subset of a MapLibre style accepted by `mapStyle`. */
|
|
126
233
|
export interface LyraMapStyleSpecification {
|
|
127
234
|
readonly version: 8;
|
|
@@ -168,29 +275,37 @@ export type LyraMapBounds = readonly [
|
|
|
168
275
|
readonly [number, number]
|
|
169
276
|
];
|
|
170
277
|
/**
|
|
171
|
-
* Builds a maplibre-gl `updateData()` diff when
|
|
172
|
-
*
|
|
278
|
+
* Builds a maplibre-gl `updateData()` diff when stable feature ids make the change addressable,
|
|
279
|
+
* and returns `null` otherwise so the caller replaces the whole source instead. Property changes,
|
|
280
|
+
* additions, removals, and order changes all stay on the incremental path.
|
|
173
281
|
*
|
|
174
282
|
* `setData()` unconditionally re-tiles and repaints an entire source with no diffing. That is
|
|
175
283
|
* invisible on a static map and expensive on an animated one: advancing a choropleth a step every
|
|
176
284
|
* few hundred milliseconds re-tiles every polygon each time, when all that changed were the values
|
|
177
285
|
* driving the colour ramp.
|
|
178
286
|
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
287
|
+
* Geometry and bbox values must remain semantically unchanged. The component's ownership boundary
|
|
288
|
+
* necessarily detaches them on every accepted assignment, so reference identity cannot establish
|
|
289
|
+
* that fact; a bounded, accessor-free comparison verifies their JSON data graph instead. Any
|
|
290
|
+
* uncertainty still falls back to `setData()`.
|
|
291
|
+
*
|
|
292
|
+
* MapLibre applies removals before additions. To preserve the feature collection's observable
|
|
293
|
+
* order, the longest next-order prefix already appearing in previous order stays in place; the
|
|
294
|
+
* remaining suffix is removed and re-added in its exact next order. Appends and ordinary removals
|
|
295
|
+
* therefore remain minimal, while a reorder changes only the suffix it invalidated.
|
|
184
296
|
*/
|
|
185
297
|
export declare function buildGeoJsonPropertyDiff(previous: unknown, next: unknown): MapLibreGeoJsonDiff | null;
|
|
186
298
|
export interface LyraMapEventMap {
|
|
187
299
|
'lr-map-load': CustomEvent<null>;
|
|
300
|
+
'lr-map-marker-activate': CustomEvent<LyraMapMarkerActivationDetail>;
|
|
188
301
|
'lr-map-click': CustomEvent<{
|
|
189
302
|
readonly lngLat: readonly [number, number];
|
|
190
303
|
readonly feature: Feature | undefined;
|
|
191
304
|
/** Which layer `feature` was hit on, so a click is attributable when both a choropleth and
|
|
192
|
-
* `dataLayers` are painted. `
|
|
193
|
-
|
|
305
|
+
* `dataLayers` are painted. `'cluster'` marks a hit on a clustered entry's aggregate circle,
|
|
306
|
+
* whose `point_count`/`cluster_id` properties describe the group rather than one feature.
|
|
307
|
+
* `undefined` whenever `feature` is. */
|
|
308
|
+
readonly origin: 'choropleth' | 'data-layer' | 'cluster' | undefined;
|
|
194
309
|
/** The authored `dataLayers[].sourceId` the hit belongs to; `undefined` for a choropleth hit
|
|
195
310
|
* (which has only one possible source) and when nothing was hit. */
|
|
196
311
|
readonly sourceId: string | undefined;
|
|
@@ -199,7 +314,8 @@ export interface LyraMapEventMap {
|
|
|
199
314
|
/**
|
|
200
315
|
* `<lr-map>` — a maplibre-gl wrapper with a declarative legend, choropleth
|
|
201
316
|
* GeoJSON layer, markers, and additive `dataLayers` GeoJSON overlays
|
|
202
|
-
* (arbitrary shapes rendered as a source plus fill/line/circle layers,
|
|
317
|
+
* (arbitrary shapes rendered as a source plus fill/line/circle layers, or — opting in per entry —
|
|
318
|
+
* as a natively clustered point set or a `heatmap` density surface,
|
|
203
319
|
* independent of `choropleth`'s field/stops color-interpolation), plus a peer-neutral
|
|
204
320
|
* `map` getter for common imperative operations. Its runtime value is the underlying MapLibre
|
|
205
321
|
* map, while its declaration stays independent of the optional peer. Requires `maplibre-gl`
|
|
@@ -227,9 +343,15 @@ export interface LyraMapEventMap {
|
|
|
227
343
|
*
|
|
228
344
|
* @customElement lr-map
|
|
229
345
|
* @event lr-map-load - Fired once the underlying maplibregl.Map loads.
|
|
346
|
+
* @event lr-map-marker-activate - Fired once when an accepted declarative marker is activated by
|
|
347
|
+
* pointer/click or by Enter/Space. The immutable detail carries its normalized `id`, validated
|
|
348
|
+
* `lngLat`, accepted marker snapshot, and activation `source`.
|
|
230
349
|
* @event lr-map-click - `detail: { lngLat, feature?, origin?, sourceId? }`. `feature` resolves
|
|
231
|
-
* against the choropleth fill *and* every applied `dataLayers` fill/line/circle layer,
|
|
232
|
-
* first; `origin`/`sourceId` name where it came from.
|
|
350
|
+
* against the choropleth fill *and* every applied `dataLayers` fill/line/circle/cluster layer,
|
|
351
|
+
* topmost first; `origin`/`sourceId` name where it came from. A hit on a clustered entry's
|
|
352
|
+
* aggregate circle reports `origin: 'cluster'` and carries MapLibre's `point_count`/`cluster_id`
|
|
353
|
+
* properties; a `kind: 'heatmap'` layer is never hit-tested, because MapLibre returns no features
|
|
354
|
+
* for a density surface.
|
|
233
355
|
* @csspart base - The non-semantic map wrapper. It exposes `aria-busy="true"` while the optional
|
|
234
356
|
* map library loads and contains ordinary, non-live localized loading text.
|
|
235
357
|
* @csspart container - The MapLibre container. Its generated canvas is the actual focusable map
|
|
@@ -288,6 +410,9 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
288
410
|
center: readonly [number, number];
|
|
289
411
|
/** Initial and controlled map zoom level. */
|
|
290
412
|
zoom: number;
|
|
413
|
+
/** Whether the constructed peer repeats the world horizontally. `undefined` leaves MapLibre's
|
|
414
|
+
* own default in force. Construction-only; set before the map is created. */
|
|
415
|
+
renderWorldCopies?: boolean;
|
|
291
416
|
/**
|
|
292
417
|
* Box the map may not pan outside, `[[west, south], [east, north]]`, or `null` for unconstrained.
|
|
293
418
|
*
|
|
@@ -349,9 +474,17 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
349
474
|
* marker is instead identified by its coordinate occurrence, so colocated idless markers remain
|
|
350
475
|
* separate. */
|
|
351
476
|
markers: readonly LyraMapMarker[];
|
|
352
|
-
/**
|
|
477
|
+
/**
|
|
478
|
+
* Additive GeoJSON layers rendered alongside the choropleth/markers -- each entry becomes a
|
|
353
479
|
* source plus fill/line/circle layers. `sourceId` values are trimmed, must be nonempty, and retain
|
|
354
|
-
* only their first occurrence. Defaults empty (zero behavior change).
|
|
480
|
+
* only their first occurrence. Defaults empty (zero behavior change).
|
|
481
|
+
*
|
|
482
|
+
* An entry opts into either of two other renderings, both strictly additive: `cluster` turns its
|
|
483
|
+
* source into a natively clustered one (aggregate circle, count label, unclustered points), which
|
|
484
|
+
* is what thousands of points need and what `markers` -- one real DOM element per entry -- cannot
|
|
485
|
+
* be; `kind: 'heatmap'` replaces the geometry split with MapLibre's own `heatmap` layer. Neither
|
|
486
|
+
* changes an entry that sets neither.
|
|
487
|
+
*/
|
|
355
488
|
dataLayers: readonly LyraMapGeoJsonDataLayer[];
|
|
356
489
|
/** Accessible name for MapLibre's focusable canvas. A nonempty host `aria-label` remains the
|
|
357
490
|
* overall component name and is not cloned onto the nested focus owner; the canvas uses this
|
|
@@ -373,6 +506,16 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
373
506
|
private _appliedChoroplethSourceId?;
|
|
374
507
|
private _appliedFillLayerId?;
|
|
375
508
|
private _appliedDataLayerIds;
|
|
509
|
+
/**
|
|
510
|
+
* The rendering shape (`'auto'`, a cluster signature, `'heatmap'`) each applied data layer was
|
|
511
|
+
* built with, keyed identically to `_appliedDataLayerIds`.
|
|
512
|
+
*
|
|
513
|
+
* MapLibre bakes `cluster`/`clusterRadius`/`clusterMaxZoom` into a GeoJSON source at `addSource()`
|
|
514
|
+
* time and exposes no setter for them, and a kind change swaps the layer set entirely. Neither
|
|
515
|
+
* can be updated in place, so a shape that no longer matches forces a full teardown and rebuild
|
|
516
|
+
* of that one entry instead of a silently stale source.
|
|
517
|
+
*/
|
|
518
|
+
private _appliedDataLayerShapes;
|
|
376
519
|
/** Last GeoJSON applied per resolved source id, so an update can be diffed against it rather
|
|
377
520
|
* than replacing the whole source. Holds a reference, not a copy -- it is only ever compared. */
|
|
378
521
|
private _appliedGeoJson;
|
|
@@ -383,10 +526,13 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
383
526
|
private _markerInstances;
|
|
384
527
|
private _markerLabels;
|
|
385
528
|
private _markerPopupIds;
|
|
529
|
+
private readonly markerActivationDetails;
|
|
386
530
|
private _configuredPopups;
|
|
387
531
|
private _nextPopupId;
|
|
388
532
|
private peerChromeObserver?;
|
|
389
533
|
private observedPeerContainer?;
|
|
534
|
+
private mapResizeObserver?;
|
|
535
|
+
private observedMapContainer?;
|
|
390
536
|
private _markerColors;
|
|
391
537
|
private _connectGeneration;
|
|
392
538
|
/** The underlying runtime `maplibregl.Map`, declared through Lyra's peer-neutral common-method
|
|
@@ -403,12 +549,22 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
403
549
|
/**
|
|
404
550
|
* Applies `maxBounds`, then verifies the peer's camera survived it.
|
|
405
551
|
*
|
|
406
|
-
* maplibre-gl constrains the camera when bounds are set, and that constrain pass can
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
552
|
+
* maplibre-gl constrains the camera when bounds are set, and that constrain pass can fail in two
|
|
553
|
+
* different ways at the same conditions -- sub-1 fractional zooms in wide containers:
|
|
554
|
+
*
|
|
555
|
+
* * It can leave the transform in a state where `getZoom()` returns a non-number. There is no
|
|
556
|
+
* exception at the call site, so the only reliable signal is to read the camera back
|
|
557
|
+
* afterwards.
|
|
558
|
+
* * It can THROW synchronously out of `setMaxBounds()` itself (maplibre-gl 6.x raises
|
|
559
|
+
* `TypeError: Cannot read properties of null (reading '0')` at a full-world box). That
|
|
560
|
+
* happens *before* the readback line, so the readback guard alone never ran in the case it
|
|
561
|
+
* was written for -- and with no `try`/`catch` the exception escaped `updated()` into the
|
|
562
|
+
* consumer's render cycle, degenerating into repeated throws from the peer's own matrix math
|
|
563
|
+
* on every later `resize`/`setZoom` and a canvas that never paints again.
|
|
564
|
+
*
|
|
565
|
+
* Either way the answer is the same: drop the constraint and restore the camera -- an
|
|
566
|
+
* unconstrained map is a far smaller defect than a blank one -- and say so once, naming the
|
|
567
|
+
* property. Both failures therefore share one revert path.
|
|
412
568
|
*/
|
|
413
569
|
private applyMaxBounds;
|
|
414
570
|
/** `zoom` normalized to a finite value clamped into `[0, 22]` -- maplibre-gl's own default
|
|
@@ -456,17 +612,80 @@ export declare class LyraMap extends LyraElement<LyraMapEventMap> {
|
|
|
456
612
|
* `applyChoropleth()`'s add-or-update-in-place pattern above.
|
|
457
613
|
*/
|
|
458
614
|
private applyDataLayers;
|
|
615
|
+
/**
|
|
616
|
+
* Adds (or repaints, when already present) the layers one entry's kind calls for. Kept separate
|
|
617
|
+
* from source management above so a theme change can re-run exactly the paint half of it without
|
|
618
|
+
* touching sources, data, or map geometry.
|
|
619
|
+
*/
|
|
620
|
+
private applyDataLayerRendering;
|
|
621
|
+
/**
|
|
622
|
+
* Rewrites only the token-derived paint of an already-applied entry, for the kind it was applied
|
|
623
|
+
* with. Split from the add-or-update path above because a theme repaint must never query or
|
|
624
|
+
* mutate map structure -- no `getLayer`, no `addLayer`, no source touch -- so that a retheme
|
|
625
|
+
* cannot re-tile data or resurrect a layer a later reconciliation removed.
|
|
626
|
+
*/
|
|
627
|
+
private paintDataLayer;
|
|
628
|
+
/** The pre-existing geometry split: polygons filled, lines/outlines stroked, points circled. */
|
|
629
|
+
private applyGeometryLayers;
|
|
630
|
+
/** Paint-only half of `applyGeometryLayers`. See `paintDataLayer` for why the halves are split. */
|
|
631
|
+
private paintGeometryLayers;
|
|
632
|
+
/**
|
|
633
|
+
* `['step', ['get', 'point_count'], …]` over the authored cluster color breaks, or the layer's
|
|
634
|
+
* own flat color when none were supplied.
|
|
635
|
+
*
|
|
636
|
+
* Every break resolves through `resolvedLayerColor()` for the same reason `layer.color` does: the
|
|
637
|
+
* breaks speak the `choropleth.stops` vocabulary, so a consumer writes `var(--lr-color-brand)` in
|
|
638
|
+
* one and reasonably expects it in the other -- and MapLibre paints to a WebGL canvas that never
|
|
639
|
+
* sees the CSS cascade, so an unresolved `var()` is not a wrong color but no paint at all.
|
|
640
|
+
*
|
|
641
|
+
* Shared by both halves of the apply/paint split so the two can never resolve differently.
|
|
642
|
+
*/
|
|
643
|
+
private clusterColorExpression;
|
|
644
|
+
/**
|
|
645
|
+
* The three layers native MapLibre clustering needs: an aggregate circle over the clustered
|
|
646
|
+
* points, its count label, and the points that stayed unclustered.
|
|
647
|
+
*
|
|
648
|
+
* No fill/line layer is created here — MapLibre's clustering keeps point features only, so those
|
|
649
|
+
* two would be permanently empty while still occupying ids the click hit-test walks.
|
|
650
|
+
*/
|
|
651
|
+
private applyClusterLayers;
|
|
652
|
+
/** Paint-only half of `applyClusterLayers`. */
|
|
653
|
+
private paintClusterLayers;
|
|
654
|
+
/** The single `heatmap` layer `kind: 'heatmap'` renders, in place of the geometry split. */
|
|
655
|
+
private applyHeatmapLayer;
|
|
656
|
+
/** Paint-only half of `applyHeatmapLayer`. */
|
|
657
|
+
private paintHeatmapLayer;
|
|
658
|
+
/**
|
|
659
|
+
* `['interpolate', ['linear'], ['heatmap-density'], …]` over the authored ramp, or the shared
|
|
660
|
+
* token ramp when none is usable. Colors resolve through the host first, since MapLibre paints to
|
|
661
|
+
* a WebGL canvas and never sees a `var()`.
|
|
662
|
+
*
|
|
663
|
+
* One authored stop is enough, as long as it sits above density 0: the transparent floor this
|
|
664
|
+
* prepends anyway makes it a real two-stop ramp, and `[[1, hot]]` is the most natural way to spell
|
|
665
|
+
* "transparent to hot". The token ramp takes over only when the result still cannot interpolate --
|
|
666
|
+
* a lone stop AT density 0, which describes a flat colour rather than a gradient.
|
|
667
|
+
*/
|
|
668
|
+
private heatmapColorExpression;
|
|
669
|
+
/**
|
|
670
|
+
* Whether the active style can render text at all. Prefers the live style (a `mapStyle` URL's
|
|
671
|
+
* glyph source is only knowable once loaded) and falls back to the declarative specification.
|
|
672
|
+
*/
|
|
673
|
+
private styleProvidesGlyphs;
|
|
459
674
|
/** Allocates a private source/layer namespace that cannot overwrite base-style resources. */
|
|
460
675
|
private resolveDataLayerSourceId;
|
|
461
676
|
/** Removes one previously-applied `dataLayers` entry's source/layers, if present. */
|
|
462
677
|
private removeDataLayer;
|
|
463
678
|
private applyMarkers;
|
|
464
679
|
private readonly configuredMarkerElements;
|
|
465
|
-
private
|
|
680
|
+
private configureMarkerInteraction;
|
|
681
|
+
private emitMarkerActivation;
|
|
466
682
|
private get effectiveMapLabel();
|
|
467
683
|
private validMarkerLngLat;
|
|
468
684
|
private popupId;
|
|
469
685
|
private configurePopupSemantics;
|
|
686
|
+
private stopObservingMapAllocation;
|
|
687
|
+
/** Keeps MapLibre's canvas allocation synchronized with this component's live container. */
|
|
688
|
+
private observeMapAllocation;
|
|
470
689
|
private stopObservingPeerChrome;
|
|
471
690
|
/** Projects stable Lyra parts onto peer-owned nodes without erasing existing part tokens. */
|
|
472
691
|
private syncPeerChromeParts;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing}from"lit";import{property,query,state}from"lit/decorators.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{devWarnOnce}from"../../../internal/dev-mode-attribute-warning.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{finiteRange}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{notifyMapCanvasReady}from"../../../internal/map-canvas-ready.js";import{acquireAnnouncementSink}from"../../../internal/announcer.js";import{srOnly}from"../../../internal/a11y.js";import{ThemeWatcher}from"../../../internal/theme-watcher.js";import{loadMaplibre}from"./map-loader.js";import{styles}from"./map.styles.js";import"../../overlays/skeleton/skeleton.class.js";import{LYRA_DEFAULT_close,LYRA_DEFAULT_items,LYRA_DEFAULT_loading,LYRA_DEFAULT_map,LYRA_DEFAULT_mapInitializationFailed,LYRA_DEFAULT_mapLegend,LYRA_DEFAULT_mapMissingLibrary,LYRA_DEFAULT_mapStyleRequired,LYRA_DEFAULT_mapWebglUnavailable,LYRA_DEFAULT_paginationSummary}from"../../../internal/default-strings.generated.js";function supportsWebGL2(host){try{return host.ownerDocument.createElement("canvas").getContext("webgl2")!==null}catch{return!1}}function hasMapStyle(style){return typeof style=="string"?style.trim().length>0:style!==void 0}const MAX_MAP_LEGEND_GRADIENT_STOPS=64;function normalizeMapLegendGradient(value){if(!Array.isArray(value))return[];const usable=[],scanCount=Math.min(value.length,MAX_MAP_LEGEND_GRADIENT_STOPS);for(let index=0;index<scanCount;index+=1){const stop=value[index];if(!Array.isArray(stop)||stop.length<2)continue;const[rawValue,rawColor]=stop;if(typeof rawValue!="number"||!Number.isFinite(rawValue)||typeof rawColor!="string")continue;const color=sanitizeCssColor(rawColor);color&&usable.push([rawValue,color])}return usable.length<2?[]:Object.freeze([...usable].sort((a,b)=>a[0]-b[0]))}const MAP_LEGEND_ITEM_LIMIT=100,MAP_LEGEND_SCAN_LIMIT=1e3,MAP_LEGEND_LABEL_LIMIT=256,MAP_LEGEND_TOTAL_LABEL_LIMIT=8192,MAP_LEGEND_COLOR_LIMIT=256,MAP_LEGEND_PATTERNS=new Set(["solid","diagonal","dots","crosshatch"]),EMPTY_MAP_LEGEND=Object.freeze([]),EMPTY_MAP_LEGEND_PROJECTION=Object.freeze({inputCount:0,renderedCount:0,omittedCount:0,truncatedLabelCount:0,truncated:!1});function boundedLegendText(value,limit){return value.length<=limit?value:`${value.slice(0,Math.max(0,limit-1))}\u2026`}function normalizeMapLegend(value){let input;try{input=Array.isArray(value)?value:[]}catch{input=[]}let inputCount=0;try{inputCount=Math.max(0,Math.min(Number.MAX_SAFE_INTEGER,input.length))}catch{inputCount=0}const entries=[];let labelCharacters=0,truncatedLabelCount=0;const scanCount=Math.min(inputCount,MAP_LEGEND_SCAN_LIMIT);for(let index=0;index<scanCount&&entries.length<MAP_LEGEND_ITEM_LIMIT;index++)try{const candidate=input[index];if(!candidate||typeof candidate!="object")continue;const rawColor=candidate.color,rawLabel=candidate.label,rawPattern=candidate.pattern;if(typeof rawColor!="string"||typeof rawLabel!="string"||typeof rawPattern!="string"||!MAP_LEGEND_PATTERNS.has(rawPattern))continue;const remaining=MAP_LEGEND_TOTAL_LABEL_LIMIT-labelCharacters;if(remaining<=0)break;const labelLimit=Math.min(MAP_LEGEND_LABEL_LIMIT,remaining),label=boundedLegendText(rawLabel,labelLimit);if(!label.trim())continue;rawLabel.length>labelLimit&&truncatedLabelCount++,labelCharacters+=label.length,entries.push(Object.freeze({color:rawColor.slice(0,MAP_LEGEND_COLOR_LIMIT),label,pattern:rawPattern}))}catch{}const frozenEntries=entries.length?Object.freeze(entries):EMPTY_MAP_LEGEND,omittedCount=Math.max(0,inputCount-frozenEntries.length),projection=Object.freeze({inputCount,renderedCount:frozenEntries.length,omittedCount,truncatedLabelCount,truncated:omittedCount>0||truncatedLabelCount>0});return{entries:frozenEntries,projection}}function addPartToken(element,token){const tokens=new Set((element.getAttribute("part")??"").split(/\s+/).filter(Boolean));tokens.add(token),element.setAttribute("part",[...tokens].join(" "))}const CHOROPLETH_LOG_INTERPOLATION_BASE=.25,MAX_MAP_MARKERS=2e3;function popupText(host,markup){const template=host.ownerDocument.createElement("template");template.innerHTML=markup;for(const hidden of template.content.querySelectorAll('script, style, template, [hidden], [aria-hidden="true"]'))hidden.remove();return(template.content.textContent??"").replace(/\s+/gu," ").trim()}const MAX_MAP_DATA_LAYERS=100;function normalizedDataLayers(value){if(!Array.isArray(value))return[];const output=[],seenSourceIds=new Set,scanCount=Math.min(value.length,MAX_MAP_DATA_LAYERS);for(let index=0;index<scanCount;index++){const candidate=value[index];try{if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const rawSourceId=candidate.sourceId;if(typeof rawSourceId!="string")continue;const sourceId=rawSourceId.trim();if(sourceId.length===0||seenSourceIds.has(sourceId))continue;seenSourceIds.add(sourceId),output.push(rawSourceId===sourceId?candidate:{...candidate,sourceId})}catch{}}return output}const FALLBACK_FILL_OPACITY=.75;function ownerWindow(host){return host.ownerDocument?.defaultView??null}function choroplethFillOpacity(host){const raw=ownerWindow(host)?.getComputedStyle(host).getPropertyValue("--lr-map-choropleth-fill-opacity").trim()??"",parsed=Number.parseFloat(raw);return Number.isFinite(parsed)?parsed:FALLBACK_FILL_OPACITY}const TONE_TOKEN={accent:"--lr-color-brand",success:"--lr-color-success",warning:"--lr-color-warning",danger:"--lr-color-danger",neutral:"--lr-color-text-quiet"};function dataLayerColor(host,tone){const token=TONE_TOKEN[tone??"accent"];return(ownerWindow(host)?.getComputedStyle(host).getPropertyValue(token).trim()??"")||"#0969da"}function resolvedLayerColor(host,explicit,tone){const candidate=typeof explicit=="string"?explicit.trim():"";if(!candidate)return dataLayerColor(host,tone);const reference=/^var\(\s*(--[\w-]+)/.exec(candidate);return reference?ownerWindow(host)?.getComputedStyle(host).getPropertyValue(reference[1]).trim()||dataLayerColor(host,tone):candidate}const UNTILEABLE_SCAN_FEATURE_LIMIT=1e4;function warnOnUntileableProperties(geojson,sourceLabel){const features=geojson?.features;if(!Array.isArray(features))return;const limit=Math.min(features.length,UNTILEABLE_SCAN_FEATURE_LIMIT);for(let index=0;index<limit;index+=1){const feature=features[index],properties=feature?.properties;if(!(!properties||typeof properties!="object"))for(const[key,value]of Object.entries(properties)){if(typeof value!="number"||!Number.isFinite(value)||Math.abs(value)<=Number.MAX_SAFE_INTEGER)continue;const identity=feature?.id??`index ${index}`;devWarnOnce(`lyra-map-untileable-property:${sourceLabel}:${key}`,`<lr-map>: feature ${String(identity)} in "${sourceLabel}" carries ${key}=${value}, which is too large to survive maplibre-gl's vector-tile encoding. Tiling happens in a worker, so the failure would reach you only as an opaque "Given varint doesn't fit into 10 bytes" error while the rest of the layer still paints. Carry a reduced figure in the feature and keep the exact value in your own data.`)}}}const GEOJSON_DIFF_FEATURE_LIMIT=1e4;function buildGeoJsonPropertyDiff(previous,next){const previousFeatures=previous?.features,nextFeatures=next?.features;if(!Array.isArray(previousFeatures)||!Array.isArray(nextFeatures)||previousFeatures.length!==nextFeatures.length||nextFeatures.length>GEOJSON_DIFF_FEATURE_LIMIT)return null;const update=[];for(let index=0;index<nextFeatures.length;index+=1){const before=previousFeatures[index],after=nextFeatures[index];if(!before||!after)return null;const id=after.id;if(typeof id!="string"&&typeof id!="number"||before.id!==id||before.geometry!==after.geometry)return null;const beforeProperties=before.properties??{},afterProperties=after.properties??{},addOrUpdateProperties=[];for(const[key,value]of Object.entries(afterProperties))Object.is(beforeProperties[key],value)||addOrUpdateProperties.push({key,value});const removeProperties=Object.keys(beforeProperties).filter(key=>!(key in afterProperties));addOrUpdateProperties.length===0&&removeProperties.length===0||update.push({id,addOrUpdateProperties,removeProperties})}return{update}}class LyraMap extends LyraElement{static{this.defaultStrings={...super.defaultStrings,close:LYRA_DEFAULT_close,items:LYRA_DEFAULT_items,loading:LYRA_DEFAULT_loading,map:LYRA_DEFAULT_map,mapInitializationFailed:LYRA_DEFAULT_mapInitializationFailed,mapLegend:LYRA_DEFAULT_mapLegend,mapMissingLibrary:LYRA_DEFAULT_mapMissingLibrary,mapStyleRequired:LYRA_DEFAULT_mapStyleRequired,mapWebglUnavailable:LYRA_DEFAULT_mapWebglUnavailable,paginationSummary:LYRA_DEFAULT_paginationSummary}}static{this.immutableEventDetails=Object.freeze(["lr-map-click"])}static{this.identityEventDetailProperties=Object.freeze({"lr-map-click":Object.freeze(["feature"])})}static{this.ownedCollectionProperties=Object.freeze(["center","mapStyle","choropleth","markers","dataLayers"])}static{this.styles=[LyraElement.styles,styles,srOnly]}static preload(){return loadMaplibre().then(module=>module!==null)}constructor(){super(),this.center=[0,0],this.zoom=2,this.maxBounds=null,this._legend=EMPTY_MAP_LEGEND,this._legendProjection=EMPTY_MAP_LEGEND_PROJECTION,this.hasLegendSlot=!1,this._legendGradient=Object.freeze([]),this.legendGradientLoLabel=null,this.legendGradientHiLabel=null,this.markers=[],this.dataLayers=[],this.label="",this.loading=!0,this.loadLibrary=loadMaplibre,this.visible=ownerWindow(this)?.IntersectionObserver===void 0,this._styleLoaded=!1,this._appliedDataLayerIds=new Map,this._appliedGeoJson=new Map,this._nextDataLayerId=0,this._webglReady=!1,this._markerInstances=new Map,this._markerLabels=new Map,this._markerPopupIds=new Map,this._configuredPopups=new WeakSet,this._nextPopupId=0,this._markerColors=new Map,this._connectGeneration=0,this.configuredMarkerElements=new WeakSet,this.onLegendSlotChange=event=>{const slot=event.target;this.hasLegendSlot=slot.assignedNodes({flatten:!0}).some(node=>node.nodeType===Node.ELEMENT_NODE||(node.textContent??"").trim().length>0)},new ThemeWatcher(this,()=>this.refreshThemePaint())}get legend(){return this._legend}set legend(value){const previous=this._legend,normalized=normalizeMapLegend(value);this._legend=normalized.entries,this._legendProjection=normalized.projection,this.requestUpdate("legend",previous)}probeLegendSlot(){for(const child of Array.from(this.children))if(child.getAttribute("slot")==="legend")return!0;return!1}get legendGradient(){return this._legendGradient}set legendGradient(value){const previous=this._legendGradient;this._legendGradient=normalizeMapLegendGradient(value),this.requestUpdate("legendGradient",previous)}get legendProjection(){return this._legendProjection}get map(){return this._map}pushGeoJson(source,resolvedSourceId,geojson){const previous=this._appliedGeoJson.get(resolvedSourceId),diff=typeof source.updateData=="function"&&previous!==void 0?buildGeoJsonPropertyDiff(previous,geojson):null;diff===null||typeof source.updateData!="function"?source.setData(geojson):diff.update.length>0&&source.updateData(diff),this._appliedGeoJson.set(resolvedSourceId,geojson)}get safeMaxBounds(){const bounds=this.maxBounds;if(!Array.isArray(bounds)||bounds.length!==2)return null;const[southWest,northEast]=bounds;if(!Array.isArray(southWest)||!Array.isArray(northEast))return null;const[west,south]=southWest,[east,north]=northEast,values=[west,south,east,north].map(Number);if(!values.every(value=>Number.isFinite(value)))return null;const[w,s,e,n]=values;return w>=e||s>=n||w<-180||e>180||s<-90||n>90?null:[[w,s],[e,n]]}applyMaxBounds(){const map=this._map;if(!map||typeof map.setMaxBounds!="function")return;const bounds=this.safeMaxBounds,zoomBefore=map.getZoom(),centerBefore=map.getCenter();map.setMaxBounds(bounds),bounds!==null&&(Number.isFinite(map.getZoom())||(map.setMaxBounds(null),Number.isFinite(zoomBefore)&&map.setZoom(zoomBefore),centerBefore&&map.setCenter([centerBefore.lng,centerBefore.lat]),devWarnOnce("lyra-map-max-bounds-rejected","<lr-map>: maxBounds left maplibre-gl without a usable zoom, so it was dropped and the camera restored. This is a peer limitation, not a bad value -- it shows up at sub-1 fractional zooms in wide containers. Raise the zoom, narrow the box, or leave maxBounds unset.")))}get safeZoom(){return finiteRange(this.zoom,2,0,22)}get safeCenter(){const center=Array.isArray(this.center)?this.center:[];return[finiteRange(Number(center[0]),0,-180,180),finiteRange(Number(center[1]),0,-90,90)]}connectedCallback(){super.connectedCallback(),this.syncErrorAnnouncementSink();const generation=++this._connectGeneration,IntersectionObserverCtor=ownerWindow(this)?.IntersectionObserver;if(this.visible=IntersectionObserverCtor===void 0,this.failure=void 0,this.loading=!0,this._webglReady=!1,IntersectionObserverCtor){const observer=new IntersectionObserverCtor(entries=>{entries[0]?.isIntersecting&&(this.visible=!0)});this.intersectionObserver=observer,observer.observe(this)}(async()=>{let mod;try{mod=await this.loadLibrary()}catch{generation===this._connectGeneration&&this.isConnected&&this.failInitialization("missing-peer");return}if(!(generation!==this._connectGeneration||!this.isConnected)){if(this.loading=!1,!mod){this.failInitialization("missing-peer");return}if(this._maplibreModule=mod,!hasMapStyle(this.mapStyle)){this.failInitialization("style-required");return}if(!supportsWebGL2(this)){this.failInitialization("webgl-unavailable");return}this._webglReady=!0,await this.updateComplete,!(generation!==this._connectGeneration||!this.containerEl||!this.isConnected)&&this.tryConstructMap()}})()}disconnectedCallback(){this.releaseErrorAnnouncementSink(),super.disconnectedCallback(),this.disposeMap(),this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0;for(const marker of this._markerInstances.values())marker.remove();this._markerInstances.clear(),this._markerColors.clear(),this._markerLabels.clear(),this._markerPopupIds.clear()}failureMessage(reason=this.failure??"initialization-failed"){switch(reason){case"missing-peer":return this.localize("mapMissingLibrary");case"style-required":return this.localize("mapStyleRequired");case"webgl-unavailable":return this.localize("mapWebglUnavailable");case"initialization-failed":return this.localize("mapInitializationFailed")}}failInitialization(reason,partialMap){try{partialMap?.remove()}catch{}this.disposeMap(),this.loading=!1,this.failure=reason,this.errorAnnouncementSink?.announce(this.failureMessage(reason))}disposeMap(){this.stopObservingPeerChrome();try{this._map?.remove()}catch{}this._map=void 0,this._styleLoaded=!1,this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0,this._appliedDataLayerIds.clear(),this._appliedGeoJson.clear()}adoptedCallback(){super.adoptedCallback(),this.stopObservingPeerChrome(),this.releaseErrorAnnouncementSink(),this.syncErrorAnnouncementSink()}syncErrorAnnouncementSink(){this.isConnected&&this.errorAnnouncementSink?.element.ownerDocument!==this.ownerDocument&&(this.releaseErrorAnnouncementSink(),this.errorAnnouncementSink=acquireAnnouncementSink("assertive",{document:this.ownerDocument,source:this}))}releaseErrorAnnouncementSink(){this.errorAnnouncementSink?.release(),this.errorAnnouncementSink=void 0}tryConstructMap(){if(this._map||!this._maplibreModule||!this._webglReady||!this.containerEl||!this.visible||!this.isConnected)return;if(!hasMapStyle(this.mapStyle)){this.failInitialization("style-required");return}const mod=this._maplibreModule;let candidate;try{candidate=new mod.Map({container:this.containerEl,style:this.mapStyle,center:this.safeCenter,zoom:this.safeZoom,locale:{"Map.Title":this.effectiveMapLabel,"Marker.Title":this.localize("map"),"Popup.Close":this.localize("close")}}),candidate.on("error",event=>{if(this._map===candidate&&!this._styleLoaded){this.failInitialization("initialization-failed");return}console.error("lr-map:",event.error??event)}),candidate.on("load",()=>{if(this._map===candidate)try{this._styleLoaded=!0,this.applyChoropleth(),this.applyMarkers(),this.applyDataLayers(),this.emit("lr-map-load")}catch{this.failInitialization("initialization-failed")}}),candidate.on("click",event=>{if(this._map!==candidate)return;const fillLayerId=this._appliedFillLayerId,layerIds=[];fillLayerId&&candidate.getLayer(fillLayerId)&&layerIds.push(fillLayerId);for(const resolvedSourceId of this._appliedDataLayerIds.values())for(const suffix of["-fill","-line","-circle"]){const layerId=`${resolvedSourceId}${suffix}`;candidate.getLayer(layerId)&&layerIds.push(layerId)}const hit=(layerIds.length?candidate.queryRenderedFeatures(event.point,{layers:layerIds}):[])[0],hitLayerId=hit?.layer?.id;let origin,sourceId;if(hitLayerId!==void 0){if(hitLayerId===fillLayerId)origin="choropleth";else for(const[publicSourceId,resolvedSourceId]of this._appliedDataLayerIds)if(hitLayerId.startsWith(`${resolvedSourceId}-`)){origin="data-layer",sourceId=publicSourceId;break}}this.emit("lr-map-click",{lngLat:[event.lngLat.lng,event.lngLat.lat],feature:hit,origin,sourceId})});const canvas=candidate.getCanvas?.();canvas&¬ifyMapCanvasReady(this,canvas),this._map=candidate,this.observePeerChrome(),this.failure=void 0}catch{this.failInitialization("initialization-failed",candidate)}}updated(changed){if(super.updated(changed),this.setAttribute("aria-busy",String(this.loading)),changed.has("visible")&&this.visible&&this.tryConstructMap(),changed.has("mapStyle")&&!hasMapStyle(this.mapStyle)&&this._maplibreModule)this.failInitialization("style-required");else if(changed.has("mapStyle")&&!this._map&&this._maplibreModule&&hasMapStyle(this.mapStyle))this.tryConstructMap();else if(changed.has("mapStyle")&&this._map){this._styleLoaded=!1,this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0;const map=this._map;try{map.once("style.load",()=>{if(this._map===map)try{this._styleLoaded=!0,this._appliedDataLayerIds.clear(),this._appliedGeoJson.clear(),this.applyChoropleth(),this.applyDataLayers()}catch{this.scheduleAfterUpdate(()=>this.failInitialization("initialization-failed"),"map-style-failure")}}),map.setStyle(this.mapStyle)}catch{this.scheduleAfterUpdate(()=>this.failInitialization("initialization-failed"),"map-style-failure")}}else if(this._styleLoaded&&(changed.has("dataLayers")||changed.has("choropleth"))){const nextChoroplethSourceId=this.choropleth?this.resolveChoroplethSourceId(this.choropleth.sourceId):void 0;this._appliedChoroplethSourceId&&this._appliedChoroplethSourceId!==nextChoroplethSourceId&&this.removeChoropleth(),changed.has("dataLayers")&&this.applyDataLayers(),this.applyChoropleth()}changed.has("center")&&this._map&&this._map.setCenter(this.safeCenter),changed.has("zoom")&&this._map&&this._map.setZoom(this.safeZoom),changed.has("maxBounds")&&this._map&&this.applyMaxBounds(),changed.has("markers")&&this._map&&this.applyMarkers(),this.syncMapSemantics()}willUpdate(changed){super.willUpdate(changed),changed.has("mapStyle")&&!this._map&&this._maplibreModule&&hasMapStyle(this.mapStyle)&&(this._webglReady||(this._webglReady=supportsWebGL2(this)),this.failure=this._webglReady?void 0:"webgl-unavailable",this._webglReady||(this.loading=!1,this.errorAnnouncementSink?.announce(this.failureMessage("webgl-unavailable"))))}refreshThemePaint(){if(!this._map||!this._styleLoaded)return;const fillOpacity=choroplethFillOpacity(this);this._appliedFillLayerId&&this._map.setPaintProperty(this._appliedFillLayerId,"fill-opacity",fillOpacity);const dataLayersBySourceId=new Map(normalizedDataLayers(this.dataLayers).map(layer=>[layer.sourceId,layer]));for(const[publicSourceId,sourceId]of this._appliedDataLayerIds){const dataLayer=dataLayersBySourceId.get(publicSourceId);if(!dataLayer)continue;const color=resolvedLayerColor(this,dataLayer.color,dataLayer.tone),stroke=resolvedLayerColor(this,dataLayer.strokeColor??dataLayer.color,dataLayer.tone);this._map.setPaintProperty(`${sourceId}-fill`,"fill-color",color),this._map.setPaintProperty(`${sourceId}-fill`,"fill-opacity",fillOpacity),this._map.setPaintProperty(`${sourceId}-line`,"line-color",stroke),this._map.setPaintProperty(`${sourceId}-circle`,"circle-color",stroke)}}applyChoropleth(){if(!this._map)return;if(!this.choropleth){this.removeChoropleth();return}const{geojson,field,stops}=this.choropleth,sourceId=this.resolveChoroplethSourceId(this.choropleth.sourceId),fillLayerId=`${sourceId}-fill`;this._appliedChoroplethSourceId&&this._appliedChoroplethSourceId!==sourceId&&this.removeChoropleth(),warnOnUntileableProperties(geojson,"choropleth");const existingSource=this._map.getSource(sourceId);if(existingSource?this.pushGeoJson(existingSource,sourceId,geojson):(this._map.addSource(sourceId,{type:"geojson",data:geojson}),this._appliedGeoJson.set(sourceId,geojson)),this._appliedChoroplethSourceId=sourceId,stops.length===0)return;let colorExpr;if(this.choropleth.interpolation==="step"){const base=typeof this.choropleth.stepBaseColor=="string"&&this.choropleth.stepBaseColor.trim()?this.choropleth.stepBaseColor.trim():stops[0][1];colorExpr=["step",["get",field],base];for(const[value,color]of stops)colorExpr.push(value,color)}else{colorExpr=["interpolate",this.choropleth.interpolation==="logarithmic"?["exponential",CHOROPLETH_LOG_INTERPOLATION_BASE]:["linear"],["get",field]];for(const[value,color]of stops)colorExpr.push(value,color)}this._map.getLayer(fillLayerId)?(this._map.setPaintProperty(fillLayerId,"fill-color",colorExpr),this._map.setPaintProperty(fillLayerId,"fill-opacity",choroplethFillOpacity(this))):this._map.addLayer({id:fillLayerId,type:"fill",source:sourceId,paint:{"fill-color":colorExpr,"fill-opacity":choroplethFillOpacity(this)}}),this._appliedFillLayerId=fillLayerId}resolveChoroplethSourceId(sourceId){const dataSourceIds=new Set(normalizedDataLayers(this.dataLayers).map(layer=>layer.sourceId));let resolved=sourceId;for(;dataSourceIds.has(resolved);)resolved=`lr-choropleth-${resolved}`;return resolved}removeChoropleth(){!this._map||!this._appliedChoroplethSourceId||(this._appliedFillLayerId&&this._map.getLayer(this._appliedFillLayerId)&&this._map.removeLayer(this._appliedFillLayerId),this._map.getSource(this._appliedChoroplethSourceId)&&this._map.removeSource(this._appliedChoroplethSourceId),this._appliedGeoJson.delete(this._appliedChoroplethSourceId),this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0)}applyDataLayers(){if(!this._map)return;const layers=normalizedDataLayers(this.dataLayers),nextIds=new Set(layers.map(layer=>layer.sourceId));for(const publicSourceId of this._appliedDataLayerIds.keys())nextIds.has(publicSourceId)||this.removeDataLayer(publicSourceId);for(const layer of layers){const{sourceId:publicSourceId,geojson,tone}=layer,sourceId=this.resolveDataLayerSourceId(publicSourceId);warnOnUntileableProperties(geojson,publicSourceId);const existingSource=this._map.getSource(sourceId);existingSource?this.pushGeoJson(existingSource,sourceId,geojson):(this._map.addSource(sourceId,{type:"geojson",data:geojson}),this._appliedGeoJson.set(sourceId,geojson));const color=resolvedLayerColor(this,layer.color,tone),stroke=resolvedLayerColor(this,layer.strokeColor??layer.color,tone),fillId=`${sourceId}-fill`,lineId=`${sourceId}-line`,circleId=`${sourceId}-circle`;this._map.getLayer(fillId)?(this._map.setPaintProperty(fillId,"fill-color",color),this._map.setPaintProperty(fillId,"fill-opacity",choroplethFillOpacity(this))):this._map.addLayer({id:fillId,type:"fill",source:sourceId,filter:["==",["geometry-type"],"Polygon"],paint:{"fill-color":color,"fill-opacity":choroplethFillOpacity(this)}}),this._map.getLayer(lineId)?this._map.setPaintProperty(lineId,"line-color",stroke):this._map.addLayer({id:lineId,type:"line",source:sourceId,filter:["in",["geometry-type"],["literal",["LineString","Polygon"]]],paint:{"line-color":stroke,"line-width":2}}),this._map.getLayer(circleId)?this._map.setPaintProperty(circleId,"circle-color",stroke):this._map.addLayer({id:circleId,type:"circle",source:sourceId,filter:["==",["geometry-type"],"Point"],paint:{"circle-color":stroke,"circle-radius":5}}),this._appliedDataLayerIds.set(publicSourceId,sourceId)}}resolveDataLayerSourceId(publicSourceId){const applied=this._appliedDataLayerIds.get(publicSourceId);if(applied)return applied;let sourceId;do sourceId=`lr-data-layer-${this._nextDataLayerId++}`;while(this._map?.getSource(sourceId)||this._map?.getLayer(`${sourceId}-fill`)||this._map?.getLayer(`${sourceId}-line`)||this._map?.getLayer(`${sourceId}-circle`));return sourceId}removeDataLayer(publicSourceId){if(!this._map)return;const sourceId=this._appliedDataLayerIds.get(publicSourceId);if(sourceId){for(const layerId of[`${sourceId}-fill`,`${sourceId}-line`,`${sourceId}-circle`])this._map.getLayer(layerId)&&this._map.removeLayer(layerId);this._map.getSource(sourceId)&&this._map.removeSource(sourceId),this._appliedDataLayerIds.delete(publicSourceId),this._appliedGeoJson.delete(sourceId)}}applyMarkers(){const map=this._map,mod=this._maplibreModule;if(!map||!mod)return;const visible=new Set,coordCounts=new Map,explicitIds=new Set,markers=Array.isArray(this.markers)?this.markers.slice(0,MAX_MAP_MARKERS):[];for(const candidate of markers){const lngLat=this.validMarkerLngLat(candidate);if(!lngLat)continue;const m=candidate,rawId=m.id;let key;if(rawId!==void 0){if(typeof rawId!="string")continue;const id=rawId.trim();if(id.length===0||explicitIds.has(id))continue;explicitIds.add(id),key=`id:${id}`}else{const coordKey=`${lngLat[0]},${lngLat[1]}`,occurrence=coordCounts.get(coordKey)??0;coordCounts.set(coordKey,occurrence+1),key=`coordinate:${coordKey}#${occurrence}`}visible.add(key);let existing=this._markerInstances.get(key);const markerColor=sanitizeCssColor(m.color);if(existing&&this._markerColors.get(key)!==markerColor&&(existing.remove(),this._markerInstances.delete(key),this._markerColors.delete(key),existing=void 0),existing){existing.setLngLat(lngLat);const popup=existing.getPopup();if(m.unsafeHtml)if(popup)popup.setHTML(m.unsafeHtml);else{const nextPopup=new mod.Popup({offset:12}).setHTML(m.unsafeHtml);existing.setPopup(nextPopup),this.configurePopupSemantics(key,existing,nextPopup)}else if(m.label)if(popup)popup.setText(m.label);else{const nextPopup=new mod.Popup({offset:12}).setText(m.label);existing.setPopup(nextPopup),this.configurePopupSemantics(key,existing,nextPopup)}else popup&&existing.setPopup(void 0)}else{const marker=new mod.Marker(markerColor?{color:markerColor}:void 0).setLngLat(lngLat);if(m.unsafeHtml||m.label){const popup=new mod.Popup({offset:12});m.unsafeHtml?popup.setHTML(m.unsafeHtml):m.label&&popup.setText(m.label),marker.setPopup(popup),this.configurePopupSemantics(key,marker,popup)}marker.addTo(map),this._markerInstances.set(key,marker),this._markerColors.set(key,markerColor)}const markerLabel=m.label?.trim()||(m.unsafeHtml?popupText(this,m.unsafeHtml):"");this._markerLabels.set(key,markerLabel||void 0);const markerElement=this._markerInstances.get(key)?.getElement?.();if(markerElement){addPartToken(markerElement,"marker"),markerElement.setAttribute("aria-label",markerLabel||this.localize("map")),markerElement.setAttribute("lang",this.effectiveLocale);const currentMarker=this._markerInstances.get(key),popup=currentMarker?.getPopup();popup&¤tMarker?(this.configurePopupSemantics(key,currentMarker,popup),this.syncPopupSemantics(key,currentMarker,popup),this.configureMarkerKeyboard(markerElement,currentMarker)):(markerElement.removeAttribute("aria-controls"),markerElement.removeAttribute("aria-expanded"))}}for(const[key,marker]of this._markerInstances)visible.has(key)||(marker.remove(),this._markerInstances.delete(key),this._markerColors.delete(key),this._markerLabels.delete(key),this._markerPopupIds.delete(key))}configureMarkerKeyboard(markerElement,marker){this.configuredMarkerElements.has(markerElement)||(this.configuredMarkerElements.add(markerElement),markerElement.addEventListener("keydown",event=>{event.key!==" "||!marker.getPopup?.()||event.defaultPrevented||event.preventDefault()},{capture:!0}))}get effectiveMapLabel(){return this.getAttribute("aria-label")===""?"":this.label||this.localize("map")}validMarkerLngLat(candidate){if(!candidate||typeof candidate!="object")return null;const lngLat=candidate.lngLat;if(!Array.isArray(lngLat)||lngLat.length<2)return null;const[lng,lat]=lngLat;return typeof lng!="number"||typeof lat!="number"||!Number.isFinite(lng)||!Number.isFinite(lat)||lat<-90||lat>90?null:[lng,lat]}popupId(key){let id=this._markerPopupIds.get(key);return id||(id=`map-popup-${this._connectGeneration}-${++this._nextPopupId}`,this._markerPopupIds.set(key,id)),id}configurePopupSemantics(key,marker,popup){!popup||typeof popup!="object"||this._configuredPopups.has(popup)||(this._configuredPopups.add(popup),popup.on?.("open",()=>this.syncPopupSemantics(key,marker,popup)),popup.on?.("close",()=>{marker.getElement?.()?.setAttribute("aria-expanded","false")}))}stopObservingPeerChrome(){this.peerChromeObserver?.disconnect(),this.peerChromeObserver=void 0,this.observedPeerContainer=void 0}syncPeerChromeParts(root=this.containerEl??this.renderRoot){const selectors=[[".maplibregl-marker","marker"],[".maplibregl-popup","popup"],[".maplibregl-popup-content","popup-content"],[".maplibregl-popup-close-button","popup-close-button"],[".maplibregl-ctrl-attrib","attribution"],[".maplibregl-ctrl-attrib-button","attribution-toggle"]];for(const[selector,part]of selectors){const candidate=root;candidate.matches?.(selector)&&addPartToken(candidate,part);for(const element of root.querySelectorAll(selector))addPartToken(element,part)}}observePeerChrome(){const container=this.containerEl;if(!container||(this.syncPeerChromeParts(container),this.observedPeerContainer===container&&this.peerChromeObserver))return;this.stopObservingPeerChrome();const MutationObserverCtor=container.ownerDocument.defaultView?.MutationObserver;MutationObserverCtor&&(this.observedPeerContainer=container,this.peerChromeObserver=new MutationObserverCtor(records=>{if(!(!this.isConnected||this.containerEl!==container))for(const record of records)for(const node of record.addedNodes)node.nodeType===Node.ELEMENT_NODE&&this.syncPeerChromeParts(node)}),this.peerChromeObserver.observe(container,{childList:!0,subtree:!0}))}syncPopupSemantics(key,marker,popup){const markerElement=marker?.getElement?.();if(!markerElement)return;const id=this.popupId(key);markerElement.setAttribute("aria-controls",id),markerElement.setAttribute("aria-expanded",popup?.isOpen?.()?"true":"false");const popupElement=popup?.getElement?.();if(!popupElement)return;addPartToken(markerElement,"marker"),addPartToken(popupElement,"popup"),popupElement.id=id,popupElement.setAttribute("role","dialog"),popupElement.setAttribute("lang",this.effectiveLocale),popupElement.setAttribute("aria-label",this._markerLabels.get(key)||this.effectiveMapLabel);const popupContent=popupElement.querySelector(".maplibregl-popup-content");popupContent&&addPartToken(popupContent,"popup-content");const closeButton=popupElement.querySelector(".maplibregl-popup-close-button");closeButton&&addPartToken(closeButton,"popup-close-button"),closeButton?.setAttribute("aria-label",this.localize("close"))}syncMapSemantics(){const canvas=this._map?.getCanvas?.();canvas&&(canvas.setAttribute("aria-label",this.effectiveMapLabel),canvas.setAttribute("lang",this.effectiveLocale),this.legend.length||this.legendProjection.truncated?canvas.setAttribute("aria-describedby","map-legend"):canvas.removeAttribute("aria-describedby"));for(const[key,marker]of this._markerInstances){const markerElement=marker.getElement?.();if(!markerElement)continue;addPartToken(markerElement,"marker"),markerElement.setAttribute("aria-label",this._markerLabels.get(key)||this.localize("map")),markerElement.setAttribute("lang",this.effectiveLocale);const popup=marker.getPopup?.();popup&&this.syncPopupSemantics(key,marker,popup)}this.syncPeerChromeParts()}formatCount(value){return getNumberFormat(this.effectiveLocale).format(value)}legendLimitText(){return this.localize("paginationSummary",void 0,{start:this.formatCount(this.legend.length===0?0:1),end:this.formatCount(this.legend.length),total:this.formatCount(this.legendProjection.inputCount),itemLabel:this.localize("items")})}renderLegendGradient(){const stops=this.legendGradient;if(stops.length<2)return nothing;const lo=stops[0],hi=stops[stops.length-1],span=hi[0]-lo[0],image=stops.map(([value,color],index)=>{const percent=span>0?(value-lo[0])/span*100:index/(stops.length-1)*100;return`${color} ${percent}%`}).join(", ");return html`<div class="legend-gradient">
|
|
1
|
+
var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing}from"lit";import{property,query,state}from"lit/decorators.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{devWarnOnce}from"../../../internal/dev-mode-attribute-warning.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{finiteRange}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{notifyMapCanvasReady}from"../../../internal/map-canvas-ready.js";import{acquireAnnouncementSink}from"../../../internal/announcer.js";import{srOnly}from"../../../internal/a11y.js";import{ThemeWatcher}from"../../../internal/theme-watcher.js";import{loadMaplibre}from"./map-loader.js";import{styles}from"./map.styles.js";import"../../overlays/skeleton/skeleton.class.js";import{LYRA_DEFAULT_close,LYRA_DEFAULT_items,LYRA_DEFAULT_loading,LYRA_DEFAULT_map,LYRA_DEFAULT_mapInitializationFailed,LYRA_DEFAULT_mapLegend,LYRA_DEFAULT_mapMissingLibrary,LYRA_DEFAULT_mapStyleRequired,LYRA_DEFAULT_mapWebglUnavailable,LYRA_DEFAULT_paginationSummary}from"../../../internal/default-strings.generated.js";function supportsWebGL2(host){try{const context=host.ownerDocument.createElement("canvas").getContext("webgl2");if(!context)return!1;try{context.getExtension("WEBGL_lose_context")?.loseContext()}catch{}return!0}catch{return!1}}function hasMapStyle(style){return typeof style=="string"?style.trim().length>0:style!==void 0}const MAX_MAP_LEGEND_GRADIENT_STOPS=64;function normalizeMapLegendGradient(value){if(!Array.isArray(value))return[];const usable=[],scanCount=Math.min(value.length,MAX_MAP_LEGEND_GRADIENT_STOPS);for(let index=0;index<scanCount;index+=1){const stop=value[index];if(!Array.isArray(stop)||stop.length<2)continue;const[rawValue,rawColor]=stop;if(typeof rawValue!="number"||!Number.isFinite(rawValue)||typeof rawColor!="string")continue;const color=sanitizeCssColor(rawColor);color&&usable.push([rawValue,color])}return usable.length<2?[]:Object.freeze([...usable].sort((a,b)=>a[0]-b[0]))}const MAP_LEGEND_ITEM_LIMIT=100,MAP_LEGEND_SCAN_LIMIT=1e3,MAP_LEGEND_LABEL_LIMIT=256,MAP_LEGEND_TOTAL_LABEL_LIMIT=8192,MAP_LEGEND_COLOR_LIMIT=256,MAP_LEGEND_PATTERNS=new Set(["solid","diagonal","dots","crosshatch"]),EMPTY_MAP_LEGEND=Object.freeze([]),EMPTY_MAP_LEGEND_PROJECTION=Object.freeze({inputCount:0,renderedCount:0,omittedCount:0,truncatedLabelCount:0,truncated:!1});function boundedLegendText(value,limit){return value.length<=limit?value:`${value.slice(0,Math.max(0,limit-1))}\u2026`}function normalizeMapLegend(value){let input;try{input=Array.isArray(value)?value:[]}catch{input=[]}let inputCount=0;try{inputCount=Math.max(0,Math.min(Number.MAX_SAFE_INTEGER,input.length))}catch{inputCount=0}const entries=[];let labelCharacters=0,truncatedLabelCount=0;const scanCount=Math.min(inputCount,MAP_LEGEND_SCAN_LIMIT);for(let index=0;index<scanCount&&entries.length<MAP_LEGEND_ITEM_LIMIT;index++)try{const candidate=input[index];if(!candidate||typeof candidate!="object")continue;const rawColor=candidate.color,rawLabel=candidate.label,rawPattern=candidate.pattern;if(typeof rawColor!="string"||typeof rawLabel!="string"||typeof rawPattern!="string"||!MAP_LEGEND_PATTERNS.has(rawPattern))continue;const remaining=MAP_LEGEND_TOTAL_LABEL_LIMIT-labelCharacters;if(remaining<=0)break;const labelLimit=Math.min(MAP_LEGEND_LABEL_LIMIT,remaining),label=boundedLegendText(rawLabel,labelLimit);if(!label.trim())continue;rawLabel.length>labelLimit&&truncatedLabelCount++,labelCharacters+=label.length,entries.push(Object.freeze({color:rawColor.slice(0,MAP_LEGEND_COLOR_LIMIT),label,pattern:rawPattern}))}catch{}const frozenEntries=entries.length?Object.freeze(entries):EMPTY_MAP_LEGEND,omittedCount=Math.max(0,inputCount-frozenEntries.length),projection=Object.freeze({inputCount,renderedCount:frozenEntries.length,omittedCount,truncatedLabelCount,truncated:omittedCount>0||truncatedLabelCount>0});return{entries:frozenEntries,projection}}function addPartToken(element,token){const tokens=new Set((element.getAttribute("part")??"").split(/\s+/).filter(Boolean));tokens.add(token),element.setAttribute("part",[...tokens].join(" "))}const CHOROPLETH_LOG_INTERPOLATION_BASE=.25,MAX_MAP_MARKERS=2e3;function popupText(host,markup){const template=host.ownerDocument.createElement("template");template.innerHTML=markup;for(const hidden of template.content.querySelectorAll('script, style, template, [hidden], [aria-hidden="true"]'))hidden.remove();return(template.content.textContent??"").replace(/\s+/gu," ").trim()}const MAX_MAP_DATA_LAYERS=100;function normalizedDataLayers(value){if(!Array.isArray(value))return[];const output=[],seenSourceIds=new Set,scanCount=Math.min(value.length,MAX_MAP_DATA_LAYERS);for(let index=0;index<scanCount;index++){const candidate=value[index];try{if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const rawSourceId=candidate.sourceId;if(typeof rawSourceId!="string")continue;const sourceId=rawSourceId.trim();if(sourceId.length===0||seenSourceIds.has(sourceId))continue;seenSourceIds.add(sourceId),output.push(rawSourceId===sourceId?candidate:{...candidate,sourceId})}catch{}}return output}const DATA_LAYER_SUFFIXES=["-fill","-line","-circle","-cluster","-cluster-count","-heatmap"],QUERYABLE_DATA_LAYER_SUFFIXES=["-fill","-line","-circle","-cluster"],MAX_MAP_STEP_STOPS=32;function normalizedSteps(value,isOutput,clampThreshold=threshold=>threshold){if(!Array.isArray(value))return[];const usable=[],scanCount=Math.min(value.length,MAX_MAP_STEP_STOPS);for(let index=0;index<scanCount;index+=1){const stop=value[index];if(!Array.isArray(stop)||stop.length<2)continue;const[rawThreshold,rawOutput]=stop;typeof rawThreshold!="number"||!Number.isFinite(rawThreshold)||isOutput(rawOutput)&&usable.push([clampThreshold(rawThreshold),rawOutput])}return usable.sort((a,b)=>a[0]-b[0]),usable.filter((stop,index)=>index===0||stop[0]>usable[index-1][0])}const isFiniteOutput=candidate=>typeof candidate=="number"&&Number.isFinite(candidate),isColorOutput=candidate=>typeof candidate=="string"&&candidate.trim().length>0;function stepExpression(input,stops){const expression=["step",input,stops[0][1]];for(const[threshold,output]of stops)expression.push(threshold,output);return expression}const DEFAULT_CLUSTER_RADIUS=50,DEFAULT_CLUSTER_MAX_ZOOM=14,DEFAULT_CLUSTER_RADIUS_STEPS=Object.freeze([[0,14],[10,18],[50,24]]),DEFAULT_HEATMAP_RADIUS=30,DEFAULT_HEATMAP_INTENSITY=1,HEATMAP_TRANSPARENT="rgba(0, 0, 0, 0)";function withTransparentFloor(stops){return stops.length&&stops[0][0]>0?[[0,HEATMAP_TRANSPARENT],...stops]:stops}const MAX_CLUSTER_COUNT_FONTS=8;function normalizedClusterOptions(value){if(value===null||typeof value!="object"||Array.isArray(value))return;const options=value,radiusSteps=normalizedSteps(options.radiusSteps,isFiniteOutput),fonts=Array.isArray(options.countFont)?options.countFont.filter(font=>typeof font=="string"&&font.trim().length>0).slice(0,MAX_CLUSTER_COUNT_FONTS):[];return{radius:finiteRange(Number(options.radius),DEFAULT_CLUSTER_RADIUS,1,1e3),maxZoom:finiteRange(Number(options.maxZoom),DEFAULT_CLUSTER_MAX_ZOOM,0,24),radiusSteps:radiusSteps.length?radiusSteps:DEFAULT_CLUSTER_RADIUS_STEPS,colorSteps:normalizedSteps(options.colorSteps,isColorOutput),countFont:fonts.length?fonts:void 0}}function dataLayerShape(layer){if(layer.kind==="heatmap")return"heatmap";const cluster=normalizedClusterOptions(layer.cluster);return cluster?`cluster:${cluster.radius}:${cluster.maxZoom}:${cluster.countFont?.join(",")??""}`:"auto"}function heatmapWeightExpression(options){const field=typeof options?.weightField=="string"?options.weightField.trim():"";if(!field)return;const range=options?.weightRange,min=Array.isArray(range)?Number(range[0]):Number.NaN,max=Array.isArray(range)?Number(range[1]):Number.NaN;return!Number.isFinite(min)||!Number.isFinite(max)||min>=max?["get",field]:["interpolate",["linear"],["get",field],min,0,max,1]}function heatmapZoomValue(value,fallback,min,max){if(!Array.isArray(value))return finiteRange(Number(value),fallback,min,max);const stops=normalizedSteps(value,isFiniteOutput,zoom=>finiteRange(zoom,0,0,24)).map(([zoom,output])=>[zoom,finiteRange(output,fallback,min,max)]);if(stops.length===0)return fallback;if(stops.length===1)return stops[0][1];const expression=["interpolate",["linear"],["zoom"]];for(const[zoom,output]of stops)expression.push(zoom,output);return expression}const FALLBACK_FILL_OPACITY=.75;function ownerWindow(host){return host.ownerDocument?.defaultView??null}function choroplethFillOpacity(host){const raw=ownerWindow(host)?.getComputedStyle(host).getPropertyValue("--lr-map-choropleth-fill-opacity").trim()??"",parsed=Number.parseFloat(raw);return Number.isFinite(parsed)?parsed:FALLBACK_FILL_OPACITY}const TONE_TOKEN={accent:"--lr-color-brand",success:"--lr-color-success",warning:"--lr-color-warning",danger:"--lr-color-danger",neutral:"--lr-color-text-quiet"},ON_TONE_TOKEN={accent:"--lr-color-on-brand",success:"--lr-color-on-success",warning:"--lr-color-on-warning",danger:"--lr-color-on-danger",neutral:"--lr-color-on-neutral"},HEATMAP_RAMP_TOKENS=Object.freeze([[.25,"--lr-color-brand"],[.5,"--lr-color-success"],[.75,"--lr-color-warning"],[1,"--lr-color-danger"]]);function dataLayerColor(host,tone){const token=TONE_TOKEN[tone??"accent"];return(ownerWindow(host)?.getComputedStyle(host).getPropertyValue(token).trim()??"")||"#0969da"}function resolvedLayerColor(host,explicit,tone){const candidate=typeof explicit=="string"?explicit.trim():"";if(!candidate)return dataLayerColor(host,tone);const reference=/^var\(\s*(--[\w-]+)/.exec(candidate);return reference?ownerWindow(host)?.getComputedStyle(host).getPropertyValue(reference[1]).trim()||dataLayerColor(host,tone):candidate}const UNTILEABLE_SCAN_FEATURE_LIMIT=1e4;function warnOnUntileableProperties(geojson,sourceLabel){const features=geojson?.features;if(!Array.isArray(features))return;const limit=Math.min(features.length,UNTILEABLE_SCAN_FEATURE_LIMIT);for(let index=0;index<limit;index+=1){const feature=features[index],properties=feature?.properties;if(!(!properties||typeof properties!="object"))for(const[key,value]of Object.entries(properties)){if(typeof value!="number"||!Number.isFinite(value)||Math.abs(value)<=Number.MAX_SAFE_INTEGER)continue;const identity=feature?.id??`index ${index}`;devWarnOnce(`lyra-map-untileable-property:${sourceLabel}:${key}`,`<lr-map>: feature ${String(identity)} in "${sourceLabel}" carries ${key}=${value}, which is too large to survive maplibre-gl's vector-tile encoding. Tiling happens in a worker, so the failure would reach you only as an opaque "Given varint doesn't fit into 10 bytes" error while the rest of the layer still paints. Carry a reduced figure in the feature and keep the exact value in your own data.`)}}}const GEOJSON_DIFF_FEATURE_LIMIT=1e4,GEOJSON_DIFF_VALUE_LIMIT=5e4;function isPlainGeoJsonRecord(value){try{const prototype=Object.getPrototypeOf(value);if(prototype===null)return!0;const constructor=Object.getOwnPropertyDescriptor(prototype,"constructor");return!!(constructor&&"value"in constructor&&typeof constructor.value=="function"&&constructor.value.name==="Object"&&Object.getPrototypeOf(prototype)===null)}catch{return!1}}function sameGeoJsonValue(previous,next,comparison){if(comparison.remaining<=0)return!1;if(comparison.remaining-=1,Object.is(previous,next))return!0;if(previous===null||next===null||typeof previous!="object"||typeof next!="object")return!1;const pairedNext=comparison.forward.get(previous);if(pairedNext)return pairedNext===next;const pairedPrevious=comparison.reverse.get(next);if(pairedPrevious)return pairedPrevious===previous;comparison.forward.set(previous,next),comparison.reverse.set(next,previous);const previousIsArray=Array.isArray(previous),nextIsArray=Array.isArray(next);if(previousIsArray||nextIsArray){if(!previousIsArray||!nextIsArray||previous.length!==next.length)return!1;for(let index=0;index<previous.length;index+=1){const before=Object.getOwnPropertyDescriptor(previous,String(index)),after=Object.getOwnPropertyDescriptor(next,String(index));if(!!before!=!!after)return!1;if(!(!before||!after)&&(!("value"in before)||!("value"in after)||!sameGeoJsonValue(before.value,after.value,comparison)))return!1}return!0}if(!isPlainGeoJsonRecord(previous)||!isPlainGeoJsonRecord(next))return!1;const previousKeys=Object.keys(previous),nextKeys=Object.keys(next);if(previousKeys.length!==nextKeys.length)return!1;for(let index=0;index<previousKeys.length;index+=1){const key=previousKeys[index];if(key!==nextKeys[index])return!1;const before=Object.getOwnPropertyDescriptor(previous,key),after=Object.getOwnPropertyDescriptor(next,key);if(!before||!after||!("value"in before)||!("value"in after)||!sameGeoJsonValue(before.value,after.value,comparison))return!1}return!0}function sameGeoJsonSnapshots(previous,next){try{return sameGeoJsonValue(previous,next,{remaining:GEOJSON_DIFF_VALUE_LIMIT,forward:new WeakMap,reverse:new WeakMap})}catch{return!1}}function indexGeoJsonCollection(value){try{if(value?.type!=="FeatureCollection")return null;const features=value?.features;if(!Array.isArray(features)||features.length>GEOJSON_DIFF_FEATURE_LIMIT)return null;const ordered=[],byId=new Map;for(let index=0;index<features.length;index+=1){const feature=features[index];if(!feature||Array.isArray(feature)||feature.type!=="Feature")return null;const id=feature.id;if(typeof id!="string"&&typeof id!="number"||byId.has(id))return null;const rawProperties=feature.properties;if(rawProperties!=null&&(typeof rawProperties!="object"||Array.isArray(rawProperties)))return null;const indexed={id,index,feature,geometry:feature.geometry,bbox:feature.bbox,properties:rawProperties??{}};ordered.push(indexed),byId.set(id,indexed)}return{ordered,byId}}catch{return null}}function buildGeoJsonPropertyDiff(previous,next){const previousCollection=indexGeoJsonCollection(previous),nextCollection=indexGeoJsonCollection(next);if(!previousCollection||!nextCollection)return null;const previousGeometry=[],nextGeometry=[];for(const after of nextCollection.ordered){const before=previousCollection.byId.get(after.id);before&&(previousGeometry.push(before.geometry,before.bbox),nextGeometry.push(after.geometry,after.bbox))}if(!sameGeoJsonSnapshots(previousGeometry,nextGeometry))return null;const retained=new Set;let previousIndex=-1;for(const feature of nextCollection.ordered){const before=previousCollection.byId.get(feature.id);if(!before||before.index<=previousIndex)break;retained.add(feature.id),previousIndex=before.index}const remove=previousCollection.ordered.filter(feature=>!retained.has(feature.id)).map(feature=>feature.id),add=nextCollection.ordered.filter(feature=>!retained.has(feature.id)).map(feature=>feature.feature),update=[];for(const after of nextCollection.ordered){if(!retained.has(after.id))continue;const before=previousCollection.byId.get(after.id),addOrUpdateProperties=[];for(const[key,value]of Object.entries(after.properties))Object.is(before.properties[key],value)||addOrUpdateProperties.push({key,value});const removeProperties=Object.keys(before.properties).filter(key=>!Object.hasOwn(after.properties,key));addOrUpdateProperties.length===0&&removeProperties.length===0||update.push({id:after.id,addOrUpdateProperties,removeProperties})}return{...remove.length?{remove}:{},...add.length?{add}:{},update}}class LyraMap extends LyraElement{static{this.defaultStrings={...super.defaultStrings,close:LYRA_DEFAULT_close,items:LYRA_DEFAULT_items,loading:LYRA_DEFAULT_loading,map:LYRA_DEFAULT_map,mapInitializationFailed:LYRA_DEFAULT_mapInitializationFailed,mapLegend:LYRA_DEFAULT_mapLegend,mapMissingLibrary:LYRA_DEFAULT_mapMissingLibrary,mapStyleRequired:LYRA_DEFAULT_mapStyleRequired,mapWebglUnavailable:LYRA_DEFAULT_mapWebglUnavailable,paginationSummary:LYRA_DEFAULT_paginationSummary}}static{this.immutableEventDetails=Object.freeze(["lr-map-click","lr-map-marker-activate"])}static{this.identityEventDetailProperties=Object.freeze({"lr-map-click":Object.freeze(["feature"])})}static{this.ownedCollectionProperties=Object.freeze(["center","mapStyle","choropleth","markers","dataLayers"])}static{this.styles=[LyraElement.styles,styles,srOnly]}static preload(){return loadMaplibre().then(module=>module!==null)}constructor(){super(),this.center=[0,0],this.zoom=2,this.maxBounds=null,this._legend=EMPTY_MAP_LEGEND,this._legendProjection=EMPTY_MAP_LEGEND_PROJECTION,this.hasLegendSlot=!1,this._legendGradient=Object.freeze([]),this.legendGradientLoLabel=null,this.legendGradientHiLabel=null,this.markers=[],this.dataLayers=[],this.label="",this.loading=!0,this.loadLibrary=loadMaplibre,this.visible=ownerWindow(this)?.IntersectionObserver===void 0,this._styleLoaded=!1,this._appliedDataLayerIds=new Map,this._appliedDataLayerShapes=new Map,this._appliedGeoJson=new Map,this._nextDataLayerId=0,this._webglReady=!1,this._markerInstances=new Map,this._markerLabels=new Map,this._markerPopupIds=new Map,this.markerActivationDetails=new WeakMap,this._configuredPopups=new WeakSet,this._nextPopupId=0,this._markerColors=new Map,this._connectGeneration=0,this.configuredMarkerElements=new WeakSet,this.onLegendSlotChange=event=>{const slot=event.target;this.hasLegendSlot=slot.assignedNodes({flatten:!0}).some(node=>node.nodeType===Node.ELEMENT_NODE||(node.textContent??"").trim().length>0)},new ThemeWatcher(this,()=>this.refreshThemePaint())}get legend(){return this._legend}set legend(value){const previous=this._legend,normalized=normalizeMapLegend(value);this._legend=normalized.entries,this._legendProjection=normalized.projection,this.requestUpdate("legend",previous)}probeLegendSlot(){for(const child of Array.from(this.children))if(child.getAttribute("slot")==="legend")return!0;return!1}get legendGradient(){return this._legendGradient}set legendGradient(value){const previous=this._legendGradient;this._legendGradient=normalizeMapLegendGradient(value),this.requestUpdate("legendGradient",previous)}get legendProjection(){return this._legendProjection}get map(){return this._map}pushGeoJson(source,resolvedSourceId,geojson){const previous=this._appliedGeoJson.get(resolvedSourceId),diff=typeof source.updateData=="function"&&previous!==void 0?buildGeoJsonPropertyDiff(previous,geojson):null;diff===null||typeof source.updateData!="function"?source.setData(geojson):(diff.update.length>0||diff.add?.length||diff.remove?.length)&&source.updateData(diff),this._appliedGeoJson.set(resolvedSourceId,geojson)}get safeMaxBounds(){const bounds=this.maxBounds;if(!Array.isArray(bounds)||bounds.length!==2)return null;const[southWest,northEast]=bounds;if(!Array.isArray(southWest)||!Array.isArray(northEast))return null;const[west,south]=southWest,[east,north]=northEast,values=[west,south,east,north].map(Number);if(!values.every(value=>Number.isFinite(value)))return null;const[w,s,e,n]=values;return w>=e||s>=n||w<-180||e>180||s<-90||n>90?null:[[w,s],[e,n]]}applyMaxBounds(){const map=this._map;if(!map||typeof map.setMaxBounds!="function")return;const bounds=this.safeMaxBounds,zoomBefore=map.getZoom(),centerBefore=map.getCenter();try{if(map.setMaxBounds(bounds),bounds===null||Number.isFinite(map.getZoom()))return}catch{}try{map.setMaxBounds(null)}catch{}Number.isFinite(zoomBefore)&&map.setZoom(zoomBefore),centerBefore&&map.setCenter([centerBefore.lng,centerBefore.lat]),devWarnOnce("lyra-map-max-bounds-rejected","<lr-map>: maxBounds left maplibre-gl without a usable camera, so it was dropped and the camera restored. This is a peer limitation, not a bad value -- it shows up at sub-1 fractional zooms in wide containers. Raise the zoom, narrow the box, or leave maxBounds unset.")}get safeZoom(){return finiteRange(this.zoom,2,0,22)}get safeCenter(){const center=Array.isArray(this.center)?this.center:[];return[finiteRange(Number(center[0]),0,-180,180),finiteRange(Number(center[1]),0,-90,90)]}connectedCallback(){super.connectedCallback(),this.syncErrorAnnouncementSink();const generation=++this._connectGeneration,IntersectionObserverCtor=ownerWindow(this)?.IntersectionObserver;if(this.visible=IntersectionObserverCtor===void 0,this.failure=void 0,this.loading=!0,this._webglReady=!1,IntersectionObserverCtor){const observer=new IntersectionObserverCtor(entries=>{entries[0]?.isIntersecting&&(this.visible=!0)});this.intersectionObserver=observer,observer.observe(this)}(async()=>{let mod;try{mod=await this.loadLibrary()}catch{generation===this._connectGeneration&&this.isConnected&&this.failInitialization("missing-peer");return}if(!(generation!==this._connectGeneration||!this.isConnected)){if(this.loading=!1,!mod){this.failInitialization("missing-peer");return}if(this._maplibreModule=mod,!hasMapStyle(this.mapStyle)){this.failInitialization("style-required");return}if(!supportsWebGL2(this)){this.failInitialization("webgl-unavailable");return}this._webglReady=!0,await this.updateComplete,!(generation!==this._connectGeneration||!this.containerEl||!this.isConnected)&&this.tryConstructMap()}})()}disconnectedCallback(){this.releaseErrorAnnouncementSink(),super.disconnectedCallback(),this.disposeMap(),this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0;for(const marker of this._markerInstances.values()){const markerElement=marker.getElement?.();markerElement&&this.markerActivationDetails.delete(markerElement),marker.remove()}this._markerInstances.clear(),this._markerColors.clear(),this._markerLabels.clear(),this._markerPopupIds.clear()}failureMessage(reason=this.failure??"initialization-failed"){switch(reason){case"missing-peer":return this.localize("mapMissingLibrary");case"style-required":return this.localize("mapStyleRequired");case"webgl-unavailable":return this.localize("mapWebglUnavailable");case"initialization-failed":return this.localize("mapInitializationFailed")}}failInitialization(reason,partialMap){try{partialMap?.remove()}catch{}this.disposeMap(),this.loading=!1,this.failure=reason,this.errorAnnouncementSink?.announce(this.failureMessage(reason))}disposeMap(){this.stopObservingMapAllocation(),this.stopObservingPeerChrome();try{this._map?.remove()}catch{}this._map=void 0,this._styleLoaded=!1,this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0,this._appliedDataLayerIds.clear(),this._appliedDataLayerShapes.clear(),this._appliedGeoJson.clear()}adoptedCallback(){super.adoptedCallback(),this.stopObservingMapAllocation(),this.stopObservingPeerChrome(),this.releaseErrorAnnouncementSink(),this.syncErrorAnnouncementSink(),this._map&&this.containerEl&&this.isConnected&&this.observeMapAllocation(this._map,this.containerEl)}syncErrorAnnouncementSink(){this.isConnected&&this.errorAnnouncementSink?.element.ownerDocument!==this.ownerDocument&&(this.releaseErrorAnnouncementSink(),this.errorAnnouncementSink=acquireAnnouncementSink("assertive",{document:this.ownerDocument,source:this}))}releaseErrorAnnouncementSink(){this.errorAnnouncementSink?.release(),this.errorAnnouncementSink=void 0}tryConstructMap(){if(this._map||!this._maplibreModule||!this._webglReady||!this.containerEl||!this.visible||!this.isConnected)return;if(!hasMapStyle(this.mapStyle)){this.failInitialization("style-required");return}const mod=this._maplibreModule;let candidate;try{candidate=new mod.Map({container:this.containerEl,style:this.mapStyle,center:this.safeCenter,zoom:this.safeZoom,...typeof this.renderWorldCopies=="boolean"?{renderWorldCopies:this.renderWorldCopies}:{},locale:{"Map.Title":this.effectiveMapLabel,"Marker.Title":this.localize("map"),"Popup.Close":this.localize("close")}}),candidate.on("error",event=>{if(this._map===candidate&&!this._styleLoaded){this.failInitialization("initialization-failed");return}console.error("lr-map:",event.error??event)}),candidate.on("load",()=>{if(this._map===candidate)try{this._styleLoaded=!0,this.applyChoropleth(),this.applyMarkers(),this.applyDataLayers(),this.emit("lr-map-load")}catch{this.failInitialization("initialization-failed")}}),candidate.on("click",event=>{if(this._map!==candidate)return;const fillLayerId=this._appliedFillLayerId,layerIds=[];fillLayerId&&candidate.getLayer(fillLayerId)&&layerIds.push(fillLayerId);for(const resolvedSourceId of this._appliedDataLayerIds.values())for(const suffix of QUERYABLE_DATA_LAYER_SUFFIXES){const layerId=`${resolvedSourceId}${suffix}`;candidate.getLayer(layerId)&&layerIds.push(layerId)}const hit=(layerIds.length?candidate.queryRenderedFeatures(event.point,{layers:layerIds}):[])[0],hitLayerId=hit?.layer?.id;let origin,sourceId;if(hitLayerId!==void 0){if(hitLayerId===fillLayerId)origin="choropleth";else for(const[publicSourceId,resolvedSourceId]of this._appliedDataLayerIds)if(hitLayerId.startsWith(`${resolvedSourceId}-`)){origin=hitLayerId===`${resolvedSourceId}-cluster`?"cluster":"data-layer",sourceId=publicSourceId;break}}this.emit("lr-map-click",{lngLat:[event.lngLat.lng,event.lngLat.lat],feature:hit,origin,sourceId})});const canvas=candidate.getCanvas?.();canvas&¬ifyMapCanvasReady(this,canvas),this._map=candidate,this.observeMapAllocation(candidate,this.containerEl),this.observePeerChrome(),this.failure=void 0}catch{this.failInitialization("initialization-failed",candidate);return}this.applyMaxBounds()}updated(changed){if(super.updated(changed),this.setAttribute("aria-busy",String(this.loading)),changed.has("visible")&&this.visible&&this.tryConstructMap(),changed.has("mapStyle")&&!hasMapStyle(this.mapStyle)&&this._maplibreModule)this.failInitialization("style-required");else if(changed.has("mapStyle")&&!this._map&&this._maplibreModule&&hasMapStyle(this.mapStyle))this.tryConstructMap();else if(changed.has("mapStyle")&&this._map){this._styleLoaded=!1,this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0;const map=this._map;try{map.once("style.load",()=>{if(this._map===map)try{this._styleLoaded=!0,this._appliedDataLayerIds.clear(),this._appliedDataLayerShapes.clear(),this._appliedGeoJson.clear(),this.applyChoropleth(),this.applyDataLayers()}catch{this.scheduleAfterUpdate(()=>this.failInitialization("initialization-failed"),"map-style-failure")}}),map.setStyle(this.mapStyle)}catch{this.scheduleAfterUpdate(()=>this.failInitialization("initialization-failed"),"map-style-failure")}}else if(this._styleLoaded&&(changed.has("dataLayers")||changed.has("choropleth"))){const nextChoroplethSourceId=this.choropleth?this.resolveChoroplethSourceId(this.choropleth.sourceId):void 0;this._appliedChoroplethSourceId&&this._appliedChoroplethSourceId!==nextChoroplethSourceId&&this.removeChoropleth(),changed.has("dataLayers")&&this.applyDataLayers(),this.applyChoropleth()}changed.has("center")&&this._map&&this._map.setCenter(this.safeCenter),changed.has("zoom")&&this._map&&this._map.setZoom(this.safeZoom),changed.has("maxBounds")&&this._map&&this.applyMaxBounds(),changed.has("markers")&&this._map&&this.applyMarkers(),this.syncMapSemantics()}willUpdate(changed){super.willUpdate(changed),changed.has("mapStyle")&&!this._map&&this._maplibreModule&&hasMapStyle(this.mapStyle)&&(this._webglReady||(this._webglReady=supportsWebGL2(this)),this.failure=this._webglReady?void 0:"webgl-unavailable",this._webglReady||(this.loading=!1,this.errorAnnouncementSink?.announce(this.failureMessage("webgl-unavailable"))))}refreshThemePaint(){if(!this._map||!this._styleLoaded)return;const fillOpacity=choroplethFillOpacity(this);this._appliedFillLayerId&&this._map.setPaintProperty(this._appliedFillLayerId,"fill-opacity",fillOpacity);const dataLayersBySourceId=new Map(normalizedDataLayers(this.dataLayers).map(layer=>[layer.sourceId,layer]));for(const[publicSourceId,sourceId]of this._appliedDataLayerIds){const dataLayer=dataLayersBySourceId.get(publicSourceId);dataLayer&&this.paintDataLayer(sourceId,dataLayer)}}applyChoropleth(){if(!this._map)return;if(!this.choropleth){this.removeChoropleth();return}const{geojson,field,stops}=this.choropleth,sourceId=this.resolveChoroplethSourceId(this.choropleth.sourceId),fillLayerId=`${sourceId}-fill`;this._appliedChoroplethSourceId&&this._appliedChoroplethSourceId!==sourceId&&this.removeChoropleth(),warnOnUntileableProperties(geojson,"choropleth");const existingSource=this._map.getSource(sourceId);if(existingSource?this.pushGeoJson(existingSource,sourceId,geojson):(this._map.addSource(sourceId,{type:"geojson",data:geojson}),this._appliedGeoJson.set(sourceId,geojson)),this._appliedChoroplethSourceId=sourceId,stops.length===0)return;let colorExpr;if(this.choropleth.interpolation==="step"){const base=typeof this.choropleth.stepBaseColor=="string"&&this.choropleth.stepBaseColor.trim()?this.choropleth.stepBaseColor.trim():stops[0][1];colorExpr=["step",["get",field],base];for(const[value,color]of stops)colorExpr.push(value,color)}else{colorExpr=["interpolate",this.choropleth.interpolation==="logarithmic"?["exponential",CHOROPLETH_LOG_INTERPOLATION_BASE]:["linear"],["get",field]];for(const[value,color]of stops)colorExpr.push(value,color)}this._map.getLayer(fillLayerId)?(this._map.setPaintProperty(fillLayerId,"fill-color",colorExpr),this._map.setPaintProperty(fillLayerId,"fill-opacity",choroplethFillOpacity(this))):this._map.addLayer({id:fillLayerId,type:"fill",source:sourceId,paint:{"fill-color":colorExpr,"fill-opacity":choroplethFillOpacity(this)}}),this._appliedFillLayerId=fillLayerId}resolveChoroplethSourceId(sourceId){const dataSourceIds=new Set(normalizedDataLayers(this.dataLayers).map(layer=>layer.sourceId));let resolved=sourceId;for(;dataSourceIds.has(resolved);)resolved=`lr-choropleth-${resolved}`;return resolved}removeChoropleth(){!this._map||!this._appliedChoroplethSourceId||(this._appliedFillLayerId&&this._map.getLayer(this._appliedFillLayerId)&&this._map.removeLayer(this._appliedFillLayerId),this._map.getSource(this._appliedChoroplethSourceId)&&this._map.removeSource(this._appliedChoroplethSourceId),this._appliedGeoJson.delete(this._appliedChoroplethSourceId),this._appliedChoroplethSourceId=void 0,this._appliedFillLayerId=void 0)}applyDataLayers(){if(!this._map)return;const layers=normalizedDataLayers(this.dataLayers),nextIds=new Set(layers.map(layer=>layer.sourceId));for(const publicSourceId of this._appliedDataLayerIds.keys())nextIds.has(publicSourceId)||this.removeDataLayer(publicSourceId);for(const layer of layers){const{sourceId:publicSourceId,geojson}=layer,shape=dataLayerShape(layer),appliedShape=this._appliedDataLayerShapes.get(publicSourceId);appliedShape!==void 0&&appliedShape!==shape&&this.removeDataLayer(publicSourceId);const sourceId=this.resolveDataLayerSourceId(publicSourceId);warnOnUntileableProperties(geojson,publicSourceId);const cluster=layer.kind==="heatmap"?void 0:normalizedClusterOptions(layer.cluster),existingSource=this._map.getSource(sourceId);existingSource?this.pushGeoJson(existingSource,sourceId,geojson):(this._map.addSource(sourceId,{type:"geojson",data:geojson,...cluster?{cluster:!0,clusterRadius:cluster.radius,clusterMaxZoom:cluster.maxZoom}:{}}),this._appliedGeoJson.set(sourceId,geojson)),this.applyDataLayerRendering(sourceId,layer),this._appliedDataLayerIds.set(publicSourceId,sourceId),this._appliedDataLayerShapes.set(publicSourceId,shape)}}applyDataLayerRendering(sourceId,layer){if(layer.kind==="heatmap"){this.applyHeatmapLayer(sourceId,layer);return}const cluster=normalizedClusterOptions(layer.cluster);if(cluster){this.applyClusterLayers(sourceId,layer,cluster);return}this.applyGeometryLayers(sourceId,layer)}paintDataLayer(sourceId,layer){if(layer.kind==="heatmap"){this.paintHeatmapLayer(sourceId,layer);return}const cluster=normalizedClusterOptions(layer.cluster);if(cluster){this.paintClusterLayers(sourceId,layer,cluster);return}this.paintGeometryLayers(sourceId,layer)}applyGeometryLayers(sourceId,layer){if(!this._map)return;const tone=layer.tone,color=resolvedLayerColor(this,layer.color,tone),stroke=resolvedLayerColor(this,layer.strokeColor??layer.color,tone),fillId=`${sourceId}-fill`,lineId=`${sourceId}-line`,circleId=`${sourceId}-circle`;this._map.getLayer(fillId)||this._map.addLayer({id:fillId,type:"fill",source:sourceId,filter:["==",["geometry-type"],"Polygon"],paint:{"fill-color":color,"fill-opacity":choroplethFillOpacity(this)}}),this._map.getLayer(lineId)||this._map.addLayer({id:lineId,type:"line",source:sourceId,filter:["in",["geometry-type"],["literal",["LineString","Polygon"]]],paint:{"line-color":stroke,"line-width":2}}),this._map.getLayer(circleId)||this._map.addLayer({id:circleId,type:"circle",source:sourceId,filter:["==",["geometry-type"],"Point"],paint:{"circle-color":stroke,"circle-radius":5}}),this.paintGeometryLayers(sourceId,layer)}paintGeometryLayers(sourceId,layer){if(!this._map)return;const tone=layer.tone,color=resolvedLayerColor(this,layer.color,tone),stroke=resolvedLayerColor(this,layer.strokeColor??layer.color,tone);this._map.setPaintProperty(`${sourceId}-fill`,"fill-color",color),this._map.setPaintProperty(`${sourceId}-fill`,"fill-opacity",choroplethFillOpacity(this)),this._map.setPaintProperty(`${sourceId}-line`,"line-color",stroke),this._map.setPaintProperty(`${sourceId}-circle`,"circle-color",stroke)}clusterColorExpression(layer,cluster){const tone=layer.tone;return cluster.colorSteps.length?stepExpression(["get","point_count"],cluster.colorSteps.map(([count,stepColor])=>[count,resolvedLayerColor(this,stepColor,tone)])):resolvedLayerColor(this,layer.color,tone)}applyClusterLayers(sourceId,layer,cluster){if(!this._map)return;const tone=layer.tone,stroke=resolvedLayerColor(this,layer.strokeColor??layer.color,tone),clusterId=`${sourceId}-cluster`,countId=`${sourceId}-cluster-count`,circleId=`${sourceId}-circle`,clusterColor=this.clusterColorExpression(layer,cluster),clusterRadius=stepExpression(["get","point_count"],cluster.radiusSteps),countColor=resolvedLayerColor(this,`var(${ON_TONE_TOKEN[tone??"accent"]})`,tone);this._map.getLayer(clusterId)||this._map.addLayer({id:clusterId,type:"circle",source:sourceId,filter:["has","point_count"],paint:{"circle-color":clusterColor,"circle-radius":clusterRadius,"circle-stroke-width":1,"circle-stroke-color":stroke}}),this.styleProvidesGlyphs()&&!this._map.getLayer(countId)&&this._map.addLayer({id:countId,type:"symbol",source:sourceId,filter:["has","point_count"],layout:{"text-field":["get","point_count_abbreviated"],"text-size":12,...cluster.countFont?{"text-font":[...cluster.countFont]}:{}},paint:{"text-color":countColor}}),this._map.getLayer(circleId)||this._map.addLayer({id:circleId,type:"circle",source:sourceId,filter:["all",["==",["geometry-type"],"Point"],["!",["has","point_count"]]],paint:{"circle-color":stroke,"circle-radius":5}}),this.paintClusterLayers(sourceId,layer,cluster)}paintClusterLayers(sourceId,layer,cluster){if(!this._map)return;const tone=layer.tone,stroke=resolvedLayerColor(this,layer.strokeColor??layer.color,tone),clusterId=`${sourceId}-cluster`;this._map.setPaintProperty(clusterId,"circle-color",this.clusterColorExpression(layer,cluster)),this._map.setPaintProperty(clusterId,"circle-radius",stepExpression(["get","point_count"],cluster.radiusSteps)),this._map.setPaintProperty(clusterId,"circle-stroke-color",stroke),this.styleProvidesGlyphs()&&this._map.setPaintProperty(`${sourceId}-cluster-count`,"text-color",resolvedLayerColor(this,`var(${ON_TONE_TOKEN[tone??"accent"]})`,tone)),this._map.setPaintProperty(`${sourceId}-circle`,"circle-color",stroke)}applyHeatmapLayer(sourceId,layer){if(!this._map)return;const heatmapId=`${sourceId}-heatmap`,options=layer.heatmap,weight=heatmapWeightExpression(options),color=this.heatmapColorExpression(layer),radius=heatmapZoomValue(options?.radius,DEFAULT_HEATMAP_RADIUS,1,200),intensity=heatmapZoomValue(options?.intensity,DEFAULT_HEATMAP_INTENSITY,0,100),opacity=finiteRange(Number(options?.opacity),1,0,1);if(!this._map.getLayer(heatmapId)){this._map.addLayer({id:heatmapId,type:"heatmap",source:sourceId,paint:{...weight?{"heatmap-weight":weight}:{},"heatmap-intensity":intensity,"heatmap-color":color,"heatmap-radius":radius,...options?.opacity===void 0?{}:{"heatmap-opacity":opacity}}});return}this.paintHeatmapLayer(sourceId,layer)}paintHeatmapLayer(sourceId,layer){if(!this._map)return;const heatmapId=`${sourceId}-heatmap`;this._map.setPaintProperty(heatmapId,"heatmap-weight",heatmapWeightExpression(layer.heatmap)??1),this._map.setPaintProperty(heatmapId,"heatmap-intensity",heatmapZoomValue(layer.heatmap?.intensity,DEFAULT_HEATMAP_INTENSITY,0,100)),this._map.setPaintProperty(heatmapId,"heatmap-color",this.heatmapColorExpression(layer)),this._map.setPaintProperty(heatmapId,"heatmap-radius",heatmapZoomValue(layer.heatmap?.radius,DEFAULT_HEATMAP_RADIUS,1,200)),this._map.setPaintProperty(heatmapId,"heatmap-opacity",finiteRange(Number(layer.heatmap?.opacity),1,0,1))}heatmapColorExpression(layer){const tone=layer.tone,authored=normalizedSteps(layer.heatmap?.stops,isColorOutput,threshold=>finiteRange(threshold,0,0,1)).map(([density,color])=>[density,resolvedLayerColor(this,color,tone)]),authoredRamp=withTransparentFloor(authored),ramp=authoredRamp.length>=2?authoredRamp:withTransparentFloor(HEATMAP_RAMP_TOKENS.map(([density,token])=>[density,resolvedLayerColor(this,`var(${token})`,tone)])),expression=["interpolate",["linear"],["heatmap-density"]];for(const[density,color]of ramp)expression.push(density,color);return expression}styleProvidesGlyphs(){try{const liveGlyphs=this._map?.getStyle?.()?.glyphs;if(typeof liveGlyphs=="string"&&liveGlyphs.trim().length>0)return!0}catch{}const declared=this.mapStyle,declaredGlyphs=declared&&typeof declared=="object"?declared.glyphs:void 0;return typeof declaredGlyphs=="string"&&declaredGlyphs.trim().length>0}resolveDataLayerSourceId(publicSourceId){const applied=this._appliedDataLayerIds.get(publicSourceId);if(applied)return applied;let sourceId;do sourceId=`lr-data-layer-${this._nextDataLayerId++}`;while(this._map?.getSource(sourceId)||DATA_LAYER_SUFFIXES.some(suffix=>this._map?.getLayer(`${sourceId}${suffix}`)));return sourceId}removeDataLayer(publicSourceId){if(!this._map)return;const sourceId=this._appliedDataLayerIds.get(publicSourceId);if(sourceId){for(const suffix of DATA_LAYER_SUFFIXES){const layerId=`${sourceId}${suffix}`;this._map.getLayer(layerId)&&this._map.removeLayer(layerId)}this._map.getSource(sourceId)&&this._map.removeSource(sourceId),this._appliedDataLayerIds.delete(publicSourceId),this._appliedDataLayerShapes.delete(publicSourceId),this._appliedGeoJson.delete(sourceId)}}applyMarkers(){const map=this._map,mod=this._maplibreModule;if(!map||!mod)return;const visible=new Set,coordCounts=new Map,explicitIds=new Set,markers=Array.isArray(this.markers)?this.markers.slice(0,MAX_MAP_MARKERS):[];for(const candidate of markers){const lngLat=this.validMarkerLngLat(candidate);if(!lngLat)continue;const m=candidate,rawId=m.id;let key,id;if(rawId!==void 0){if(typeof rawId!="string"||(id=rawId.trim(),id.length===0||explicitIds.has(id)))continue;explicitIds.add(id),key=`id:${id}`}else{const coordKey=`${lngLat[0]},${lngLat[1]}`,occurrence=coordCounts.get(coordKey)??0;coordCounts.set(coordKey,occurrence+1),key=`coordinate:${coordKey}#${occurrence}`}visible.add(key);let existing=this._markerInstances.get(key);const markerColor=sanitizeCssColor(m.color);if(existing&&this._markerColors.get(key)!==markerColor){const existingElement=existing.getElement?.();existingElement&&this.markerActivationDetails.delete(existingElement),existing.remove(),this._markerInstances.delete(key),this._markerColors.delete(key),existing=void 0}if(existing){existing.setLngLat(lngLat);const popup=existing.getPopup();if(m.unsafeHtml)if(popup)popup.setHTML(m.unsafeHtml);else{const nextPopup=new mod.Popup({offset:12}).setHTML(m.unsafeHtml);existing.setPopup(nextPopup),this.configurePopupSemantics(key,existing,nextPopup)}else if(m.label)if(popup)popup.setText(m.label);else{const nextPopup=new mod.Popup({offset:12}).setText(m.label);existing.setPopup(nextPopup),this.configurePopupSemantics(key,existing,nextPopup)}else popup&&existing.setPopup(void 0)}else{const marker=new mod.Marker(markerColor?{color:markerColor}:void 0).setLngLat(lngLat);if(m.unsafeHtml||m.label){const popup=new mod.Popup({offset:12});m.unsafeHtml?popup.setHTML(m.unsafeHtml):m.label&&popup.setText(m.label),marker.setPopup(popup),this.configurePopupSemantics(key,marker,popup)}marker.addTo(map),this._markerInstances.set(key,marker),this._markerColors.set(key,markerColor)}const markerLabel=m.label?.trim()||(m.unsafeHtml?popupText(this,m.unsafeHtml):"");this._markerLabels.set(key,markerLabel||void 0);const markerElement=this._markerInstances.get(key)?.getElement?.();if(markerElement){addPartToken(markerElement,"marker"),markerElement.setAttribute("aria-label",markerLabel||this.localize("map")),markerElement.setAttribute("lang",this.effectiveLocale);const currentMarker=this._markerInstances.get(key);this.configureMarkerInteraction(markerElement,{id,lngLat,marker:m});const popup=currentMarker?.getPopup();popup&¤tMarker?(this.configurePopupSemantics(key,currentMarker,popup),this.syncPopupSemantics(key,currentMarker,popup)):(markerElement.removeAttribute("aria-controls"),markerElement.removeAttribute("aria-expanded"),markerElement.removeAttribute("aria-haspopup"))}}for(const[key,marker]of this._markerInstances)if(!visible.has(key)){const markerElement=marker.getElement?.();markerElement&&this.markerActivationDetails.delete(markerElement),marker.remove(),this._markerInstances.delete(key),this._markerColors.delete(key),this._markerLabels.delete(key),this._markerPopupIds.delete(key)}}configureMarkerInteraction(markerElement,activation){this.markerActivationDetails.set(markerElement,activation),markerElement.setAttribute("role","button"),markerElement.tabIndex=0;const markerLabel=activation.marker.label?.trim()||(activation.marker.unsafeHtml?popupText(this,activation.marker.unsafeHtml):"");markerElement.setAttribute("aria-label",markerLabel||this.localize("map")),markerElement.setAttribute("lang",this.effectiveLocale),!this.configuredMarkerElements.has(markerElement)&&(this.configuredMarkerElements.add(markerElement),markerElement.addEventListener("click",event=>{event.defaultPrevented||this.emitMarkerActivation(markerElement,"pointer")}),markerElement.addEventListener("keydown",event=>{event.key!==" "&&event.key!=="Enter"||event.repeat||event.defaultPrevented||(event.key===" "&&event.preventDefault(),this.emitMarkerActivation(markerElement,"keyboard"))},{capture:!0}))}emitMarkerActivation(markerElement,source){if(!this.isConnected)return;const activation=this.markerActivationDetails.get(markerElement);activation&&this.emit("lr-map-marker-activate",{...activation,source})}get effectiveMapLabel(){return this.getAttribute("aria-label")===""?"":this.label||this.localize("map")}validMarkerLngLat(candidate){if(!candidate||typeof candidate!="object")return null;const lngLat=candidate.lngLat;if(!Array.isArray(lngLat)||lngLat.length<2)return null;const[lng,lat]=lngLat;return typeof lng!="number"||typeof lat!="number"||!Number.isFinite(lng)||!Number.isFinite(lat)||lat<-90||lat>90?null:[lng,lat]}popupId(key){let id=this._markerPopupIds.get(key);return id||(id=`map-popup-${this._connectGeneration}-${++this._nextPopupId}`,this._markerPopupIds.set(key,id)),id}configurePopupSemantics(key,marker,popup){!popup||typeof popup!="object"||this._configuredPopups.has(popup)||(this._configuredPopups.add(popup),popup.on?.("open",()=>this.syncPopupSemantics(key,marker,popup)),popup.on?.("close",()=>{marker.getElement?.()?.setAttribute("aria-expanded","false")}))}stopObservingMapAllocation(){this.mapResizeObserver?.disconnect(),this.mapResizeObserver=void 0,this.observedMapContainer=void 0}observeMapAllocation(map,container){this.stopObservingMapAllocation();const ResizeObserverCtor=container.ownerDocument.defaultView?.ResizeObserver;if(!ResizeObserverCtor)return;let observer;observer=new ResizeObserverCtor(()=>{if(!(this.mapResizeObserver!==observer||this.observedMapContainer!==container||this.containerEl!==container||this._map!==map||!this.isConnected))try{map.resize()}catch{}}),this.mapResizeObserver=observer,this.observedMapContainer=container;try{observer.observe(container)}catch{this.stopObservingMapAllocation()}}stopObservingPeerChrome(){this.peerChromeObserver?.disconnect(),this.peerChromeObserver=void 0,this.observedPeerContainer=void 0}syncPeerChromeParts(root=this.containerEl??this.renderRoot){const selectors=[[".maplibregl-marker","marker"],[".maplibregl-popup","popup"],[".maplibregl-popup-content","popup-content"],[".maplibregl-popup-close-button","popup-close-button"],[".maplibregl-ctrl-attrib","attribution"],[".maplibregl-ctrl-attrib-button","attribution-toggle"]];for(const[selector,part]of selectors){const candidate=root;candidate.matches?.(selector)&&addPartToken(candidate,part);for(const element of root.querySelectorAll(selector))addPartToken(element,part)}}observePeerChrome(){const container=this.containerEl;if(!container||(this.syncPeerChromeParts(container),this.observedPeerContainer===container&&this.peerChromeObserver))return;this.stopObservingPeerChrome();const MutationObserverCtor=container.ownerDocument.defaultView?.MutationObserver;MutationObserverCtor&&(this.observedPeerContainer=container,this.peerChromeObserver=new MutationObserverCtor(records=>{if(!(!this.isConnected||this.containerEl!==container))for(const record of records)for(const node of record.addedNodes)node.nodeType===Node.ELEMENT_NODE&&this.syncPeerChromeParts(node)}),this.peerChromeObserver.observe(container,{childList:!0,subtree:!0}))}syncPopupSemantics(key,marker,popup){const markerElement=marker?.getElement?.();if(!markerElement)return;const id=this.popupId(key);markerElement.setAttribute("aria-controls",id),markerElement.setAttribute("aria-haspopup","dialog"),markerElement.setAttribute("aria-expanded",popup?.isOpen?.()?"true":"false");const popupElement=popup?.getElement?.();if(!popupElement)return;addPartToken(markerElement,"marker"),addPartToken(popupElement,"popup"),popupElement.id=id,popupElement.setAttribute("role","dialog"),popupElement.setAttribute("lang",this.effectiveLocale),popupElement.setAttribute("aria-label",this._markerLabels.get(key)||this.effectiveMapLabel);const popupContent=popupElement.querySelector(".maplibregl-popup-content");popupContent&&addPartToken(popupContent,"popup-content");const closeButton=popupElement.querySelector(".maplibregl-popup-close-button");closeButton&&addPartToken(closeButton,"popup-close-button"),closeButton?.setAttribute("aria-label",this.localize("close"))}syncMapSemantics(){const canvas=this._map?.getCanvas?.();canvas&&(canvas.setAttribute("aria-label",this.effectiveMapLabel),canvas.setAttribute("lang",this.effectiveLocale),this.legend.length||this.legendProjection.truncated?canvas.setAttribute("aria-describedby","map-legend"):canvas.removeAttribute("aria-describedby"));for(const[key,marker]of this._markerInstances){const markerElement=marker.getElement?.();if(!markerElement)continue;addPartToken(markerElement,"marker"),markerElement.setAttribute("role","button"),markerElement.tabIndex=0,markerElement.setAttribute("aria-label",this._markerLabels.get(key)||this.localize("map")),markerElement.setAttribute("lang",this.effectiveLocale);const popup=marker.getPopup?.();popup?this.syncPopupSemantics(key,marker,popup):(markerElement.removeAttribute("aria-controls"),markerElement.removeAttribute("aria-expanded"),markerElement.removeAttribute("aria-haspopup"))}this.syncPeerChromeParts()}formatCount(value){return getNumberFormat(this.effectiveLocale).format(value)}legendLimitText(){return this.localize("paginationSummary",void 0,{start:this.formatCount(this.legend.length===0?0:1),end:this.formatCount(this.legend.length),total:this.formatCount(this.legendProjection.inputCount),itemLabel:this.localize("items")})}renderLegendGradient(){const stops=this.legendGradient;if(stops.length<2)return nothing;const lo=stops[0],hi=stops[stops.length-1],span=hi[0]-lo[0],image=stops.map(([value,color],index)=>{const percent=span>0?(value-lo[0])/span*100:index/(stops.length-1)*100;return`${color} ${percent}%`}).join(", ");return html`<div class="legend-gradient">
|
|
2
2
|
<span part="legend-lo">${this.legendGradientLoLabel??this.formatCount(lo[0])}</span>
|
|
3
3
|
<span
|
|
4
4
|
part="legend-gradient"
|
|
@@ -49,4 +49,4 @@ var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3
|
|
|
49
49
|
<slot name="legend" @slotchange=${this.onLegendSlotChange}></slot>
|
|
50
50
|
</div>`:nothing}
|
|
51
51
|
</div>
|
|
52
|
-
`}}__decorate([property({type:Array})],LyraMap.prototype,"center",void 0),__decorate([property({type:Number})],LyraMap.prototype,"zoom",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"maxBounds",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"mapStyle",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"legend",null),__decorate([state()],LyraMap.prototype,"hasLegendSlot",void 0),__decorate([property({attribute:"legend-gradient-lo-label"})],LyraMap.prototype,"legendGradientLoLabel",void 0),__decorate([property({attribute:"legend-gradient-hi-label"})],LyraMap.prototype,"legendGradientHiLabel",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"choropleth",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"markers",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"dataLayers",void 0),__decorate([property()],LyraMap.prototype,"label",void 0),__decorate([state()],LyraMap.prototype,"loading",void 0),__decorate([state()],LyraMap.prototype,"failure",void 0),__decorate([state()],LyraMap.prototype,"visible",void 0),__decorate([query('[part="container"]')],LyraMap.prototype,"containerEl",void 0);export{LyraMap,buildGeoJsonPropertyDiff};
|
|
52
|
+
`}}__decorate([property({type:Array})],LyraMap.prototype,"center",void 0),__decorate([property({type:Number})],LyraMap.prototype,"zoom",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"renderWorldCopies",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"maxBounds",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"mapStyle",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"legend",null),__decorate([state()],LyraMap.prototype,"hasLegendSlot",void 0),__decorate([property({attribute:"legend-gradient-lo-label"})],LyraMap.prototype,"legendGradientLoLabel",void 0),__decorate([property({attribute:"legend-gradient-hi-label"})],LyraMap.prototype,"legendGradientHiLabel",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"choropleth",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"markers",void 0),__decorate([property({attribute:!1})],LyraMap.prototype,"dataLayers",void 0),__decorate([property()],LyraMap.prototype,"label",void 0),__decorate([state()],LyraMap.prototype,"loading",void 0),__decorate([state()],LyraMap.prototype,"failure",void 0),__decorate([state()],LyraMap.prototype,"visible",void 0),__decorate([query('[part="container"]')],LyraMap.prototype,"containerEl",void 0);export{LyraMap,buildGeoJsonPropertyDiff};
|