@abi-software/mapintegratedvuer 1.22.0 → 1.24.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 (39) hide show
  1. package/dist/{ConnectivityGraph-BBZ3Dgat.js → ConnectivityGraph-CCxk8vcE.js} +6 -6
  2. package/dist/{ContentMixin-B-O_IwPg.js → ContentMixin-Db8nqZax.js} +303 -247
  3. package/dist/{DynamicMarkerMixin-B9iqtP_f.js → DynamicMarkerMixin-LB2RYdSY.js} +1 -1
  4. package/dist/{Flatmap-BoEFI50b.js → Flatmap-CqUzOkdl.js} +5 -5
  5. package/dist/{Iframe-Slj-LQTF.js → Iframe-I-xdZ2FP.js} +2 -2
  6. package/dist/{MultiFlatmap-l6aBn6x3.js → MultiFlatmap-11L97ycJ.js} +6 -6
  7. package/dist/{Plot-CIhEip5b.js → Plot-Bd9RqyVD.js} +2 -2
  8. package/dist/{Scaffold-D5ZGCDvt.js → Scaffold-CySWXQxI.js} +46 -36
  9. package/dist/Simulation-ChUbGudZ.js +32 -0
  10. package/dist/{connectivities-Br3MpoAv.js → connectivities-LtlFwLOp.js} +6399 -5790
  11. package/dist/es-D-YkSGXX.js +436 -0
  12. package/dist/mapintegratedvuer.js +13061 -11664
  13. package/dist/mapintegratedvuer.umd.cjs +191 -190
  14. package/dist/style.css +1 -1
  15. package/package.json +7 -7
  16. package/src/assets/header-icon.scss +9 -3
  17. package/src/components/ContentBar.vue +172 -92
  18. package/src/components/ContentVuer.vue +41 -1
  19. package/src/components/ContextCard.vue +15 -3
  20. package/src/components/DatasetHeader.vue +4 -1
  21. package/src/components/DialogToolbarContent.vue +45 -4
  22. package/src/components/EventBus.js +8 -0
  23. package/src/components/MapContent.vue +85 -31
  24. package/src/components/ResizeSensor.vue +7 -9
  25. package/src/components/ScreenshotPopover.vue +526 -0
  26. package/src/components/SplitDialog.vue +94 -93
  27. package/src/components/SplitFlow.vue +158 -96
  28. package/src/components/scripts/utilities.js +56 -1
  29. package/src/components/viewers/Flatmap.vue +1 -0
  30. package/src/components/viewers/MultiFlatmap.vue +3 -0
  31. package/src/components/viewers/Scaffold.vue +25 -13
  32. package/src/components/viewers/Simulation.vue +23 -1
  33. package/src/components.d.ts +2 -0
  34. package/src/mixins/ContentMixin.js +23 -10
  35. package/src/services/screenshot.js +1186 -0
  36. package/src/stores/connectivities.js +38 -5
  37. package/src/stores/settings.js +18 -0
  38. package/vite.config.js +27 -4
  39. package/dist/Simulation-C5o5DXRb.js +0 -25
@@ -1,3 +1,11 @@
1
1
  import mitt from 'mitt';
2
2
  const EventBus = new mitt();
3
+
4
+ // Subscribe a map of { eventName: handler } and return a function that
5
+ // unsubscribes them all.
6
+ export const onEvents = (handlers) => {
7
+ Object.entries(handlers).forEach(([name, fn]) => EventBus.on(name, fn));
8
+ return () => Object.entries(handlers).forEach(([name, fn]) => EventBus.off(name, fn));
9
+ };
10
+
3
11
  export default EventBus;
@@ -22,7 +22,7 @@
22
22
  import { computed } from 'vue';
23
23
  import Tagging from '../services/tagging.js';
24
24
  import SplitFlow from './SplitFlow.vue';
25
- import EventBus from './EventBus';
25
+ import { onEvents } from './EventBus';
26
26
  import { mapStores } from 'pinia';
27
27
  import { useSettingsStore } from '../stores/settings';
28
28
  import { useSplitFlowStore } from '../stores/splitFlow';
@@ -33,6 +33,24 @@ import RetrieveContextCardMixin from '../mixins/RetrieveContextCardMixin.js';
33
33
 
