@vidro/map-handler 1.2.178 → 1.2.179

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 (29) hide show
  1. package/dist/map-handler.js +1 -1
  2. package/examples/react-next/README.md +40 -0
  3. package/examples/react-next/components/MapButtons.js +40 -0
  4. package/examples/react-next/components/MapIframe.js +25 -0
  5. package/examples/react-next/components/SessionComponent.js +136 -0
  6. package/examples/react-next/contexts/auth.js +99 -0
  7. package/examples/react-next/contexts/maps.js +139 -0
  8. package/examples/react-next/contexts/messages.js +345 -0
  9. package/examples/react-next/eslint.config.mjs +14 -0
  10. package/examples/react-next/hooks/useMapEvents.js +209 -0
  11. package/examples/react-next/jsconfig.json +7 -0
  12. package/examples/react-next/next.config.mjs +6 -0
  13. package/examples/react-next/package.json +24 -0
  14. package/examples/react-next/pages/_app.js +5 -0
  15. package/examples/react-next/pages/_document.js +13 -0
  16. package/examples/react-next/pages/index.js +77 -0
  17. package/examples/react-next/postcss.config.mjs +8 -0
  18. package/examples/react-next/public/favicon.ico +0 -0
  19. package/examples/react-next/public/file.svg +1 -0
  20. package/examples/react-next/public/globe.svg +1 -0
  21. package/examples/react-next/public/next.svg +1 -0
  22. package/examples/react-next/public/vercel.svg +1 -0
  23. package/examples/react-next/public/window.svg +1 -0
  24. package/examples/react-next/shared/constants.js +47 -0
  25. package/examples/react-next/shared/maps-service.js +65 -0
  26. package/examples/react-next/styles/globals.css +24 -0
  27. package/examples/react-next/tailwind.config.mjs +17 -0
  28. package/package.json +1 -1
  29. package/src/index.js +7 -7
