@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.
Files changed (222) hide show
  1. package/CHANGELOG.md +407 -0
  2. package/README.md +11 -8
  3. package/custom-elements.json +1 -1
  4. package/dist/all.d.ts +1 -0
  5. package/dist/all.js +1 -1
  6. package/dist/autoloader.js +1 -1
  7. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +0 -1
  8. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +1 -1
  9. package/dist/components/charts/chart/chart.class.d.ts +13 -1
  10. package/dist/components/charts/chart/histogram-bin.d.ts +0 -1
  11. package/dist/components/charts/chart/histogram-bin.js +1 -1
  12. package/dist/components/charts/chart/lite-chart.class.d.ts +22 -9
  13. package/dist/components/charts/chart/lite-chart.class.js +6 -6
  14. package/dist/components/conversation/code-block/code-block-shared.d.ts +4 -54
  15. package/dist/components/conversation/code-block/code-block-shared.js +1 -1
  16. package/dist/components/conversation/code-block/shiki-types.d.ts +2 -1
  17. package/dist/components/conversation/generation-metrics/generation-metrics.class.js +1 -1
  18. package/dist/components/conversation/model-select/model-select.class.d.ts +0 -3
  19. package/dist/components/conversation/model-select/model-select.class.js +1 -1
  20. package/dist/components/conversation/selection-toolbar/selection-toolbar.class.js +1 -1
  21. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +0 -1
  22. package/dist/components/conversation/voice-picker/voice-picker.class.js +1 -1
  23. package/dist/components/data/data-grid/data-grid.class.js +1 -1
  24. package/dist/components/data/funnel/funnel.class.d.ts +92 -0
  25. package/dist/components/data/funnel/funnel.class.js +25 -0
  26. package/dist/components/data/funnel/funnel.d.ts +1 -0
  27. package/dist/components/data/funnel/funnel.js +1 -0
  28. package/dist/components/data/funnel/funnel.styles.d.ts +1 -0
  29. package/dist/components/data/funnel/funnel.styles.js +127 -0
  30. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +0 -1
  31. package/dist/components/data/graph-query-builder/graph-query-builder.class.js +1 -1
  32. package/dist/components/data/heatmap/heatmap.class.d.ts +199 -14
  33. package/dist/components/data/heatmap/heatmap.class.js +30 -22
  34. package/dist/components/data/heatmap/heatmap.styles.js +36 -0
  35. package/dist/components/data/index.d.ts +1 -0
  36. package/dist/components/data/index.js +1 -1
  37. package/dist/components/data/table/table.class.d.ts +18 -4
  38. package/dist/components/data/table/table.class.js +2 -2
  39. package/dist/components/data/table/table.styles.js +2 -1
  40. package/dist/components/data/timeline/timeline-cluster.d.ts +1 -0
  41. package/dist/components/data/timeline/timeline-cluster.js +1 -0
  42. package/dist/components/data/timeline/timeline-item.class.d.ts +17 -2
  43. package/dist/components/data/timeline/timeline-item.class.js +13 -2
  44. package/dist/components/data/timeline/timeline-item.styles.js +65 -0
  45. package/dist/components/data/timeline/timeline.class.d.ts +83 -27
  46. package/dist/components/data/timeline/timeline.class.js +3 -3
  47. package/dist/components/data/timeline/timeline.d.ts +1 -0
  48. package/dist/components/data/timeline/timeline.js +1 -1
  49. package/dist/components/data/timeline/timeline.styles.js +14 -0
  50. package/dist/components/forms/button/button.class.js +1 -1
  51. package/dist/components/forms/checkbox/checkbox.class.d.ts +0 -1
  52. package/dist/components/forms/checkbox/checkbox.class.js +1 -1
  53. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +0 -1
  54. package/dist/components/forms/checkbox-group/checkbox-group.class.js +1 -1
  55. package/dist/components/forms/code-editor/code-editor.class.js +1 -1
  56. package/dist/components/forms/color-picker/color-picker.class.js +1 -1
  57. package/dist/components/forms/combobox/combobox.class.d.ts +7 -1
  58. package/dist/components/forms/combobox/combobox.class.js +3 -2
  59. package/dist/components/forms/combobox/combobox.styles.js +1 -1
  60. package/dist/components/forms/date-picker/date-input.class.d.ts +23 -0
  61. package/dist/components/forms/date-picker/date-input.class.js +1 -1
  62. package/dist/components/forms/emoji-picker/emoji-data-loader.d.ts +0 -1
  63. package/dist/components/forms/input/native-time-input.class.js +1 -1
  64. package/dist/components/forms/input/time-input-shared.d.ts +2 -1
  65. package/dist/components/forms/input/time-input.class.js +1 -1
  66. package/dist/components/forms/locale-picker/locale-picker.class.d.ts +0 -1
  67. package/dist/components/forms/locale-picker/locale-picker.class.js +1 -1
  68. package/dist/components/forms/radio/radio-button.styles.d.ts +0 -1
  69. package/dist/components/forms/radio/radio-button.styles.js +1 -1
  70. package/dist/components/forms/radio/radio-group.class.d.ts +0 -1
  71. package/dist/components/forms/radio/radio-group.class.js +1 -1
  72. package/dist/components/forms/radio/radio.class.d.ts +0 -1
  73. package/dist/components/forms/radio/radio.class.js +1 -1
  74. package/dist/components/forms/rubric-form/rubric-form.class.d.ts +0 -1
  75. package/dist/components/forms/rubric-form/rubric-form.class.js +1 -1
  76. package/dist/components/forms/select/select.class.d.ts +0 -1
  77. package/dist/components/forms/select/select.class.js +1 -1
  78. package/dist/components/forms/slider/slider.class.d.ts +0 -1
  79. package/dist/components/forms/slider/slider.class.js +1 -1
  80. package/dist/components/forms/switch/switch.class.d.ts +0 -1
  81. package/dist/components/forms/switch/switch.class.js +1 -1
  82. package/dist/components/forms/time-range/time-range.class.d.ts +0 -1
  83. package/dist/components/forms/time-range/time-range.class.js +1 -1
  84. package/dist/components/forms/token-input/token-input.class.d.ts +0 -1
  85. package/dist/components/forms/token-input/token-input.class.js +1 -1
  86. package/dist/components/layout/app-rail/app-rail-item.class.d.ts +16 -0
  87. package/dist/components/layout/app-rail/app-rail-item.class.js +4 -4
  88. package/dist/components/layout/dashboard-grid/layout-internal.d.ts +0 -1
  89. package/dist/components/layout/dashboard-grid/layout-internal.js +1 -1
  90. package/dist/components/layout/details/accordion-owner.d.ts +1 -1
  91. package/dist/components/layout/filter-bar/filter-bar.class.d.ts +32 -3
  92. package/dist/components/layout/filter-bar/filter-bar.class.js +2 -1
  93. package/dist/components/layout/menu/menu-item.class.js +1 -1
  94. package/dist/components/layout/virtual-list/virtual-list.class.js +1 -1
  95. package/dist/components/layout/widget/widget.class.d.ts +16 -0
  96. package/dist/components/layout/widget/widget.class.js +2 -2
  97. package/dist/components/lr-funnel.d.ts +1 -0
  98. package/dist/components/lr-funnel.js +1 -0
  99. package/dist/components/media/av-player/av-metadata.d.ts +0 -2
  100. package/dist/components/media/av-player/av-metadata.js +1 -1
  101. package/dist/components/media/file-input/file-input.class.d.ts +0 -1
  102. package/dist/components/media/file-input/file-input.class.js +1 -1
  103. package/dist/components/media/flag/flag-peer-bulk-standard.d.ts +25 -0
  104. package/dist/components/media/flag/flag-peer-bulk-standard.js +1 -0
  105. package/dist/components/media/flag/flag.class.d.ts +8 -0
  106. package/dist/components/media/flag/flag.class.js +1 -1
  107. package/dist/components/media/map/map-loader.d.ts +4 -1
  108. package/dist/components/media/map/map.class.d.ts +242 -23
  109. package/dist/components/media/map/map.class.js +2 -2
  110. package/dist/components/overlays/chip/chip-group.class.d.ts +16 -0
  111. package/dist/components/overlays/chip/chip-group.class.js +10 -3
  112. package/dist/components/overlays/overlay/popover.class.d.ts +7 -1
  113. package/dist/components/overlays/overlay/popover.class.js +1 -1
  114. package/dist/components/overlays/overlay/tooltip.class.d.ts +1 -0
  115. package/dist/components/overlays/overlay/tooltip.class.js +1 -1
  116. package/dist/components/overlays/progress/progress-shared.d.ts +0 -2
  117. package/dist/components/overlays/progress/progress-shared.js +1 -1
  118. package/dist/components/overlays/rating/rating.class.js +1 -1
  119. package/dist/components/retrieval/graph/graph-canvas.d.ts +10 -9
  120. package/dist/components/retrieval/mind-map/mind-map-layout.d.ts +0 -4
  121. package/dist/components/retrieval/mind-map/mind-map-layout.js +1 -1
  122. package/dist/components/utility/format/format-options.d.ts +0 -2
  123. package/dist/components/utility/format/format-options.js +1 -1
  124. package/dist/components/utility/icon/icon-resource.d.ts +0 -2
  125. package/dist/components/utility/icon/icon-resource.js +1 -1
  126. package/dist/components/viewers/archive-viewer/zip-resource-guard.d.ts +2 -1
  127. package/dist/components/viewers/docx-viewer/docx-resource-guard.d.ts +0 -3
  128. package/dist/components/viewers/docx-viewer/docx-resource-guard.js +1 -1
  129. package/dist/components/viewers/ebook-viewer/ebook-loader.d.ts +2 -1
  130. package/dist/components/viewers/ebook-viewer/epub-resource-guard.d.ts +0 -3
  131. package/dist/components/viewers/ebook-viewer/epub-resource-guard.js +1 -1
  132. package/dist/components/viewers/pdf-viewer/pdf-loader.d.ts +2 -2
  133. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +2 -2
  134. package/dist/components/viewers/pptx-viewer/pptx-resource-guard.d.ts +0 -2
  135. package/dist/components/viewers/pptx-viewer/pptx-resource-guard.js +1 -1
  136. package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.d.ts +0 -5
  137. package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.js +1 -1
  138. package/dist/custom-elements-jsx.d.ts +16 -8
  139. package/dist/events.d.ts +15 -0
  140. package/dist/internal/accessibility-visibility.d.ts +1 -1
  141. package/dist/internal/anchor-target.d.ts +1 -3
  142. package/dist/internal/anchor-target.js +2 -2
  143. package/dist/internal/anchored-overlay-runtime.d.ts +7 -0
  144. package/dist/internal/anchored-overlay-runtime.js +1 -0
  145. package/dist/internal/announcement-text.d.ts +1 -1
  146. package/dist/internal/ansi.d.ts +0 -4
  147. package/dist/internal/ansi.js +1 -1
  148. package/dist/internal/aria-ownership.d.ts +2 -1
  149. package/dist/internal/autoloader-manifest.js +1 -1
  150. package/dist/internal/autoloader-tags.d.ts +1 -1
  151. package/dist/internal/autoloader-tags.js +1 -1
  152. package/dist/internal/default-strings.generated.d.ts +1 -0
  153. package/dist/internal/default-strings.generated.js +1 -1
  154. package/dist/internal/focus-navigation.d.ts +3 -2
  155. package/dist/internal/form-associated.d.ts +0 -1
  156. package/dist/internal/form-associated.js +1 -1
  157. package/dist/internal/form-control-labels.d.ts +0 -3
  158. package/dist/internal/form-control-labels.js +1 -1
  159. package/dist/internal/localization-runtime.js +1 -1
  160. package/dist/internal/localization-types.d.ts +1 -1
  161. package/dist/internal/localization.js +1 -1
  162. package/dist/internal/lyra-element.d.ts +7 -14
  163. package/dist/internal/lyra-element.js +1 -1
  164. package/dist/internal/nonmodal-overlay-manager.d.ts +9 -0
  165. package/dist/internal/nonmodal-overlay-manager.js +1 -0
  166. package/dist/internal/overlay-manager.d.ts +4 -20
  167. package/dist/internal/overlay-manager.js +1 -1
  168. package/dist/internal/overlay-stack.d.ts +66 -0
  169. package/dist/internal/overlay-stack.js +1 -0
  170. package/dist/internal/package-metadata.d.ts +1 -1
  171. package/dist/internal/package-metadata.js +1 -1
  172. package/dist/internal/positioner.js +1 -1
  173. package/dist/internal/root-registration-allowlist.d.ts +1 -1
  174. package/dist/internal/root-registration-allowlist.js +1 -1
  175. package/dist/internal/text-quote.d.ts +1 -1
  176. package/dist/lyra.d.ts +5 -4
  177. package/dist/lyra.js +1 -1
  178. package/dist/ssr/all.d.ts +1 -0
  179. package/dist/ssr/all.js +1 -1
  180. package/dist/ssr.d.ts +4 -4
  181. package/dist/styles/tokens-root.css +488 -0
  182. package/dist/svelte.d.ts +17 -8
  183. package/dist/translations/ar.js +1 -1
  184. package/dist/translations/de.js +1 -1
  185. package/dist/translations/es.js +1 -1
  186. package/dist/translations/fa.js +1 -1
  187. package/dist/translations/fr.js +1 -1
  188. package/dist/translations/he.js +1 -1
  189. package/dist/translations/ja.js +1 -1
  190. package/dist/translations/pt-BR.js +1 -1
  191. package/dist/translations/ru.js +1 -1
  192. package/dist/translations/zh-CN.js +1 -1
  193. package/dist/utilities/localization.js +1 -1
  194. package/dist/vue.d.ts +16 -8
  195. package/llms/components/lr-app-rail-item.md +8 -1
  196. package/llms/components/lr-app-rail.md +6 -0
  197. package/llms/components/lr-chip-group.md +7 -0
  198. package/llms/components/lr-chip.md +7 -0
  199. package/llms/components/lr-combobox.md +42 -0
  200. package/llms/components/lr-date-input.md +19 -1
  201. package/llms/components/lr-date-picker.md +19 -1
  202. package/llms/components/lr-filter-bar.md +50 -1
  203. package/llms/components/lr-flag.md +14 -0
  204. package/llms/components/lr-funnel.md +122 -0
  205. package/llms/components/lr-heatmap.md +55 -8
  206. package/llms/components/lr-lite-chart.md +20 -8
  207. package/llms/components/lr-map.md +109 -22
  208. package/llms/components/lr-option.md +42 -0
  209. package/llms/components/lr-popover.md +39 -0
  210. package/llms/components/lr-table.md +7 -3
  211. package/llms/components/lr-timeline-item.md +49 -24
  212. package/llms/components/lr-timeline.md +49 -24
  213. package/llms/components/lr-widget.md +7 -1
  214. package/llms/index.md +3 -2
  215. package/llms/peers.md +1 -1
  216. package/llms/shared.md +110 -1
  217. package/llms-full.txt +681 -67
  218. package/llms.txt +1 -1
  219. package/package.json +26 -8
  220. package/vscode-css-data.json +63 -0
  221. package/vscode-html-data.json +108 -23
  222. 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). Colors resolve from `--lr-*` tokens at
