@vidro/map-handler 1.2.177 → 1.2.179

Sign up to get free protection for your applications and to get access to all the features.
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
+ }