@@ -0,0 +1,345 @@
1
+ import { createContext, useContext, useEffect, useState } from "react";
2
+ import { MAP_EVENTS } from "@/shared/constants";
3
+
4
+ const MessageContext = createContext({});
5
+
6
+ export const MessageProvider = ({ children }) => {
7
+ const [events, setEvents] = useState(false);
8
+ const [communicator, setCommunicator] = useState(false);
9
+ const [message, setMessage] = useState(null);
10
+ const [messageQueue, setMessageQueue] = useState([]);
11
+
12
+ useEffect(() => {
13
+ if (!communicator) return;
14
+ console.log("MapHandler is ready for use");
15
+ }, [communicator]);
16
+
17
+ const start = async (sessionToken) => {
18
+ const { Communicator } = await import("@vidro/map-handler");
19
+ const _communicator = new Communicator({ sessionToken });
20
+ setCommunicator(_communicator);
21
+ };
22
+
23
+ const reloadLayers = () => {
24
+ if (!communicator) return;
25
+ communicator.reloadDisplayedLayers();
26
+ };
27
+
28
+ const ZoomIn = () => {
29
+ console.log("ZoomIn");
30
+ if (!communicator) return;
31
+ console.log("ZoomIn 2");
32
+ communicator.ZoomIn();
33
+ };
34
+
35
+ const zoomToExtent = () => {
36
+ if (!communicator) return;
37
+ communicator.zoomToExtent();
38
+ };
39
+
40
+ const ZoomOut = () => {
41
+ if (!communicator) return;
42
+ communicator.ZoomOut();
43
+ };
44
+
45
+ const Clear = () => {
46
+ if (!communicator) return;
47
+ communicator.clear();
48
+ };
49
+
50
+ const Info = (type = "geojson", layer, format = "json") => {
51
+ const hitTolerance = 5;
52
+ communicator.infoFromCoordinates(type, layer, hitTolerance, format);
53
+ };
54
+
55
+ const Geolocalize = (what) => {
56
+ if (!communicator) return;
57
+ communicator.Geolocalize(what);
58
+ };
59
+
60
+ const Filters = (filters) => {
61
+ if (!communicator) return;
62
+ communicator.setFilters(filters);
63
+ };
64
+
65
+ const RemoveElementFromMap = (id, layer) => {
66
+ communicator.RemoveGeometry(id, layer);
67
+ };
68
+
69
+ const CancelAddGeom = () => {
70
+ if (!communicator) return;
71
+ console.log("CancelAddGeom");
72
+ communicator.CancelAddGeom();
73
+ };
74
+
75
+ const Highlight = (item, center, animate, id, style, zoom = null) => {
76
+ if (!communicator) return;
77
+ console.log("Highlight", { item, center, animate, id, style, zoom });
78
+ let options = {
79
+ geom: item.geom,
80
+ zoom,
81
+ center,
82
+ animate,
83
+ data: item,
84
+ style,
85
+ };
86
+ communicator.Highlight(options);
87
+ };
88
+
89
+ const RemoveGeometriesByProperty = (layer, property, value) => {
90
+ if (!communicator) return;
91
+ communicator.RemoveGeometriesByProperty(layer, property, value);
92
+ };
93
+
94
+ const UpdateGeometriesByProperty = (layer, property, value, style) => {
95
+ if (!communicator) return;
96
+ console.log("UpdateGeometriesByProperty", {
97
+ layer,
98
+ property,
99
+ value,
100
+ style,
101
+ });
102
+ communicator.UpdateGeometriesByProperty(layer, property, value, style);
103
+ };
104
+
105
+ const DrawGeometries = (geoms) => {
106
+ if (!communicator) return;
107
+ console.log("DrawGeometries", geoms);
108
+ communicator.DrawGeometries(geoms);
109
+ };
110
+
111
+ const DrawGeometry = (geom, featureId, style) => {
112
+ if (!communicator) return;
113
+ console.log("DrawGeometry", { geom, featureId, style });
114
+ communicator.DrawGeometries([{ geom, style, featureId, id: featureId }]);
115
+ };
116
+
117
+ const ToggleLayer = (layer, properties) => {
118
+ if (!communicator) return;
119
+ communicator.toggleLayer(layer, properties);
120
+ };
121
+
122
+ const doSetActiveLayer = (name) => {
123
+ if (!communicator) return;
124
+ console.log("doSetActiveLayer", { name });
125
+ communicator.setActiveLayer(name);
126
+ };
127
+
128
+ const removeLayer = (name) => {
129
+ if (!communicator) return;
130
+ console.log("removeLayer", { name });
131
+ communicator.removeLayer(name);
132
+ };
133
+
134
+ const startDrawPolygon = () => {
135
+ const options = {
136
+ texts: {
137
+ start: t({
138
+ id: "COMMON.COMMON.CLICK_TO_START_DRAWING",
139
+ }),
140
+ continue: t({
141
+ id: "COMMON.COMMON.CLICK_TO_CONTINUE_DRAWING_POLYGON",
142
+ }),
143
+ },
144
+ style: {
145
+ fill: "rgb(249, 34, 34,0.3)",
146
+ stroke: "rgb(249, 34, 34)",
147
+ },
148
+ drawOnEnd: false,
149
+ showConfirm: false,
150
+ };
151
+ communicator.AddGeom("Polygon", options);
152
+ };
153
+
154
+ const BBoxForClicks = (size) => {
155
+ if (!communicator) return;
156
+ communicator.setBboxSize(size);
157
+ };
158
+
159
+ const cancelMeasure = () => {
160
+ if (!communicator) return;
161
+ communicator.cancelMeasure();
162
+ };
163
+
164
+ const initMeasure = (type, startMsg, continueMsg) => {
165
+ if (!communicator) return;
166
+ communicator.cancelMeasure();
167
+ communicator.initMeasure(type, startMsg, continueMsg);
168
+ };
169
+
170
+ const zoomToCoordinates = (coordinates, zoomLevel) => {
171
+ if (!communicator) return;
172
+ communicator.zoomToCoordinates(coordinates[0], coordinates[1], zoomLevel);
173
+ };
174
+
175
+ const zoomToGeometry = (geom, limits) => {
176
+ if (!communicator) return;
177
+ communicator.zoomToGeometry(geom, limits);
178
+ };
179
+
180
+ const centerMap = (coordinates) => {
181
+ if (!communicator) return;
182
+ communicator.CenterMap(coordinates[0], coordinates[1]);
183
+ };
184
+
185
+ const drawPoint = ({ drawOnEnd = false, showConfirm = false }) => {
186
+ if (!communicator) return;
187
+ communicator.AddGeom("Point", { drawOnEnd, showConfirm: true });
188
+ };
189
+
190
+ const addIcon = (icon, coordinates) => {
191
+ communicator.addIcon({ icon, coordinates });
192
+ };
193
+
194
+ const zoomToScale = (scale) => {
195
+ const allowedScales = [
196
+ "1:100",
197
+ "1:200",
198
+ "1:400",
199
+ "1:500",
200
+ "1:1000",
201
+ "1:2000",
202
+ "1:5000",
203
+ "1:10000",
204
+ "1:50000",
205
+ ];
206
+ if (!allowedScales.includes(scale)) {
207
+ console.error(
208
+ `Invalid scale: ${scale}. Allowed values are: ${allowedScales.join(
209
+ ", "
210
+ )}`
211
+ );
212
+ return;
213
+ }
214
+ if (!communicator) return;
215
+ console.log("zoomToScale", { scale });
216
+ communicator.zoomToScale(scale);
217
+ };
218
+
219
+ const onMapEvent = (data) => {
220
+ console.log(`onMapEvent`, { type: data.type, data });
221
+ setMessageQueue((prevQueue) => [...prevQueue, data]);
222
+ };
223
+
224
+ useEffect(() => {
225
+ if (message) return;
226
+ if (messageQueue.length === 0) {
227
+ return;
228
+ }
229
+ setMessage(messageQueue[0]);
230
+ setMessageQueue((prevQueue) => {
231
+ return prevQueue.slice(1);
232
+ });
233
+ }, [messageQueue, message]);
234
+
235
+ useEffect(() => {
236
+ if (!communicator) return;
237
+ communicator.on(MAP_EVENTS.ZOOM_CHANGE, onMapEvent);
238
+ communicator.on(MAP_EVENTS.LOADED, onMapEvent);
239
+ communicator.on(MAP_EVENTS.CAPABILITIES, onMapEvent);
240
+ communicator.on(MAP_EVENTS.ERROR, onMapEvent);
241
+ communicator.on(MAP_EVENTS.GEOLOCATION, onMapEvent);
242
+ communicator.on(MAP_EVENTS.END_MEASURE, onMapEvent);
243
+ communicator.on(MAP_EVENTS.START_MEASURE, onMapEvent);
244
+ communicator.on(MAP_EVENTS.UNLOADED, onMapEvent);
245
+ communicator.on(MAP_EVENTS.COORDINATES, onMapEvent);
246
+ communicator.on(MAP_EVENTS.CENTER_CHANGE, onMapEvent);
247
+ communicator.on(MAP_EVENTS.ACTIVE_LAYER, onMapEvent);
248
+ communicator.on(MAP_EVENTS.WMS_LAYERS, onMapEvent);
249
+ communicator.on(MAP_EVENTS.STATUS, onMapEvent);
250
+ communicator.on(MAP_EVENTS.INFO, onMapEvent);
251
+ communicator.on(MAP_EVENTS.GEOM_ADDED, onMapEvent);
252
+ communicator.on(MAP_EVENTS.LAYERS, onMapEvent);
253
+ communicator.on(MAP_EVENTS.VERSION, onMapEvent);
254
+ communicator.on(MAP_EVENTS.SCREENSHOT, onMapEvent);
255
+ return () => {
256
+ if (!communicator) return;
257
+ communicator.off(MAP_EVENTS.ZOOM_CHANGE, onMapEvent);
258
+ communicator.off(MAP_EVENTS.LOADED, onMapEvent);
259
+ communicator.off(MAP_EVENTS.CAPABILITIES, onMapEvent);
260
+ communicator.off(MAP_EVENTS.ERROR, onMapEvent);
261
+ communicator.off(MAP_EVENTS.GEOLOCATION, onMapEvent);
262
+ communicator.off(MAP_EVENTS.END_MEASURE, onMapEvent);
263
+ communicator.off(MAP_EVENTS.START_MEASURE, onMapEvent);
264
+ communicator.off(MAP_EVENTS.UNLOADED, onMapEvent);
265
+ communicator.off(MAP_EVENTS.COORDINATES, onMapEvent);
266
+ communicator.off(MAP_EVENTS.CENTER_CHANGE, onMapEvent);
267
+ communicator.off(MAP_EVENTS.ACTIVE_LAYER, onMapEvent);
268
+ communicator.off(MAP_EVENTS.WMS_LAYERS, onMapEvent);
269
+ communicator.off(MAP_EVENTS.STATUS, onMapEvent);
270
+ communicator.off(MAP_EVENTS.INFO, onMapEvent);
271
+ communicator.off(MAP_EVENTS.LAYERS, onMapEvent);
272
+ communicator.off(MAP_EVENTS.VERSION, onMapEvent);
273
+ communicator.off(MAP_EVENTS.SCREENSHOT, onMapEvent);
274
+ setCommunicator(null);
275
+ };
276
+ }, [communicator, events]);
277
+
278
+ useEffect(() => {
279
+ // Clean up
280
+ return function cleanup() {
281
+ if (communicator) {
282
+ communicator.off(MAP_EVENTS.ZOOM_CHANGE, onMapEvent);
283
+ communicator.off(MAP_EVENTS.LOADED, onMapEvent);
284
+ communicator.off(MAP_EVENTS.CAPABILITIES, onMapEvent);
285
+ communicator.off(MAP_EVENTS.ERROR, onMapEvent);
286
+ communicator.off(MAP_EVENTS.GEOLOCATION, onMapEvent);
287
+ communicator.off(MAP_EVENTS.END_MEASURE, onMapEvent);
288
+ communicator.off(MAP_EVENTS.START_MEASURE, onMapEvent);
289
+ communicator.off(MAP_EVENTS.UNLOADED, onMapEvent);
290
+ communicator.off(MAP_EVENTS.COORDINATES, onMapEvent);
291
+ communicator.off(MAP_EVENTS.CENTER_CHANGE, onMapEvent);
292
+ communicator.off(MAP_EVENTS.ACTIVE_LAYER, onMapEvent);
293
+ communicator.off(MAP_EVENTS.WMS_LAYERS, onMapEvent);
294
+ communicator.off(MAP_EVENTS.STATUS, onMapEvent);
295
+ communicator.off(MAP_EVENTS.INFO, onMapEvent);
296
+ communicator.off(MAP_EVENTS.VERSION, onMapEvent);
297
+ }
298
+ setMessage(null);
299
+ setEvents(false);
300
+ };
301
+ }, []);
302
+
303
+ return (
304
+ <MessageContext.Provider
305
+ value={{
306
+ communicator,
307
+ start,
308
+ ZoomIn,
309
+ ZoomOut,
310
+ zoomToExtent,
311
+ DrawGeometry,
312
+ DrawGeometries,
313
+
314
+ startDrawPolygon,
315
+ CancelAddGeom,
316
+ Clear,
317
+ Info,
318
+ RemoveElementFromMap,
319
+ Highlight,
320
+ RemoveGeometriesByProperty,
321
+ UpdateGeometriesByProperty,
322
+ ToggleLayer,
323
+ message,
324
+ setMessage,
325
+ Filters,
326
+ reloadLayers,
327
+ BBoxForClicks,
328
+ cancelMeasure,
329
+ initMeasure,
330
+ removeLayer,
331
+ Geolocalize,
332
+ zoomToCoordinates,
333
+ zoomToGeometry,
334
+ centerMap,
335
+ drawPoint,
336
+ addIcon,
337
+ zoomToScale,
338
+ }}
339
+ >
340
+ {children}
341
+ </MessageContext.Provider>
342
+ );
343
+ };
344
+
345
+ export const useMessages = () => useContext(MessageContext);
@@ -0,0 +1,14 @@
1
+ import { dirname } from "path";
2
+ import { fileURLToPath } from "url";
3
+ import { FlatCompat } from "@eslint/eslintrc";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ const compat = new FlatCompat({
9
+ baseDirectory: __dirname,
10
+ });
11
+
12
+ const eslintConfig = [...compat.extends("next/core-web-vitals")];
13
+
14
+ export default eslintConfig;
@@ -0,0 +1,209 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ import Logger from "@/shared/logger";
4
+ import { useIntl } from "react-intl";
5
+ import { toast } from "react-toastify";
6
+ import { ERRORS, MAP_EVENTS, PLUGINS } from "@/shared/constants";
7
+ import { useMessages } from "@/contexts/messages";
8
+ import { useMaps } from "@/contexts/maps";
9
+ import { storeMapCookie, readMapCookie } from "@/shared/cookies";
10
+
11
+ const logger = new Logger("Hooks - useMapEvents");
12
+ const useMapEvents = (setShowInfo) => {
13
+ const {
14
+ doInfo,
15
+ setTiledReady,
16
+ setMapReady,
17
+ setDisplayedLayers,
18
+ setCurrentMapAction,
19
+ displayedLayers,
20
+ setZoomLevel,
21
+ mapInfo,
22
+ mapReady,
23
+ AddLayerToPreselectedLayers,
24
+ mapScale,
25
+ setMapScale,
26
+ } = useMaps();
27
+ const { message, setMessage, zoomToCoordinates } = useMessages();
28
+ const [cookieCoordinates, setCookieCoordindates] = useState(null);
29
+ const [cookieZoom, setCookieZoom] = useState(null);
30
+ const [cookieToc, setCookieToc] = useState(null);
31
+
32
+ useEffect(() => {
33
+ if (!cookieCoordinates) return;
34
+ if (!cookieZoom) return;
35
+ try {
36
+ logger.log("Cookie zoom", { cookieZoom, cookieCoordinates });
37
+ zoomToCoordinates(JSON.parse(cookieCoordinates), cookieZoom);
38
+ } catch (e) {
39
+ logger.error("error parsing coordinates", e);
40
+ }
41
+ }, [cookieCoordinates, cookieZoom]);
42
+
43
+ useEffect(() => {
44
+ if (!mapInfo) return;
45
+ if (mapInfo?.layers.length === 0) return;
46
+ logger.log("Cookie layers", { mapInfo, cookieToc });
47
+ if (!cookieToc || cookieToc === "undefined") return;
48
+ try {
49
+ const tocLayers = JSON.parse(cookieToc);
50
+ logger.log("Cookie layers", tocLayers);
51
+ tocLayers.forEach((element) => {
52
+ logger.log("Cookie layers adding", element);
53
+ //find layer in project layers
54
+ const lay = mapInfo.layers.find((ly) => ly.qgis_name === element);
55
+ //render layer
56
+ AddLayerToPreselectedLayers(lay.id);
57
+ });
58
+ } catch (e) {
59
+ logger.error("error parsing cookieToc", e);
60
+ }
61
+ }, [cookieToc, mapInfo]);
62
+
63
+ useEffect(() => {
64
+ if (!message) return;
65
+ if (!mapReady) return;
66
+ if (!mapInfo) return;
67
+
68
+ switch (message.type) {
69
+ case MAP_EVENTS.ZOOM_CHANGE:
70
+ //store in cookie zoom level
71
+ if (mapInfo.zoomcookie) {
72
+ storeMapCookie(`${mapInfo.id}_zoom`, message.zoom);
73
+ setZoomLevel(message.zoom);
74
+ }
75
+ setMapScale(message?.meta?.scale);
76
+ setMessage(null);
77
+ break;
78
+ case MAP_EVENTS.CENTER_CHANGE:
79
+ if (mapInfo.zoomcookie) {
80
+ storeMapCookie(
81
+ `${mapInfo.id}_center`,
82
+ JSON.stringify(message.coordinates)
83
+ );
84
+ }
85
+ setMessage(null);
86
+ break;
87
+ default:
88
+ setMessage(null);
89
+ break;
90
+ }
91
+ }, [message, cookieCoordinates, cookieZoom, mapReady, mapInfo]);
92
+
93
+ useEffect(() => {
94
+ if (!message) return;
95
+ switch (message.type) {
96
+ case MAP_EVENTS.VERSION:
97
+ //ToDo
98
+ break;
99
+ case MAP_EVENTS.LOADED:
100
+ if (message.what === "map") {
101
+ logger.log("Map loaded and ready");
102
+ //use cookie for zoom and position only if map is configured with zoomcookie
103
+ if (mapInfo.zoomcookie) {
104
+ setCookieCoordindates(readMapCookie(`${mapInfo.id}_center`));
105
+ setCookieZoom(readMapCookie(`${mapInfo.id}_zoom`));
106
+ }
107
+ //use cookie for toc layers configured with tocusecookie
108
+ if (mapInfo.tocusecookie) {
109
+ setCookieToc(readMapCookie(`${mapInfo.id}_toc`));
110
+ }
111
+ setMapReady(true);
112
+ } else if (message.what === "tiled") {
113
+ logger.log("Tiled loaded");
114
+ setTiledReady(true);
115
+ }
116
+ if (message.what === "layer") {
117
+ if (mapInfo.tocusecookie) {
118
+ if (cookieToc && cookieToc !== "undefined") {
119
+ let currentCookie = JSON.parse(cookieToc);
120
+ if (!currentCookie.find((l) => l === message.layer)) {
121
+ logger.log("Store layer in TOC cookie", message.layer);
122
+ currentCookie.push(message.layer);
123
+ storeMapCookie(
124
+ `${mapInfo.id}_toc`,
125
+ JSON.stringify(currentCookie)
126
+ );
127
+ }
128
+ } else {
129
+ logger.log("Store layer in TOC cookie", message.layer);
130
+ storeMapCookie(
131
+ `${mapInfo.id}_toc`,
132
+ JSON.stringify([message.layer])
133
+ );
134
+ }
135
+ }
136
+ }
137
+ setMessage(null);
138
+ break;
139
+ case MAP_EVENTS.UNLOADED:
140
+ if (message.what === "tiled") {
141
+ logger.log("Tiled unloaded");
142
+ setTiledReady(false);
143
+ }
144
+ setMessage(null);
145
+ break;
146
+ case MAP_EVENTS.LAYERS:
147
+ logger.log("MapComponent displayed layers", message.layers);
148
+ if (!message.layers) returns;
149
+ //check if is already displayed
150
+ setDisplayedLayers(message.layers);
151
+ setMessage(null);
152
+ break;
153
+ case MAP_EVENTS.GEOM_ADDED:
154
+ logger.log("GeomAdded", message);
155
+ setCurrentMapAction(null);
156
+ if (message?.geom_astext === null) {
157
+ setMessage(null);
158
+ return;
159
+ }
160
+ /************************************************************************************
161
+ ***************** INFO *************************
162
+ ***********************************************************************************/
163
+ (async () => {
164
+ /*
165
+ try {
166
+ const { data, error } = await doInfo(
167
+ message.geom_astext,
168
+ message.srid,
169
+ currentElementType.name
170
+ );
171
+
172
+ logger.log("GeomAdded info", { data, error });
173
+ if (error) {
174
+ return { error: error };
175
+ }
176
+ } catch (err) {
177
+ // Handle errors
178
+ logger.error("Error occurred:", err);
179
+ } finally {
180
+ // Clean up or perform additional actions
181
+ setMessage(null);
182
+ // setCurrentMapAction(null);
183
+ }*/
184
+ })();
185
+ break;
186
+
187
+ /************************************************************************************
188
+ ***************** END INFO *************************
189
+ ***********************************************************************************/
190
+
191
+ /************************************************************************************
192
+ ***************** CLICKED COORDINATES *************************
193
+ ***********************************************************************************/
194
+
195
+ /*** MAP_EVENTS.COORDINATES handled in contexts/info
196
+
197
+ /************************************************************************************
198
+ ***************** END CLICKED COORDINATES *************************
199
+ ***********************************************************************************/
200
+
201
+ default:
202
+ setMessage(null);
203
+ break;
204
+ }
205
+ }, [message, displayedLayers]);
206
+
207
+ return {};
208
+ };
209
+ export default useMapEvents;
@@ -0,0 +1,7 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "@/*": ["./*"]
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ };
5
+
6
+ export default nextConfig;
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "react-next",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "@vidro/map-handler": "^1.2.178",
13
+ "next": "15.1.6",
14
+ "react": "^19.0.0",
15
+ "react-dom": "^19.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@eslint/eslintrc": "^3",
19
+ "eslint": "^9",
20
+ "eslint-config-next": "15.1.6",
21
+ "postcss": "^8",
22
+ "tailwindcss": "^3.4.1"
23
+ }
24
+ }
@@ -0,0 +1,5 @@
1
+ import "@/styles/globals.css";
2
+
3
+ export default function App({ Component, pageProps }) {
4
+ return <Component {...pageProps} />;
5
+ }
@@ -0,0 +1,13 @@
1
+ import { Html, Head, Main, NextScript } from "next/document";
2
+
3
+ export default function Document() {
4
+ return (
5
+ <Html lang="en">
6
+ <Head />
7
+ <body>
8
+ <Main />
9
+ <NextScript />
10
+ </body>
11
+ </Html>
12
+ );
13
+ }