@omnitron-dev/prism 0.3.0 → 0.3.1

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 (214) hide show
  1. package/README.md +148 -0
  2. package/dist/blocks/index.js +3 -1
  3. package/dist/blocks/index.js.map +1 -1
  4. package/dist/{chunk-S6SEGBX6.js → chunk-472SOF76.js} +4 -4
  5. package/dist/{chunk-S6SEGBX6.js.map → chunk-472SOF76.js.map} +1 -1
  6. package/dist/{chunk-Z5OSPAOC.js → chunk-4Z5DE5GK.js} +78 -75
  7. package/dist/chunk-4Z5DE5GK.js.map +1 -0
  8. package/dist/chunk-52PQL67Q.js +559 -0
  9. package/dist/chunk-52PQL67Q.js.map +1 -0
  10. package/dist/chunk-75FQ5IW3.js +590 -0
  11. package/dist/chunk-75FQ5IW3.js.map +1 -0
  12. package/dist/{chunk-6AHI4GSV.js → chunk-7G5D5PTC.js} +4 -3
  13. package/dist/chunk-7G5D5PTC.js.map +1 -0
  14. package/dist/chunk-BJE2AKD4.js +105 -0
  15. package/dist/chunk-BJE2AKD4.js.map +1 -0
  16. package/dist/chunk-FF5RF32O.js +248 -0
  17. package/dist/chunk-FF5RF32O.js.map +1 -0
  18. package/dist/{chunk-OBJ244BO.js → chunk-GMIE6III.js} +9 -42
  19. package/dist/chunk-GMIE6III.js.map +1 -0
  20. package/dist/chunk-GUGTDURV.js +826 -0
  21. package/dist/chunk-GUGTDURV.js.map +1 -0
  22. package/dist/chunk-HOXFSQUV.js +573 -0
  23. package/dist/chunk-HOXFSQUV.js.map +1 -0
  24. package/dist/chunk-JSQTYDPG.js +3 -0
  25. package/dist/chunk-JSQTYDPG.js.map +1 -0
  26. package/dist/{chunk-ZTATTUH7.js → chunk-KQ67XB6T.js} +213 -651
  27. package/dist/chunk-KQ67XB6T.js.map +1 -0
  28. package/dist/{chunk-WFD54GQQ.js → chunk-LOY2NPCO.js} +14 -573
  29. package/dist/chunk-LOY2NPCO.js.map +1 -0
  30. package/dist/{chunk-YQW43BDH.js → chunk-LSPFFEJT.js} +240 -1824
  31. package/dist/chunk-LSPFFEJT.js.map +1 -0
  32. package/dist/{chunk-BZOL7GMU.js → chunk-OKTLA23Q.js} +4 -4
  33. package/dist/chunk-OKTLA23Q.js.map +1 -0
  34. package/dist/chunk-PFT2BNYO.js +191 -0
  35. package/dist/chunk-PFT2BNYO.js.map +1 -0
  36. package/dist/chunk-PGHEP4JD.js +106 -0
  37. package/dist/chunk-PGHEP4JD.js.map +1 -0
  38. package/dist/chunk-PXXPLHIY.js +74 -0
  39. package/dist/chunk-PXXPLHIY.js.map +1 -0
  40. package/dist/chunk-SU3LVQ7N.js +518 -0
  41. package/dist/chunk-SU3LVQ7N.js.map +1 -0
  42. package/dist/chunk-YHE7HXSG.js +206 -0
  43. package/dist/chunk-YHE7HXSG.js.map +1 -0
  44. package/dist/cli/index.js +7 -2
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/components/accordion/accordion.d.ts.map +1 -1
  47. package/dist/components/admin-filters/admin-data-table.d.ts.map +1 -1
  48. package/dist/components/admin-filters/filter-toolbar.d.ts.map +1 -1
  49. package/dist/components/date-input/date-input.d.ts +27 -0
  50. package/dist/components/date-input/date-input.d.ts.map +1 -0
  51. package/dist/components/date-input/index.d.ts +4 -0
  52. package/dist/components/date-input/index.d.ts.map +1 -0
  53. package/dist/components/date-input/value.d.ts +9 -0
  54. package/dist/components/date-input/value.d.ts.map +1 -0
  55. package/dist/components/doc-layout/doc-sidebar.d.ts +4 -1
  56. package/dist/components/doc-layout/doc-sidebar.d.ts.map +1 -1
  57. package/dist/components/doc-layout/index.js +6 -0
  58. package/dist/components/doc-layout/index.js.map +1 -0
  59. package/dist/components/editor/editor.d.ts.map +1 -1
  60. package/dist/components/editor/icons/index.d.ts +32 -40
  61. package/dist/components/editor/icons/index.d.ts.map +1 -1
  62. package/dist/components/editor/index.js +3 -1
  63. package/dist/components/error-boundary/error-boundary.d.ts.map +1 -1
  64. package/dist/components/index.css +4 -0
  65. package/dist/components/index.css.map +1 -1
  66. package/dist/components/index.d.ts +4 -4
  67. package/dist/components/index.d.ts.map +1 -1
  68. package/dist/components/index.js +18 -8
  69. package/dist/components/knowledge-graph/edge-labels.d.ts +14 -0
  70. package/dist/components/knowledge-graph/edge-labels.d.ts.map +1 -0
  71. package/dist/components/knowledge-graph/graph.d.ts +56 -0
  72. package/dist/components/knowledge-graph/graph.d.ts.map +1 -0
  73. package/dist/components/knowledge-graph/index.css +176 -0
  74. package/dist/components/knowledge-graph/index.css.map +1 -0
  75. package/dist/components/knowledge-graph/index.d.ts +3 -0
  76. package/dist/components/knowledge-graph/index.d.ts.map +1 -0
  77. package/dist/components/knowledge-graph/index.js +795 -0
  78. package/dist/components/knowledge-graph/index.js.map +1 -0
  79. package/dist/components/knowledge-graph/label-layout.d.ts +28 -0
  80. package/dist/components/knowledge-graph/label-layout.d.ts.map +1 -0
  81. package/dist/components/knowledge-graph/label-store.d.ts +15 -0
  82. package/dist/components/knowledge-graph/label-store.d.ts.map +1 -0
  83. package/dist/components/knowledge-graph/model.d.ts +92 -0
  84. package/dist/components/knowledge-graph/model.d.ts.map +1 -0
  85. package/dist/components/lightbox/lightbox.d.ts.map +1 -1
  86. package/dist/components/map/Map.d.ts +19 -43
  87. package/dist/components/map/Map.d.ts.map +1 -1
  88. package/dist/components/map/MapCoverageLayer.d.ts +1 -1
  89. package/dist/components/map/MapCoverageLayer.d.ts.map +1 -1
  90. package/dist/components/map/MapMarker.d.ts +1 -1
  91. package/dist/components/map/MapMarker.d.ts.map +1 -1
  92. package/dist/components/map/MapPlaceSearch.d.ts +33 -0
  93. package/dist/components/map/MapPlaceSearch.d.ts.map +1 -0
  94. package/dist/components/map/MapPointPicker.d.ts +21 -12
  95. package/dist/components/map/MapPointPicker.d.ts.map +1 -1
  96. package/dist/components/map/coordinates.d.ts +10 -0
  97. package/dist/components/map/coordinates.d.ts.map +1 -0
  98. package/dist/components/map/index.css +4 -0
  99. package/dist/components/map/index.css.map +1 -0
  100. package/dist/components/map/index.d.ts +7 -2
  101. package/dist/components/map/index.d.ts.map +1 -1
  102. package/dist/components/map/index.js +3 -0
  103. package/dist/components/map/index.js.map +1 -0
  104. package/dist/components/nav-card/nav-card.d.ts.map +1 -1
  105. package/dist/components/rail/rail.d.ts.map +1 -1
  106. package/dist/components/research/diagram-image.d.ts +11 -0
  107. package/dist/components/research/diagram-image.d.ts.map +1 -0
  108. package/dist/components/research/diagram.d.ts +8 -0
  109. package/dist/components/research/diagram.d.ts.map +1 -0
  110. package/dist/components/research/document.d.ts +33 -0
  111. package/dist/components/research/document.d.ts.map +1 -0
  112. package/dist/components/research/frontmatter.d.ts +15 -0
  113. package/dist/components/research/frontmatter.d.ts.map +1 -0
  114. package/dist/components/research/index.css +51 -0
  115. package/dist/components/research/index.css.map +1 -0
  116. package/dist/components/research/index.d.ts +3 -0
  117. package/dist/components/research/index.d.ts.map +1 -0
  118. package/dist/components/research/index.js +6 -0
  119. package/dist/components/research/index.js.map +1 -0
  120. package/dist/components/research/parse.d.ts +29 -0
  121. package/dist/components/research/parse.d.ts.map +1 -0
  122. package/dist/components/research-editor/block-commands.d.ts +20 -0
  123. package/dist/components/research-editor/block-commands.d.ts.map +1 -0
  124. package/dist/components/research-editor/block-controls.d.ts +13 -0
  125. package/dist/components/research-editor/block-controls.d.ts.map +1 -0
  126. package/dist/components/research-editor/editor.d.ts +75 -0
  127. package/dist/components/research-editor/editor.d.ts.map +1 -0
  128. package/dist/components/research-editor/extensions.d.ts +14 -0
  129. package/dist/components/research-editor/extensions.d.ts.map +1 -0
  130. package/dist/components/research-editor/index.css +332 -0
  131. package/dist/components/research-editor/index.css.map +1 -0
  132. package/dist/components/research-editor/index.d.ts +5 -0
  133. package/dist/components/research-editor/index.d.ts.map +1 -0
  134. package/dist/components/research-editor/index.js +1592 -0
  135. package/dist/components/research-editor/index.js.map +1 -0
  136. package/dist/components/research-editor/math-input.d.ts +32 -0
  137. package/dist/components/research-editor/math-input.d.ts.map +1 -0
  138. package/dist/components/research-editor/math-markup.d.ts +4 -0
  139. package/dist/components/research-editor/math-markup.d.ts.map +1 -0
  140. package/dist/components/research-editor/math-navigation.d.ts +6 -0
  141. package/dist/components/research-editor/math-navigation.d.ts.map +1 -0
  142. package/dist/components/research-editor/math-node.d.ts +11 -0
  143. package/dist/components/research-editor/math-node.d.ts.map +1 -0
  144. package/dist/components/research-editor/source.d.ts +19 -0
  145. package/dist/components/research-editor/source.d.ts.map +1 -0
  146. package/dist/components/scrollbar/scrollbar.d.ts +4 -2
  147. package/dist/components/scrollbar/scrollbar.d.ts.map +1 -1
  148. package/dist/components/search-input/search-input.d.ts +0 -10
  149. package/dist/components/search-input/search-input.d.ts.map +1 -1
  150. package/dist/components/tiptap-renderer/tiptap-renderer.d.ts +4 -3
  151. package/dist/components/tiptap-renderer/tiptap-renderer.d.ts.map +1 -1
  152. package/dist/core/index.d.ts +1 -1
  153. package/dist/core/index.d.ts.map +1 -1
  154. package/dist/core/index.js +8 -4
  155. package/dist/core/provider.d.ts +7 -2
  156. package/dist/core/provider.d.ts.map +1 -1
  157. package/dist/forms/schema-provider.d.ts +3 -3
  158. package/dist/forms/schema-utils.d.ts +3 -3
  159. package/dist/hooks/index.js +9 -5
  160. package/dist/icons/context.d.ts +17 -0
  161. package/dist/icons/context.d.ts.map +1 -0
  162. package/dist/icons/controls.d.ts +51 -0
  163. package/dist/icons/controls.d.ts.map +1 -0
  164. package/dist/icons/index.d.ts +3 -0
  165. package/dist/icons/index.d.ts.map +1 -0
  166. package/dist/icons/index.js +4 -0
  167. package/dist/icons/index.js.map +1 -0
  168. package/dist/icons/theme.d.ts +4 -0
  169. package/dist/icons/theme.d.ts.map +1 -0
  170. package/dist/index.css +4 -0
  171. package/dist/index.css.map +1 -1
  172. package/dist/index.js +24 -13
  173. package/dist/index.js.map +1 -1
  174. package/dist/layouts/core/header-section.d.ts.map +1 -1
  175. package/dist/layouts/dashboard/labels.d.ts +12 -0
  176. package/dist/layouts/dashboard/labels.d.ts.map +1 -0
  177. package/dist/layouts/dashboard/layout.d.ts +7 -1
  178. package/dist/layouts/dashboard/layout.d.ts.map +1 -1
  179. package/dist/layouts/dashboard/sidenav.d.ts +7 -3
  180. package/dist/layouts/dashboard/sidenav.d.ts.map +1 -1
  181. package/dist/layouts/index.d.ts +5 -0
  182. package/dist/layouts/index.d.ts.map +1 -1
  183. package/dist/layouts/index.js +6 -1
  184. package/dist/layouts/panel-layout.d.ts +35 -0
  185. package/dist/layouts/panel-layout.d.ts.map +1 -0
  186. package/dist/layouts/sidebar-toggle.d.ts +11 -0
  187. package/dist/layouts/sidebar-toggle.d.ts.map +1 -0
  188. package/dist/state/stores/auth.d.ts +4 -16
  189. package/dist/state/stores/auth.d.ts.map +1 -1
  190. package/dist/state/stores/ui.d.ts +7 -105
  191. package/dist/state/stores/ui.d.ts.map +1 -1
  192. package/dist/theme/components/Button.d.ts.map +1 -1
  193. package/dist/theme/components/FormControls.d.ts +3 -12
  194. package/dist/theme/components/FormControls.d.ts.map +1 -1
  195. package/dist/theme/components/index.d.ts.map +1 -1
  196. package/dist/theme/create-theme.d.ts +5 -17
  197. package/dist/theme/create-theme.d.ts.map +1 -1
  198. package/dist/theme/index.js +6 -2
  199. package/dist/theme/mixins.d.ts +3 -1
  200. package/dist/theme/mixins.d.ts.map +1 -1
  201. package/dist/theme/palette/overrides.d.ts +23 -0
  202. package/dist/theme/palette/overrides.d.ts.map +1 -0
  203. package/dist/ui/index.d.ts +18 -0
  204. package/dist/ui/index.d.ts.map +1 -0
  205. package/dist/ui/index.js +148 -0
  206. package/dist/ui/index.js.map +1 -0
  207. package/package.json +92 -45
  208. package/dist/chunk-6AHI4GSV.js.map +0 -1
  209. package/dist/chunk-BZOL7GMU.js.map +0 -1
  210. package/dist/chunk-OBJ244BO.js.map +0 -1
  211. package/dist/chunk-WFD54GQQ.js.map +0 -1
  212. package/dist/chunk-YQW43BDH.js.map +0 -1
  213. package/dist/chunk-Z5OSPAOC.js.map +0 -1
  214. package/dist/chunk-ZTATTUH7.js.map +0 -1