34
34
  /**
35
35
  * Content of the app. More work flows will be added here.
36
+ *
37
+ * ## Screenshots
38
+ *
39
+ * Each viewer pane has a camera button in its header that downloads a screenshot of that pane.
40
+ * The camera button in the top toolbar downloads all visible panes together, including the sidebar if it is open.
41
+ * Screenshots are saved as PNG. Pick the resolution (1x to 4x the device pixel ratio) before downloading; higher resolutions suit printing.
42
+ * On-screen controls such as zoom buttons and settings panels are left out of the image.
43
+ * Very large outputs are reduced automatically to stay within browser canvas limits.
44
+ *
45
+ * Default screenshot settings can be set with `options.screenshot`,
46
+ * and screenshots can be triggered programmatically with the `captureScreenshot` method:
47
+ *
48
+ * ```js
49
+ * // All visible panes
50
+ * this.$refs.map.captureScreenshot({ scale: 3 });
51
+ * // A single pane, by entry id
52
+ * this.$refs.map.captureScreenshot({ paneId: 1, scale: 2 });
53
+ * ```
36
54
  */
37
55
  export default {
38
56
  name: 'MapContent',
@@ -70,6 +88,8 @@ export default {
70
88
  },
71
89
  /**
72
90
  * The options include APIs and Keys.
91
+ * `options.screenshot` sets the screenshot defaults,
92
+ * e.g. `{ scale: 2, legend: 'include', toolbar: true }`.
73
93
  */
74
94
  options: {
75
95
  type: Object,
@@ -142,9 +162,17 @@ export default {
142
162
  type: Boolean,
143
163
  default: true,
144
164
  },
165
+ /**
166
+ * The `crossorigin` attribute value used for images.
167
+ */
168
+ crossorigin: {
169
+ type: String,
170
+ default: 'anonymous',
171
+ },
145
172
  },
146
173
  provide: function () {
147
174
  return {
175
+ crossorigin: computed(() => this.crossorigin),
148
176
  showGlobalSettings: this.showGlobalSettings,
149
177
  showOpenMapButton: this.showOpenMapButton,
150
178
  truncateLongLabel: computed(() => this.truncateLongLabel),
@@ -268,6 +296,20 @@ export default {
268
296
  getState: function (anonymousAnnotations = false) {
269
297
  return this.$refs.flow.getState(anonymousAnnotations);
270
298
  },
299
+ /**
300
+ * @public
301
+ * Capture a screenshot and download it as PNG.
302
+ * Captures the pane with `paneId` (entry id) if provided,
303
+ * otherwise all visible panes including the sidebar.
304
+ * `legend` is `exclude` (default), `include` or `only`,
305
+ * the latter downloads only the legend panel of each pane.
306
+ * `toolbar` includes the header bar of each pane (default `false`).
307
+ * The default `scale`, `legend` and `toolbar` come from `options.screenshot`.
308
+ * @arg `options` { paneId, scale: Number, legend: String, toolbar: Boolean }
309
+ */
310
+ captureScreenshot: function (options = {}) {
311
+ return this.$refs.flow.captureScreenshot(options);
312
+ },
271
313
  /**
272
314
  * @public
273
315
  * Provide a way to set the current view, this is currently limited
@@ -446,51 +488,63 @@ export default {
446
488
  : null;
447
489
  this.options.flatmapAPI ? this.settingsStore.updateFlatmapAPI(this.options.flatmapAPI) : null;
448
490
  this.options.rootUrl ? this.settingsStore.updateRootUrl(this.options.rootUrl) : null;
491
+ this.options.screenshot
492
+ ? this.settingsStore.updateScreenshotOptions(this.options.screenshot)
493
+ : null;
449
494
  }
450
495
  this.settingsStore.updateAllClosable(this.allClosable);
451
496
  this.splitFlowStore?.reset();
452
497
  this.splitFlowStore?.getAvailableTerms(this.settingsStore.sparcApi);
453
498
  },
454
499
  mounted: async function () {
455
- EventBus.on('updateShareLinkRequested', (data) => {
456
- /**
457
- * This event emits when the share link is requested.
458
- */
459
- this.$emit('updateShareLinkRequested', data);
460
- });
461
- EventBus.on('trackEvent', (taggingData) => {
462
- /**
463
- * This event triggers data tracking for Google Tag Manager (GTM) related to map interactions.
464
- */
465
- this.$emit('trackEvent', taggingData);
500
+ this._offBus = onEvents({
501
+ updateShareLinkRequested: (data) => {
502
+ /**
503
+ * This event emits when the share link is requested.
504
+ */
505
+ this.$emit('updateShareLinkRequested', data);
506
+ },
507
+ trackEvent: (taggingData) => {
508
+ /**
509
+ * This event triggers data tracking for Google Tag Manager (GTM) related to map interactions.
510
+ */
511
+ this.$emit('trackEvent', taggingData);
512
+ },
513
+ mapLoaded: (map) => {
514
+ // Check if there is a search term to display
515
+ if (this.displaySearchFromQuery) {
516
+ setTimeout(() => {
517
+ this.$refs.flow?.onDisplaySearch({ term: this.displaySearchFromQuery });
518
+ this.displaySearchFromQuery = ''; // Clear after using it from first load
519
+ });
520
+ }
521
+ /**
522
+ * This event emit when the map is loaded.
523
+ */
524
+ this.$emit('mapLoaded', map);
525
+ },
526
+ // Allow other components to request opening a map via setCurrentEntry
527
+ SetCurrentEntry: (entry) => {
528
+ // Ignore requests until the flow is ready, as before
529
+ if (entry && this.isReady) {
530
+ this.setCurrentEntry(entry);
531
+ }
532
+ },
466
533
  });
467
534
  if (!this.state) {
468
535
  this.initialState = await initialState(this.startingMap, this.options.sparcApi);
536
+ // The component may have been unmounted while awaiting
537
+ if (this._unmounted) return;
469
538
  }
470
- EventBus.on('mapLoaded', (map) => {
471
- // Check if there is a search term to display
472
- if (this.displaySearchFromQuery) {
473
- setTimeout(() => {
474
- this.$refs.flow.onDisplaySearch({ term: this.displaySearchFromQuery });
475
- this.displaySearchFromQuery = ''; // Clear after using it from first load
476
- });
477
- }
478
- /**
479
- * This event emit when the map is loaded.
480
- */
481
- this.$emit('mapLoaded', map);
482
- });
483
- // Allow other components to request opening a map via setCurrentEntry
484
- EventBus.on('SetCurrentEntry', (entry) => {
485
- if (entry) {
486
- this.setCurrentEntry(entry);
487
- }
488
- });
489
539
  this.isReady = true;
490
540
  this.settingsStore.updateUseHelpModeDialog(this.useHelpModeDialog);
491
541
  this.settingsStore.updateConnectivityInfoSidebar(this.connectivityInfoSidebar);
492
542
  this.settingsStore.updateAnnotationSidebar(this.annotationSidebar);
493
543
  },
544
+ beforeUnmount: function () {
545
+ this._unmounted = true;
546
+ this._offBus?.();
547
+ },
494
548
  };
495
549
  </script>
496
550
 
@@ -3,22 +3,20 @@
3
3
  </template>
4
4
 
5
5
  <script>
6
- import ResizeSensor from 'css-element-queries/src/ResizeSensor';
7
-
8
6
  export default {
9
7
  name: 'ResizeSensor',
10
8
  methods: {
11
9
  activate: function () {
12
- if (!this._sensor) {
13
- this._sensor = new ResizeSensor(this.$refs.display, this.displayResize);
10
+ if (!this._observer && this.$refs.display) {
11
+ this._observer = new ResizeObserver(() => this.displayResize());
12
+ this._observer.observe(this.$refs.display);
14
13
  this.displayResize();
15
14
  }
16
15
  },
17
16
  deactivate: function () {
18
- if (this._sensor) {
19
- this._sensor.detach(this.$refs.display, this.displayResize);
20
- delete this._sensor;
21
- this._sensor = undefined;
17
+ if (this._observer) {
18
+ this._observer.disconnect();
19
+ this._observer = undefined;
22
20
  this.displayResize();
23
21
  }
24
22
  },
@@ -26,7 +24,7 @@ export default {
26
24
  this.$emit('resize');
27
25
  },
28
26
  },
29
- unmounted() {
27
+ beforeUnmount() {
30
28
  this.deactivate();
31
29
  },
32
30
  activated() {