@kispace-io/gs-lib 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/base-map-builder.d.ts.map +1 -1
  2. package/dist/gs-model.d.ts +6 -0
  3. package/dist/gs-model.d.ts.map +1 -1
  4. package/dist/index.d.ts +3 -5
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +890 -288
  7. package/dist/index.js.map +1 -1
  8. package/dist/map-renderer.d.ts +94 -0
  9. package/dist/map-renderer.d.ts.map +1 -0
  10. package/dist/ml/gs-gs2ml.d.ts +96 -0
  11. package/dist/ml/gs-gs2ml.d.ts.map +1 -0
  12. package/dist/ml/gs-ml-adapters.d.ts +41 -0
  13. package/dist/ml/gs-ml-adapters.d.ts.map +1 -0
  14. package/dist/ml/gs-ml-lib.d.ts +17 -0
  15. package/dist/ml/gs-ml-lib.d.ts.map +1 -0
  16. package/dist/ml/gs-ml2gs.d.ts +10 -0
  17. package/dist/ml/gs-ml2gs.d.ts.map +1 -0
  18. package/dist/ml/gs-mlns.d.ts +10 -0
  19. package/dist/ml/gs-mlns.d.ts.map +1 -0
  20. package/dist/ml/index.d.ts +9 -0
  21. package/dist/ml/index.d.ts.map +1 -0
  22. package/dist/ml/maplibre-map-renderer.d.ts +66 -0
  23. package/dist/ml/maplibre-map-renderer.d.ts.map +1 -0
  24. package/dist/{gs-gs2ol.d.ts → ol/gs-gs2ol.d.ts} +2 -2
  25. package/dist/ol/gs-gs2ol.d.ts.map +1 -0
  26. package/dist/ol/gs-ol-adapters.d.ts.map +1 -0
  27. package/dist/{gs-lib.d.ts → ol/gs-ol-lib.d.ts} +4 -4
  28. package/dist/ol/gs-ol-lib.d.ts.map +1 -0
  29. package/dist/{gs-ol2gs.d.ts → ol/gs-ol2gs.d.ts} +1 -1
  30. package/dist/ol/gs-ol2gs.d.ts.map +1 -0
  31. package/dist/ol/gs-olns.d.ts.map +1 -0
  32. package/dist/ol/index.d.ts +9 -0
  33. package/dist/ol/index.d.ts.map +1 -0
  34. package/dist/ol/openlayers-map-renderer.d.ts +68 -0
  35. package/dist/ol/openlayers-map-renderer.d.ts.map +1 -0
  36. package/package.json +6 -2
  37. package/src/base-map-builder.ts +8 -9
  38. package/src/gs-model.ts +7 -1
  39. package/src/index.ts +12 -7
  40. package/src/map-renderer.ts +115 -0
  41. package/src/ml/gs-gs2ml.ts +717 -0
  42. package/src/ml/gs-ml-adapters.ts +134 -0
  43. package/src/ml/gs-ml-lib.ts +124 -0
  44. package/src/ml/gs-ml2gs.ts +66 -0
  45. package/src/ml/gs-mlns.ts +50 -0
  46. package/src/ml/index.ts +41 -0
  47. package/src/ml/maplibre-map-renderer.ts +428 -0
  48. package/src/{gs-gs2ol.ts → ol/gs-gs2ol.ts} +10 -4
  49. package/src/{gs-lib.ts → ol/gs-ol-lib.ts} +7 -6
  50. package/src/{gs-ol2gs.ts → ol/gs-ol2gs.ts} +1 -1
  51. package/src/ol/index.ts +21 -0
  52. package/src/ol/openlayers-map-renderer.ts +719 -0
  53. package/dist/gs-gs2ol.d.ts.map +0 -1
  54. package/dist/gs-lib.d.ts.map +0 -1
  55. package/dist/gs-ol-adapters.d.ts.map +0 -1
  56. package/dist/gs-ol2gs.d.ts.map +0 -1
  57. package/dist/gs-olns.d.ts.map +0 -1
  58. /package/dist/{gs-ol-adapters.d.ts → ol/gs-ol-adapters.d.ts} +0 -0
  59. /package/dist/{gs-olns.d.ts → ol/gs-olns.d.ts} +0 -0
  60. /package/src/{gs-ol-adapters.ts → ol/gs-ol-adapters.ts} +0 -0
  61. /package/src/{gs-olns.ts → ol/gs-olns.ts} +0 -0
package/dist/index.js CHANGED
@@ -1,26 +1,26 @@
1
- const byteToHex = [];
1
+ const byteToHex$1 = [];
2
2
  for (let i5 = 0; i5 < 256; ++i5) {
3
- byteToHex.push((i5 + 256).toString(16).slice(1));
3
+ byteToHex$1.push((i5 + 256).toString(16).slice(1));
4
4
  }