@@ -0,0 +1,559 @@
1
+ import { forwardRef, useRef, useState, useCallback, useEffect, useMemo } from 'react';
2
+ import { Box, Alert, LinearProgress, Stack, Paper, Typography, CircularProgress, Button, Autocomplete, TextField } from '@mui/material';
3
+ import { useTheme } from '@mui/material/styles';
4
+ import { Map as Map$1, NavigationControl, ScaleControl, Marker, Popup, Source, Layer } from 'react-map-gl/maplibre';
5
+ export { Layer, Popup, Source, useMap } from 'react-map-gl/maplibre';
6
+ import { addProtocol } from 'maplibre-gl';
7
+ import { Protocol } from 'pmtiles';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+
10
+ var protocol = new Protocol();
11
+ addProtocol("pmtiles", protocol.tile);
12
+ var messages = {
13
+ label: "Interactive map",
14
+ missingStyle: "A map source has not been configured.",
15
+ loading: "Loading map",
16
+ error: "Some map data could not be loaded. Check the connection or map source."
17
+ };
18
+ var world = { longitude: 0, latitude: 0, zoom: 1, bearing: 0, pitch: 0 };
19
+ var Map = forwardRef(function MapView({
20
+ styleUrl,
21
+ styles,
22
+ viewport,
23
+ initialViewport,
24
+ onViewportChange,
25
+ showNavigation = true,
26
+ showScale = true,
27
+ showAttribution = true,
28
+ style,
29
+ messages: overrides,
30
+ children,
31
+ onMove,
32
+ onLoad,
33
+ onError,
34
+ cooperativeGestures = true,
35
+ ...engine
36
+ }, forwardedRef) {
37
+ const theme = useTheme();
38
+ const copy = { ...messages, ...overrides };
39
+ const legacyStyle = typeof window !== "undefined" ? window.__MAP_STYLE_URL__ : void 0;
40
+ const mapStyle = styleUrl ?? styles?.[theme.palette.mode] ?? legacyStyle;
41
+ const initial = { ...world, ...initialViewport };
42
+ const host = useRef(null);
43
+ const map = useRef(null);
44
+ const [readyStyle, setReadyStyle] = useState();
45
+ const [error, setError] = useState(false);
46
+ const setMap = useCallback(
47
+ (value) => {
48
+ map.current = value;
49
+ if (typeof forwardedRef === "function") forwardedRef(value);
50
+ else if (forwardedRef) forwardedRef.current = value;
51
+ },
52
+ [forwardedRef]
53
+ );
54
+ useEffect(() => {
55
+ if (!host.current || typeof ResizeObserver === "undefined") return;
56
+ const observer = new ResizeObserver(() => map.current?.resize());
57
+ observer.observe(host.current);
58
+ return () => observer.disconnect();
59
+ }, []);
60
+ useEffect(() => setError(false), [mapStyle]);
61
+ return /* @__PURE__ */ jsx(
62
+ Box,
63
+ {
64
+ ref: host,
65
+ role: "region",
66
+ "aria-label": copy.label,
67
+ style,
68
+ sx: {
69
+ width: "100%",
70
+ height: 400,
71
+ position: "relative",
72
+ borderRadius: 1,
73
+ overflow: "hidden",
74
+ bgcolor: "background.paper",
75
+ "& .maplibregl-ctrl-group, & .maplibregl-popup-content": {
76
+ bgcolor: "background.paper",
77
+ color: "text.primary",
78
+ boxShadow: theme.shadows[2],
79
+ borderRadius: 1,
80
+ border: 1,
81
+ borderColor: "divider"
82
+ },
83
+ "& .maplibregl-ctrl-group button": { color: "text.primary", borderColor: "divider" },
84
+ "& .maplibregl-ctrl-icon": { filter: theme.palette.mode === "dark" ? "invert(1)" : "none" },
85
+ "& .maplibregl-ctrl-attrib": { bgcolor: "background.paper", color: "text.secondary" },
86
+ "& .maplibregl-ctrl-attrib a": { color: "inherit" },
87
+ "& .maplibregl-ctrl-scale": {
88
+ bgcolor: "background.paper",
89
+ color: "text.primary",
90
+ borderColor: "text.secondary"
91
+ },
92
+ "& .maplibregl-ctrl button:focus-visible": {
93
+ outline: `2px solid ${theme.palette.primary.main}`,
94
+ outlineOffset: -2
95
+ }
96
+ },
97
+ children: !mapStyle ? /* @__PURE__ */ jsx(Alert, { severity: "info", sx: { m: 2 }, children: copy.missingStyle }) : /* @__PURE__ */ jsxs(Fragment, { children: [
98
+ /* @__PURE__ */ jsxs(
99
+ Map$1,
100
+ {
101
+ ...engine,
102
+ ref: setMap,
103
+ mapStyle,
104
+ cooperativeGestures,
105
+ ...viewport ? { ...initial, ...viewport } : {
106
+ initialViewState: initial,
107
+ ...engine.initialViewState ? { initialViewState: engine.initialViewState } : {}
108
+ },
109
+ onMove: (event) => {
110
+ onViewportChange?.(event.viewState);
111
+ onMove?.(event);
112
+ },
113
+ onLoad: (event) => {
114
+ setReadyStyle(mapStyle);
115
+ onLoad?.(event);
116
+ },
117
+ onIdle: (event) => {
118
+ setReadyStyle(mapStyle);
119
+ engine.onIdle?.(event);
120
+ },
121
+ onError: (event) => {
122
+ setError(true);
123
+ onError?.(event);
124
+ },
125
+ attributionControl: showAttribution ? engine.attributionControl ?? {} : false,
126
+ style: { width: "100%", height: "100%" },
127
+ children: [
128
+ showNavigation && /* @__PURE__ */ jsx(NavigationControl, { position: "top-right" }),
129
+ showScale && /* @__PURE__ */ jsx(ScaleControl, { position: "bottom-left" }),
130
+ children
131
+ ]
132
+ }
133
+ ),
134
+ readyStyle !== mapStyle && !error && /* @__PURE__ */ jsx(LinearProgress, { "aria-label": copy.loading, sx: { position: "absolute", top: 0, left: 0, right: 0 } }),
135
+ error && /* @__PURE__ */ jsx(
136
+ Alert,
137
+ {
138
+ severity: "warning",
139
+ onClose: () => setError(false),
140
+ sx: { position: "absolute", left: 8, right: 8, top: 8 },
141
+ children: copy.error
142
+ }
143
+ )
144
+ ] })
145
+ }
146
+ );
147
+ });
148
+ function MapMarker({ longitude, latitude, color, children, popup, anchor = "bottom", onClick }) {
149
+ const theme = useTheme();
150
+ const [open, setOpen] = useState(false);
151
+ const fill = color ?? theme.palette.primary.main;
152
+ const handleClick = (e) => {
153
+ e.originalEvent?.stopPropagation?.();
154
+ if (popup) setOpen((v) => !v);
155
+ onClick?.();
156
+ };
157
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
158
+ /* @__PURE__ */ jsx(Marker, { longitude, latitude, anchor, onClick: handleClick, children: children ?? /* @__PURE__ */ jsxs("svg", { width: "24", height: "32", viewBox: "0 0 24 32", "aria-hidden": true, style: { display: "block" }, children: [
159
+ /* @__PURE__ */ jsx("path", { d: "M12 0C5.4 0 0 5.4 0 12c0 9 12 20 12 20s12-11 12-20C24 5.4 18.6 0 12 0z", fill }),
160
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4", fill: "#fff" })
161
+ ] }) }),
162
+ popup && open && /* @__PURE__ */ jsx(
163
+ Popup,
164
+ {
165
+ longitude,
166
+ latitude,
167
+ anchor: "top",
168
+ offset: [0, -32],
169
+ closeOnClick: false,
170
+ onClose: () => setOpen(false),
171
+ children: popup
172
+ }
173
+ )
174
+ ] });
175
+ }
176
+
177
+ // src/components/map/coordinates.ts
178
+ function isMapPoint(value) {
179
+ return Number.isFinite(value.lng) && Number.isFinite(value.lat) && value.lng >= -180 && value.lng <= 180 && value.lat >= -90 && value.lat <= 90;
180
+ }
181
+ function normalizeMapPoint(lng, lat) {
182
+ if (!Number.isFinite(lng) || !Number.isFinite(lat) || Math.abs(lat) > 90) return null;
183
+ return { lng: lng >= -180 && lng <= 180 ? lng : ((lng + 180) % 360 + 360) % 360 - 180, lat };
184
+ }
185
+ function mapCameraLatitude(latitude) {
186
+ return Math.max(-85.0511287798066, Math.min(85.0511287798066, latitude));
187
+ }
188
+ var defaults = {
189
+ placeholder: "Choose a point on the map, or move the map and select its centre.",
190
+ coordinates: "Coordinates",
191
+ place: "Place",
192
+ loading: "Finding place\u2026",
193
+ unknown: "No place name for this point",
194
+ chooseCenter: "Select map centre",
195
+ clear: "Clear selection",
196
+ marker: "Selected point"
197
+ };
198
+ function MapPointPicker({
199
+ value,
200
+ onChange,
201
+ onClear,
202
+ initialViewport,
203
+ selectionZoom = 10,
204
+ styleUrl,
205
+ height = 480,
206
+ geocodeResult,
207
+ geocodeLoading = false,
208
+ geocodeError,
209
+ placeholder,
210
+ labels,
211
+ readOnly = false,
212
+ showDetails = true,
213
+ mapProps
214
+ }) {
215
+ const copy = { ...defaults, ...labels, ...placeholder ? { placeholder } : {} };
216
+ const valid = value && isMapPoint(value) ? value : null;
217
+ const [camera, setCamera] = useState(() => ({
218
+ longitude: valid?.lng ?? 0,
219
+ latitude: valid ? mapCameraLatitude(valid.lat) : 0,
220
+ zoom: valid ? 10 : 1,
221
+ ...initialViewport
222
+ }));
223
+ const [loaded, setLoaded] = useState(false);
224
+ useEffect(() => {
225
+ if (value && isMapPoint(value))
226
+ setCamera((old) => ({
227
+ ...old,
228
+ longitude: value.lng,
229
+ latitude: mapCameraLatitude(value.lat),
230
+ zoom: Math.max(old.zoom, selectionZoom)
231
+ }));
232
+ }, [value?.lng, value?.lat, selectionZoom]);
233
+ function choose(lng, lat) {
234
+ const point = normalizeMapPoint(lng, lat);
235
+ if (point && !readOnly) onChange(point);
236
+ }
237
+ return /* @__PURE__ */ jsxs(Stack, { sx: { gap: 2, width: "100%" }, children: [
238
+ /* @__PURE__ */ jsxs(
239
+ Box,
240
+ {
241
+ sx: {
242
+ display: "grid",
243
+ gridTemplateColumns: showDetails ? { xs: "1fr", md: "minmax(0,1fr) 280px" } : "1fr",
244
+ gap: 2
245
+ },
246
+ children: [
247
+ /* @__PURE__ */ jsxs(
248
+ Map,
249
+ {
250
+ ...mapProps,
251
+ styleUrl,
252
+ viewport: camera,
253
+ onViewportChange: setCamera,
254
+ cursor: readOnly ? "grab" : "crosshair",
255
+ onClick: (event) => choose(event.lngLat.lng, event.lngLat.lat),
256
+ onLoad: (event) => {
257
+ setLoaded(true);
258
+ mapProps?.onLoad?.(event);
259
+ },
260
+ style: { ...mapProps?.style, height },
261
+ children: [
262
+ mapProps?.children,
263
+ valid && /* @__PURE__ */ jsx(
264
+ Marker,
265
+ {
266
+ longitude: valid.lng,
267
+ latitude: valid.lat,
268
+ anchor: "center",
269
+ draggable: !readOnly,
270
+ onDragEnd: (event) => choose(event.lngLat.lng, event.lngLat.lat),
271
+ children: /* @__PURE__ */ jsx(
272
+ Box,
273
+ {
274
+ role: "img",
275
+ "aria-label": copy.marker,
276
+ sx: {
277
+ width: 22,
278
+ height: 22,
279
+ borderRadius: "50%",
280
+ bgcolor: "primary.main",
281
+ border: "3px solid",
282
+ borderColor: "background.paper",
283
+ boxShadow: 2
284
+ }
285
+ }
286
+ )
287
+ }
288
+ )
289
+ ]
290
+ }
291
+ ),
292
+ showDetails && /* @__PURE__ */ jsx(Paper, { variant: "outlined", sx: { p: 2, minWidth: 0 }, children: valid ? /* @__PURE__ */ jsxs(Stack, { sx: { gap: 1.5 }, children: [
293
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: copy.coordinates }),
294
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" }, children: [
295
+ valid.lat.toFixed(5),
296
+ ", ",
297
+ valid.lng.toFixed(5)
298
+ ] }),
299
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: copy.place }),
300
+ geocodeLoading ? /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1, alignItems: "center" }, role: "status", children: [
301
+ /* @__PURE__ */ jsx(CircularProgress, { size: 16 }),
302
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: copy.loading })
303
+ ] }) : geocodeError ? /* @__PURE__ */ jsx(Alert, { severity: "warning", children: geocodeError }) : /* @__PURE__ */ jsx(Box, { sx: { overflowWrap: "anywhere" }, children: geocodeResult ?? /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: copy.unknown }) })
304
+ ] }) : /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: copy.placeholder }) })
305
+ ]
306
+ }
307
+ ),
308
+ !readOnly && /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1, flexWrap: "wrap" }, children: [
309
+ /* @__PURE__ */ jsx(Button, { type: "button", disabled: !loaded, onClick: () => choose(camera.longitude, camera.latitude), children: copy.chooseCenter }),
310
+ onClear && /* @__PURE__ */ jsx(Button, { type: "button", disabled: !value, onClick: onClear, children: copy.clear })
311
+ ] })
312
+ ] });
313
+ }
314
+ function MapCoverageLayer({ id, points, colorByStatus, radius = 6, showLabels = false }) {
315
+ const theme = useTheme();
316
+ const palette = useMemo(
317
+ () => ({
318
+ active: theme.palette.success.main,
319
+ pending: theme.palette.warning.main,
320
+ expired: theme.palette.text.disabled,
321
+ disabled: theme.palette.text.disabled,
322
+ retired: theme.palette.text.disabled,
323
+ ...colorByStatus ?? {}
324
+ }),
325
+ [theme, colorByStatus]
326
+ );
327
+ const geojson = useMemo(
328
+ () => ({
329
+ type: "FeatureCollection",
330
+ features: points.map((p) => ({
331
+ type: "Feature",
332
+ id: p.id,
333
+ geometry: {
334
+ type: "Point",
335
+ coordinates: [p.longitude, p.latitude]
336
+ },
337
+ properties: {
338
+ status: p.status ?? "active",
339
+ label: p.label ?? "",
340
+ color: palette[p.status ?? "active"] ?? theme.palette.primary.main
341
+ }
342
+ }))
343
+ }),
344
+ [points, palette, theme]
345
+ );
346
+ return /* @__PURE__ */ jsxs(Source, { id, type: "geojson", data: geojson, children: [
347
+ /* @__PURE__ */ jsx(
348
+ Layer,
349
+ {
350
+ id: `${id}-circles`,
351
+ type: "circle",
352
+ paint: {
353
+ "circle-radius": radius,
354
+ "circle-color": ["get", "color"],
355
+ "circle-stroke-color": theme.palette.background.paper,
356
+ "circle-stroke-width": 1.5
357
+ }
358
+ }
359
+ ),
360
+ showLabels && /* @__PURE__ */ jsx(
361
+ Layer,
362
+ {
363
+ id: `${id}-labels`,
364
+ type: "symbol",
365
+ minzoom: 11,
366
+ layout: {
367
+ "text-field": ["get", "label"],
368
+ "text-size": 11,
369
+ "text-offset": [0, 1.2],
370
+ "text-anchor": "top",
371
+ "text-font": ["Noto Sans Regular"]
372
+ },
373
+ paint: {
374
+ "text-color": theme.palette.text.primary,
375
+ "text-halo-color": theme.palette.background.paper,
376
+ "text-halo-width": 1
377
+ }
378
+ }
379
+ )
380
+ ] });
381
+ }
382
+ var defaults2 = {
383
+ label: "Find a place",
384
+ search: "Search",
385
+ clear: "Clear",
386
+ loading: "Searching\u2026",
387
+ empty: "No places found",
388
+ hint: "Enter a place and search",
389
+ error: "Place search is unavailable. Try again."
390
+ };
391
+ function MapPlaceSearch({
392
+ search,
393
+ onSelect,
394
+ mode = "submit",
395
+ debounceMs = 300,
396
+ minLength = 2,
397
+ limit = 8,
398
+ disabled = false,
399
+ labels
400
+ }) {
401
+ const copy = { ...defaults2, ...labels };
402
+ const [query, setQuery] = useState("");
403
+ const [results, setResults] = useState([]);
404
+ const [selected, setSelected] = useState(null);
405
+ const [loading, setLoading] = useState(false);
406
+ const [error, setError] = useState(false);
407
+ const [searched, setSearched] = useState(false);
408
+ const [open, setOpen] = useState(false);
409
+ const generation = useRef(0), active = useRef(null);
410
+ const highlighted = useRef(null);
411
+ const provider = useRef(search);
412
+ provider.current = search;
413
+ const validQuery = query.trim().length >= minLength && query.length <= 200;
414
+ function cancel() {
415
+ generation.current++;
416
+ active.current?.abort();
417
+ active.current = null;
418
+ }
419
+ async function run() {
420
+ cancel();
421
+ if (!validQuery || disabled) return;
422
+ const id = generation.current;
423
+ const controller = new AbortController();
424
+ active.current = controller;
425
+ setLoading(true);
426
+ setError(false);
427
+ setSearched(true);
428
+ setOpen(true);
429
+ try {
430
+ const values = await provider.current(query.trim(), { signal: controller.signal, limit });
431
+ if (id !== generation.current || controller.signal.aborted) return;
432
+ if (!Array.isArray(values) || values.some((v) => !v || !v.id || !v.label || !v.point || !isMapPoint(v.point)))
433
+ throw new Error("Invalid geocoder response");
434
+ const ids = /* @__PURE__ */ new Set();
435
+ setResults(
436
+ values.filter((v) => {
437
+ if (ids.has(v.id)) return false;
438
+ ids.add(v.id);
439
+ return true;
440
+ }).slice(0, limit)
441
+ );
442
+ } catch {
443
+ if (id === generation.current && !controller.signal.aborted) {
444
+ setError(true);
445
+ setResults([]);
446
+ setOpen(false);
447
+ }
448
+ } finally {
449
+ if (id === generation.current) setLoading(false);
450
+ }
451
+ }
452
+ useEffect(() => {
453
+ if (mode !== "autocomplete" || !validQuery || disabled || selected) return;
454
+ const timer = setTimeout(() => void run(), debounceMs);
455
+ return () => clearTimeout(timer);
456
+ }, [query, mode, debounceMs, disabled, selected]);
457
+ useEffect(() => {
458
+ if (disabled) {
459
+ cancel();
460
+ setLoading(false);
461
+ setOpen(false);
462
+ }
463
+ }, [disabled]);
464
+ useEffect(() => () => cancel(), []);
465
+ function input(value) {
466
+ cancel();
467
+ setQuery(value);
468
+ setSelected(null);
469
+ setResults([]);
470
+ setError(false);
471
+ setLoading(false);
472
+ setSearched(false);
473
+ highlighted.current = null;
474
+ }
475
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "grid", gap: 1 }, children: [
476
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "flex-start", gap: 1 }, children: [
477
+ /* @__PURE__ */ jsx(
478
+ Autocomplete,
479
+ {
480
+ sx: { flex: 1, minWidth: 0 },
481
+ disabled,
482
+ options: results,
483
+ value: selected,
484
+ inputValue: query,
485
+ open,
486
+ onOpen: () => setOpen(true),
487
+ onClose: () => setOpen(false),
488
+ onInputChange: (_, value, reason) => {
489
+ if (reason === "input" || reason === "clear") input(value);
490
+ },
491
+ onChange: (_, place) => {
492
+ if (place) {
493
+ cancel();
494
+ setLoading(false);
495
+ setSelected(place);
496
+ setQuery(place.label);
497
+ setOpen(false);
498
+ onSelect(place);
499
+ }
500
+ },
501
+ onHighlightChange: (_, option) => {
502
+ highlighted.current = option;
503
+ },
504
+ onKeyDown: (event) => {
505
+ if (event.key !== "Enter") return;
506
+ event.preventDefault();
507
+ if (!highlighted.current) {
508
+ event.defaultMuiPrevented = true;
509
+ void run();
510
+ }
511
+ },
512
+ getOptionLabel: (place) => place.label,
513
+ getOptionKey: (place) => place.id,
514
+ isOptionEqualToValue: (a, b) => a.id === b.id,
515
+ filterOptions: (options) => options,
516
+ loading,
517
+ loadingText: copy.loading,
518
+ clearText: copy.clear,
519
+ noOptionsText: searched ? copy.empty : copy.hint,
520
+ forcePopupIcon: false,
521
+ renderInput: (params) => /* @__PURE__ */ jsx(
522
+ TextField,
523
+ {
524
+ ...params,
525
+ label: copy.label,
526
+ slotProps: {
527
+ ...params.slotProps,
528
+ htmlInput: { ...params.slotProps.htmlInput, maxLength: 200 },
529
+ input: {
530
+ ...params.slotProps.input,
531
+ endAdornment: /* @__PURE__ */ jsxs(Fragment, { children: [
532
+ loading && /* @__PURE__ */ jsx(CircularProgress, { color: "inherit", size: 18 }),
533
+ params.slotProps.input.endAdornment
534
+ ] })
535
+ }
536
+ }
537
+ }
538
+ )
539
+ }
540
+ ),
541
+ mode === "submit" && /* @__PURE__ */ jsx(
542
+ Button,
543
+ {
544
+ type: "button",
545
+ variant: "outlined",
546
+ disabled: disabled || loading || !validQuery,
547
+ onClick: () => void run(),
548
+ sx: { minHeight: 40 },
549
+ children: copy.search
550
+ }
551
+ )
552
+ ] }),
553
+ error && /* @__PURE__ */ jsx(Alert, { severity: "warning", children: copy.error })
554
+ ] });
555
+ }
556
+
557
+ export { Map, MapCoverageLayer, MapMarker, MapPlaceSearch, MapPointPicker, isMapPoint, normalizeMapPoint };
558
+ //# sourceMappingURL=chunk-52PQL67Q.js.map
559
+ //# sourceMappingURL=chunk-52PQL67Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/map/Map.tsx","../src/components/map/MapMarker.tsx","../src/components/map/coordinates.ts","../src/components/map/MapPointPicker.tsx","../src/components/map/MapCoverageLayer.tsx","../src/components/map/MapPlaceSearch.tsx"],"names":["ReactMapGL","useTheme","useState","jsxs","Fragment","jsx","useEffect","Box","Marker","Alert","defaults","useRef","CircularProgress","Button"],"mappings":"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","file":"chunk-52PQL67Q.js","sourcesContent":["'use client';\n\nimport './map.css';\nimport { forwardRef, useCallback, useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport { Alert, Box, LinearProgress } from '@mui/material';\nimport { useTheme } from '@mui/material/styles';\nimport { Map as ReactMapGL, NavigationControl, ScaleControl } from 'react-map-gl/maplibre';\nimport type { MapProps as EngineProps, MapRef } from 'react-map-gl/maplibre';\nimport { addProtocol } from 'maplibre-gl';\nimport type { StyleSpecification } from 'maplibre-gl';\nimport { Protocol } from 'pmtiles';\n\n// Register before creating a map; style loading can begin before parent effects.\n// PMTiles maintains its own bounded archive/directory cache. Map instances do not\n// remove this shared protocol when another instance might still be using it.\nconst protocol = new Protocol();\naddProtocol('pmtiles', protocol.tile);\n\nexport interface MapViewport {\n longitude: number;\n latitude: number;\n zoom: number;\n bearing?: number;\n pitch?: number;\n}\nexport type MapStyle = string | StyleSpecification;\nexport interface MapMessages {\n label: string;\n missingStyle: string;\n loading: string;\n error: string;\n}\nconst messages: MapMessages = {\n label: 'Interactive map',\n missingStyle: 'A map source has not been configured.',\n loading: 'Loading map',\n error: 'Some map data could not be loaded. Check the connection or map source.',\n};\nexport interface MapProps extends Omit<EngineProps, 'mapStyle' | 'style' | 'children'> {\n /** Explicit style, or legacy host-injected window.__MAP_STYLE_URL__. No public fallback. */\n styleUrl?: MapStyle;\n /** Separate complete styles; selecting a theme does not rewrite provider layers. */\n styles?: { light: MapStyle; dark: MapStyle };\n viewport?: Partial<MapViewport>;\n initialViewport?: Partial<MapViewport>;\n onViewportChange?: (next: MapViewport) => void;\n showNavigation?: boolean;\n showScale?: boolean;\n showAttribution?: boolean;\n style?: CSSProperties;\n messages?: Partial<MapMessages>;\n children?: ReactNode;\n}\nconst world: MapViewport = { longitude: 0, latitude: 0, zoom: 1, bearing: 0, pitch: 0 };\n\n/** Provider-neutral MapLibre surface. Sources/layers/events remain fully typed. */\nexport const Map = forwardRef<MapRef, MapProps>(function MapView(\n {\n styleUrl,\n styles,\n viewport,\n initialViewport,\n onViewportChange,\n showNavigation = true,\n showScale = true,\n showAttribution = true,\n style,\n messages: overrides,\n children,\n onMove,\n onLoad,\n onError,\n cooperativeGestures = true,\n ...engine\n },\n forwardedRef\n) {\n const theme = useTheme();\n const copy = { ...messages, ...overrides };\n const legacyStyle =\n typeof window !== 'undefined' ? (window as Window & { __MAP_STYLE_URL__?: string }).__MAP_STYLE_URL__ : undefined;\n const mapStyle = styleUrl ?? styles?.[theme.palette.mode] ?? legacyStyle;\n const initial = { ...world, ...initialViewport };\n const host = useRef<HTMLDivElement>(null);\n const map = useRef<MapRef | null>(null);\n const [readyStyle, setReadyStyle] = useState<MapStyle>();\n const [error, setError] = useState(false);\n const setMap = useCallback(\n (value: MapRef | null) => {\n map.current = value;\n if (typeof forwardedRef === 'function') forwardedRef(value);\n else if (forwardedRef) forwardedRef.current = value;\n },\n [forwardedRef]\n );\n useEffect(() => {\n if (!host.current || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => map.current?.resize());\n observer.observe(host.current);\n return () => observer.disconnect();\n }, []);\n useEffect(() => setError(false), [mapStyle]);\n return (\n <Box\n ref={host}\n role=\"region\"\n aria-label={copy.label}\n style={style}\n sx={{\n width: '100%',\n height: 400,\n position: 'relative',\n borderRadius: 1,\n overflow: 'hidden',\n bgcolor: 'background.paper',\n '& .maplibregl-ctrl-group, & .maplibregl-popup-content': {\n bgcolor: 'background.paper',\n color: 'text.primary',\n boxShadow: theme.shadows[2],\n borderRadius: 1,\n border: 1,\n borderColor: 'divider',\n },\n '& .maplibregl-ctrl-group button': { color: 'text.primary', borderColor: 'divider' },\n '& .maplibregl-ctrl-icon': { filter: theme.palette.mode === 'dark' ? 'invert(1)' : 'none' },\n '& .maplibregl-ctrl-attrib': { bgcolor: 'background.paper', color: 'text.secondary' },\n '& .maplibregl-ctrl-attrib a': { color: 'inherit' },\n '& .maplibregl-ctrl-scale': {\n bgcolor: 'background.paper',\n color: 'text.primary',\n borderColor: 'text.secondary',\n },\n '& .maplibregl-ctrl button:focus-visible': {\n outline: `2px solid ${theme.palette.primary.main}`,\n outlineOffset: -2,\n },\n }}\n >\n {!mapStyle ? (\n <Alert severity=\"info\" sx={{ m: 2 }}>\n {copy.missingStyle}\n </Alert>\n ) : (\n <>\n <ReactMapGL\n {...engine}\n ref={setMap}\n mapStyle={mapStyle}\n cooperativeGestures={cooperativeGestures}\n {...(viewport\n ? { ...initial, ...viewport }\n : {\n initialViewState: initial,\n ...(engine.initialViewState ? { initialViewState: engine.initialViewState } : {}),\n })}\n onMove={(event) => {\n onViewportChange?.(event.viewState);\n onMove?.(event);\n }}\n onLoad={(event) => {\n setReadyStyle(mapStyle);\n onLoad?.(event);\n }}\n onIdle={(event) => {\n setReadyStyle(mapStyle);\n engine.onIdle?.(event);\n }}\n onError={(event) => {\n setError(true);\n onError?.(event);\n }}\n attributionControl={showAttribution ? (engine.attributionControl ?? {}) : false}\n style={{ width: '100%', height: '100%' }}\n >\n {showNavigation && <NavigationControl position=\"top-right\" />}\n {showScale && <ScaleControl position=\"bottom-left\" />}\n {children}\n </ReactMapGL>\n {readyStyle !== mapStyle && !error && (\n <LinearProgress aria-label={copy.loading} sx={{ position: 'absolute', top: 0, left: 0, right: 0 }} />\n )}\n {error && (\n <Alert\n severity=\"warning\"\n onClose={() => setError(false)}\n sx={{ position: 'absolute', left: 8, right: 8, top: 8 }}\n >\n {copy.error}\n </Alert>\n )}\n </>\n )}\n </Box>\n );\n});\n","'use client';\n\n/**\n * MapMarker Component\n *\n * Decorative marker pinned at `[longitude, latitude]` on the\n * parent `<Map>`. Renders a HugeIcons-styled pin by default;\n * pass `children` for a fully custom marker DOM. Optional\n * `popup` opens a Popup on click.\n *\n * @module components/map\n */\n\nimport { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { Marker, Popup } from 'react-map-gl/maplibre';\nimport { useTheme } from '@mui/material/styles';\n\nexport interface MapMarkerProps {\n longitude: number;\n latitude: number;\n /** Marker fill colour. Defaults to theme primary. */\n color?: string;\n /** Custom DOM (overrides the default pin icon). */\n children?: ReactNode;\n /** Popup body shown on click. */\n popup?: ReactNode;\n /** Anchor side. Defaults to bottom (pin tip at coordinate). */\n anchor?: 'center' | 'top' | 'bottom' | 'left' | 'right';\n /** Click-through handler. */\n onClick?: () => void;\n}\n\nexport function MapMarker({ longitude, latitude, color, children, popup, anchor = 'bottom', onClick }: MapMarkerProps) {\n const theme = useTheme();\n const [open, setOpen] = useState(false);\n const fill = color ?? theme.palette.primary.main;\n\n const handleClick = (e: { originalEvent?: { stopPropagation?: () => void } }) => {\n e.originalEvent?.stopPropagation?.();\n if (popup) setOpen((v) => !v);\n onClick?.();\n };\n\n return (\n <>\n <Marker longitude={longitude} latitude={latitude} anchor={anchor} onClick={handleClick}>\n {children ?? (\n <svg width=\"24\" height=\"32\" viewBox=\"0 0 24 32\" aria-hidden style={{ display: 'block' }}>\n <path d=\"M12 0C5.4 0 0 5.4 0 12c0 9 12 20 12 20s12-11 12-20C24 5.4 18.6 0 12 0z\" fill={fill} />\n <circle cx=\"12\" cy=\"12\" r=\"4\" fill=\"#fff\" />\n </svg>\n )}\n </Marker>\n {popup && open && (\n <Popup\n longitude={longitude}\n latitude={latitude}\n anchor=\"top\"\n offset={[0, -32]}\n closeOnClick={false}\n onClose={() => setOpen(false)}\n >\n {popup}\n </Popup>\n )}\n </>\n );\n}\n","/** WGS84 geographic coordinates. Camera constraints never alter the stored point. */\nexport interface MapPointPickerValue {\n lng: number;\n lat: number;\n}\nexport function isMapPoint(value: MapPointPickerValue): boolean {\n return (\n Number.isFinite(value.lng) &&\n Number.isFinite(value.lat) &&\n value.lng >= -180 &&\n value.lng <= 180 &&\n value.lat >= -90 &&\n value.lat <= 90\n );\n}\n/** MapLibre may emit a longitude in another world copy after panning. */\nexport function normalizeMapPoint(lng: number, lat: number): MapPointPickerValue | null {\n if (!Number.isFinite(lng) || !Number.isFinite(lat) || Math.abs(lat) > 90) return null;\n return { lng: lng >= -180 && lng <= 180 ? lng : ((((lng + 180) % 360) + 360) % 360) - 180, lat };\n}\nexport function mapCameraLatitude(latitude: number): number {\n return Math.max(-85.0511287798066, Math.min(85.0511287798066, latitude));\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport { Marker } from 'react-map-gl/maplibre';\nimport { Stack, Paper, Typography, CircularProgress, Box, Button, Alert } from '@mui/material';\nimport { Map } from './Map.js';\nimport type { MapProps, MapViewport } from './Map.js';\nimport { isMapPoint, normalizeMapPoint, mapCameraLatitude } from './coordinates.js';\nimport type { MapPointPickerValue } from './coordinates.js';\nexport type { MapPointPickerValue } from './coordinates.js';\n\nexport interface MapPointPickerLabels {\n placeholder: string;\n coordinates: string;\n place: string;\n loading: string;\n unknown: string;\n chooseCenter: string;\n clear: string;\n marker: string;\n}\nconst defaults: MapPointPickerLabels = {\n placeholder: 'Choose a point on the map, or move the map and select its centre.',\n coordinates: 'Coordinates',\n place: 'Place',\n loading: 'Finding place…',\n unknown: 'No place name for this point',\n chooseCenter: 'Select map centre',\n clear: 'Clear selection',\n marker: 'Selected point',\n};\nexport interface MapPointPickerProps {\n value: MapPointPickerValue | null;\n onChange: (next: MapPointPickerValue) => void;\n onClear?: () => void;\n initialViewport?: Partial<MapViewport>;\n /** Minimum zoom when receiving a newly selected point. */\n selectionZoom?: number;\n styleUrl?: MapProps['styleUrl'];\n height?: number;\n geocodeResult?: ReactNode;\n geocodeLoading?: boolean;\n geocodeError?: ReactNode;\n placeholder?: string;\n labels?: Partial<MapPointPickerLabels>;\n readOnly?: boolean;\n showDetails?: boolean;\n /** MapLibre sources, overlays and interaction configuration are reusable. */\n mapProps?: Omit<MapProps, 'viewport' | 'onViewportChange' | 'onClick' | 'styleUrl' | 'initialViewport'>;\n}\nexport function MapPointPicker({\n value,\n onChange,\n onClear,\n initialViewport,\n selectionZoom = 10,\n styleUrl,\n height = 480,\n geocodeResult,\n geocodeLoading = false,\n geocodeError,\n placeholder,\n labels,\n readOnly = false,\n showDetails = true,\n mapProps,\n}: MapPointPickerProps) {\n const copy = { ...defaults, ...labels, ...(placeholder ? { placeholder } : {}) };\n const valid = value && isMapPoint(value) ? value : null;\n const [camera, setCamera] = useState<MapViewport>(() => ({\n longitude: valid?.lng ?? 0,\n latitude: valid ? mapCameraLatitude(valid.lat) : 0,\n zoom: valid ? 10 : 1,\n ...initialViewport,\n }));\n const [loaded, setLoaded] = useState(false);\n useEffect(() => {\n if (value && isMapPoint(value))\n setCamera((old) => ({\n ...old,\n longitude: value.lng,\n latitude: mapCameraLatitude(value.lat),\n zoom: Math.max(old.zoom, selectionZoom),\n }));\n }, [value?.lng, value?.lat, selectionZoom]);\n function choose(lng: number, lat: number) {\n const point = normalizeMapPoint(lng, lat);\n if (point && !readOnly) onChange(point);\n }\n return (\n <Stack sx={{ gap: 2, width: '100%' }}>\n <Box\n sx={{\n display: 'grid',\n gridTemplateColumns: showDetails ? { xs: '1fr', md: 'minmax(0,1fr) 280px' } : '1fr',\n gap: 2,\n }}\n >\n <Map\n {...mapProps}\n styleUrl={styleUrl}\n viewport={camera}\n onViewportChange={setCamera}\n cursor={readOnly ? 'grab' : 'crosshair'}\n onClick={(event) => choose(event.lngLat.lng, event.lngLat.lat)}\n onLoad={(event) => {\n setLoaded(true);\n mapProps?.onLoad?.(event);\n }}\n style={{ ...mapProps?.style, height }}\n >\n {mapProps?.children}\n {valid && (\n <Marker\n longitude={valid.lng}\n latitude={valid.lat}\n anchor=\"center\"\n draggable={!readOnly}\n onDragEnd={(event) => choose(event.lngLat.lng, event.lngLat.lat)}\n >\n <Box\n role=\"img\"\n aria-label={copy.marker}\n sx={{\n width: 22,\n height: 22,\n borderRadius: '50%',\n bgcolor: 'primary.main',\n border: '3px solid',\n borderColor: 'background.paper',\n boxShadow: 2,\n }}\n />\n </Marker>\n )}\n </Map>\n {showDetails && (\n <Paper variant=\"outlined\" sx={{ p: 2, minWidth: 0 }}>\n {valid ? (\n <Stack sx={{ gap: 1.5 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {copy.coordinates}\n </Typography>\n <Typography variant=\"body2\" sx={{ fontVariantNumeric: 'tabular-nums' }}>\n {valid.lat.toFixed(5)}, {valid.lng.toFixed(5)}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {copy.place}\n </Typography>\n {geocodeLoading ? (\n <Stack direction=\"row\" sx={{ gap: 1, alignItems: 'center' }} role=\"status\">\n <CircularProgress size={16} />\n <Typography variant=\"body2\">{copy.loading}</Typography>\n </Stack>\n ) : geocodeError ? (\n <Alert severity=\"warning\">{geocodeError}</Alert>\n ) : (\n <Box sx={{ overflowWrap: 'anywhere' }}>\n {geocodeResult ?? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.unknown}\n </Typography>\n )}\n </Box>\n )}\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {copy.placeholder}\n </Typography>\n )}\n </Paper>\n )}\n </Box>\n {!readOnly && (\n <Stack direction=\"row\" sx={{ gap: 1, flexWrap: 'wrap' }}>\n <Button type=\"button\" disabled={!loaded} onClick={() => choose(camera.longitude, camera.latitude)}>\n {copy.chooseCenter}\n </Button>\n {onClear && (\n <Button type=\"button\" disabled={!value} onClick={onClear}>\n {copy.clear}\n </Button>\n )}\n </Stack>\n )}\n </Stack>\n );\n}\n","'use client';\n\n/**\n * MapCoverageLayer Component\n *\n * Renders an array of typed points on the parent `<Map>` as\n * colour-coded circles. Designed for \"coverage\" use cases\n * (dead-drops by status, pickup points by enabled/disabled,\n * shops by tier). Uses a single MapLibre symbol layer driven by\n * an in-memory GeoJSON source so rendering scales to a few\n * thousand points without DOM thrash.\n *\n * For < ~200 points, prefer composing `<MapMarker>` directly —\n * it gives you click + popup affordances per marker. This layer\n * is for the \"show me the whole network\" view.\n *\n * @module components/map\n */\n\nimport { useMemo } from 'react';\nimport { Source, Layer } from 'react-map-gl/maplibre';\nimport { useTheme } from '@mui/material/styles';\n\nexport interface CoveragePoint {\n /** Unique id within the layer; used as feature id for clicks. */\n id: string;\n longitude: number;\n latitude: number;\n /** Free-form bucket; the layer maps it to a colour via\n * the `colorByStatus` prop. Default mapping covers the\n * generic 'active'/'pending'/'expired'/'disabled' buckets. */\n status?: string;\n /** Optional label shown next to the point when zoomed in. */\n label?: string;\n}\n\nexport interface MapCoverageLayerProps {\n id: string;\n points: CoveragePoint[];\n /** Map of status → colour. Override to project custom domain\n * semantics. Default uses theme palette. */\n colorByStatus?: Record<string, string>;\n /** Marker radius in pixels (zoom-stable). Default 6. */\n radius?: number;\n /** Show label text alongside each marker (zoom 12+). */\n showLabels?: boolean;\n}\n\nexport function MapCoverageLayer({ id, points, colorByStatus, radius = 6, showLabels = false }: MapCoverageLayerProps) {\n const theme = useTheme();\n\n const palette = useMemo<Record<string, string>>(\n () => ({\n active: theme.palette.success.main,\n pending: theme.palette.warning.main,\n expired: theme.palette.text.disabled,\n disabled: theme.palette.text.disabled,\n retired: theme.palette.text.disabled,\n ...(colorByStatus ?? {}),\n }),\n [theme, colorByStatus]\n );\n\n const geojson = useMemo(\n () => ({\n type: 'FeatureCollection' as const,\n features: points.map((p) => ({\n type: 'Feature' as const,\n id: p.id,\n geometry: {\n type: 'Point' as const,\n coordinates: [p.longitude, p.latitude],\n },\n properties: {\n status: p.status ?? 'active',\n label: p.label ?? '',\n color: palette[p.status ?? 'active'] ?? theme.palette.primary.main,\n },\n })),\n }),\n [points, palette, theme]\n );\n\n return (\n <Source id={id} type=\"geojson\" data={geojson}>\n <Layer\n id={`${id}-circles`}\n type=\"circle\"\n paint={{\n 'circle-radius': radius,\n 'circle-color': ['get', 'color'],\n 'circle-stroke-color': theme.palette.background.paper,\n 'circle-stroke-width': 1.5,\n }}\n />\n {showLabels && (\n <Layer\n id={`${id}-labels`}\n type=\"symbol\"\n minzoom={11}\n layout={{\n 'text-field': ['get', 'label'],\n 'text-size': 11,\n 'text-offset': [0, 1.2],\n 'text-anchor': 'top',\n 'text-font': ['Noto Sans Regular'],\n }}\n paint={{\n 'text-color': theme.palette.text.primary,\n 'text-halo-color': theme.palette.background.paper,\n 'text-halo-width': 1,\n }}\n />\n )}\n </Source>\n );\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Alert, Autocomplete, Box, Button, CircularProgress, TextField } from '@mui/material';\nimport { isMapPoint } from './coordinates.js';\nimport type { MapPointPickerValue } from './coordinates.js';\n\nexport interface MapPlace {\n /** Provider-stable identifier, qualified with the provider name. */\n id: string;\n label: string;\n point: MapPointPickerValue;\n}\nexport interface MapPlaceSearchLabels {\n label: string;\n search: string;\n clear: string;\n loading: string;\n empty: string;\n hint: string;\n error: string;\n}\nconst defaults: MapPlaceSearchLabels = {\n label: 'Find a place',\n search: 'Search',\n clear: 'Clear',\n loading: 'Searching…',\n empty: 'No places found',\n hint: 'Enter a place and search',\n error: 'Place search is unavailable. Try again.',\n};\nexport interface MapPlaceSearchProps<T extends MapPlace = MapPlace> {\n /** Supply a Netron/API adapter. Prism makes no requests to a provider itself. */\n search: (query: string, options: { signal: AbortSignal; limit: number }) => Promise<readonly T[]>;\n onSelect: (place: T) => void;\n /** Explicit submission works with every geocoder; autocomplete must be provider-supported. */\n mode?: 'submit' | 'autocomplete';\n debounceMs?: number;\n minLength?: number;\n limit?: number;\n disabled?: boolean;\n labels?: Partial<MapPlaceSearchLabels>;\n}\nexport function MapPlaceSearch<T extends MapPlace>({\n search,\n onSelect,\n mode = 'submit',\n debounceMs = 300,\n minLength = 2,\n limit = 8,\n disabled = false,\n labels,\n}: MapPlaceSearchProps<T>) {\n const copy = { ...defaults, ...labels };\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<T[]>([]);\n const [selected, setSelected] = useState<T | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState(false);\n const [searched, setSearched] = useState(false);\n const [open, setOpen] = useState(false);\n const generation = useRef(0),\n active = useRef<AbortController | null>(null);\n const highlighted = useRef<T | null>(null);\n const provider = useRef(search);\n provider.current = search;\n const validQuery = query.trim().length >= minLength && query.length <= 200;\n function cancel() {\n generation.current++;\n active.current?.abort();\n active.current = null;\n }\n async function run() {\n cancel();\n if (!validQuery || disabled) return;\n const id = generation.current;\n const controller = new AbortController();\n active.current = controller;\n setLoading(true);\n setError(false);\n setSearched(true);\n setOpen(true);\n try {\n const values = await provider.current(query.trim(), { signal: controller.signal, limit });\n if (id !== generation.current || controller.signal.aborted) return;\n if (!Array.isArray(values) || values.some((v) => !v || !v.id || !v.label || !v.point || !isMapPoint(v.point)))\n throw new Error('Invalid geocoder response');\n const ids = new Set<string>();\n setResults(\n values\n .filter((v) => {\n if (ids.has(v.id)) return false;\n ids.add(v.id);\n return true;\n })\n .slice(0, limit)\n );\n } catch {\n if (id === generation.current && !controller.signal.aborted) {\n setError(true);\n setResults([]);\n setOpen(false);\n }\n } finally {\n if (id === generation.current) setLoading(false);\n }\n }\n useEffect(() => {\n if (mode !== 'autocomplete' || !validQuery || disabled || selected) return;\n const timer = setTimeout(() => void run(), debounceMs);\n return () => clearTimeout(timer);\n }, [query, mode, debounceMs, disabled, selected]);\n useEffect(() => {\n if (disabled) {\n cancel();\n setLoading(false);\n setOpen(false);\n }\n }, [disabled]);\n useEffect(() => () => cancel(), []);\n function input(value: string) {\n cancel();\n setQuery(value);\n setSelected(null);\n setResults([]);\n setError(false);\n setLoading(false);\n setSearched(false);\n highlighted.current = null;\n }\n return (\n <Box sx={{ display: 'grid', gap: 1 }}>\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1 }}>\n <Autocomplete<T, false, false, false>\n sx={{ flex: 1, minWidth: 0 }}\n disabled={disabled}\n options={results}\n value={selected}\n inputValue={query}\n open={open}\n onOpen={() => setOpen(true)}\n onClose={() => setOpen(false)}\n onInputChange={(_, value, reason) => {\n if (reason === 'input' || reason === 'clear') input(value);\n }}\n onChange={(_, place) => {\n if (place) {\n cancel();\n setLoading(false);\n setSelected(place);\n setQuery(place.label);\n setOpen(false);\n onSelect(place);\n }\n }}\n onHighlightChange={(_, option) => {\n highlighted.current = option;\n }}\n onKeyDown={(event) => {\n if (event.key !== 'Enter') return;\n event.preventDefault();\n if (!highlighted.current) {\n (event as typeof event & { defaultMuiPrevented: boolean }).defaultMuiPrevented = true;\n void run();\n }\n }}\n getOptionLabel={(place) => place.label}\n getOptionKey={(place) => place.id}\n isOptionEqualToValue={(a, b) => a.id === b.id}\n filterOptions={(options) => options}\n loading={loading}\n loadingText={copy.loading}\n clearText={copy.clear}\n noOptionsText={searched ? copy.empty : copy.hint}\n forcePopupIcon={false}\n renderInput={(params) => (\n <TextField\n {...params}\n label={copy.label}\n slotProps={{\n ...params.slotProps,\n htmlInput: { ...params.slotProps.htmlInput, maxLength: 200 },\n input: {\n ...params.slotProps.input,\n endAdornment: (\n <>\n {loading && <CircularProgress color=\"inherit\" size={18} />}\n {params.slotProps.input.endAdornment}\n </>\n ),\n },\n }}\n />\n )}\n />\n {mode === 'submit' && (\n <Button\n type=\"button\"\n variant=\"outlined\"\n disabled={disabled || loading || !validQuery}\n onClick={() => void run()}\n sx={{ minHeight: 40 }}\n >\n {copy.search}\n </Button>\n )}\n </Box>\n {error && <Alert severity=\"warning\">{copy.error}</Alert>}\n </Box>\n );\n}\n"]}