@abi-software/flatmapvuer 1.14.0 → 1.15.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.
@@ -0,0 +1,23 @@
1
+ import js from "@eslint/js";
2
+ import vue from "eslint-plugin-vue";
3
+ import globals from "globals";
4
+
5
+ export default [
6
+ {
7
+ ignores: ["dist/**", "docs/.vitepress/**", "docs/components/**"],
8
+ },
9
+ js.configs.recommended,
10
+ ...vue.configs["flat/essential"],
11
+ {
12
+ files: ["**/*.{js,vue}"],
13
+ languageOptions: {
14
+ ecmaVersion: "latest",
15
+ sourceType: "module",
16
+ globals: {
17
+ ...globals.node,
18
+ ...globals.browser,
19
+ },
20
+ },
21
+ rules: {},
22
+ },
23
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/flatmapvuer",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "license": "Apache-2.0",
5
5
  "engines": {
6
6
  "node": ">=20"
@@ -20,6 +20,7 @@
20
20
  "serve": "vite --host --force",
21
21
  "build-bundle": "vite build",
22
22
  "build-static": "vite build -c vite.static-build.js",
23
+ "lint": "eslint .",
23
24
  "cypress:open": "cypress open",
24
25
  "cypress:component": "cypress run --component",
25
26
  "cypress:record": "cypress run --component --record",
@@ -47,56 +48,44 @@
47
48
  "./src/*": "./src/*"
48
49
  },
49
50
  "dependencies": {
50
- "@abi-software/map-utilities": "1.9.0",
51
+ "@abi-software/map-utilities": "1.10.0",
51
52
  "@abi-software/sparc-annotation": "0.3.2",
52
- "@abi-software/svg-sprite": "1.1.0",
53
- "@element-plus/icons-vue": "^2.3.1",
54
- "css-element-queries": "^1.2.2",
55
- "element-plus": "2.8.4",
53
+ "@abi-software/svg-sprite": "1.2.0",
54
+ "@element-plus/icons-vue": "^2.3.2",
55
+ "css-element-queries": "^1.2.3",
56
+ "element-plus": "^2.14.5",
56
57
  "mitt": "^3.0.1",
57
- "pinia": "^2.1.7",
58
- "unplugin-vue-components": "^0.26.0",
59
- "vue": "^3.4.21"
58
+ "pinia": "^4.0.3",
59
+ "vue": "^3.5.41"
60
60
  },
61
61
  "devDependencies": {
62
- "@vitejs/plugin-vue": "^4.6.2",
62
+ "@eslint/js": "^10.0.1",
63
+ "@vitejs/plugin-vue": "^6.0.8",
64
+ "unplugin-vue-components": "^32.1.0",
63
65
  "@vuese/markdown-render": "^2.11.3",
64
- "auto-changelog": "^2.4.0",
65
- "babel-eslint": "^10.1.0",
66
- "chokidar": "^3.6.0",
67
- "concurrently": "^8.2.2",
68
- "cypress": "^13.6.6",
69
- "cypress-multi-reporters": "^1.6.4",
70
- "cypress-visual-regression": "^5.3.0",
71
- "cypress-wait-until": "^2.0.1",
72
- "eslint": "^8.56.0",
73
- "eslint-plugin-cypress": "^2.15.1",
74
- "eslint-plugin-vue": "^9.19.2",
75
- "mochawesome": "^7.1.3",
76
- "sass": "^1.69.5",
77
- "vite": "^5.0.10",
78
- "vitepress": "^1.0.0-rc.44",
66
+ "auto-changelog": "^2.6.0",
67
+ "chokidar": "^5.0.0",
68
+ "concurrently": "^9.2.4",
69
+ "cypress": "^15.21.0",
70
+ "cypress-multi-reporters": "^2.0.5",
71
+ "cypress-visual-regression": "^6.0.0",
72
+ "cypress-wait-until": "^3.0.2",
73
+ "eslint": "^10.9.1",
74
+ "eslint-plugin-cypress": "^7.0.0",
75
+ "eslint-plugin-vue": "^10.10.0",
76
+ "globals": "^17.11.0",
77
+ "mochawesome": "^8.0.1",
78
+ "sass": "^1.103.1",
79
+ "vite": "^8.2.1",
80
+ "vitepress": "^1.6.4",
79
81
  "vue-docgen-api": "^4.79.2"
80
82
  },
81
83
  "optionalDependencies": {
82
- "@esbuild/linux-x64": "0.25.3",
83
- "@rollup/rollup-darwin-arm64": "4.59.0",
84
- "@rollup/rollup-linux-x64-gnu": "4.59.0",
85
- "@rollup/rollup-win32-x64-msvc": "4.59.0"
86
- },
87
- "eslintConfig": {
88
- "root": true,
89
- "env": {
90
- "node": true
91
- },
92
- "extends": [
93
- "plugin:vue/essential",
94
- "eslint:recommended"
95
- ],
96
- "rules": {},
97
- "parserOptions": {
98
- "parser": "babel-eslint"
99
- }
84
+ "@esbuild/darwin-arm64": "0.28.2",
85
+ "@esbuild/linux-x64": "0.28.2",
86
+ "@rollup/rollup-darwin-arm64": "4.63.0",
87
+ "@rollup/rollup-linux-x64-gnu": "4.63.0",
88
+ "@rollup/rollup-win32-x64-msvc": "4.63.0"
100
89
  },
101
90
  "browserslist": [
102
91
  "> 1%",
@@ -1,4 +1,5 @@
1
- @import '_variables';
1
+ @use '_variables' as *;
2
+ @forward '_variables';
2
3
 
3
4
  @import url('https://fonts.googleapis.com/css?family=Asap:400,400i,500,600,700&display=swap');
4
5
 
@@ -1737,6 +1737,9 @@ export default {
1737
1737
  provenanceTaxonomy: taxons,
1738
1738
  alert: featuresAlert
1739
1739
  }]
1740
+ if (eventType === 'mouseenter') {
1741
+ this.lastHoveredFeature = data;
1742
+ }
1740
1743
  if (eventType === 'click') {
1741
1744
  // If multiple paths overlap at the click location,
1742
1745
  // `data` is an object with numeric keys for each feature (e.g., {0: {...}, 1: {...}, ..., mapUUID: '...'}).
@@ -1856,6 +1859,7 @@ export default {
1856
1859
  // Fallback: remove any existing toolitp on DOM
1857
1860
  const tooltips = this.$el.querySelectorAll('.flatmap-tooltip-popup');
1858
1861
  tooltips.forEach((tooltip) => tooltip.remove());
1862
+ this.lastHoveredFeature = null;
1859
1863
  },
1860
1864
  /**
1861
1865
  * Function to create tooltip for the provided connectivity data.
@@ -1899,6 +1903,9 @@ export default {
1899
1903
  const connectivityData = [];
1900
1904
  const errorData = [];
1901
1905
 
1906
+ // Remove last hovered feature to avoid showing tooltip for the last hovered feature.
1907
+ this.lastHoveredFeature = null;
1908
+
1902
1909
  // to keep the highlighted path on map
1903
1910
  if (connectivityInfo && connectivityInfo.featureId) {
1904
1911
  featuresToHighlight.push(...connectivityInfo.featureId);
@@ -2302,6 +2309,7 @@ export default {
2302
2309
  document.querySelectorAll('.maplibregl-popup').forEach((item) => {
2303
2310
  item.style.display = 'none'
2304
2311
  })
2312
+ this.lastHoveredFeature = null;
2305
2313
  },
2306
2314
  /**
2307
2315
  * @public
@@ -3106,10 +3114,22 @@ export default {
3106
3114
  provenanceTaxonomy: feature.taxons,
3107
3115
  alert: normaliseAlertToStringArray(feature.alert),
3108
3116
  }
3117
+
3109
3118
  // Show popup for all modes
3110
3119
  this.checkAndCreatePopups([data], mapclick)
3120
+
3121
+ // Check pathway fetures and set lastHoveredFeature for tooltip content replacement.
3122
+ const isPathwayFeature = (feature.id.startsWith('ilxtr:') || feature.id.startsWith('ilx:'));
3123
+ if (isPathwayFeature) {
3124
+ this.lastHoveredFeature = feature;
3125
+ this.lastHoveredFeature.mapUUID = this.mapImp.uuid;
3126
+ } else {
3127
+ this.lastHoveredFeature = null;
3128
+ }
3129
+
3130
+ // flatmap-tooltip-popup is used for custom tooltip content replacement.
3111
3131
  this.mapImp.showPopup(featureId, capitalise(feature.label), {
3112
- className: 'custom-popup',
3132
+ className: isPathwayFeature ? 'flatmap-tooltip-popup' : 'custom-popup',
3113
3133
  positionAtLastClick: false,
3114
3134
  preserveSelection: true,
3115
3135
  })
@@ -3153,6 +3173,62 @@ export default {
3153
3173
  setConnectionType: function (type) {
3154
3174
  this.connectionType = type;
3155
3175
  },
3176
+ /**
3177
+ * MutationObserver callback to intercept tooltip popup DOM elements
3178
+ * and customize their content before the browser renders them.
3179
+ */
3180
+ _handleTooltipMutation: function (mutations) {
3181
+ for (const mutation of mutations) {
3182
+ for (const node of mutation.addedNodes) {
3183
+ if (node.nodeType === 1) {
3184
+ // Check if the added node itself is the tooltip popup
3185
+ if (node.matches && node.matches('.flatmap-tooltip-popup')) {
3186
+ this._applyCustomTooltipContent(node);
3187
+ } else if (node.querySelector) {
3188
+ // Check if it contains a tooltip popup
3189
+ const popup = node.querySelector('.flatmap-tooltip-popup');
3190
+ if (popup) {
3191
+ this._applyCustomTooltipContent(popup);
3192
+ }
3193
+ }
3194
+ }
3195
+ }
3196
+ }
3197
+ },
3198
+ /**
3199
+ * Replace the default tooltip content with custom content from
3200
+ * the tooltipContentProvider prop, if available.
3201
+ */
3202
+ _applyCustomTooltipContent: function (popupEl) {
3203
+ if (!this.tooltipContentProvider || !this.lastHoveredFeature) return;
3204
+ try {
3205
+ const featureData = this.lastHoveredFeature;
3206
+ // Detect multi-feature data format used by click events when multiple
3207
+ // paths overlap: {0: {...}, 1: {...}, ..., mapUUID: '...'}
3208
+ const isMultiFeature = featureData[0] && typeof featureData[0] === 'object';
3209
+ let customHtml;
3210
+ if (isMultiFeature) {
3211
+ const features = [];
3212
+ const mapUUID = featureData.mapUUID;
3213
+ for (const [key, value] of Object.entries(featureData)) {
3214
+ if (key !== 'mapUUID' && value && typeof value === 'object') {
3215
+ features.push({ ...value, mapUUID });
3216
+ }
3217
+ }
3218
+ customHtml = this.tooltipContentProvider(features.length > 1 ? features : features[0]);
3219
+ } else {
3220
+ customHtml = this.tooltipContentProvider(featureData);
3221
+ }
3222
+ if (customHtml) {
3223
+ const contentEl = popupEl.querySelector('.maplibregl-popup-content');
3224
+ if (contentEl) {
3225
+ contentEl.innerHTML = customHtml;
3226
+ }
3227
+ }
3228
+ } catch (e) {
3229
+ console.warn('[flatmapvuer] Error in tooltipContentProvider:', e);
3230
+ }
3231
+ },
3156
3232
  },
3157
3233
  props: {
3158
3234
  /**
@@ -3393,6 +3469,17 @@ export default {
3393
3469
  return []
3394
3470
  },
3395
3471
  },
3472
+ /**
3473
+ * A function that provides custom tooltip HTML content for path features.
3474
+ * The function receives the feature data from the mouseenter event (including `id`, `label`, etc.)
3475
+ * and should return an HTML string to display in the tooltip, or return null/undefined
3476
+ * to keep the default tooltip.
3477
+ * This is used by mapintegratedvuer to show 'long-label' from connectivity knowledge.
3478
+ */
3479
+ tooltipContentProvider: {
3480
+ type: Function,
3481
+ default: null,
3482
+ },
3396
3483
  },
3397
3484
  provide() {
3398
3485
  return {
@@ -3495,6 +3582,8 @@ export default {
3495
3582
  drawnCreatedEvent: {},
3496
3583
  previousEditEvent: {},
3497
3584
  previousDeletedEvent: {},
3585
+ lastHoveredFeature: null,
3586
+ tooltipObserver: null,
3498
3587
  connectionEntry: {},
3499
3588
  existDrawnFeatures: [], // Store all exist drawn features
3500
3589
  doubleClickedFeature: false,
@@ -3693,6 +3782,27 @@ export default {
3693
3782
  this.createFlatmap()
3694
3783
  }
3695
3784
  refreshFlatmapKnowledgeCache();
3785
+
3786
+ // Set up MutationObserver to customize tooltip content when
3787
+ // tooltipContentProvider prop is provided.
3788
+ if (this.tooltipContentProvider) {
3789
+ this.$nextTick(() => {
3790
+ const container = this.$refs.flatmapContainer || this.$el;
3791
+ if (container) {
3792
+ this.tooltipObserver = new MutationObserver(this._handleTooltipMutation.bind(this));
3793
+ this.tooltipObserver.observe(container, {
3794
+ childList: true,
3795
+ subtree: true,
3796
+ });
3797
+ }
3798
+ });
3799
+ }
3800
+ },
3801
+ beforeUnmount: function () {
3802
+ if (this.tooltipObserver) {
3803
+ this.tooltipObserver.disconnect();
3804
+ this.tooltipObserver = null;
3805
+ }
3696
3806
  },
3697
3807
  }
3698
3808
  </script>
@@ -3855,6 +3965,9 @@ export default {
3855
3965
 
3856
3966
  :deep(.flatmap-tooltip-popup),
3857
3967
  :deep(.custom-popup) {
3968
+ font-family: Asap, sans-serif !important;
3969
+ font-size: 14px !important;
3970
+
3858
3971
  &.maplibregl-popup-anchor-bottom {
3859
3972
  .maplibregl-popup-content {
3860
3973
  margin-bottom: 12px;
@@ -4449,4 +4562,23 @@ export default {
4449
4562
  }
4450
4563
  }
4451
4564
 
4565
+ .flatmap-feature-label {
4566
+ padding: 6px !important;
4567
+ font-family: Asap, sans-serif !important;
4568
+ font-size: 14px !important;
4569
+
4570
+ // provided by tooltipContentProvider from mapintegratedvuer
4571
+ &.flatmap-connectivity-label {
4572
+ text-align: left !important;
4573
+ }
4574
+ }
4575
+
4576
+ .id-tag {
4577
+ color: #444;
4578
+ background: #e0e0e0;
4579
+ padding: 2px 4px;
4580
+ border-radius: 4px;
4581
+ font-size: .75rem !important;
4582
+ letter-spacing: 1.05px;
4583
+ }
4452
4584
  </style>
@@ -94,6 +94,7 @@
94
94
  :showOpenMapButton="showOpenMapButton"
95
95
  :showPathwayFilter="showPathwayFilter"
96
96
  :externalLegends="externalLegends"
97
+ :tooltipContentProvider="tooltipContentProvider"
97
98
  />
98
99
 
99
100
  <!-- multiflatmap-error -->
@@ -893,6 +894,14 @@ export default {
893
894
  return []
894
895
  },
895
896
  },
897
+ /**
898
+ * A function that provides custom tooltip HTML content for path features.
899
+ * Passed through to each FlatmapVuer instance.
900
+ */
901
+ tooltipContentProvider: {
902
+ type: Function,
903
+ default: null,
904
+ },
896
905
  },
897
906
  data: function () {
898
907
  return {
@@ -1,10 +1,14 @@
1
1
  /* eslint-disable */
2
- /* prettier-ignore */
3
2
  // @ts-nocheck
3
+ // biome-ignore lint: disable
4
+ // oxlint-disable
5
+ // ------
4
6
  // Generated by unplugin-vue-components
5
7
  // Read more: https://github.com/vuejs/core/pull/3399
8
+
6
9
  export {}
7
10
 
11
+ /* prettier-ignore */
8
12
  declare module 'vue' {
9
13
  export interface GlobalComponents {
10
14
  DynamicLegends: typeof import('./components/legends/DynamicLegends.vue')['default']
@@ -31,7 +35,7 @@ declare module 'vue' {
31
35
  SelectionsGroup: typeof import('./components/SelectionsGroup.vue')['default']
32
36
  SvgLegends: typeof import('./components/legends/SvgLegends.vue')['default']
33
37
  }
34
- export interface ComponentCustomProperties {
38
+ export interface GlobalDirectives {
35
39
  vLoading: typeof import('element-plus/es')['ElLoadingDirective']
36
40
  vPopover: typeof import('element-plus/es')['ElPopoverDirective']
37
41
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * a single source for the flatmap-viewer library import
3
3
  */
4
- import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.4.3/+esm';
4
+ import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.4.5/+esm';
5
5
 
6
6
  export default flatmap;
package/vite.config.js CHANGED
@@ -10,7 +10,8 @@ export default defineConfig(({ command, mode }) => {
10
10
  css: {
11
11
  preprocessorOptions: {
12
12
  scss: {
13
- additionalData: `@use './src/assets/styles' as *;`
13
+ api: 'modern-compiler',
14
+ additionalData: `@use '@/assets/styles' as *;`,
14
15
  },
15
16
  },
16
17
  },
@@ -61,6 +62,11 @@ export default defineConfig(({ command, mode }) => {
61
62
  "@element-plus/icons-vue": "@element-plus/icons-vue",
62
63
  "pinia": "pinia"
63
64
  },
65
+ // keep css output name stable for the "./dist/style.css" export/import paths
66
+ assetFileNames: (assetInfo) =>
67
+ assetInfo.name?.endsWith(".css")
68
+ ? "style.css"
69
+ : "assets/[name][extname]",
64
70
  },
65
71
  },
66
72
  },
package/babel.config.js DELETED
File without changes