@optimum-intelligence/opti-ui 0.6.2 → 0.7.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.
@@ -0,0 +1,2030 @@
1
+ "use client";
2
+ import { cx } from "../../utils/cx.js";
3
+ import { seriesColor } from "../../theme/series.js";
4
+ import { EyeIcon, EyeOffIcon } from "../../icons/index.js";
5
+ import { SegmentedControl } from "../toggle/Toggle.js";
6
+ import { useResolvedColors } from "./colors.js";
7
+ import { c } from "react/compiler-runtime";
8
+ import * as React from "react";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ import { createPortal } from "react-dom";
11
+ import { AttributionControl, Layer, Map, Marker, NavigationControl, Popup, Source, useControl } from "@vis.gl/react-maplibre";
12
+ //#region src/components/map/Map.tsx
13
+ /**
14
+ * Loads MapLibre and points it at its worker, once, on the first map mount. The `?url` import stays
15
+ * external, so the app's Vite resolves the worker of the installed maplibre-gl. It is a dynamic import
16
+ * because Node would run the worker file when importing this module (docs generation, SSR).
17
+ */
18
+ var mapLib;
19
+ function loadMapLib() {
20
+ mapLib ??= Promise.all([import("maplibre-gl"), import("maplibre-gl/dist/maplibre-gl-worker.mjs?url")]).then(([lib, worker]) => {
21
+ lib.setWorkerUrl(worker.default);
22
+ return lib;
23
+ });
24
+ return mapLib;
25
+ }
26
+ var defaultLabels = {
27
+ zoomIn: "Zoom in",
28
+ zoomOut: "Zoom out",
29
+ showAll: "Show all",
30
+ hideAll: "Hide all",
31
+ show: "Show",
32
+ hide: "Hide",
33
+ depot: "Depot",
34
+ noData: "No data to show",
35
+ expand: "Expand map",
36
+ collapse: "Exit expanded map"
37
+ };
38
+ var MapContext = React.createContext(null);
39
+ function useMapContext(part) {
40
+ const ctx = React.use(MapContext);
41
+ if (!ctx) throw new Error(`${part} must be used inside Map.Root`);
42
+ return ctx;
43
+ }
44
+ /**
45
+ * Builds a MapLibre style from a raster tile URL template (`{z}`, `{x}`, `{y}`), for `MapBaseLayer.style`.
46
+ *
47
+ * @example
48
+ * const satellite = rasterStyle('https://tiles.example.com/{z}/{x}/{y}.jpg', '© Example');
49
+ */
50
+ function rasterStyle(tiles, attribution, tileSize = 256) {
51
+ return {
52
+ version: 8,
53
+ sources: { raster: {
54
+ type: "raster",
55
+ tiles: Array.isArray(tiles) ? tiles : [tiles],
56
+ tileSize,
57
+ attribution
58
+ } },
59
+ layers: [{
60
+ id: "raster",
61
+ type: "raster",
62
+ source: "raster"
63
+ }]
64
+ };
65
+ }
66
+ /** True when `coords` nests at least `min` positions and every one is a finite `[lng, lat]`. */
67
+ function hasValidPositions(coords, min) {
68
+ let count = 0;
69
+ const check = (value) => {
70
+ if (!Array.isArray(value) || value.length === 0) return false;
71
+ if (typeof value[0] !== "object") {
72
+ count++;
73
+ return value.length >= 2 && Number.isFinite(value[0]) && Number.isFinite(value[1]);
74
+ }
75
+ return value.every(check);
76
+ };
77
+ return check(coords) && count >= min;
78
+ }
79
+ /** Grows `bounds` by every `[lng, lat]` pair nested in `coords`. */
80
+ function extend(bounds, coords) {
81
+ if (!Array.isArray(coords)) return bounds;
82
+ if (typeof coords[0] === "number") {
83
+ const [x, y] = coords;
84
+ return bounds ? [
85
+ Math.min(bounds[0], x),
86
+ Math.min(bounds[1], y),
87
+ Math.max(bounds[2], x),
88
+ Math.max(bounds[3], y)
89
+ ] : [
90
+ x,
91
+ y,
92
+ x,
93
+ y
94
+ ];
95
+ }
96
+ return coords.reduce(extend, bounds);
97
+ }
98
+ var toneColors = {
99
+ neutral: {
100
+ solid: "var(--oui-color-text-muted)",
101
+ fill: "var(--oui-color-border-subtle)",
102
+ line: "var(--oui-color-border)"
103
+ },
104
+ accent: {
105
+ solid: "var(--oui-color-accent)",
106
+ fill: "var(--oui-color-accent-subtle)",
107
+ line: "var(--oui-color-info-border)"
108
+ },
109
+ success: {
110
+ solid: "var(--oui-color-success)",
111
+ fill: "var(--oui-color-success-subtle)",
112
+ line: "var(--oui-color-success-border)"
113
+ },
114
+ warning: {
115
+ solid: "var(--oui-color-warning)",
116
+ fill: "var(--oui-color-warning-subtle)",
117
+ line: "var(--oui-color-warning-border)"
118
+ },
119
+ danger: {
120
+ solid: "var(--oui-color-danger)",
121
+ fill: "var(--oui-color-danger-subtle)",
122
+ line: "var(--oui-color-danger-border)"
123
+ }
124
+ };
125
+ var SELECTED = [
126
+ "boolean",
127
+ ["feature-state", "selected"],
128
+ false
129
+ ];
130
+ var HOVER = [
131
+ "boolean",
132
+ ["feature-state", "hover"],
133
+ false
134
+ ];
135
+ var ACTIVE = [
136
+ "any",
137
+ SELECTED,
138
+ HOVER
139
+ ];
140
+ /** Full opacity for selected or hovered items, `dim` for the rest while anything is selected. */
141
+ var dimmed = (hasSelection, dim) => hasSelection ? [
142
+ "case",
143
+ ACTIVE,
144
+ 1,
145
+ dim
146
+ ] : 1;
147
+ /**
148
+ * Shared wiring of the data parts: registers layers and bounds with the root, routes events back,
149
+ * and keeps the `selected` feature state in sync (also after a style switch re-adds the source).
150
+ */
151
+ function useDataPart(partName, sourceId, options) {
152
+ const $ = c(36);
153
+ const ctx = useMapContext(partName);
154
+ const { items, selectedIds: t0, layerIds, coordinates, minPositions: t1, onItemClick, onItemHover } = options;
155
+ let t2;
156
+ if ($[0] !== t0) {
157
+ t2 = t0 === void 0 ? [] : t0;
158
+ $[0] = t0;
159
+ $[1] = t2;
160
+ } else t2 = $[1];
161
+ const selectedIds = t2;
162
+ const minPositions = t1 === void 0 ? 1 : t1;
163
+ const { register, setHandlers, map } = ctx;
164
+ const selected = new Set(selectedIds);
165
+ let t3;
166
+ if ($[2] !== selectedIds) {
167
+ t3 = selectedIds.join("\0");
168
+ $[2] = selectedIds;
169
+ $[3] = t3;
170
+ } else t3 = $[3];
171
+ const selectedKey = t3;
172
+ let t4;
173
+ if ($[4] !== coordinates || $[5] !== minPositions) {
174
+ t4 = (item) => hasValidPositions(coordinates(item), minPositions);
175
+ $[4] = coordinates;
176
+ $[5] = minPositions;
177
+ $[6] = t4;
178
+ } else t4 = $[6];
179
+ const valid = new Set(items.filter(t4));
180
+ const invalidIds = items.filter((item_0) => !valid.has(item_0)).map(_temp).join(", ");
181
+ let t5;
182
+ let t6;
183
+ if ($[7] !== invalidIds || $[8] !== partName) {
184
+ t5 = () => {
185
+ if (invalidIds && process.env.NODE_ENV !== "production") console.warn(`${partName}: skipped items with invalid coordinates: ${invalidIds}`);
186
+ };
187
+ t6 = [partName, invalidIds];
188
+ $[7] = invalidIds;
189
+ $[8] = partName;
190
+ $[9] = t5;
191
+ $[10] = t6;
192
+ } else {
193
+ t5 = $[9];
194
+ t6 = $[10];
195
+ }
196
+ React.useEffect(t5, t6);
197
+ let bounds = null;
198
+ let selectedBounds = null;
199
+ for (const item_2 of valid) {
200
+ bounds = extend(bounds, coordinates(item_2));
201
+ if (selected.has(item_2.id)) selectedBounds = extend(selectedBounds, coordinates(item_2));
202
+ }
203
+ const boundsKey = `${bounds}|${selectedBounds}|${layerIds}`;
204
+ let t7;
205
+ if ($[11] !== bounds || $[12] !== layerIds || $[13] !== register || $[14] !== selectedBounds || $[15] !== sourceId) {
206
+ t7 = () => {
207
+ register(sourceId, {
208
+ layerIds,
209
+ bounds,
210
+ selectedBounds
211
+ });
212
+ };
213
+ $[11] = bounds;
214
+ $[12] = layerIds;
215
+ $[13] = register;
216
+ $[14] = selectedBounds;
217
+ $[15] = sourceId;
218
+ $[16] = t7;
219
+ } else t7 = $[16];
220
+ let t8;
221
+ if ($[17] !== boundsKey || $[18] !== register || $[19] !== sourceId) {
222
+ t8 = [
223
+ register,
224
+ sourceId,
225
+ boundsKey
226
+ ];
227
+ $[17] = boundsKey;
228
+ $[18] = register;
229
+ $[19] = sourceId;
230
+ $[20] = t8;
231
+ } else t8 = $[20];
232
+ React.useEffect(t7, t8);
233
+ let t10;
234
+ let t9;
235
+ if ($[21] !== register || $[22] !== sourceId) {
236
+ t9 = () => () => register(sourceId, null);
237
+ t10 = [register, sourceId];
238
+ $[21] = register;
239
+ $[22] = sourceId;
240
+ $[23] = t10;
241
+ $[24] = t9;
242
+ } else {
243
+ t10 = $[23];
244
+ t9 = $[24];
245
+ }
246
+ React.useEffect(t9, t10);
247
+ let t11;
248
+ if ($[25] !== items || $[26] !== onItemClick || $[27] !== onItemHover || $[28] !== setHandlers || $[29] !== sourceId) {
249
+ t11 = () => {
250
+ const byId = (id) => items.find((item_3) => item_3.id === id);
251
+ setHandlers(sourceId, {
252
+ onClick: (id_0, event) => {
253
+ const item_4 = byId(id_0);
254
+ if (item_4) onItemClick?.(item_4, event);
255
+ },
256
+ onHover: (id_1, event_0) => onItemHover?.(id_1 == null ? null : byId(id_1) ?? null, event_0)
257
+ });
258
+ };
259
+ $[25] = items;
260
+ $[26] = onItemClick;
261
+ $[27] = onItemHover;
262
+ $[28] = setHandlers;
263
+ $[29] = sourceId;
264
+ $[30] = t11;
265
+ } else t11 = $[30];
266
+ React.useEffect(t11);
267
+ let t12;
268
+ let t13;
269
+ if ($[31] !== setHandlers || $[32] !== sourceId) {
270
+ t12 = () => () => setHandlers(sourceId, null);
271
+ t13 = [setHandlers, sourceId];
272
+ $[31] = setHandlers;
273
+ $[32] = sourceId;
274
+ $[33] = t12;
275
+ $[34] = t13;
276
+ } else {
277
+ t12 = $[33];
278
+ t13 = $[34];
279
+ }
280
+ React.useEffect(t12, t13);
281
+ let t14;
282
+ if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
283
+ t14 = /* @__PURE__ */ new Set();
284
+ $[35] = t14;
285
+ } else t14 = $[35];
286
+ const applied = React.useRef(t14);
287
+ React.useEffect(() => {
288
+ const instance = map?.getMap();
289
+ if (!instance) return;
290
+ const drawn = new Set([...valid].map(_temp2));
291
+ const target = new Set((selectedKey ? selectedKey.split("\0") : []).filter((id_2) => drawn.has(id_2)));
292
+ const sync = () => {
293
+ if (!instance.getSource(sourceId)) return;
294
+ const prev = applied.current;
295
+ for (const id_3 of prev) if (!target.has(id_3)) instance.setFeatureState({
296
+ source: sourceId,
297
+ id: id_3
298
+ }, { selected: false });
299
+ for (const id_4 of target) if (!prev.has(id_4)) instance.setFeatureState({
300
+ source: sourceId,
301
+ id: id_4
302
+ }, { selected: true });
303
+ applied.current = target;
304
+ };
305
+ sync();
306
+ const onData = (e) => {
307
+ if (e.sourceId !== sourceId || e.sourceDataType !== "metadata") return;
308
+ applied.current = /* @__PURE__ */ new Set();
309
+ sync();
310
+ };
311
+ instance.on("sourcedata", onData);
312
+ return () => {
313
+ instance.off("sourcedata", onData);
314
+ };
315
+ }, [
316
+ map,
317
+ sourceId,
318
+ valid,
319
+ selectedKey
320
+ ]);
321
+ return {
322
+ colors: ctx.colors,
323
+ hasSelection: selectedIds.length > 0,
324
+ valid
325
+ };
326
+ }
327
+ /** A source id that is safe in MapLibre layer ids. */
328
+ function _temp2(item_5) {
329
+ return item_5.id;
330
+ }
331
+ function _temp(item_1) {
332
+ return item_1.id;
333
+ }
334
+ function usePartId(prefix) {
335
+ const $ = c(3);
336
+ const t0 = React.useId();
337
+ let t1;
338
+ if ($[0] !== t0) {
339
+ let t2;
340
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
341
+ t2 = /[^\w-]/g;
342
+ $[2] = t2;
343
+ } else t2 = $[2];
344
+ t1 = t0.replace(t2, "");
345
+ $[0] = t0;
346
+ $[1] = t1;
347
+ } else t1 = $[1];
348
+ return `oui-${prefix}-${t1}`;
349
+ }
350
+ /**
351
+ * A MapLibre map styled and themed with the library tokens. Holds the base layer state and routes clicks
352
+ * and hovers to the data parts inside it. `Map.Root` › data parts (`Map.Areas`, `Map.Routes`,
353
+ * `Map.Points`) and `Map.Marker`s, with `Map.Overlay`s for legends, switches and cards on top.
354
+ * Needs `@optimum-intelligence/opti-ui/map.css` imported; MapLibre's worker is set up for Vite apps.
355
+ *
356
+ * @example
357
+ * <Map.Root
358
+ * baseLayers={[{ id: 'streets', label: 'Streets', style: 'https://tiles.openfreemap.org/styles/bright' }]}
359
+ * initialView={{ longitude: 19.04, latitude: 47.5, zoom: 10 }}
360
+ * >
361
+ * <Map.Routes
362
+ * items={[{ id: 'trip-1', coordinates: [[19.0, 47.48], [19.08, 47.52]] }]}
363
+ * selectedIds={selected}
364
+ * onItemClick={(trip) => setSelected([trip.id])}
365
+ * />
366
+ * <Map.Marker kind="depot" position={[19.0, 47.48]} />
367
+ * </Map.Root>
368
+ */
369
+ function MapRoot(t0) {
370
+ const $ = c(82);
371
+ let baseLayer;
372
+ let baseLayers;
373
+ let children;
374
+ let className;
375
+ let defaultBaseLayer;
376
+ let initialView;
377
+ let labels;
378
+ let onBaseLayerChange;
379
+ let onClick;
380
+ let onMouseMove;
381
+ let onMouseOut;
382
+ let props;
383
+ let ref;
384
+ let style;
385
+ let t1;
386
+ let t2;
387
+ let t3;
388
+ if ($[0] !== t0) {
389
+ ({ref, baseLayers, baseLayer, defaultBaseLayer, onBaseLayerChange, initialView, fit: t1, labels, controlsPosition: t2, expandable: t3, className, style, children, onClick, onMouseMove, onMouseOut, ...props} = t0);
390
+ $[0] = t0;
391
+ $[1] = baseLayer;
392
+ $[2] = baseLayers;
393
+ $[3] = children;
394
+ $[4] = className;
395
+ $[5] = defaultBaseLayer;
396
+ $[6] = initialView;
397
+ $[7] = labels;
398
+ $[8] = onBaseLayerChange;
399
+ $[9] = onClick;
400
+ $[10] = onMouseMove;
401
+ $[11] = onMouseOut;
402
+ $[12] = props;
403
+ $[13] = ref;
404
+ $[14] = style;
405
+ $[15] = t1;
406
+ $[16] = t2;
407
+ $[17] = t3;
408
+ } else {
409
+ baseLayer = $[1];
410
+ baseLayers = $[2];
411
+ children = $[3];
412
+ className = $[4];
413
+ defaultBaseLayer = $[5];
414
+ initialView = $[6];
415
+ labels = $[7];
416
+ onBaseLayerChange = $[8];
417
+ onClick = $[9];
418
+ onMouseMove = $[10];
419
+ onMouseOut = $[11];
420
+ props = $[12];
421
+ ref = $[13];
422
+ style = $[14];
423
+ t1 = $[15];
424
+ t2 = $[16];
425
+ t3 = $[17];
426
+ }
427
+ const fit = t1 === void 0 ? "data" : t1;
428
+ const controlsPosition = t2 === void 0 ? "top-right" : t2;
429
+ const expandable = t3 === void 0 ? false : t3;
430
+ const [element, setElement] = React.useState(null);
431
+ const [map, setMap] = React.useState(null);
432
+ let t4;
433
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
434
+ t4 = {};
435
+ $[18] = t4;
436
+ } else t4 = $[18];
437
+ const [parts, setParts] = React.useState(t4);
438
+ const [internalLayer, setInternalLayer] = React.useState(defaultBaseLayer ?? baseLayers[0]?.id ?? "");
439
+ const [cursor, setCursor] = React.useState("");
440
+ const [expanded, setExpanded] = React.useState(false);
441
+ let t5;
442
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
443
+ t5 = {};
444
+ $[19] = t5;
445
+ } else t5 = $[19];
446
+ const handlers = React.useRef(t5);
447
+ const hovered = React.useRef(null);
448
+ const colors = useResolvedColors(element);
449
+ let t6;
450
+ if ($[20] !== labels) {
451
+ t6 = {
452
+ ...defaultLabels,
453
+ ...labels
454
+ };
455
+ $[20] = labels;
456
+ $[21] = t6;
457
+ } else t6 = $[21];
458
+ const text = t6;
459
+ const currentId = baseLayer ?? internalLayer;
460
+ let t7;
461
+ if ($[22] !== baseLayers || $[23] !== currentId) {
462
+ t7 = baseLayers.find((l) => l.id === currentId) ?? baseLayers[0];
463
+ $[22] = baseLayers;
464
+ $[23] = currentId;
465
+ $[24] = t7;
466
+ } else t7 = $[24];
467
+ const current = t7;
468
+ const mapStyle = colors.dark && current?.darkStyle ? current.darkStyle : current?.style;
469
+ let t8;
470
+ if ($[25] !== onBaseLayerChange) {
471
+ t8 = (id) => {
472
+ setInternalLayer(id);
473
+ onBaseLayerChange?.(id);
474
+ };
475
+ $[25] = onBaseLayerChange;
476
+ $[26] = t8;
477
+ } else t8 = $[26];
478
+ const setBaseLayer = t8;
479
+ let t9;
480
+ if ($[27] === Symbol.for("react.memo_cache_sentinel")) {
481
+ t9 = (partId, part) => {
482
+ setParts((prev) => {
483
+ const next = { ...prev };
484
+ if (part) next[partId] = part;
485
+ else delete next[partId];
486
+ return next;
487
+ });
488
+ };
489
+ $[27] = t9;
490
+ } else t9 = $[27];
491
+ const register = t9;
492
+ let t10;
493
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
494
+ t10 = (partId_0, value) => {
495
+ if (value) handlers.current[partId_0] = value;
496
+ else delete handlers.current[partId_0];
497
+ };
498
+ $[28] = t10;
499
+ } else t10 = $[28];
500
+ const setHandlers = t10;
501
+ let dataKey;
502
+ let empty;
503
+ let interactiveLayerIds;
504
+ let ownerOf;
505
+ let t11;
506
+ if ($[29] !== fit || $[30] !== parts) {
507
+ const entries = Object.entries(parts);
508
+ interactiveLayerIds = entries.flatMap(_temp3);
509
+ ownerOf = (layerId) => entries.find((t12) => {
510
+ const [, part_1] = t12;
511
+ return part_1.layerIds.includes(layerId);
512
+ })?.[0];
513
+ empty = entries.length > 0 && entries.every(_temp4);
514
+ const corners = _temp5;
515
+ const boundsKey = _temp7;
516
+ dataKey = fit === "none" ? "" : boundsKey(extend(null, entries.map((t13) => {
517
+ const [, part_3] = t13;
518
+ return corners(part_3.bounds);
519
+ })));
520
+ t11 = fit === "selected" ? boundsKey(extend(null, entries.map((t14) => {
521
+ const [, part_4] = t14;
522
+ return corners(part_4.selectedBounds);
523
+ }))) : "";
524
+ $[29] = fit;
525
+ $[30] = parts;
526
+ $[31] = dataKey;
527
+ $[32] = empty;
528
+ $[33] = interactiveLayerIds;
529
+ $[34] = ownerOf;
530
+ $[35] = t11;
531
+ } else {
532
+ dataKey = $[31];
533
+ empty = $[32];
534
+ interactiveLayerIds = $[33];
535
+ ownerOf = $[34];
536
+ t11 = $[35];
537
+ }
538
+ const selectionKey = t11;
539
+ const userMoved = React.useRef(false);
540
+ let t12;
541
+ let t13;
542
+ if ($[36] !== map) {
543
+ t12 = () => {
544
+ const instance = map?.getMap();
545
+ if (!instance) return;
546
+ const onMoveStart = (event) => {
547
+ if (event.originalEvent) userMoved.current = true;
548
+ };
549
+ instance.on("movestart", onMoveStart);
550
+ return () => {
551
+ instance.off("movestart", onMoveStart);
552
+ };
553
+ };
554
+ t13 = [map];
555
+ $[36] = map;
556
+ $[37] = t12;
557
+ $[38] = t13;
558
+ } else {
559
+ t12 = $[37];
560
+ t13 = $[38];
561
+ }
562
+ React.useEffect(t12, t13);
563
+ let t14;
564
+ if ($[39] === Symbol.for("react.memo_cache_sentinel")) {
565
+ t14 = {
566
+ data: "",
567
+ selection: ""
568
+ };
569
+ $[39] = t14;
570
+ } else t14 = $[39];
571
+ const fitted = React.useRef(t14);
572
+ let t15;
573
+ let t16;
574
+ if ($[40] !== dataKey || $[41] !== map || $[42] !== selectionKey) {
575
+ t15 = () => {
576
+ if (!map) return;
577
+ const prev_0 = fitted.current;
578
+ fitted.current = {
579
+ data: dataKey,
580
+ selection: selectionKey
581
+ };
582
+ const selectionChanged = selectionKey !== prev_0.selection;
583
+ const dataChanged = dataKey !== prev_0.data && !userMoved.current;
584
+ const key = selectionKey || dataKey;
585
+ if (!key || !(selectionChanged || dataChanged)) return;
586
+ const [w, s, e, n_0] = key.split(",").map(Number);
587
+ map.fitBounds([[w, s], [e, n_0]], {
588
+ padding: 48,
589
+ maxZoom: 15,
590
+ duration: 400
591
+ });
592
+ };
593
+ t16 = [
594
+ map,
595
+ dataKey,
596
+ selectionKey
597
+ ];
598
+ $[40] = dataKey;
599
+ $[41] = map;
600
+ $[42] = selectionKey;
601
+ $[43] = t15;
602
+ $[44] = t16;
603
+ } else {
604
+ t15 = $[43];
605
+ t16 = $[44];
606
+ }
607
+ React.useEffect(t15, t16);
608
+ let t17;
609
+ if ($[45] === Symbol.for("react.memo_cache_sentinel")) {
610
+ t17 = (next_0, event_0) => {
611
+ const prev_1 = hovered.current;
612
+ const key_0 = _temp8;
613
+ if (key_0(prev_1) === key_0(next_0)) return;
614
+ const instance_0 = event_0.target;
615
+ if (prev_1) {
616
+ if (instance_0.getSource(prev_1.source)) instance_0.setFeatureState(prev_1, { hover: false });
617
+ handlers.current[prev_1.source]?.onHover?.(null, event_0);
618
+ }
619
+ if (next_0) {
620
+ instance_0.setFeatureState(next_0, { hover: true });
621
+ handlers.current[next_0.source]?.onHover?.(String(next_0.id), event_0);
622
+ }
623
+ hovered.current = next_0;
624
+ setCursor(next_0 ? "pointer" : "");
625
+ };
626
+ $[45] = t17;
627
+ } else t17 = $[45];
628
+ const setHover = t17;
629
+ let t18;
630
+ let t19;
631
+ if ($[46] !== expanded) {
632
+ t18 = () => {
633
+ if (!expanded) return;
634
+ const onKeyDown = (event_1) => {
635
+ if (event_1.key === "Escape" && !event_1.defaultPrevented) setExpanded(false);
636
+ };
637
+ document.addEventListener("keydown", onKeyDown);
638
+ return () => document.removeEventListener("keydown", onKeyDown);
639
+ };
640
+ t19 = [expanded];
641
+ $[46] = expanded;
642
+ $[47] = t18;
643
+ $[48] = t19;
644
+ } else {
645
+ t18 = $[47];
646
+ t19 = $[48];
647
+ }
648
+ React.useEffect(t18, t19);
649
+ let t20;
650
+ if ($[49] !== initialView) {
651
+ t20 = initialView && "bounds" in initialView ? {
652
+ bounds: initialView.bounds,
653
+ fitBoundsOptions: { padding: 48 }
654
+ } : initialView;
655
+ $[49] = initialView;
656
+ $[50] = t20;
657
+ } else t20 = $[50];
658
+ const initialViewState = t20;
659
+ let t21;
660
+ if ($[51] !== className) {
661
+ t21 = cx("oui-map", className);
662
+ $[51] = className;
663
+ $[52] = t21;
664
+ } else t21 = $[52];
665
+ const t22 = expanded || void 0;
666
+ let t23;
667
+ if ($[53] !== baseLayers || $[54] !== children || $[55] !== colors || $[56] !== controlsPosition || $[57] !== current?.attribution || $[58] !== current?.id || $[59] !== cursor || $[60] !== element || $[61] !== empty || $[62] !== expandable || $[63] !== expanded || $[64] !== initialViewState || $[65] !== interactiveLayerIds || $[66] !== map || $[67] !== mapStyle || $[68] !== onClick || $[69] !== onMouseMove || $[70] !== onMouseOut || $[71] !== ownerOf || $[72] !== props || $[73] !== ref || $[74] !== setBaseLayer || $[75] !== text) {
668
+ t23 = element && /* @__PURE__ */ jsx(Map, {
669
+ ...props,
670
+ mapLib: loadMapLib(),
671
+ ref: (instance_1) => {
672
+ setMap(instance_1);
673
+ if (typeof ref === "function") ref(instance_1);
674
+ else if (ref) ref.current = instance_1;
675
+ },
676
+ mapStyle,
677
+ initialViewState,
678
+ interactiveLayerIds,
679
+ cursor,
680
+ attributionControl: false,
681
+ locale: {
682
+ "NavigationControl.ZoomIn": text.zoomIn,
683
+ "NavigationControl.ZoomOut": text.zoomOut
684
+ },
685
+ onClick: (event_2) => {
686
+ const feature = event_2.features?.[0];
687
+ const owner = feature && ownerOf(feature.layer.id);
688
+ if (feature && owner && feature.id != null) handlers.current[owner]?.onClick?.(String(feature.id), event_2);
689
+ onClick?.(event_2);
690
+ },
691
+ onMouseMove: (event_3) => {
692
+ const feature_0 = event_3.features?.[0];
693
+ const owner_0 = feature_0 && ownerOf(feature_0.layer.id);
694
+ setHover(feature_0 && owner_0 && feature_0.id != null ? {
695
+ source: owner_0,
696
+ id: feature_0.id
697
+ } : null, event_3);
698
+ onMouseMove?.(event_3);
699
+ },
700
+ onMouseOut: (event_4) => {
701
+ setHover(null, event_4);
702
+ onMouseOut?.(event_4);
703
+ },
704
+ children: /* @__PURE__ */ jsxs(MapContext, {
705
+ value: {
706
+ map,
707
+ colors,
708
+ labels: text,
709
+ baseLayers,
710
+ baseLayer: current?.id ?? "",
711
+ setBaseLayer,
712
+ register,
713
+ setHandlers
714
+ },
715
+ children: [
716
+ controlsPosition && /* @__PURE__ */ jsx(NavigationControl, {
717
+ position: controlsPosition,
718
+ showCompass: false
719
+ }),
720
+ expandable && /* @__PURE__ */ jsx(ExpandControl, {
721
+ position: controlsPosition || "top-right",
722
+ expanded,
723
+ label: expanded ? text.collapse : text.expand,
724
+ onToggle: () => setExpanded(_temp9)
725
+ }),
726
+ /* @__PURE__ */ jsx(AttributionControl, {
727
+ compact: true,
728
+ customAttribution: current?.attribution
729
+ }, current?.id),
730
+ children,
731
+ empty && /* @__PURE__ */ jsx("div", {
732
+ className: "oui-map__empty",
733
+ children: text.noData
734
+ })
735
+ ]
736
+ })
737
+ });
738
+ $[53] = baseLayers;
739
+ $[54] = children;
740
+ $[55] = colors;
741
+ $[56] = controlsPosition;
742
+ $[57] = current?.attribution;
743
+ $[58] = current?.id;
744
+ $[59] = cursor;
745
+ $[60] = element;
746
+ $[61] = empty;
747
+ $[62] = expandable;
748
+ $[63] = expanded;
749
+ $[64] = initialViewState;
750
+ $[65] = interactiveLayerIds;
751
+ $[66] = map;
752
+ $[67] = mapStyle;
753
+ $[68] = onClick;
754
+ $[69] = onMouseMove;
755
+ $[70] = onMouseOut;
756
+ $[71] = ownerOf;
757
+ $[72] = props;
758
+ $[73] = ref;
759
+ $[74] = setBaseLayer;
760
+ $[75] = text;
761
+ $[76] = t23;
762
+ } else t23 = $[76];
763
+ let t24;
764
+ if ($[77] !== style || $[78] !== t21 || $[79] !== t22 || $[80] !== t23) {
765
+ t24 = /* @__PURE__ */ jsx("div", {
766
+ ref: setElement,
767
+ className: t21,
768
+ style,
769
+ "data-expanded": t22,
770
+ children: t23
771
+ });
772
+ $[77] = style;
773
+ $[78] = t21;
774
+ $[79] = t22;
775
+ $[80] = t23;
776
+ $[81] = t24;
777
+ } else t24 = $[81];
778
+ return t24;
779
+ }
780
+ /** The expand button as a MapLibre control, so it stacks with the zoom buttons in the same corner. */
781
+ function _temp9(value_0) {
782
+ return !value_0;
783
+ }
784
+ function _temp8(h) {
785
+ return h ? `${h.source}|${h.id}` : "";
786
+ }
787
+ function _temp7(b_0) {
788
+ return b_0?.map(_temp6).join(",") ?? "";
789
+ }
790
+ function _temp6(n) {
791
+ return n.toFixed(5);
792
+ }
793
+ function _temp5(b) {
794
+ return b && [b.slice(0, 2), b.slice(2)];
795
+ }
796
+ function _temp4(t0) {
797
+ const [, part_2] = t0;
798
+ return !part_2.bounds;
799
+ }
800
+ function _temp3(t0) {
801
+ const [, part_0] = t0;
802
+ return part_0.layerIds;
803
+ }
804
+ function ExpandControl(t0) {
805
+ const $ = c(12);
806
+ const { position, expanded, label, onToggle } = t0;
807
+ const [host] = React.useState(_temp0);
808
+ let t1;
809
+ if ($[0] !== host) {
810
+ t1 = () => ({
811
+ onAdd: () => host,
812
+ onRemove: () => host.remove()
813
+ });
814
+ $[0] = host;
815
+ $[1] = t1;
816
+ } else t1 = $[1];
817
+ let t2;
818
+ if ($[2] !== position) {
819
+ t2 = { position };
820
+ $[2] = position;
821
+ $[3] = t2;
822
+ } else t2 = $[3];
823
+ useControl(t1, t2);
824
+ let t3;
825
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
826
+ t3 = /* @__PURE__ */ jsx("span", {
827
+ className: "maplibregl-ctrl-icon",
828
+ "aria-hidden": "true"
829
+ });
830
+ $[4] = t3;
831
+ } else t3 = $[4];
832
+ let t4;
833
+ if ($[5] !== expanded || $[6] !== label || $[7] !== onToggle) {
834
+ t4 = /* @__PURE__ */ jsx("button", {
835
+ type: "button",
836
+ className: "oui-map__expand",
837
+ "aria-label": label,
838
+ title: label,
839
+ "aria-pressed": expanded,
840
+ onClick: onToggle,
841
+ children: t3
842
+ });
843
+ $[5] = expanded;
844
+ $[6] = label;
845
+ $[7] = onToggle;
846
+ $[8] = t4;
847
+ } else t4 = $[8];
848
+ let t5;
849
+ if ($[9] !== host || $[10] !== t4) {
850
+ t5 = createPortal(t4, host);
851
+ $[9] = host;
852
+ $[10] = t4;
853
+ $[11] = t5;
854
+ } else t5 = $[11];
855
+ return t5;
856
+ }
857
+ function _temp0() {
858
+ const element = document.createElement("div");
859
+ element.className = "maplibregl-ctrl maplibregl-ctrl-group";
860
+ return element;
861
+ }
862
+ /**
863
+ * Lines such as trips or tracks, drawn as one source with a casing, a solid and a dashed layer. Selected
864
+ * routes get a halo in the surface colour; hover and selection use feature state, so they never rebuild
865
+ * the data. Colours come from `color` or the chart palette.
866
+ *
867
+ * @example
868
+ * <Map.Routes
869
+ * items={trips.map((t) => ({ id: t.id, coordinates: t.path, dashed: t.planned }))}
870
+ * selectedIds={selected}
871
+ * onItemClick={(trip) => setSelected([trip.id])}
872
+ * />
873
+ */
874
+ function MapRoutes(t0) {
875
+ const $ = c(68);
876
+ const { items, selectedIds, onItemClick, onItemHover } = t0;
877
+ const sourceId = usePartId("routes");
878
+ const t1 = `${sourceId}-casing`;
879
+ const t2 = `${sourceId}-solid`;
880
+ const t3 = `${sourceId}-dashed`;
881
+ let t4;
882
+ if ($[0] !== t1 || $[1] !== t2 || $[2] !== t3) {
883
+ t4 = {
884
+ casing: t1,
885
+ solid: t2,
886
+ dashed: t3
887
+ };
888
+ $[0] = t1;
889
+ $[1] = t2;
890
+ $[2] = t3;
891
+ $[3] = t4;
892
+ } else t4 = $[3];
893
+ const ids = t4;
894
+ let t5;
895
+ if ($[4] !== ids.dashed || $[5] !== ids.solid) {
896
+ t5 = [ids.solid, ids.dashed];
897
+ $[4] = ids.dashed;
898
+ $[5] = ids.solid;
899
+ $[6] = t5;
900
+ } else t5 = $[6];
901
+ let t6;
902
+ if ($[7] !== items || $[8] !== onItemClick || $[9] !== onItemHover || $[10] !== selectedIds || $[11] !== t5) {
903
+ t6 = {
904
+ items,
905
+ selectedIds,
906
+ layerIds: t5,
907
+ coordinates: _temp1,
908
+ minPositions: 2,
909
+ onItemClick,
910
+ onItemHover
911
+ };
912
+ $[7] = items;
913
+ $[8] = onItemClick;
914
+ $[9] = onItemHover;
915
+ $[10] = selectedIds;
916
+ $[11] = t5;
917
+ $[12] = t6;
918
+ } else t6 = $[12];
919
+ const { colors, hasSelection, valid } = useDataPart("Map.Routes", sourceId, t6);
920
+ let t7;
921
+ if ($[13] !== colors || $[14] !== items || $[15] !== valid) {
922
+ let t8;
923
+ if ($[17] !== colors || $[18] !== valid) {
924
+ t8 = (item_0, index) => valid.has(item_0) ? [{
925
+ type: "Feature",
926
+ properties: {
927
+ id: item_0.id,
928
+ dashed: !!item_0.dashed,
929
+ color: colors.color(item_0.color ?? seriesColor(item_0.colorIndex ?? index))
930
+ },
931
+ geometry: {
932
+ type: "LineString",
933
+ coordinates: item_0.coordinates
934
+ }
935
+ }] : [];
936
+ $[17] = colors;
937
+ $[18] = valid;
938
+ $[19] = t8;
939
+ } else t8 = $[19];
940
+ t7 = items.flatMap(t8);
941
+ $[13] = colors;
942
+ $[14] = items;
943
+ $[15] = valid;
944
+ $[16] = t7;
945
+ } else t7 = $[16];
946
+ let t8;
947
+ if ($[20] !== t7) {
948
+ t8 = {
949
+ type: "FeatureCollection",
950
+ features: t7
951
+ };
952
+ $[20] = t7;
953
+ $[21] = t8;
954
+ } else t8 = $[21];
955
+ const data = t8;
956
+ const weight = colors.number("--oui-map-route-weight", 4);
957
+ let t9;
958
+ let width;
959
+ if ($[22] !== colors || $[23] !== hasSelection || $[24] !== weight) {
960
+ const dim = colors.number("--oui-map-dim-opacity", .35);
961
+ const t10 = weight + 1.5;
962
+ let t11;
963
+ if ($[27] !== t10 || $[28] !== weight) {
964
+ t11 = [
965
+ "case",
966
+ HOVER,
967
+ t10,
968
+ weight
969
+ ];
970
+ $[27] = t10;
971
+ $[28] = weight;
972
+ $[29] = t11;
973
+ } else t11 = $[29];
974
+ width = t11;
975
+ t9 = dimmed(hasSelection, dim);
976
+ $[22] = colors;
977
+ $[23] = hasSelection;
978
+ $[24] = weight;
979
+ $[25] = t9;
980
+ $[26] = width;
981
+ } else {
982
+ t9 = $[25];
983
+ width = $[26];
984
+ }
985
+ const opacity = t9;
986
+ let t10;
987
+ if ($[30] === Symbol.for("react.memo_cache_sentinel")) {
988
+ t10 = {
989
+ "line-join": "round",
990
+ "line-cap": "round"
991
+ };
992
+ $[30] = t10;
993
+ } else t10 = $[30];
994
+ const layout = t10;
995
+ const t11 = ids.casing;
996
+ let t12;
997
+ if ($[31] !== colors) {
998
+ t12 = colors.color("var(--oui-map-casing-color)");
999
+ $[31] = colors;
1000
+ $[32] = t12;
1001
+ } else t12 = $[32];
1002
+ const t13 = weight + 4;
1003
+ let t14;
1004
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
1005
+ t14 = [
1006
+ "case",
1007
+ SELECTED,
1008
+ 1,
1009
+ 0
1010
+ ];
1011
+ $[33] = t14;
1012
+ } else t14 = $[33];
1013
+ let t15;
1014
+ if ($[34] !== t12 || $[35] !== t13) {
1015
+ t15 = {
1016
+ "line-color": t12,
1017
+ "line-width": t13,
1018
+ "line-opacity": t14
1019
+ };
1020
+ $[34] = t12;
1021
+ $[35] = t13;
1022
+ $[36] = t15;
1023
+ } else t15 = $[36];
1024
+ let t16;
1025
+ if ($[37] !== ids.casing || $[38] !== t15) {
1026
+ t16 = {
1027
+ id: t11,
1028
+ type: "line",
1029
+ layout,
1030
+ paint: t15
1031
+ };
1032
+ $[37] = ids.casing;
1033
+ $[38] = t15;
1034
+ $[39] = t16;
1035
+ } else t16 = $[39];
1036
+ let t17;
1037
+ if ($[40] === Symbol.for("react.memo_cache_sentinel")) {
1038
+ t17 = [
1039
+ "!=",
1040
+ ["get", "dashed"],
1041
+ true
1042
+ ];
1043
+ $[40] = t17;
1044
+ } else t17 = $[40];
1045
+ let t18;
1046
+ if ($[41] === Symbol.for("react.memo_cache_sentinel")) {
1047
+ t18 = ["get", "color"];
1048
+ $[41] = t18;
1049
+ } else t18 = $[41];
1050
+ let t19;
1051
+ if ($[42] !== opacity || $[43] !== width) {
1052
+ t19 = {
1053
+ "line-color": t18,
1054
+ "line-width": width,
1055
+ "line-opacity": opacity
1056
+ };
1057
+ $[42] = opacity;
1058
+ $[43] = width;
1059
+ $[44] = t19;
1060
+ } else t19 = $[44];
1061
+ let t20;
1062
+ if ($[45] !== ids.solid || $[46] !== t19) {
1063
+ t20 = {
1064
+ id: ids.solid,
1065
+ type: "line",
1066
+ filter: t17,
1067
+ layout,
1068
+ paint: t19
1069
+ };
1070
+ $[45] = ids.solid;
1071
+ $[46] = t19;
1072
+ $[47] = t20;
1073
+ } else t20 = $[47];
1074
+ let t21;
1075
+ let t22;
1076
+ let t23;
1077
+ if ($[48] === Symbol.for("react.memo_cache_sentinel")) {
1078
+ t21 = [
1079
+ "==",
1080
+ ["get", "dashed"],
1081
+ true
1082
+ ];
1083
+ t22 = {
1084
+ "line-join": "round",
1085
+ "line-cap": "butt"
1086
+ };
1087
+ t23 = ["get", "color"];
1088
+ $[48] = t21;
1089
+ $[49] = t22;
1090
+ $[50] = t23;
1091
+ } else {
1092
+ t21 = $[48];
1093
+ t22 = $[49];
1094
+ t23 = $[50];
1095
+ }
1096
+ let t24;
1097
+ if ($[51] === Symbol.for("react.memo_cache_sentinel")) {
1098
+ t24 = [2, 1.5];
1099
+ $[51] = t24;
1100
+ } else t24 = $[51];
1101
+ let t25;
1102
+ if ($[52] !== opacity || $[53] !== width) {
1103
+ t25 = {
1104
+ "line-color": t23,
1105
+ "line-width": width,
1106
+ "line-opacity": opacity,
1107
+ "line-dasharray": t24
1108
+ };
1109
+ $[52] = opacity;
1110
+ $[53] = width;
1111
+ $[54] = t25;
1112
+ } else t25 = $[54];
1113
+ let t26;
1114
+ if ($[55] !== ids.dashed || $[56] !== t25) {
1115
+ t26 = {
1116
+ id: ids.dashed,
1117
+ type: "line",
1118
+ filter: t21,
1119
+ layout: t22,
1120
+ paint: t25
1121
+ };
1122
+ $[55] = ids.dashed;
1123
+ $[56] = t25;
1124
+ $[57] = t26;
1125
+ } else t26 = $[57];
1126
+ let t27;
1127
+ if ($[58] !== t16 || $[59] !== t20 || $[60] !== t26) {
1128
+ t27 = [
1129
+ t16,
1130
+ t20,
1131
+ t26
1132
+ ];
1133
+ $[58] = t16;
1134
+ $[59] = t20;
1135
+ $[60] = t26;
1136
+ $[61] = t27;
1137
+ } else t27 = $[61];
1138
+ const layers = t27;
1139
+ let t28;
1140
+ if ($[62] !== layers) {
1141
+ t28 = layers.map(_temp10);
1142
+ $[62] = layers;
1143
+ $[63] = t28;
1144
+ } else t28 = $[63];
1145
+ let t29;
1146
+ if ($[64] !== data || $[65] !== sourceId || $[66] !== t28) {
1147
+ t29 = /* @__PURE__ */ jsx(Source, {
1148
+ id: sourceId,
1149
+ type: "geojson",
1150
+ data,
1151
+ promoteId: "id",
1152
+ children: t28
1153
+ });
1154
+ $[64] = data;
1155
+ $[65] = sourceId;
1156
+ $[66] = t28;
1157
+ $[67] = t29;
1158
+ } else t29 = $[67];
1159
+ return t29;
1160
+ }
1161
+ function _temp10(layer) {
1162
+ return /* @__PURE__ */ jsx(Layer, { ...layer }, layer.id);
1163
+ }
1164
+ function _temp1(item) {
1165
+ return item.coordinates;
1166
+ }
1167
+ /**
1168
+ * Polygons such as fields, zones or service areas, as one fill and one outline layer. Selected and
1169
+ * hovered areas get a heavier outline.
1170
+ *
1171
+ * @example
1172
+ * <Map.Areas items={fields.map((f) => ({ id: f.id, geometry: f.shape, tone: f.late ? 'warning' : 'success' }))} />
1173
+ */
1174
+ function MapAreas(t0) {
1175
+ const $ = c(38);
1176
+ const { items, selectedIds, onItemClick, onItemHover } = t0;
1177
+ const sourceId = usePartId("areas");
1178
+ const t1 = `${sourceId}-fill`;
1179
+ const t2 = `${sourceId}-line`;
1180
+ let t3;
1181
+ if ($[0] !== t1 || $[1] !== t2) {
1182
+ t3 = {
1183
+ fill: t1,
1184
+ line: t2
1185
+ };
1186
+ $[0] = t1;
1187
+ $[1] = t2;
1188
+ $[2] = t3;
1189
+ } else t3 = $[2];
1190
+ const ids = t3;
1191
+ let t4;
1192
+ if ($[3] !== ids.fill) {
1193
+ t4 = [ids.fill];
1194
+ $[3] = ids.fill;
1195
+ $[4] = t4;
1196
+ } else t4 = $[4];
1197
+ let t5;
1198
+ if ($[5] !== items || $[6] !== onItemClick || $[7] !== onItemHover || $[8] !== selectedIds || $[9] !== t4) {
1199
+ t5 = {
1200
+ items,
1201
+ selectedIds,
1202
+ layerIds: t4,
1203
+ coordinates: _temp11,
1204
+ onItemClick,
1205
+ onItemHover
1206
+ };
1207
+ $[5] = items;
1208
+ $[6] = onItemClick;
1209
+ $[7] = onItemHover;
1210
+ $[8] = selectedIds;
1211
+ $[9] = t4;
1212
+ $[10] = t5;
1213
+ } else t5 = $[10];
1214
+ const { colors, hasSelection, valid } = useDataPart("Map.Areas", sourceId, t5);
1215
+ let t6;
1216
+ if ($[11] !== valid) {
1217
+ t6 = [...valid];
1218
+ $[11] = valid;
1219
+ $[12] = t6;
1220
+ } else t6 = $[12];
1221
+ let t7;
1222
+ if ($[13] !== colors || $[14] !== t6) {
1223
+ t7 = {
1224
+ type: "FeatureCollection",
1225
+ features: t6.map((item_0) => {
1226
+ const tone = toneColors[item_0.tone ?? "neutral"];
1227
+ return {
1228
+ type: "Feature",
1229
+ properties: {
1230
+ id: item_0.id,
1231
+ fill: colors.color(tone.fill),
1232
+ line: colors.color(tone.line)
1233
+ },
1234
+ geometry: item_0.geometry
1235
+ };
1236
+ })
1237
+ };
1238
+ $[13] = colors;
1239
+ $[14] = t6;
1240
+ $[15] = t7;
1241
+ } else t7 = $[15];
1242
+ const data = t7;
1243
+ let t8;
1244
+ if ($[16] !== colors || $[17] !== hasSelection) {
1245
+ t8 = dimmed(hasSelection, colors.number("--oui-map-dim-opacity", .35));
1246
+ $[16] = colors;
1247
+ $[17] = hasSelection;
1248
+ $[18] = t8;
1249
+ } else t8 = $[18];
1250
+ const opacity = t8;
1251
+ let t9;
1252
+ if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
1253
+ t9 = ["get", "fill"];
1254
+ $[19] = t9;
1255
+ } else t9 = $[19];
1256
+ let t10;
1257
+ if ($[20] !== opacity) {
1258
+ t10 = {
1259
+ "fill-color": t9,
1260
+ "fill-opacity": opacity
1261
+ };
1262
+ $[20] = opacity;
1263
+ $[21] = t10;
1264
+ } else t10 = $[21];
1265
+ let t11;
1266
+ if ($[22] !== ids.fill || $[23] !== t10) {
1267
+ t11 = /* @__PURE__ */ jsx(Layer, {
1268
+ id: ids.fill,
1269
+ type: "fill",
1270
+ paint: t10
1271
+ });
1272
+ $[22] = ids.fill;
1273
+ $[23] = t10;
1274
+ $[24] = t11;
1275
+ } else t11 = $[24];
1276
+ let t12;
1277
+ let t13;
1278
+ let t14;
1279
+ if ($[25] === Symbol.for("react.memo_cache_sentinel")) {
1280
+ t12 = { "line-join": "round" };
1281
+ t13 = ["get", "line"];
1282
+ t14 = [
1283
+ "case",
1284
+ ACTIVE,
1285
+ 2.5,
1286
+ 1.25
1287
+ ];
1288
+ $[25] = t12;
1289
+ $[26] = t13;
1290
+ $[27] = t14;
1291
+ } else {
1292
+ t12 = $[25];
1293
+ t13 = $[26];
1294
+ t14 = $[27];
1295
+ }
1296
+ let t15;
1297
+ if ($[28] !== opacity) {
1298
+ t15 = {
1299
+ "line-color": t13,
1300
+ "line-width": t14,
1301
+ "line-opacity": opacity
1302
+ };
1303
+ $[28] = opacity;
1304
+ $[29] = t15;
1305
+ } else t15 = $[29];
1306
+ let t16;
1307
+ if ($[30] !== ids.line || $[31] !== t15) {
1308
+ t16 = /* @__PURE__ */ jsx(Layer, {
1309
+ id: ids.line,
1310
+ type: "line",
1311
+ layout: t12,
1312
+ paint: t15
1313
+ });
1314
+ $[30] = ids.line;
1315
+ $[31] = t15;
1316
+ $[32] = t16;
1317
+ } else t16 = $[32];
1318
+ let t17;
1319
+ if ($[33] !== data || $[34] !== sourceId || $[35] !== t11 || $[36] !== t16) {
1320
+ t17 = /* @__PURE__ */ jsxs(Source, {
1321
+ id: sourceId,
1322
+ type: "geojson",
1323
+ data,
1324
+ promoteId: "id",
1325
+ children: [t11, t16]
1326
+ });
1327
+ $[33] = data;
1328
+ $[34] = sourceId;
1329
+ $[35] = t11;
1330
+ $[36] = t16;
1331
+ $[37] = t17;
1332
+ } else t17 = $[37];
1333
+ return t17;
1334
+ }
1335
+ function _temp11(item) {
1336
+ return item.geometry.coordinates;
1337
+ }
1338
+ /**
1339
+ * Many simple points (sensors, stops, events) as one circle layer. For a few dozen styled pins with HTML
1340
+ * content, use `Map.Marker` instead.
1341
+ *
1342
+ * @example
1343
+ * <Map.Points items={sensors.map((s) => ({ id: s.id, coordinates: s.position, tone: s.ok ? 'success' : 'danger' }))} />
1344
+ */
1345
+ function MapPoints(t0) {
1346
+ const $ = c(34);
1347
+ const { items, selectedIds, onItemClick, onItemHover } = t0;
1348
+ const sourceId = usePartId("points");
1349
+ const circleId = `${sourceId}-circle`;
1350
+ let t1;
1351
+ if ($[0] !== circleId) {
1352
+ t1 = [circleId];
1353
+ $[0] = circleId;
1354
+ $[1] = t1;
1355
+ } else t1 = $[1];
1356
+ let t2;
1357
+ if ($[2] !== items || $[3] !== onItemClick || $[4] !== onItemHover || $[5] !== selectedIds || $[6] !== t1) {
1358
+ t2 = {
1359
+ items,
1360
+ selectedIds,
1361
+ layerIds: t1,
1362
+ coordinates: _temp12,
1363
+ onItemClick,
1364
+ onItemHover
1365
+ };
1366
+ $[2] = items;
1367
+ $[3] = onItemClick;
1368
+ $[4] = onItemHover;
1369
+ $[5] = selectedIds;
1370
+ $[6] = t1;
1371
+ $[7] = t2;
1372
+ } else t2 = $[7];
1373
+ const { colors, hasSelection, valid } = useDataPart("Map.Points", sourceId, t2);
1374
+ let t3;
1375
+ if ($[8] !== colors || $[9] !== items || $[10] !== valid) {
1376
+ let t4;
1377
+ if ($[12] !== colors || $[13] !== valid) {
1378
+ t4 = (item_0, index) => valid.has(item_0) ? [{
1379
+ type: "Feature",
1380
+ properties: {
1381
+ id: item_0.id,
1382
+ color: colors.color(item_0.color ?? (item_0.tone ? toneColors[item_0.tone].solid : seriesColor(item_0.colorIndex ?? index)))
1383
+ },
1384
+ geometry: {
1385
+ type: "Point",
1386
+ coordinates: item_0.coordinates
1387
+ }
1388
+ }] : [];
1389
+ $[12] = colors;
1390
+ $[13] = valid;
1391
+ $[14] = t4;
1392
+ } else t4 = $[14];
1393
+ t3 = items.flatMap(t4);
1394
+ $[8] = colors;
1395
+ $[9] = items;
1396
+ $[10] = valid;
1397
+ $[11] = t3;
1398
+ } else t3 = $[11];
1399
+ let t4;
1400
+ if ($[15] !== t3) {
1401
+ t4 = {
1402
+ type: "FeatureCollection",
1403
+ features: t3
1404
+ };
1405
+ $[15] = t3;
1406
+ $[16] = t4;
1407
+ } else t4 = $[16];
1408
+ const data = t4;
1409
+ let t5;
1410
+ if ($[17] !== colors || $[18] !== hasSelection) {
1411
+ t5 = dimmed(hasSelection, colors.number("--oui-map-dim-opacity", .35));
1412
+ $[17] = colors;
1413
+ $[18] = hasSelection;
1414
+ $[19] = t5;
1415
+ } else t5 = $[19];
1416
+ const opacity = t5;
1417
+ let t6;
1418
+ let t7;
1419
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
1420
+ t6 = ["get", "color"];
1421
+ t7 = [
1422
+ "case",
1423
+ ACTIVE,
1424
+ 7,
1425
+ 5
1426
+ ];
1427
+ $[20] = t6;
1428
+ $[21] = t7;
1429
+ } else {
1430
+ t6 = $[20];
1431
+ t7 = $[21];
1432
+ }
1433
+ let t8;
1434
+ if ($[22] !== colors) {
1435
+ t8 = colors.color("var(--oui-map-casing-color)");
1436
+ $[22] = colors;
1437
+ $[23] = t8;
1438
+ } else t8 = $[23];
1439
+ let t9;
1440
+ if ($[24] !== opacity || $[25] !== t8) {
1441
+ t9 = {
1442
+ "circle-color": t6,
1443
+ "circle-radius": t7,
1444
+ "circle-stroke-color": t8,
1445
+ "circle-stroke-width": 1.5,
1446
+ "circle-opacity": opacity,
1447
+ "circle-stroke-opacity": opacity
1448
+ };
1449
+ $[24] = opacity;
1450
+ $[25] = t8;
1451
+ $[26] = t9;
1452
+ } else t9 = $[26];
1453
+ let t10;
1454
+ if ($[27] !== circleId || $[28] !== t9) {
1455
+ t10 = /* @__PURE__ */ jsx(Layer, {
1456
+ id: circleId,
1457
+ type: "circle",
1458
+ paint: t9
1459
+ });
1460
+ $[27] = circleId;
1461
+ $[28] = t9;
1462
+ $[29] = t10;
1463
+ } else t10 = $[29];
1464
+ let t11;
1465
+ if ($[30] !== data || $[31] !== sourceId || $[32] !== t10) {
1466
+ t11 = /* @__PURE__ */ jsx(Source, {
1467
+ id: sourceId,
1468
+ type: "geojson",
1469
+ data,
1470
+ promoteId: "id",
1471
+ children: t10
1472
+ });
1473
+ $[30] = data;
1474
+ $[31] = sourceId;
1475
+ $[32] = t10;
1476
+ $[33] = t11;
1477
+ } else t11 = $[33];
1478
+ return t11;
1479
+ }
1480
+ function _temp12(item) {
1481
+ return item.coordinates;
1482
+ }
1483
+ /**
1484
+ * An HTML pin at one position: numbered stops, depots, vehicles. Each marker is a DOM element, so use it
1485
+ * for dozens of pins, not thousands (use `Map.Points` for those).
1486
+ *
1487
+ * @example
1488
+ * <Map.Marker kind="stop" sequence={3} position={[19.05, 47.5]} color={seriesColor(0)} />
1489
+ */
1490
+ function MapMarker(t0) {
1491
+ const $ = c(25);
1492
+ const { position, kind: t1, sequence, color, tone, label, selected, dimmed, onClick, children, className } = t0;
1493
+ const kind = t1 === void 0 ? "stop" : t1;
1494
+ const { labels } = useMapContext("Map.Marker");
1495
+ const name = label ?? (kind === "depot" ? labels.depot : void 0);
1496
+ const pinColor = color ?? (tone ? toneColors[tone].solid : void 0);
1497
+ const t2 = position[0];
1498
+ const t3 = position[1];
1499
+ let t4;
1500
+ if ($[0] !== onClick) {
1501
+ t4 = (event) => {
1502
+ event.originalEvent.stopPropagation();
1503
+ onClick?.();
1504
+ };
1505
+ $[0] = onClick;
1506
+ $[1] = t4;
1507
+ } else t4 = $[1];
1508
+ let t5;
1509
+ if ($[2] !== className) {
1510
+ t5 = cx("oui-map__marker", className);
1511
+ $[2] = className;
1512
+ $[3] = t5;
1513
+ } else t5 = $[3];
1514
+ const t6 = selected || void 0;
1515
+ const t7 = dimmed || void 0;
1516
+ const t8 = onClick ? "" : void 0;
1517
+ const t9 = name ? "img" : void 0;
1518
+ let t10;
1519
+ if ($[4] !== pinColor) {
1520
+ t10 = pinColor ? { "--_pin-color": pinColor } : void 0;
1521
+ $[4] = pinColor;
1522
+ $[5] = t10;
1523
+ } else t10 = $[5];
1524
+ let t11;
1525
+ if ($[6] !== children || $[7] !== kind || $[8] !== sequence) {
1526
+ t11 = children ?? (kind === "stop" && sequence != null ? sequence : kind === "depot" ? /* @__PURE__ */ jsx(DepotGlyph, {}) : null);
1527
+ $[6] = children;
1528
+ $[7] = kind;
1529
+ $[8] = sequence;
1530
+ $[9] = t11;
1531
+ } else t11 = $[9];
1532
+ let t12;
1533
+ if ($[10] !== kind || $[11] !== name || $[12] !== t10 || $[13] !== t11 || $[14] !== t5 || $[15] !== t6 || $[16] !== t7 || $[17] !== t8 || $[18] !== t9) {
1534
+ t12 = /* @__PURE__ */ jsx("div", {
1535
+ className: t5,
1536
+ "data-kind": kind,
1537
+ "data-selected": t6,
1538
+ "data-dimmed": t7,
1539
+ "data-interactive": t8,
1540
+ role: t9,
1541
+ "aria-label": name,
1542
+ title: name,
1543
+ style: t10,
1544
+ children: t11
1545
+ });
1546
+ $[10] = kind;
1547
+ $[11] = name;
1548
+ $[12] = t10;
1549
+ $[13] = t11;
1550
+ $[14] = t5;
1551
+ $[15] = t6;
1552
+ $[16] = t7;
1553
+ $[17] = t8;
1554
+ $[18] = t9;
1555
+ $[19] = t12;
1556
+ } else t12 = $[19];
1557
+ let t13;
1558
+ if ($[20] !== position[0] || $[21] !== position[1] || $[22] !== t12 || $[23] !== t4) {
1559
+ t13 = /* @__PURE__ */ jsx(Marker, {
1560
+ longitude: t2,
1561
+ latitude: t3,
1562
+ anchor: "center",
1563
+ onClick: t4,
1564
+ children: t12
1565
+ });
1566
+ $[20] = position[0];
1567
+ $[21] = position[1];
1568
+ $[22] = t12;
1569
+ $[23] = t4;
1570
+ $[24] = t13;
1571
+ } else t13 = $[24];
1572
+ return t13;
1573
+ }
1574
+ function DepotGlyph() {
1575
+ const $ = c(1);
1576
+ let t0;
1577
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
1578
+ t0 = /* @__PURE__ */ jsxs("svg", {
1579
+ viewBox: "0 0 24 24",
1580
+ width: "1em",
1581
+ height: "1em",
1582
+ fill: "none",
1583
+ stroke: "currentColor",
1584
+ strokeWidth: 2.2,
1585
+ "aria-hidden": true,
1586
+ children: [/* @__PURE__ */ jsx("path", {
1587
+ d: "M3 10.5 12 4l9 6.5V20H3z",
1588
+ strokeLinejoin: "round"
1589
+ }), /* @__PURE__ */ jsx("path", {
1590
+ d: "M9 20v-6h6v6",
1591
+ strokeLinejoin: "round"
1592
+ })]
1593
+ });
1594
+ $[0] = t0;
1595
+ } else t0 = $[0];
1596
+ return t0;
1597
+ }
1598
+ /**
1599
+ * A popup anchored to a position, styled as a library card. Render it while something is selected and
1600
+ * close it from `onClose`.
1601
+ *
1602
+ * @example
1603
+ * {picked && (
1604
+ * <Map.Popup position={picked.position} onClose={() => setPicked(null)}>
1605
+ * <strong>{picked.name}</strong>
1606
+ * </Map.Popup>
1607
+ * )}
1608
+ */
1609
+ function MapPopup(t0) {
1610
+ const $ = c(15);
1611
+ let className;
1612
+ let position;
1613
+ let props;
1614
+ let t1;
1615
+ let t2;
1616
+ if ($[0] !== t0) {
1617
+ ({position, className, offset: t1, maxWidth: t2, ...props} = t0);
1618
+ $[0] = t0;
1619
+ $[1] = className;
1620
+ $[2] = position;
1621
+ $[3] = props;
1622
+ $[4] = t1;
1623
+ $[5] = t2;
1624
+ } else {
1625
+ className = $[1];
1626
+ position = $[2];
1627
+ props = $[3];
1628
+ t1 = $[4];
1629
+ t2 = $[5];
1630
+ }
1631
+ const offset = t1 === void 0 ? 14 : t1;
1632
+ const maxWidth = t2 === void 0 ? "20rem" : t2;
1633
+ const t3 = position[0];
1634
+ const t4 = position[1];
1635
+ let t5;
1636
+ if ($[6] !== className) {
1637
+ t5 = cx("oui-map__popup", className);
1638
+ $[6] = className;
1639
+ $[7] = t5;
1640
+ } else t5 = $[7];
1641
+ let t6;
1642
+ if ($[8] !== maxWidth || $[9] !== offset || $[10] !== position[0] || $[11] !== position[1] || $[12] !== props || $[13] !== t5) {
1643
+ t6 = /* @__PURE__ */ jsx(Popup, {
1644
+ longitude: t3,
1645
+ latitude: t4,
1646
+ offset,
1647
+ maxWidth,
1648
+ className: t5,
1649
+ ...props
1650
+ });
1651
+ $[8] = maxWidth;
1652
+ $[9] = offset;
1653
+ $[10] = position[0];
1654
+ $[11] = position[1];
1655
+ $[12] = props;
1656
+ $[13] = t5;
1657
+ $[14] = t6;
1658
+ } else t6 = $[14];
1659
+ return t6;
1660
+ }
1661
+ /**
1662
+ * Hover content: a popup without a close button that stays open on map clicks. Show it from
1663
+ * `onItemHover` and hide it when the item is `null`.
1664
+ *
1665
+ * @example
1666
+ * {hovered && <Map.Tooltip position={hovered.position}>{hovered.name}</Map.Tooltip>}
1667
+ */
1668
+ function MapTooltip(t0) {
1669
+ const $ = c(13);
1670
+ let className;
1671
+ let position;
1672
+ let props;
1673
+ let t1;
1674
+ if ($[0] !== t0) {
1675
+ ({position, className, offset: t1, ...props} = t0);
1676
+ $[0] = t0;
1677
+ $[1] = className;
1678
+ $[2] = position;
1679
+ $[3] = props;
1680
+ $[4] = t1;
1681
+ } else {
1682
+ className = $[1];
1683
+ position = $[2];
1684
+ props = $[3];
1685
+ t1 = $[4];
1686
+ }
1687
+ const offset = t1 === void 0 ? 10 : t1;
1688
+ const t2 = position[0];
1689
+ const t3 = position[1];
1690
+ let t4;
1691
+ if ($[5] !== className) {
1692
+ t4 = cx("oui-map__popup oui-map__tooltip", className);
1693
+ $[5] = className;
1694
+ $[6] = t4;
1695
+ } else t4 = $[6];
1696
+ let t5;
1697
+ if ($[7] !== offset || $[8] !== position[0] || $[9] !== position[1] || $[10] !== props || $[11] !== t4) {
1698
+ t5 = /* @__PURE__ */ jsx(Popup, {
1699
+ longitude: t2,
1700
+ latitude: t3,
1701
+ offset,
1702
+ closeButton: false,
1703
+ closeOnClick: false,
1704
+ className: t4,
1705
+ ...props
1706
+ });
1707
+ $[7] = offset;
1708
+ $[8] = position[0];
1709
+ $[9] = position[1];
1710
+ $[10] = props;
1711
+ $[11] = t4;
1712
+ $[12] = t5;
1713
+ } else t5 = $[12];
1714
+ return t5;
1715
+ }
1716
+ /** Content floating over a corner of the map: stat cards, selects, a legend or `Map.BaseLayerSwitch`. */
1717
+ function MapOverlay(t0) {
1718
+ const $ = c(12);
1719
+ let className;
1720
+ let props;
1721
+ let ref;
1722
+ let t1;
1723
+ if ($[0] !== t0) {
1724
+ ({position: t1, className, ref, ...props} = t0);
1725
+ $[0] = t0;
1726
+ $[1] = className;
1727
+ $[2] = props;
1728
+ $[3] = ref;
1729
+ $[4] = t1;
1730
+ } else {
1731
+ className = $[1];
1732
+ props = $[2];
1733
+ ref = $[3];
1734
+ t1 = $[4];
1735
+ }
1736
+ const position = t1 === void 0 ? "top-left" : t1;
1737
+ let t2;
1738
+ if ($[5] !== className) {
1739
+ t2 = cx("oui-map__overlay", className);
1740
+ $[5] = className;
1741
+ $[6] = t2;
1742
+ } else t2 = $[6];
1743
+ let t3;
1744
+ if ($[7] !== position || $[8] !== props || $[9] !== ref || $[10] !== t2) {
1745
+ t3 = /* @__PURE__ */ jsx("div", {
1746
+ ref,
1747
+ className: t2,
1748
+ "data-position": position,
1749
+ ...props
1750
+ });
1751
+ $[7] = position;
1752
+ $[8] = props;
1753
+ $[9] = ref;
1754
+ $[10] = t2;
1755
+ $[11] = t3;
1756
+ } else t3 = $[11];
1757
+ return t3;
1758
+ }
1759
+ /**
1760
+ * The key to a map's colours, with optional selection and show/hide per entry. Plain DOM, so it also
1761
+ * works outside the map; inside `Map.Root` it takes the root's labels. Put it in a `Map.Overlay`.
1762
+ *
1763
+ * @example
1764
+ * <Map.Legend
1765
+ * items={trips.map((t, i) => ({ id: t.id, label: t.name, color: seriesColor(i), visible: !hidden.includes(t.id) }))}
1766
+ * selectionMode="multi"
1767
+ * selectedIds={selected}
1768
+ * onSelectedIdsChange={setSelected}
1769
+ * onVisibilityChange={(ids, visible) => setHidden((h) => (visible ? h.filter((id) => !ids.includes(id)) : [...h, ...ids]))}
1770
+ * showAllToggle
1771
+ * />
1772
+ */
1773
+ function MapLegend(t0) {
1774
+ const $ = c(48);
1775
+ let className;
1776
+ let items;
1777
+ let onSelectedIdsChange;
1778
+ let onVisibilityChange;
1779
+ let props;
1780
+ let ref;
1781
+ let t1;
1782
+ let t2;
1783
+ let t3;
1784
+ if ($[0] !== t0) {
1785
+ ({items, selectionMode: t1, selectedIds: t2, onSelectedIdsChange, onVisibilityChange, showAllToggle: t3, className, ref, ...props} = t0);
1786
+ $[0] = t0;
1787
+ $[1] = className;
1788
+ $[2] = items;
1789
+ $[3] = onSelectedIdsChange;
1790
+ $[4] = onVisibilityChange;
1791
+ $[5] = props;
1792
+ $[6] = ref;
1793
+ $[7] = t1;
1794
+ $[8] = t2;
1795
+ $[9] = t3;
1796
+ } else {
1797
+ className = $[1];
1798
+ items = $[2];
1799
+ onSelectedIdsChange = $[3];
1800
+ onVisibilityChange = $[4];
1801
+ props = $[5];
1802
+ ref = $[6];
1803
+ t1 = $[7];
1804
+ t2 = $[8];
1805
+ t3 = $[9];
1806
+ }
1807
+ const selectionMode = t1 === void 0 ? "none" : t1;
1808
+ let t4;
1809
+ if ($[10] !== t2) {
1810
+ t4 = t2 === void 0 ? [] : t2;
1811
+ $[10] = t2;
1812
+ $[11] = t4;
1813
+ } else t4 = $[11];
1814
+ const selectedIds = t4;
1815
+ const showAllToggle = t3 === void 0 ? false : t3;
1816
+ const labels = React.use(MapContext)?.labels ?? defaultLabels;
1817
+ let t5;
1818
+ if ($[12] !== items) {
1819
+ t5 = items.every(_temp13);
1820
+ $[12] = items;
1821
+ $[13] = t5;
1822
+ } else t5 = $[13];
1823
+ const allVisible = t5;
1824
+ let t6;
1825
+ if ($[14] !== onSelectedIdsChange || $[15] !== selectedIds || $[16] !== selectionMode) {
1826
+ t6 = (id) => {
1827
+ const on = selectedIds.includes(id);
1828
+ if (selectionMode === "single") onSelectedIdsChange?.(on ? [] : [id]);
1829
+ else onSelectedIdsChange?.(on ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]);
1830
+ };
1831
+ $[14] = onSelectedIdsChange;
1832
+ $[15] = selectedIds;
1833
+ $[16] = selectionMode;
1834
+ $[17] = t6;
1835
+ } else t6 = $[17];
1836
+ const toggle = t6;
1837
+ let t7;
1838
+ if ($[18] !== className) {
1839
+ t7 = cx("oui-map-legend", className);
1840
+ $[18] = className;
1841
+ $[19] = t7;
1842
+ } else t7 = $[19];
1843
+ let t8;
1844
+ if ($[20] !== allVisible || $[21] !== items || $[22] !== labels || $[23] !== onVisibilityChange || $[24] !== showAllToggle) {
1845
+ t8 = onVisibilityChange && showAllToggle && /* @__PURE__ */ jsx("button", {
1846
+ type: "button",
1847
+ className: "oui-map-legend__toggle-all",
1848
+ onClick: () => onVisibilityChange(items.map(_temp14), !allVisible),
1849
+ children: allVisible ? labels.hideAll : labels.showAll
1850
+ });
1851
+ $[20] = allVisible;
1852
+ $[21] = items;
1853
+ $[22] = labels;
1854
+ $[23] = onVisibilityChange;
1855
+ $[24] = showAllToggle;
1856
+ $[25] = t8;
1857
+ } else t8 = $[25];
1858
+ let t9;
1859
+ if ($[26] !== items || $[27] !== labels || $[28] !== onVisibilityChange || $[29] !== selectedIds || $[30] !== selectionMode || $[31] !== toggle) {
1860
+ let t10;
1861
+ if ($[33] !== labels || $[34] !== onVisibilityChange || $[35] !== selectedIds || $[36] !== selectionMode || $[37] !== toggle) {
1862
+ t10 = (item_1) => {
1863
+ const selected = selectedIds.includes(item_1.id);
1864
+ const visible = item_1.visible !== false;
1865
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1866
+ /* @__PURE__ */ jsx("span", {
1867
+ className: "oui-map-legend__swatch",
1868
+ style: { "--_swatch": item_1.color }
1869
+ }),
1870
+ /* @__PURE__ */ jsx("span", {
1871
+ className: "oui-map-legend__label",
1872
+ children: item_1.label
1873
+ }),
1874
+ item_1.count != null && /* @__PURE__ */ jsx("span", {
1875
+ className: "oui-map-legend__count",
1876
+ children: item_1.count
1877
+ })
1878
+ ] });
1879
+ return /* @__PURE__ */ jsxs("li", {
1880
+ className: "oui-map-legend__item",
1881
+ "data-selected": selected || void 0,
1882
+ "data-hidden": visible ? void 0 : "",
1883
+ children: [selectionMode === "none" ? /* @__PURE__ */ jsx("span", {
1884
+ className: "oui-map-legend__entry",
1885
+ children: content
1886
+ }) : /* @__PURE__ */ jsx("button", {
1887
+ type: "button",
1888
+ className: "oui-map-legend__entry",
1889
+ "aria-pressed": selected,
1890
+ onClick: () => toggle(item_1.id),
1891
+ children: content
1892
+ }), onVisibilityChange && /* @__PURE__ */ jsx("button", {
1893
+ type: "button",
1894
+ className: "oui-map-legend__visibility",
1895
+ "aria-label": `${visible ? labels.hide : labels.show} ${typeof item_1.label === "string" ? item_1.label : item_1.id}`,
1896
+ onClick: () => onVisibilityChange([item_1.id], !visible),
1897
+ children: visible ? /* @__PURE__ */ jsx(EyeIcon, {}) : /* @__PURE__ */ jsx(EyeOffIcon, {})
1898
+ })]
1899
+ }, item_1.id);
1900
+ };
1901
+ $[33] = labels;
1902
+ $[34] = onVisibilityChange;
1903
+ $[35] = selectedIds;
1904
+ $[36] = selectionMode;
1905
+ $[37] = toggle;
1906
+ $[38] = t10;
1907
+ } else t10 = $[38];
1908
+ t9 = items.map(t10);
1909
+ $[26] = items;
1910
+ $[27] = labels;
1911
+ $[28] = onVisibilityChange;
1912
+ $[29] = selectedIds;
1913
+ $[30] = selectionMode;
1914
+ $[31] = toggle;
1915
+ $[32] = t9;
1916
+ } else t9 = $[32];
1917
+ let t10;
1918
+ if ($[39] !== t9) {
1919
+ t10 = /* @__PURE__ */ jsx("ul", {
1920
+ className: "oui-map-legend__list",
1921
+ children: t9
1922
+ });
1923
+ $[39] = t9;
1924
+ $[40] = t10;
1925
+ } else t10 = $[40];
1926
+ let t11;
1927
+ if ($[41] !== props || $[42] !== ref || $[43] !== selectionMode || $[44] !== t10 || $[45] !== t7 || $[46] !== t8) {
1928
+ t11 = /* @__PURE__ */ jsxs("div", {
1929
+ ref,
1930
+ className: t7,
1931
+ "data-selection-mode": selectionMode,
1932
+ ...props,
1933
+ children: [t8, t10]
1934
+ });
1935
+ $[41] = props;
1936
+ $[42] = ref;
1937
+ $[43] = selectionMode;
1938
+ $[44] = t10;
1939
+ $[45] = t7;
1940
+ $[46] = t8;
1941
+ $[47] = t11;
1942
+ } else t11 = $[47];
1943
+ return t11;
1944
+ }
1945
+ function _temp14(item_0) {
1946
+ return item_0.id;
1947
+ }
1948
+ function _temp13(item) {
1949
+ return item.visible !== false;
1950
+ }
1951
+ /** Segmented switch between the root's `baseLayers` (e.g. streets and satellite). Put it in a `Map.Overlay`. */
1952
+ function MapBaseLayerSwitch(t0) {
1953
+ const $ = c(11);
1954
+ let props;
1955
+ let t1;
1956
+ if ($[0] !== t0) {
1957
+ ({size: t1, ...props} = t0);
1958
+ $[0] = t0;
1959
+ $[1] = props;
1960
+ $[2] = t1;
1961
+ } else {
1962
+ props = $[1];
1963
+ t1 = $[2];
1964
+ }
1965
+ const size = t1 === void 0 ? "sm" : t1;
1966
+ const { baseLayers, baseLayer, setBaseLayer } = useMapContext("Map.BaseLayerSwitch");
1967
+ let t2;
1968
+ if ($[3] !== baseLayers) {
1969
+ t2 = baseLayers.map(_temp15);
1970
+ $[3] = baseLayers;
1971
+ $[4] = t2;
1972
+ } else t2 = $[4];
1973
+ let t3;
1974
+ if ($[5] !== baseLayer || $[6] !== props || $[7] !== setBaseLayer || $[8] !== size || $[9] !== t2) {
1975
+ t3 = /* @__PURE__ */ jsx(SegmentedControl, {
1976
+ size,
1977
+ options: t2,
1978
+ value: baseLayer,
1979
+ onValueChange: setBaseLayer,
1980
+ ...props
1981
+ });
1982
+ $[5] = baseLayer;
1983
+ $[6] = props;
1984
+ $[7] = setBaseLayer;
1985
+ $[8] = size;
1986
+ $[9] = t2;
1987
+ $[10] = t3;
1988
+ } else t3 = $[10];
1989
+ return t3;
1990
+ }
1991
+ /**
1992
+ * Map components on MapLibre, from `@optimum-intelligence/opti-ui/map`. `Map.Root` holds the map; inside
1993
+ * it, `Map.Areas`, `Map.Routes` and `Map.Points` draw arrays of items as single GeoJSON layers,
1994
+ * `Map.Marker` adds HTML pins, `Map.Popup` and `Map.Tooltip` show content at a position, and
1995
+ * `Map.Overlay` floats `Map.Legend`, `Map.BaseLayerSwitch` or cards over a corner.
1996
+ *
1997
+ * @example
1998
+ * <Map.Root baseLayers={baseLayers} fit="selected">
1999
+ * <Map.Areas items={zones} />
2000
+ * <Map.Routes items={trips} selectedIds={selected} onItemClick={(t) => setSelected([t.id])} />
2001
+ * <Map.Overlay position="top-left">
2002
+ * <Map.Legend items={legend} selectionMode="single" selectedIds={selected} onSelectedIdsChange={setSelected} />
2003
+ * </Map.Overlay>
2004
+ * <Map.Overlay position="bottom-left">
2005
+ * <Map.BaseLayerSwitch />
2006
+ * </Map.Overlay>
2007
+ * </Map.Root>
2008
+ */
2009
+ function _temp15(layer) {
2010
+ return {
2011
+ value: layer.id,
2012
+ label: layer.label
2013
+ };
2014
+ }
2015
+ var Map$1 = {
2016
+ Root: MapRoot,
2017
+ Routes: MapRoutes,
2018
+ Areas: MapAreas,
2019
+ Points: MapPoints,
2020
+ Marker: MapMarker,
2021
+ Popup: MapPopup,
2022
+ Tooltip: MapTooltip,
2023
+ Overlay: MapOverlay,
2024
+ Legend: MapLegend,
2025
+ BaseLayerSwitch: MapBaseLayerSwitch
2026
+ };
2027
+ //#endregion
2028
+ export { Map$1 as Map, rasterStyle };
2029
+
2030
+ //# sourceMappingURL=Map.js.map