80
- * apply time, defaulting to `accent`. */
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 `next` differs from `previous` only in feature
172
- * properties, and returns `null` otherwise so the caller replaces the whole source instead.
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
- * Deliberately strict about what counts as "geometry unchanged": geometries must be the *same
180
- * object*, not merely deep-equal. Structurally comparing polygon rings would cost on the order of
181
- * the re-tile this exists to avoid, and a false positive here paints stale geometry -- a visibly
182
- * wrong map -- whereas a false negative merely takes the old path. An animation that reuses its
183
- * geometry across frames, which is the efficient way to build one anyway, hits the fast path.
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. `undefined` whenever `feature` is. */
193
- readonly origin: 'choropleth' | 'data-layer' | undefined;
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, topmost
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
- /** Additive GeoJSON layers rendered alongside the choropleth/markers -- each entry becomes a
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 leave the
407
- * transform in a state where `getZoom()` returns a non-number; from then on the map throws every
408
- * frame from inside its own matrix math and never paints. There is no exception at the call site
409
- * to catch, so the only reliable signal is to read the camera back afterwards. If it did not
410
- * survive, drop the constraint and restore the camera -- an unconstrained map is a far smaller
411
- * defect than a blank one -- and say so once, naming the property.
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 configureMarkerKeyboard;
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&&notifyMapCanvasReady(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&&currentMarker?(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&&notifyMapCanvasReady(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&&currentMarker?(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};