5
- function unsafeStringify(arr, offset2 = 0) {
6
- return (byteToHex[arr[offset2 + 0]] + byteToHex[arr[offset2 + 1]] + byteToHex[arr[offset2 + 2]] + byteToHex[arr[offset2 + 3]] + "-" + byteToHex[arr[offset2 + 4]] + byteToHex[arr[offset2 + 5]] + "-" + byteToHex[arr[offset2 + 6]] + byteToHex[arr[offset2 + 7]] + "-" + byteToHex[arr[offset2 + 8]] + byteToHex[arr[offset2 + 9]] + "-" + byteToHex[arr[offset2 + 10]] + byteToHex[arr[offset2 + 11]] + byteToHex[arr[offset2 + 12]] + byteToHex[arr[offset2 + 13]] + byteToHex[arr[offset2 + 14]] + byteToHex[arr[offset2 + 15]]).toLowerCase();
5
+ function unsafeStringify$1(arr, offset2 = 0) {
6
+ return (byteToHex$1[arr[offset2 + 0]] + byteToHex$1[arr[offset2 + 1]] + byteToHex$1[arr[offset2 + 2]] + byteToHex$1[arr[offset2 + 3]] + "-" + byteToHex$1[arr[offset2 + 4]] + byteToHex$1[arr[offset2 + 5]] + "-" + byteToHex$1[arr[offset2 + 6]] + byteToHex$1[arr[offset2 + 7]] + "-" + byteToHex$1[arr[offset2 + 8]] + byteToHex$1[arr[offset2 + 9]] + "-" + byteToHex$1[arr[offset2 + 10]] + byteToHex$1[arr[offset2 + 11]] + byteToHex$1[arr[offset2 + 12]] + byteToHex$1[arr[offset2 + 13]] + byteToHex$1[arr[offset2 + 14]] + byteToHex$1[arr[offset2 + 15]]).toLowerCase();
7
7
  }
8
- let getRandomValues;
9
- const rnds8 = new Uint8Array(16);
10
- function rng() {
11
- if (!getRandomValues) {
8
+ let getRandomValues$1;
9
+ const rnds8$1 = new Uint8Array(16);
10
+ function rng$1() {
11
+ if (!getRandomValues$1) {
12
12
  if (typeof crypto === "undefined" || !crypto.getRandomValues) {
13
13
  throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
14
14
  }
15
- getRandomValues = crypto.getRandomValues.bind(crypto);
15
+ getRandomValues$1 = crypto.getRandomValues.bind(crypto);
16
16
  }
17
- return getRandomValues(rnds8);
17
+ return getRandomValues$1(rnds8$1);
18
18
  }
19
- const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
20
- const native = { randomUUID };
19
+ const randomUUID$1 = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
20
+ const native$1 = { randomUUID: randomUUID$1 };
21
21
  function _v4(options, buf, offset2) {
22
22
  options = options || {};
23
- const rnds = options.random ?? options.rng?.() ?? rng();
23
+ const rnds = options.random ?? options.rng?.() ?? rng$1();
24
24
  if (rnds.length < 16) {
25
25
  throw new Error("Random bytes length must be >= 16");
26
26
  }
@@ -36,11 +36,11 @@ function _v4(options, buf, offset2) {
36
36
  }
37
37
  return buf;
38
38
  }
39
- return unsafeStringify(rnds);
39
+ return unsafeStringify$1(rnds);
40
40
  }
41
- function v4(options, buf, offset2) {
42
- if (native.randomUUID && !buf && !options) {
43
- return native.randomUUID();
41
+ function v4$1(options, buf, offset2) {
42
+ if (native$1.randomUUID && !buf && !options) {
43
+ return native$1.randomUUID();
44
44
  }
45
45
  return _v4(options, buf, offset2);
46
46
  }
@@ -60,7 +60,7 @@ const KEY_EVENT_SUBSCRIPTIONS = "_eventSubscriptions";
60
60
  const LAYER_GEOCODED_MARKERS = "geocoded-markers";
61
61
  function ensureUuid(obj) {
62
62
  if (!obj.uuid) {
63
- obj.uuid = v4();
63
+ obj.uuid = v4$1();
64
64
  }
65
65
  return obj;
66
66
  }
@@ -268,6 +268,333 @@ const DEFAULT_GSMAP = ensureUuid({
268
268
  styles: { ...DEFAULT_STYLES },
269
269
  styleRules: [...DEFAULT_STYLE_RULES]
270
270
  });
271
+ function findLayerByUuid(gsMap, uuid) {
272
+ return gsMap.layers.find((layer2) => layer2.uuid === uuid);
273
+ }
274
+ function findLayerIndexByUuid(gsMap, uuid) {
275
+ return gsMap.layers.findIndex((layer2) => layer2.uuid === uuid);
276
+ }
277
+ function findControlByUuid(gsMap, uuid) {
278
+ return gsMap.controls.find((control) => control.uuid === uuid);
279
+ }
280
+ function findControlIndexByUuid(gsMap, uuid) {
281
+ return gsMap.controls.findIndex((control) => control.uuid === uuid);
282
+ }
283
+ function findOverlayByUuid(gsMap, uuid) {
284
+ return gsMap.overlays.find((overlay) => overlay.uuid === uuid);
285
+ }
286
+ function findOverlayIndexByUuid(gsMap, uuid) {
287
+ return gsMap.overlays.findIndex((overlay) => overlay.uuid === uuid);
288
+ }
289
+ const createProxy = (operations) => {
290
+ return new Proxy({}, {
291
+ get: (_2, prop) => {
292
+ return async (...args) => {
293
+ for (const operation of operations) {
294
+ await operation[prop](...args);
295
+ }
296
+ };
297
+ }
298
+ });
299
+ };
300
+ function generateAppJs(vars) {
301
+ const allScripts = [...vars.gsMap.controls || [], ...vars.gsMap.overlays || []];
302
+ const scriptPaths = allScripts.map((script) => script.src).filter((src) => src);
303
+ const scriptImports = scriptPaths.map((src, index) => {
304
+ const escapedSrc = src.replace(/`/g, "\\`").replace(/\$/g, "\\$");
305
+ return `import script${index} from '${escapedSrc}'`;
306
+ });
307
+ const modulesMap = scriptPaths.map((src, index) => {
308
+ const escapedSrc = JSON.stringify(src);
309
+ return `${escapedSrc}: script${index}`;
310
+ }).join(",\n ");
311
+ return `
312
+ import {gsLib} from "${vars.gsLibPath}"
313
+ import "./gs-lib/gs-lib.css"
314
+
315
+ ${scriptImports.join("\n")}
316
+
317
+ export const renderMap = (mapContainerSelector) => {
318
+ const modules = {
319
+ ${modulesMap}
320
+ }
321
+ return gsLib({
322
+ containerSelector: mapContainerSelector,
323
+ gsMap: ${JSON.stringify(vars.gsMap)},
324
+ mapOptions: {
325
+ controls: {zoom: false, attribution: false}
326
+ },
327
+ env: ${JSON.stringify(vars.env || {})},
328
+ modules: modules
329
+ })
330
+ }
331
+ `;
332
+ }
333
+ function generatePrecacheManifest(assets) {
334
+ return JSON.stringify(assets, null, 2);
335
+ }
336
+ function processServiceWorker(content, precacheManifest) {
337
+ if (precacheManifest) {
338
+ const manifestJson = generatePrecacheManifest(precacheManifest);
339
+ if (content.includes("self.__WB_MANIFEST")) {
340
+ return content.replace(
341
+ "self.__WB_MANIFEST || []",
342
+ `${manifestJson}`
343
+ );
344
+ } else {
345
+ return content.replace(
346
+ /workbox\.precaching\.precacheAndRoute\(/,
347
+ `self.__WB_MANIFEST = ${manifestJson};
348
+ workbox.precaching.precacheAndRoute(`
349
+ );
350
+ }
351
+ }
352
+ return content;
353
+ }
354
+ function processManifest(content, title, version) {
355
+ const manifest = JSON.parse(content);
356
+ manifest.name = title;
357
+ manifest.short_name = title;
358
+ manifest.description = title;
359
+ manifest.version = version;
360
+ return JSON.stringify(manifest, null, 2);
361
+ }
362
+ function processHtml(content, title, appJsFilename, appCssFilename) {
363
+ let processed = content.replace(/\$TITLE/g, title);
364
+ if (appJsFilename) {
365
+ processed = processed.replace(/\.\/app\.js/g, `./${appJsFilename}`);
366
+ }
367
+ if (appCssFilename) {
368
+ processed = processed.replace(/href=["']app\.css["']/g, `href="${appCssFilename}"`);
369
+ }
370
+ return processed;
371
+ }
372
+ async function bundleApp(entryPointPath, outputDir, gsLibPath, fileSys, resolvePlugin, esbuildInstance, progress, currentStep, totalSteps) {
373
+ const updateProgress = (message) => {
374
+ if (progress) {
375
+ if (currentStep !== void 0) {
376
+ progress(++currentStep.value, message, totalSteps);
377
+ } else {
378
+ progress(0, message, totalSteps);
379
+ }
380
+ }
381
+ };
382
+ updateProgress("Bundling and minifying code...");
383
+ const result = await esbuildInstance.build({
384
+ entryPoints: [entryPointPath],
385
+ bundle: true,
386
+ outdir: outputDir,
387
+ format: "esm",
388
+ minify: true,
389
+ plugins: [resolvePlugin],
390
+ entryNames: "[name]-[hash]",
391
+ // Runtime dependencies (lit, webawesome) are bundled with gs-lib
392
+ external: [],
393
+ // Bundle all dependencies
394
+ packages: "bundle",
395
+ write: false,
396
+ // Don't write to disk, we'll handle it
397
+ metafile: true
398
+ // Generate metafile to get output information
399
+ });
400
+ updateProgress("Saving bundled output...");
401
+ if (!result.outputFiles || result.outputFiles.length === 0) {
402
+ throw new Error("No output files generated by esbuild");
403
+ }
404
+ let mainOutputFile = null;
405
+ let cssOutputFile = null;
406
+ if (result.metafile && result.metafile.outputs) {
407
+ const entryName = "app";
408
+ for (const [outputPath, output] of Object.entries(result.metafile.outputs)) {
409
+ if (output && typeof output === "object" && "entryPoint" in output) {
410
+ if (outputPath.includes(entryName) && outputPath.endsWith(".js")) {
411
+ mainOutputFile = outputPath;
412
+ } else if (outputPath.endsWith(".css")) {
413
+ cssOutputFile = outputPath;
414
+ }
415
+ }
416
+ }
417
+ }
418
+ const extractFilename = (filePath) => {
419
+ const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
420
+ return lastSlash >= 0 ? filePath.substring(lastSlash + 1) : filePath;
421
+ };
422
+ for (const file of result.outputFiles) {
423
+ let filePath = file.path || "";
424
+ let relativePath;
425
+ let filename;
426
+ if (filePath.startsWith("/") || filePath.length > 2 && filePath[1] === ":") {
427
+ filename = extractFilename(filePath);
428
+ relativePath = `${outputDir}/${filename}`;
429
+ } else {
430
+ filename = extractFilename(filePath);
431
+ relativePath = filePath.startsWith(outputDir) ? filePath : `${outputDir}/${filePath}`;
432
+ }
433
+ await fileSys.writeFile(relativePath, file.contents);
434
+ if (!mainOutputFile && filename.includes("app-") && filename.endsWith(".js")) {
435
+ mainOutputFile = filename;
436
+ }
437
+ if (!cssOutputFile && filename.includes("app-") && filename.endsWith(".css")) {
438
+ cssOutputFile = filename;
439
+ }
440
+ }
441
+ if (!mainOutputFile) {
442
+ throw new Error("Could not find main output file");
443
+ }
444
+ return {
445
+ js: extractFilename(mainOutputFile),
446
+ css: cssOutputFile ? extractFilename(cssOutputFile) : null
447
+ };
448
+ }
449
+ function createFileSystemGsLibCopier(fs2, gsLibPackagePath) {
450
+ const copyFile = async (srcPath, destPath, asText, processor) => {
451
+ const fullSrcPath = `${gsLibPackagePath}/${srcPath}`;
452
+ let content = await fs2.readFile(fullSrcPath);
453
+ if (asText) {
454
+ if (content instanceof Uint8Array) {
455
+ content = new TextDecoder().decode(content);
456
+ } else {
457
+ content = content;
458
+ }
459
+ if (processor) {
460
+ content = await processor(content);
461
+ }
462
+ }
463
+ await fs2.writeFile(destPath, content);
464
+ };
465
+ return {
466
+ async copyTextFile(srcPath, destPath, processor) {
467
+ await copyFile(srcPath, destPath, true, processor);
468
+ },
469
+ async copyBinaryFile(srcPath, destPath) {
470
+ await copyFile(srcPath, destPath, false);
471
+ }
472
+ };
473
+ }
474
+ async function buildMap(options, fs2, resolvePlugin, esbuildInstance, config = {}, progress) {
475
+ const {
476
+ outputDir = "dist",
477
+ buildDir = "__build",
478
+ gsLibPath = `${buildDir}/gs-lib/index.js`,
479
+ gsLibPackagePath,
480
+ gsLibCopier: providedGsLibCopier,
481
+ cleanBeforeBuild = true,
482
+ cleanAfterBuild = true,
483
+ copyAssets
484
+ } = config;
485
+ const gsLibCopier = providedGsLibCopier || (gsLibPackagePath ? createFileSystemGsLibCopier(fs2, gsLibPackagePath) : null);
486
+ if (!gsLibCopier) {
487
+ throw new Error("Either gsLibCopier or gsLibPackagePath must be provided");
488
+ }
489
+ const buildGsLibPath = gsLibPath;
490
+ let step = config.startingStep ?? 0;
491
+ const totalSteps = config.totalSteps;
492
+ const updateProgress = (message) => {
493
+ if (progress) progress(++step, message, totalSteps);
494
+ };
495
+ if (cleanBeforeBuild) {
496
+ updateProgress("Cleaning build directories...");
497
+ const cleanupPromises = [];
498
+ if (fs2.deleteDir) {
499
+ cleanupPromises.push(
500
+ fs2.deleteDir(buildDir).catch(() => {
501
+ }),
502
+ // Ignore errors if directory doesn't exist
503
+ fs2.deleteDir(outputDir).catch(() => {
504
+ })
505
+ );
506
+ } else {
507
+ try {
508
+ const nodeFs = await Promise.resolve().then(() => __viteBrowserExternal);
509
+ const path = await Promise.resolve().then(() => __viteBrowserExternal);
510
+ const projectRoot = process.cwd();
511
+ cleanupPromises.push(
512
+ nodeFs.rm(path.resolve(projectRoot, buildDir), { recursive: true, force: true }).catch(() => {
513
+ }),
514
+ nodeFs.rm(path.resolve(projectRoot, outputDir), { recursive: true, force: true }).catch(() => {
515
+ })
516
+ );
517
+ } catch {
518
+ }
519
+ }
520
+ await Promise.all(cleanupPromises);
521
+ }
522
+ updateProgress("Preparing build directories...");
523
+ await Promise.all([
524
+ fs2.ensureDir(`${outputDir}/assets/icons/`),
525
+ fs2.ensureDir(`${buildDir}/gs-lib/`)
526
+ ]);
527
+ updateProgress("Copying gs-lib package...");
528
+ await Promise.all([
529
+ gsLibCopier.copyTextFile("dist/index.js", `${buildDir}/gs-lib/index.js`),
530
+ gsLibCopier.copyTextFile("dist/gs-lib.css", `${buildDir}/gs-lib/gs-lib.css`)
531
+ ]);
532
+ updateProgress("Copying PWA core files...");
533
+ await gsLibCopier.copyTextFile("public/pwa/staticwebapp.config.json", `${outputDir}/staticwebapp.config.json`);
534
+ updateProgress("Creating manifest file...");
535
+ await gsLibCopier.copyTextFile("public/pwa/manifest.json", `${outputDir}/manifest.json`, (content) => processManifest(content, options.title, options.version));
536
+ updateProgress("Copying PWA icons...");
537
+ const iconFiles = [
538
+ "24x24.png",
539
+ "48x48.png",
540
+ "192x192.png",
541
+ "512x512.png",
542
+ "icon_24.png",
543
+ "icon_48.png",
544
+ "icon_192.png",
545
+ "icon_512.png"
546
+ ];
547
+ await Promise.all(iconFiles.map(
548
+ (icon) => gsLibCopier.copyBinaryFile(`public/pwa/assets/icons/${icon}`, `${outputDir}/assets/icons/${icon}`)
549
+ ));
550
+ if (copyAssets) {
551
+ updateProgress("Copying workspace assets...");
552
+ await copyAssets(fs2, outputDir, progress);
553
+ }
554
+ updateProgress("Generating application code...");
555
+ const entryPointContent = generateAppJs({
556
+ gsMap: options.gsMap,
557
+ gsLibPath: buildGsLibPath,
558
+ env: { ...options.env, BUILD_TIME: /* @__PURE__ */ new Date() }
559
+ });
560
+ await fs2.writeFile(`${buildDir}/app.js`, entryPointContent);
561
+ const stepRef = { value: step };
562
+ const bundleResult = await bundleApp(`${buildDir}/app.js`, outputDir, buildGsLibPath, fs2, resolvePlugin, esbuildInstance, progress, stepRef, totalSteps);
563
+ step = stepRef.value;
564
+ const appJsFilename = bundleResult.js;
565
+ const appCssFilename = bundleResult.css;
566
+ updateProgress("Generating HTML file...");
567
+ await gsLibCopier.copyTextFile("public/index.html", `${outputDir}/index.html`, (content) => processHtml(content, options.title, appJsFilename, appCssFilename || void 0));
568
+ const precacheManifest = [
569
+ { url: `/${appJsFilename}`, revision: null },
570
+ // Hashed filename handles versioning
571
+ ...appCssFilename ? [{ url: `/${appCssFilename}`, revision: null }] : [],
572
+ // Hashed CSS filename handles versioning
573
+ ...iconFiles.map((icon) => ({ url: `/assets/icons/${icon}`, revision: null }))
574
+ // Workbox will check file content
575
+ ];
576
+ updateProgress("Processing service worker...");
577
+ await gsLibCopier.copyTextFile(
578
+ "public/pwa/sw.js",
579
+ `${outputDir}/sw.js`,
580
+ (content) => processServiceWorker(content, precacheManifest)
581
+ );
582
+ if (cleanAfterBuild) {
583
+ updateProgress("Cleaning up temporary files...");
584
+ if (fs2.deleteDir) {
585
+ await fs2.deleteDir(buildDir);
586
+ } else {
587
+ try {
588
+ const nodeFs = await Promise.resolve().then(() => __viteBrowserExternal);
589
+ const path = await Promise.resolve().then(() => __viteBrowserExternal);
590
+ const fullPath = path.resolve(process.cwd(), buildDir);
591
+ await nodeFs.rm(fullPath, { recursive: true, force: true });
592
+ } catch (error2) {
593
+ }
594
+ }
595
+ }
596
+ updateProgress("Build completed!");
597
+ }
271
598
  const CollectionEventType = {
272
599
  /**
273
600
  * Triggered when an item is added to the collection.
@@ -99027,7 +99354,7 @@ const importSrc = async (adapter, src, importer) => {
99027
99354
  ol,
99028
99355
  env: olMap.get(KEY_ENV) || {},
99029
99356
  utils: {
99030
- uuid: v4
99357
+ uuid: v4$1
99031
99358
  },
99032
99359
  asset: (path) => {
99033
99360
  return rtUtils.resolveUrl(`assets/${path}`);
@@ -99176,7 +99503,7 @@ const cleanupEventSubscriptions = (olMap) => {
99176
99503
  olMap.set(KEY_EVENT_SUBSCRIPTIONS, []);
99177
99504
  }
99178
99505
  };
99179
- const toOlMap = async (gsMap, options, env, importer) => {
99506
+ const toOlMap = async (gsMap, options, env, importer, target) => {
99180
99507
  const olMap = withState(gsMap, new Map$1(options));
99181
99508
  olMap.set(KEY_ENV, env);
99182
99509
  olMap.setView(new View({
@@ -99188,6 +99515,9 @@ const toOlMap = async (gsMap, options, env, importer) => {
99188
99515
  const olLayer = toOlLayer(layer2);
99189
99516
  olMap.addLayer(olLayer);
99190
99517
  }
99518
+ if (target) {
99519
+ olMap.setTarget(target);
99520
+ }
99191
99521
  for (const overlay of gsMap.overlays || []) {
99192
99522
  const olOverlay = toOlOverlay(overlay);
99193
99523
  olMap.addOverlay(olOverlay);
@@ -99259,7 +99589,7 @@ function toGsFeature(feature) {
99259
99589
  geometry: toGsGeometry(feature.getGeometry())
99260
99590
  });
99261
99591
  }
99262
- const gsLib = async (options) => {
99592
+ const olLib = async (options) => {
99263
99593
  const mapOptions = {
99264
99594
  interactions: defaults({ keyboard: false }),
99265
99595
  controls: defaults$1(options.mapOptions?.controls)
@@ -99277,309 +99607,572 @@ const gsLib = async (options) => {
99277
99607
  throw new Error(`Module not found: ${src}`);
99278
99608
  };
99279
99609
  }
99280
- const olMap = await toOlMap(options.gsMap, mapOptions, options.env, importer);
99281
99610
  const target = typeof options.containerSelector === "string" ? document.querySelector(options.containerSelector) : options.containerSelector;
99282
- olMap.setTarget(target);
99611
+ const olMap = await toOlMap(options.gsMap, mapOptions, options.env, importer, target);
99283
99612
  return olMap;
99284
99613
  };
99285
- function generateAppJs(vars) {
99286
- const allScripts = [...vars.gsMap.controls || [], ...vars.gsMap.overlays || []];
99287
- const scriptPaths = allScripts.map((script) => script.src).filter((src) => src);
99288
- const scriptImports = scriptPaths.map((src, index) => {
99289
- const escapedSrc = src.replace(/`/g, "\\`").replace(/\$/g, "\\$");
99290
- return `import script${index} from '${escapedSrc}'`;
99291
- });
99292
- const modulesMap = scriptPaths.map((src, index) => {
99293
- const escapedSrc = JSON.stringify(src);
99294
- return `${escapedSrc}: script${index}`;
99295
- }).join(",\n ");
99296
- return `
99297
- import {gsLib} from "${vars.gsLibPath}"
99298
- import "./gs-lib/gs-lib.css"
99299
-
99300
- ${scriptImports.join("\n")}
99301
-
99302
- export const renderMap = (mapContainerSelector) => {
99303
- const modules = {
99304
- ${modulesMap}
99305
- }
99306
- return gsLib({
99307
- containerSelector: mapContainerSelector,
99308
- gsMap: ${JSON.stringify(vars.gsMap)},
99309
- mapOptions: {
99310
- controls: {zoom: false, attribution: false}
99311
- },
99312
- env: ${JSON.stringify(vars.env || {})},
99313
- modules: modules
99314
- })
99315
- }
99316
- `;
99614
+ const byteToHex = [];
99615
+ for (let i5 = 0; i5 < 256; ++i5) {
99616
+ byteToHex.push((i5 + 256).toString(16).slice(1));
99317
99617
  }
99318
- function generatePrecacheManifest(assets) {
99319
- return JSON.stringify(assets, null, 2);
99618
+ function unsafeStringify(arr, offset2 = 0) {
99619
+ return (byteToHex[arr[offset2 + 0]] + byteToHex[arr[offset2 + 1]] + byteToHex[arr[offset2 + 2]] + byteToHex[arr[offset2 + 3]] + "-" + byteToHex[arr[offset2 + 4]] + byteToHex[arr[offset2 + 5]] + "-" + byteToHex[arr[offset2 + 6]] + byteToHex[arr[offset2 + 7]] + "-" + byteToHex[arr[offset2 + 8]] + byteToHex[arr[offset2 + 9]] + "-" + byteToHex[arr[offset2 + 10]] + byteToHex[arr[offset2 + 11]] + byteToHex[arr[offset2 + 12]] + byteToHex[arr[offset2 + 13]] + byteToHex[arr[offset2 + 14]] + byteToHex[arr[offset2 + 15]]).toLowerCase();
99320
99620
  }
99321
- function processServiceWorker(content, precacheManifest) {
99322
- if (precacheManifest) {
99323
- const manifestJson = generatePrecacheManifest(precacheManifest);
99324
- if (content.includes("self.__WB_MANIFEST")) {
99325
- return content.replace(
99326
- "self.__WB_MANIFEST || []",
99327
- `${manifestJson}`
99328
- );
99329
- } else {
99330
- return content.replace(
99331
- /workbox\.precaching\.precacheAndRoute\(/,
99332
- `self.__WB_MANIFEST = ${manifestJson};
99333
- workbox.precaching.precacheAndRoute(`
99334
- );
99621
+ let getRandomValues;
99622
+ const rnds8 = new Uint8Array(16);
99623
+ function rng() {
99624
+ if (!getRandomValues) {
99625
+ if (typeof crypto === "undefined" || !crypto.getRandomValues) {
99626
+ throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
99335
99627
  }
99628
+ getRandomValues = crypto.getRandomValues.bind(crypto);
99336
99629
  }
99337
- return content;
99338
- }
99339
- function processManifest(content, title, version) {
99340
- const manifest = JSON.parse(content);
99341
- manifest.name = title;
99342
- manifest.short_name = title;
99343
- manifest.description = title;
99344
- manifest.version = version;
99345
- return JSON.stringify(manifest, null, 2);
99630
+ return getRandomValues(rnds8);
99346
99631
  }
99347
- function processHtml(content, title, appJsFilename, appCssFilename) {
99348
- let processed = content.replace(/\$TITLE/g, title);
99349
- if (appJsFilename) {
99350
- processed = processed.replace(/\.\/app\.js/g, `./${appJsFilename}`);
99632
+ const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
99633
+ const native = { randomUUID };
99634
+ function v4(options, buf, offset2) {
99635
+ if (native.randomUUID && true && !options) {
99636
+ return native.randomUUID();
99351
99637
  }
99352
- if (appCssFilename) {
99353
- processed = processed.replace(/href=["']app\.css["']/g, `href="${appCssFilename}"`);
99638
+ options = options || {};
99639
+ const rnds = options.random ?? options.rng?.() ?? rng();
99640
+ if (rnds.length < 16) {
99641
+ throw new Error("Random bytes length must be >= 16");
99354
99642
  }
99355
- return processed;
99643
+ rnds[6] = rnds[6] & 15 | 64;
99644
+ rnds[8] = rnds[8] & 63 | 128;
99645
+ return unsafeStringify(rnds);
99356
99646
  }
99357
- async function bundleApp(entryPointPath, outputDir, gsLibPath, fileSys, resolvePlugin, esbuildInstance, progress, currentStep, totalSteps) {
99358
- const updateProgress = (message) => {
99359
- if (progress) {
99360
- if (currentStep !== void 0) {
99361
- progress(++currentStep.value, message, totalSteps);
99362
- } else {
99363
- progress(0, message, totalSteps);
99364
- }
99365
- }
99366
- };
99367
- updateProgress("Bundling and minifying code...");
99368
- const result = await esbuildInstance.build({
99369
- entryPoints: [entryPointPath],
99370
- bundle: true,
99371
- outdir: outputDir,
99372
- format: "esm",
99373
- minify: true,
99374
- plugins: [resolvePlugin],
99375
- entryNames: "[name]-[hash]",
99376
- // Runtime dependencies (lit, webawesome) are bundled with gs-lib
99377
- external: [],
99378
- // Bundle all dependencies
99379
- packages: "bundle",
99380
- write: false,
99381
- // Don't write to disk, we'll handle it
99382
- metafile: true
99383
- // Generate metafile to get output information
99647
+ function getFeatureStyleData(feature) {
99648
+ const geometry = feature.getGeometry();
99649
+ return ensureUuid({
99650
+ geometry: ensureUuid({
99651
+ type: geometry.getType(),
99652
+ coordinates: []
99653
+ // Not needed for style rules
99654
+ }),
99655
+ state: feature.get(KEY_STATE)
99384
99656
  });
99385
- updateProgress("Saving bundled output...");
99386
- if (!result.outputFiles || result.outputFiles.length === 0) {
99387
- throw new Error("No output files generated by esbuild");
99657
+ }
99658
+ class OpenLayersMapRenderer {
99659
+ constructor(gsMap, env) {
99660
+ this.isDestroyed = false;
99661
+ this.styleCache = /* @__PURE__ */ new Map();
99662
+ this.gsMap = gsMap;
99663
+ this.env = env;
99388
99664
  }
99389
- let mainOutputFile = null;
99390
- let cssOutputFile = null;
99391
- if (result.metafile && result.metafile.outputs) {
99392
- const entryName = "app";
99393
- for (const [outputPath, output] of Object.entries(result.metafile.outputs)) {
99394
- if (output && typeof output === "object" && "entryPoint" in output) {
99395
- if (outputPath.includes(entryName) && outputPath.endsWith(".js")) {
99396
- mainOutputFile = outputPath;
99397
- } else if (outputPath.endsWith(".css")) {
99398
- cssOutputFile = outputPath;
99665
+ async reattached() {
99666
+ }
99667
+ async render(container) {
99668
+ try {
99669
+ this.olMap = await olLib({
99670
+ containerSelector: container,
99671
+ gsMap: this.gsMap,
99672
+ env: this.env,
99673
+ mapOptions: {
99674
+ controls: { zoom: false, attribution: false }
99399
99675
  }
99676
+ });
99677
+ this.operations = new OpenLayersMapOperations(this.olMap, this);
99678
+ this.applyStylesToLayers();
99679
+ this.olMap.once("rendercomplete", () => {
99680
+ this.setupEventListeners();
99681
+ });
99682
+ } catch (error2) {
99683
+ console.error("Failed to render map:", error2);
99684
+ throw error2;
99685
+ }
99686
+ }
99687
+ applyStylesToLayers() {
99688
+ if (!this.olMap) return;
99689
+ const layers = this.olMap.getLayers().getArray();
99690
+ layers.forEach((layer$12) => {
99691
+ if (layer$12 instanceof VectorLayer) {
99692
+ this.applyStyleToVectorLayer(layer$12);
99400
99693
  }
99694
+ });
99695
+ }
99696
+ applyStyleToVectorLayer(layer2) {
99697
+ const layerName = layer2.get(KEY_NAME);
99698
+ const styleFunction = (feature) => {
99699
+ if (!(feature instanceof Feature)) {
99700
+ return void 0;
99701
+ }
99702
+ const featureStyleData = getFeatureStyleData(feature);
99703
+ const styleRules = this.gsMap.styleRules;
99704
+ const stylesMap = this.gsMap.styles;
99705
+ if (styleRules && stylesMap) {
99706
+ const gsStyle = getStyleForFeature(featureStyleData, styleRules, stylesMap, layerName);
99707
+ if (gsStyle && gsStyle.id) {
99708
+ let olStyle = this.styleCache.get(gsStyle.id);
99709
+ if (!olStyle) {
99710
+ olStyle = toOlStyle(gsStyle);
99711
+ this.styleCache.set(gsStyle.id, olStyle);
99712
+ }
99713
+ return olStyle;
99714
+ } else if (gsStyle) {
99715
+ return toOlStyle(gsStyle);
99716
+ }
99717
+ }
99718
+ return void 0;
99719
+ };
99720
+ layer2.setStyle(styleFunction);
99721
+ }
99722
+ clearStyleCache() {
99723
+ this.styleCache.clear();
99724
+ }
99725
+ async modelToUI(updatedGsMap) {
99726
+ if (!this.olMap) {
99727
+ throw new Error("Map not initialized");
99728
+ }
99729
+ if (updatedGsMap) {
99730
+ this.gsMap = updatedGsMap;
99731
+ }
99732
+ this.clearStyleCache();
99733
+ const target = this.olMap.getTarget();
99734
+ if (!target || typeof target === "string") {
99735
+ throw new Error("Map container not found or invalid");
99401
99736
  }
99737
+ this.destroy();
99738
+ target.innerHTML = "";
99739
+ this.isDestroyed = false;
99740
+ await this.render(target);
99402
99741
  }
99403
- const path = await Promise.resolve().then(() => __viteBrowserExternal);
99404
- for (const file of result.outputFiles) {
99405
- let filePath = file.path || "";
99406
- let relativePath;
99407
- let filename;
99408
- if (filePath.startsWith("/") || filePath.length > 2 && filePath[1] === ":") {
99409
- filename = path.basename(filePath);
99410
- relativePath = `${outputDir}/${filename}`;
99411
- } else {
99412
- filename = path.basename(filePath);
99413
- relativePath = filePath.startsWith(outputDir) ? filePath : `${outputDir}/${filePath}`;
99742
+ getOperations() {
99743
+ if (!this.operations) {
99744
+ throw new Error("Operations not available - map not rendered yet");
99414
99745
  }
99415
- await fileSys.writeFile(relativePath, file.contents);
99416
- if (!mainOutputFile && filename.includes("app-") && filename.endsWith(".js")) {
99417
- mainOutputFile = filename;
99746
+ return this.operations;
99747
+ }
99748
+ async getViewExtent() {
99749
+ console.debug("Getting view extent");
99750
+ if (!this.olMap) {
99751
+ throw new Error("Map not available for extent calculation");
99418
99752
  }
99419
- if (!cssOutputFile && filename.includes("app-") && filename.endsWith(".css")) {
99420
- cssOutputFile = filename;
99753
+ const view = this.olMap.getView();
99754
+ const extent2 = view.calculateExtent();
99755
+ console.debug(`View extent: ${extent2}`);
99756
+ return extent2;
99757
+ }
99758
+ async captureScreenshot() {
99759
+ if (!this.olMap) {
99760
+ return { success: false, error: "Map not available" };
99761
+ }
99762
+ const olMap = this.olMap;
99763
+ await new Promise((resolve) => {
99764
+ olMap.renderSync();
99765
+ olMap.once("rendercomplete", () => resolve());
99766
+ setTimeout(() => resolve(), 2e3);
99767
+ });
99768
+ const size2 = olMap.getSize();
99769
+ const width = size2 ? size2[0] : olMap.getViewport().clientWidth;
99770
+ const height = size2 ? size2[1] : olMap.getViewport().clientHeight;
99771
+ try {
99772
+ const canvas = olMap.getViewport().querySelector("canvas");
99773
+ if (!canvas) {
99774
+ return { success: false, error: "Map canvas not found" };
99775
+ }
99776
+ const dataUrl = canvas.toDataURL("image/png");
99777
+ return { success: true, dataUrl, width, height };
99778
+ } catch (error2) {
99779
+ return { success: false, error: `Failed to capture canvas: ${error2.message}` };
99421
99780
  }
99422
99781
  }
99423
- if (!mainOutputFile) {
99424
- throw new Error("Could not find main output file");
99782
+ setOnDirty(callback) {
99783
+ this.onDirtyCallback = callback;
99425
99784
  }
99426
- const extractFilename = (filePath) => {
99427
- const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
99428
- return lastSlash >= 0 ? filePath.substring(lastSlash + 1) : filePath;
99429
- };
99430
- return {
99431
- js: extractFilename(mainOutputFile),
99432
- css: cssOutputFile ? extractFilename(cssOutputFile) : null
99433
- };
99434
- }
99435
- function createFileSystemGsLibCopier(fs2, gsLibPackagePath) {
99436
- const copyFile = async (srcPath, destPath, asText, processor) => {
99437
- const fullSrcPath = `${gsLibPackagePath}/${srcPath}`;
99438
- let content = await fs2.readFile(fullSrcPath);
99439
- if (asText) {
99440
- if (content instanceof Uint8Array) {
99441
- content = new TextDecoder().decode(content);
99442
- } else {
99443
- content = content;
99785
+ setOnSync(callback) {
99786
+ this.onSyncCallback = callback;
99787
+ }
99788
+ triggerDirty() {
99789
+ if (this.isDestroyed || !this.onDirtyCallback) return;
99790
+ this.onDirtyCallback();
99791
+ }
99792
+ triggerSync(event) {
99793
+ if (this.isDestroyed || !this.onSyncCallback) return;
99794
+ this.onSyncCallback(event);
99795
+ }
99796
+ syncViewToModel() {
99797
+ if (!this.olMap) return;
99798
+ const view = this.olMap.getView();
99799
+ const center = view.getCenter();
99800
+ const zoom = view.getZoom();
99801
+ const rotation = view.getRotation();
99802
+ if (center && zoom !== void 0) {
99803
+ this.triggerSync({
99804
+ type: "viewChanged",
99805
+ view: { center, zoom, rotation }
99806
+ });
99807
+ }
99808
+ }
99809
+ syncLayerFeaturesToModel(layerUuid) {
99810
+ if (!this.olMap) return;
99811
+ const layers = this.olMap.getLayers();
99812
+ let olLayer;
99813
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
99814
+ const layer2 = layers.item(i5);
99815
+ if (layer2.get(KEY_UUID) === layerUuid) {
99816
+ olLayer = layer2;
99817
+ break;
99444
99818
  }
99445
- if (processor) {
99446
- content = await processor(content);
99819
+ }
99820
+ if (!olLayer || !(olLayer instanceof VectorLayer)) return;
99821
+ const source2 = olLayer.getSource();
99822
+ if (!source2) return;
99823
+ const olFeatures = source2.getFeatures();
99824
+ const gsFeatures = olFeatures.map((olFeature) => toGsFeature(olFeature));
99825
+ this.triggerSync({
99826
+ type: "featuresChanged",
99827
+ layerUuid,
99828
+ features: gsFeatures
99829
+ });
99830
+ }
99831
+ setupEventListeners() {
99832
+ if (!this.olMap) return;
99833
+ this.olMap.getView().on("change:center", () => {
99834
+ this.syncViewToModel();
99835
+ this.triggerDirty();
99836
+ });
99837
+ this.olMap.getView().on("change:resolution", () => {
99838
+ this.syncViewToModel();
99839
+ this.triggerDirty();
99840
+ });
99841
+ this.olMap.getView().on("change:rotation", () => {
99842
+ this.syncViewToModel();
99843
+ this.triggerDirty();
99844
+ });
99845
+ this.olMap.getLayers().on("add", () => this.triggerDirty());
99846
+ this.olMap.getLayers().on("remove", () => this.triggerDirty());
99847
+ this.olMap.getControls().on("add", () => this.triggerDirty());
99848
+ this.olMap.getControls().on("remove", () => this.triggerDirty());
99849
+ this.olMap.getOverlays().on("add", () => this.triggerDirty());
99850
+ this.olMap.getOverlays().on("remove", () => this.triggerDirty());
99851
+ }
99852
+ destroy() {
99853
+ this.isDestroyed = true;
99854
+ this.clearStyleCache();
99855
+ if (this.operations) {
99856
+ const ops = this.operations;
99857
+ if (ops.cleanup) {
99858
+ ops.cleanup();
99447
99859
  }
99448
99860
  }
99449
- await fs2.writeFile(destPath, content);
99450
- };
99451
- return {
99452
- async copyTextFile(srcPath, destPath, processor) {
99453
- await copyFile(srcPath, destPath, true, processor);
99454
- },
99455
- async copyBinaryFile(srcPath, destPath) {
99456
- await copyFile(srcPath, destPath, false);
99861
+ if (this.olMap) {
99862
+ cleanupEventSubscriptions(this.olMap);
99457
99863
  }
99458
- };
99864
+ this.olMap?.dispose();
99865
+ this.olMap = void 0;
99866
+ }
99459
99867
  }
99460
- async function buildMap(options, fs2, resolvePlugin, esbuildInstance, config = {}, progress) {
99461
- const {
99462
- outputDir = "dist",
99463
- buildDir = "__build",
99464
- gsLibPath = `${buildDir}/gs-lib/index.js`,
99465
- gsLibPackagePath,
99466
- gsLibCopier: providedGsLibCopier,
99467
- cleanBeforeBuild = true,
99468
- cleanAfterBuild = true,
99469
- copyAssets
99470
- } = config;
99471
- const gsLibCopier = providedGsLibCopier || (gsLibPackagePath ? createFileSystemGsLibCopier(fs2, gsLibPackagePath) : null);
99472
- if (!gsLibCopier) {
99473
- throw new Error("Either gsLibCopier or gsLibPackagePath must be provided");
99868
+ class OpenLayersMapOperations {
99869
+ constructor(olMap, renderer) {
99870
+ this.olMap = olMap;
99871
+ this.renderer = renderer;
99872
+ if (!olMap) {
99873
+ throw new Error("OpenLayers map is required for operations");
99874
+ }
99875
+ this.keyDownListener = (event) => {
99876
+ if (event.key === "Escape") {
99877
+ if (this.drawInteraction) {
99878
+ this.disableDrawing();
99879
+ this.renderer?.triggerSync({ type: "drawingDisabled" });
99880
+ }
99881
+ if (this.selectInteraction) {
99882
+ this.disableSelection();
99883
+ }
99884
+ }
99885
+ };
99886
+ const target = this.olMap.getTargetElement();
99887
+ if (target && target instanceof HTMLElement) {
99888
+ target.setAttribute("tabindex", "-1");
99889
+ target.addEventListener("keydown", this.keyDownListener);
99890
+ }
99474
99891
  }
99475
- const buildGsLibPath = gsLibPath;
99476
- let step = config.startingStep ?? 0;
99477
- const totalSteps = config.totalSteps;
99478
- const updateProgress = (message) => {
99479
- if (progress) progress(++step, message, totalSteps);
99480
- };
99481
- if (cleanBeforeBuild) {
99482
- updateProgress("Cleaning build directories...");
99483
- const cleanupPromises = [];
99484
- if (fs2.deleteDir) {
99485
- cleanupPromises.push(
99486
- fs2.deleteDir(buildDir).catch(() => {
99487
- }),
99488
- // Ignore errors if directory doesn't exist
99489
- fs2.deleteDir(outputDir).catch(() => {
99490
- })
99491
- );
99892
+ async setZoom(zoom) {
99893
+ this.olMap.getView().setZoom(zoom);
99894
+ }
99895
+ async setCenter(center) {
99896
+ this.olMap.getView().setCenter(center);
99897
+ }
99898
+ async switchColorMode(mode) {
99899
+ const olMap = this.olMap;
99900
+ let darkMode = olMap.get("darkmode") ?? false;
99901
+ if (mode === "dark") {
99902
+ darkMode = true;
99903
+ } else if (mode === "light") {
99904
+ darkMode = false;
99492
99905
  } else {
99493
- try {
99494
- const nodeFs = await Promise.resolve().then(() => __viteBrowserExternal);
99495
- const path = await Promise.resolve().then(() => __viteBrowserExternal);
99496
- const projectRoot = process.cwd();
99497
- cleanupPromises.push(
99498
- nodeFs.rm(path.resolve(projectRoot, buildDir), { recursive: true, force: true }).catch(() => {
99499
- }),
99500
- nodeFs.rm(path.resolve(projectRoot, outputDir), { recursive: true, force: true }).catch(() => {
99501
- })
99502
- );
99503
- } catch {
99906
+ darkMode = !darkMode;
99907
+ }
99908
+ olMap.set("darkmode", darkMode);
99909
+ const canvasElements = document.querySelectorAll("canvas");
99910
+ canvasElements.forEach((canvas) => {
99911
+ canvas.style.filter = darkMode ? "invert(100%)" : "";
99912
+ });
99913
+ olMap.render();
99914
+ }
99915
+ async addLayer(layer2, isBasemap) {
99916
+ const olLayer = toOlLayer(layer2);
99917
+ if (isBasemap) {
99918
+ this.olMap.getLayers().insertAt(0, olLayer);
99919
+ } else {
99920
+ this.olMap.getLayers().push(olLayer);
99921
+ }
99922
+ }
99923
+ async deleteLayer(uuid) {
99924
+ const layers = this.olMap.getLayers();
99925
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
99926
+ const layer2 = layers.item(i5);
99927
+ if (layer2.get(KEY_UUID) === uuid) {
99928
+ layers.removeAt(i5);
99929
+ return;
99504
99930
  }
99505
99931
  }
99506
- await Promise.all(cleanupPromises);
99507
99932
  }
99508
- updateProgress("Preparing build directories...");
99509
- await Promise.all([
99510
- fs2.ensureDir(`${outputDir}/assets/icons/`),
99511
- fs2.ensureDir(`${buildDir}/gs-lib/`)
99512
- ]);
99513
- updateProgress("Copying gs-lib package...");
99514
- await Promise.all([
99515
- gsLibCopier.copyTextFile("dist/index.js", `${buildDir}/gs-lib/index.js`),
99516
- gsLibCopier.copyTextFile("dist/gs-lib.css", `${buildDir}/gs-lib/gs-lib.css`)
99517
- ]);
99518
- updateProgress("Copying PWA core files...");
99519
- await gsLibCopier.copyTextFile("public/pwa/staticwebapp.config.json", `${outputDir}/staticwebapp.config.json`);
99520
- updateProgress("Creating manifest file...");
99521
- await gsLibCopier.copyTextFile("public/pwa/manifest.json", `${outputDir}/manifest.json`, (content) => processManifest(content, options.title, options.version));
99522
- updateProgress("Copying PWA icons...");
99523
- const iconFiles = [
99524
- "24x24.png",
99525
- "48x48.png",
99526
- "192x192.png",
99527
- "512x512.png",
99528
- "icon_24.png",
99529
- "icon_48.png",
99530
- "icon_192.png",
99531
- "icon_512.png"
99532
- ];
99533
- await Promise.all(iconFiles.map(
99534
- (icon) => gsLibCopier.copyBinaryFile(`public/pwa/assets/icons/${icon}`, `${outputDir}/assets/icons/${icon}`)
99535
- ));
99536
- if (copyAssets) {
99537
- updateProgress("Copying workspace assets...");
99538
- await copyAssets(fs2, outputDir, progress);
99933
+ async renameLayer(uuid, newName) {
99934
+ const layers = this.olMap.getLayers();
99935
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
99936
+ const layer2 = layers.item(i5);
99937
+ if (layer2.get(KEY_UUID) === uuid) {
99938
+ layer2.set(KEY_NAME, newName);
99939
+ return;
99940
+ }
99941
+ }
99539
99942
  }
99540
- updateProgress("Generating application code...");
99541
- const entryPointContent = generateAppJs({
99542
- gsMap: options.gsMap,
99543
- gsLibPath: buildGsLibPath,
99544
- env: { ...options.env, BUILD_TIME: /* @__PURE__ */ new Date() }
99545
- });
99546
- await fs2.writeFile(`${buildDir}/app.js`, entryPointContent);
99547
- const stepRef = { value: step };
99548
- const bundleResult = await bundleApp(`${buildDir}/app.js`, outputDir, buildGsLibPath, fs2, resolvePlugin, esbuildInstance, progress, stepRef, totalSteps);
99549
- step = stepRef.value;
99550
- const appJsFilename = bundleResult.js;
99551
- const appCssFilename = bundleResult.css;
99552
- updateProgress("Generating HTML file...");
99553
- await gsLibCopier.copyTextFile("public/index.html", `${outputDir}/index.html`, (content) => processHtml(content, options.title, appJsFilename, appCssFilename || void 0));
99554
- const precacheManifest = [
99555
- { url: `/${appJsFilename}`, revision: null },
99556
- // Hashed filename handles versioning
99557
- ...appCssFilename ? [{ url: `/${appCssFilename}`, revision: null }] : [],
99558
- // Hashed CSS filename handles versioning
99559
- ...iconFiles.map((icon) => ({ url: `/assets/icons/${icon}`, revision: null }))
99560
- // Workbox will check file content
99561
- ];
99562
- updateProgress("Processing service worker...");
99563
- await gsLibCopier.copyTextFile(
99564
- "public/pwa/sw.js",
99565
- `${outputDir}/sw.js`,
99566
- (content) => processServiceWorker(content, precacheManifest)
99567
- );
99568
- if (cleanAfterBuild) {
99569
- updateProgress("Cleaning up temporary files...");
99570
- if (fs2.deleteDir) {
99571
- await fs2.deleteDir(buildDir);
99943
+ async moveLayer(uuid, targetUuid) {
99944
+ const layers = this.olMap.getLayers();
99945
+ let fromIndex = -1;
99946
+ let toIndex = -1;
99947
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
99948
+ const layer2 = layers.item(i5);
99949
+ if (layer2.get(KEY_UUID) === uuid) {
99950
+ fromIndex = i5;
99951
+ }
99952
+ if (targetUuid && layer2.get(KEY_UUID) === targetUuid) {
99953
+ toIndex = i5;
99954
+ }
99955
+ }
99956
+ if (fromIndex < 0) return;
99957
+ if (targetUuid) {
99958
+ if (toIndex < 0 || fromIndex === toIndex) return;
99572
99959
  } else {
99573
- try {
99574
- const nodeFs = await Promise.resolve().then(() => __viteBrowserExternal);
99575
- const path = await Promise.resolve().then(() => __viteBrowserExternal);
99576
- const fullPath = path.resolve(process.cwd(), buildDir);
99577
- await nodeFs.rm(fullPath, { recursive: true, force: true });
99578
- } catch (error2) {
99960
+ toIndex = fromIndex > 0 ? fromIndex - 1 : fromIndex + 1;
99961
+ }
99962
+ if (toIndex >= 0 && toIndex < layers.getLength() && fromIndex !== toIndex) {
99963
+ const layer2 = layers.item(fromIndex);
99964
+ layers.removeAt(fromIndex);
99965
+ layers.insertAt(toIndex, layer2);
99966
+ }
99967
+ }
99968
+ async setLayerVisible(uuid, visible) {
99969
+ const layers = this.olMap.getLayers();
99970
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
99971
+ const layer2 = layers.item(i5);
99972
+ if (layer2.get(KEY_UUID) === uuid) {
99973
+ layer2.setVisible(visible);
99974
+ return;
99579
99975
  }
99580
99976
  }
99581
99977
  }
99582
- updateProgress("Build completed!");
99978
+ async addControlFromModule(_src) {
99979
+ }
99980
+ async removeControl(_uuid) {
99981
+ }
99982
+ async addOverlayFromModule(_src, _position) {
99983
+ }
99984
+ async removeOverlay(_uuid) {
99985
+ }
99986
+ setCursor(cursor) {
99987
+ const viewport = this.olMap.getViewport();
99988
+ if (viewport) {
99989
+ viewport.style.cursor = cursor;
99990
+ }
99991
+ }
99992
+ async enableDrawing(geometryType, layerUuid) {
99993
+ this.disableSelection();
99994
+ if (this.drawInteraction) {
99995
+ this.olMap.removeInteraction(this.drawInteraction);
99996
+ }
99997
+ this.activeDrawingLayerUuid = layerUuid;
99998
+ this.setCursor("crosshair");
99999
+ const layers = this.olMap.getLayers();
100000
+ let layer$12;
100001
+ for (let i5 = 0; i5 < layers.getLength(); i5++) {
100002
+ const l2 = layers.item(i5);
100003
+ if (l2.get(KEY_UUID) === layerUuid) {
100004
+ layer$12 = l2;
100005
+ break;
100006
+ }
100007
+ }
100008
+ if (!layer$12 || !(layer$12 instanceof VectorLayer)) {
100009
+ throw new Error("Drawing only supported on vector layers");
100010
+ }
100011
+ const source2 = layer$12.getSource();
100012
+ if (!source2) {
100013
+ throw new Error("Layer has no source");
100014
+ }
100015
+ const layerSourceType = layer$12.get("sourceType");
100016
+ if (layerSourceType && layerSourceType !== GsSourceType.Features) {
100017
+ throw new Error("Drawing only supported on layers with in-memory features");
100018
+ }
100019
+ this.drawInteraction = new Draw({
100020
+ source: source2,
100021
+ type: geometryType
100022
+ });
100023
+ const onFeatureAdded = (event) => {
100024
+ const feature = event.feature;
100025
+ if (feature && !feature.get(KEY_UUID)) {
100026
+ const uuid = v4();
100027
+ feature.set(KEY_UUID, uuid);
100028
+ const state = feature.get(KEY_STATE) || {};
100029
+ state.uuid = uuid;
100030
+ feature.set(KEY_STATE, state);
100031
+ }
100032
+ if (this.renderer && this.activeDrawingLayerUuid) {
100033
+ this.renderer.syncLayerFeaturesToModel(this.activeDrawingLayerUuid);
100034
+ }
100035
+ this.renderer?.triggerDirty();
100036
+ };
100037
+ source2.on("addfeature", onFeatureAdded);
100038
+ this.drawInteraction._featureAddedListener = onFeatureAdded;
100039
+ this.drawInteraction._sourceRef = source2;
100040
+ this.olMap.addInteraction(this.drawInteraction);
100041
+ }
100042
+ async disableDrawing() {
100043
+ if (this.drawInteraction) {
100044
+ const listener = this.drawInteraction._featureAddedListener;
100045
+ const source2 = this.drawInteraction._sourceRef;
100046
+ if (listener && source2) {
100047
+ source2.un("addfeature", listener);
100048
+ }
100049
+ this.olMap.removeInteraction(this.drawInteraction);
100050
+ this.drawInteraction = void 0;
100051
+ this.setCursor("");
100052
+ }
100053
+ }
100054
+ cleanup() {
100055
+ if (this.keyDownListener) {
100056
+ const target = this.olMap.getTargetElement();
100057
+ if (target && target instanceof HTMLElement) {
100058
+ target.removeEventListener("keydown", this.keyDownListener);
100059
+ }
100060
+ this.keyDownListener = void 0;
100061
+ }
100062
+ }
100063
+ async enableFeatureSelection() {
100064
+ this.disableDrawing();
100065
+ this.disableSelection();
100066
+ const olLayers = this.olMap.getLayers();
100067
+ const vectorLayers = olLayers.getArray().filter((layer$12) => layer$12 instanceof VectorLayer);
100068
+ if (vectorLayers.length === 0) {
100069
+ throw new Error("No vector layers available for selection");
100070
+ }
100071
+ const gsMap = this.renderer?.gsMap;
100072
+ const selectionStyle = gsMap?.styles?.["selection"];
100073
+ const selectOptions = {
100074
+ condition: click,
100075
+ layers: vectorLayers,
100076
+ hitTolerance: 5,
100077
+ style: selectionStyle ? toOlStyle(selectionStyle) : (_feature) => {
100078
+ const stroke = new Stroke({ color: "rgba(255, 255, 0, 1)", width: 3 });
100079
+ const fill = new Fill({ color: "rgba(255, 255, 0, 0.3)" });
100080
+ return new Style({
100081
+ image: new CircleStyle({ radius: 7, fill, stroke }),
100082
+ stroke,
100083
+ fill
100084
+ });
100085
+ }
100086
+ };
100087
+ this.selectInteraction = new Select(selectOptions);
100088
+ this.selectInteraction.on("select", (event) => {
100089
+ if (event.selected.length > 0) {
100090
+ const selectedFeature = event.selected[0];
100091
+ let featureLayerUuid;
100092
+ olLayers.getArray().forEach((layer$12) => {
100093
+ if (layer$12 instanceof VectorLayer) {
100094
+ const source2 = layer$12.getSource();
100095
+ if (source2 && source2.hasFeature(selectedFeature)) {
100096
+ const uuid = layer$12.get(KEY_UUID);
100097
+ if (uuid) featureLayerUuid = uuid;
100098
+ }
100099
+ }
100100
+ });
100101
+ if (featureLayerUuid && this.renderer) {
100102
+ const gsFeature = toGsFeature(selectedFeature);
100103
+ const geometry = selectedFeature.getGeometry();
100104
+ const metrics = {};
100105
+ if (geometry) {
100106
+ const geometryType = geometry.getType();
100107
+ try {
100108
+ if (geometryType === "LineString" || geometryType === "MultiLineString") {
100109
+ metrics.length = getLength(geometry, { projection: this.olMap.getView().getProjection() });
100110
+ } else if (geometryType === "Polygon" || geometryType === "MultiPolygon") {
100111
+ metrics.area = getArea(geometry, { projection: this.olMap.getView().getProjection() });
100112
+ const coordinates2 = geometryType === "Polygon" ? geometry.getCoordinates()[0] : geometry.getCoordinates()[0][0];
100113
+ if (coordinates2?.length > 0) {
100114
+ const perimeterLine = new LineString(coordinates2);
100115
+ metrics.length = getLength(perimeterLine, { projection: this.olMap.getView().getProjection() });
100116
+ }
100117
+ }
100118
+ } catch (error2) {
100119
+ console.warn("Error calculating feature metrics:", error2);
100120
+ }
100121
+ }
100122
+ this.renderer.triggerSync({
100123
+ type: "featureSelected",
100124
+ layerUuid: featureLayerUuid,
100125
+ feature: gsFeature,
100126
+ metrics
100127
+ });
100128
+ }
100129
+ } else if (event.deselected.length > 0) {
100130
+ this.renderer?.triggerSync({ type: "featureDeselected" });
100131
+ }
100132
+ });
100133
+ this.olMap.addInteraction(this.selectInteraction);
100134
+ this.setCursor("pointer");
100135
+ }
100136
+ async deleteSelectedFeatures() {
100137
+ if (!this.selectInteraction) {
100138
+ throw new Error("No selection interaction active");
100139
+ }
100140
+ const selectedFeatures = this.selectInteraction.getFeatures();
100141
+ if (selectedFeatures.getLength() === 0) {
100142
+ throw new Error("No features selected");
100143
+ }
100144
+ const layersToSync = /* @__PURE__ */ new Set();
100145
+ const olLayers = this.olMap.getLayers();
100146
+ selectedFeatures.forEach((feature) => {
100147
+ for (let i5 = 0; i5 < olLayers.getLength(); i5++) {
100148
+ const layer$12 = olLayers.item(i5);
100149
+ if (layer$12 instanceof VectorLayer) {
100150
+ const source2 = layer$12.getSource();
100151
+ if (source2 && source2.hasFeature(feature)) {
100152
+ source2.removeFeature(feature);
100153
+ const layerUuid = layer$12.get(KEY_UUID);
100154
+ if (layerUuid) layersToSync.add(layerUuid);
100155
+ break;
100156
+ }
100157
+ }
100158
+ }
100159
+ });
100160
+ selectedFeatures.clear();
100161
+ if (this.renderer && layersToSync.size > 0) {
100162
+ layersToSync.forEach((layerUuid) => {
100163
+ this.renderer.syncLayerFeaturesToModel(layerUuid);
100164
+ });
100165
+ }
100166
+ this.renderer?.triggerDirty();
100167
+ }
100168
+ async disableSelection() {
100169
+ if (this.selectInteraction) {
100170
+ this.olMap.removeInteraction(this.selectInteraction);
100171
+ this.selectInteraction = void 0;
100172
+ this.setCursor("");
100173
+ this.renderer?.triggerSync({ type: "featureDeselected" });
100174
+ }
100175
+ }
99583
100176
  }
99584
100177
  const rtUtils = {
99585
100178
  async resolveUrl(url) {
@@ -105600,6 +106193,7 @@ export {
105600
106193
  OL_SOURCES,
105601
106194
  BaseObject as Object,
105602
106195
  Observable,
106196
+ OpenLayersMapRenderer,
105603
106197
  Overlay,
105604
106198
  Tile,
105605
106199
  TileQueue,
@@ -105612,6 +106206,7 @@ export {
105612
106206
  buildMap,
105613
106207
  bundleApp,
105614
106208
  cleanupEventSubscriptions,
106209
+ createProxy,
105615
106210
  defaults$1 as defaultControls,
105616
106211
  defaults as defaultInteractions,
105617
106212
  ensureUuid,
@@ -105620,16 +106215,23 @@ export {
105620
106215
  events,
105621
106216
  condition as eventsCondition,
105622
106217
  extent,
106218
+ findControlByUuid,
106219
+ findControlIndexByUuid,
106220
+ findLayerByUuid,
106221
+ findLayerIndexByUuid,
106222
+ findOverlayByUuid,
106223
+ findOverlayIndexByUuid,
105623
106224
  format,
105624
106225
  generateAppJs,
105625
106226
  olGeom as geom,
105626
106227
  getStyleForFeature,
105627
106228
  getUid,
105628
- gsLib,
106229
+ olLib as gsLib,
105629
106230
  importControlSource,
105630
106231
  importOverlaySource,
105631
106232
  interaction,
105632
106233
  layer,
106234
+ olLib,
105633
106235
  processHtml,
105634
106236
  processManifest,
105635
106237
  processServiceWorker,