diff --git a/demo/js/planning.js b/demo/js/planning.js index b58c3373..6dec37a9 100755 --- a/demo/js/planning.js +++ b/demo/js/planning.js @@ -57,8 +57,8 @@ const interactiveMap = new InteractiveMap('map', { // minDesktopWidth: 960, mapLabel: 'Ambleside', // zoom: 14, - minZoom: 2, - maxZoom: 15, + minZoom: 6, + maxZoom: 20, autoColorScheme: true, // center: [337672, 504580], extent: [337047, 503795, 338120, 505281], @@ -69,7 +69,11 @@ const interactiveMap = new InteractiveMap('map', { hasExitButton: true, plugins: [ mapStylesPlugin({ - mapStyles: vtsMapStyles27700 + mapStyles: vtsMapStyles27700, + manifest: { + buttons: [{ id: 'mapStyles', desktop: { slot: 'right-top', showLabel: false }}], + panels: [{ id: 'mapStyles', desktop: { slot: 'map-styles-button', width: '400px', modal: false }}] + } }), scaleBarPlugin({ units: 'metric' @@ -92,6 +96,14 @@ const interactiveMap = new InteractiveMap('map', { }) interactiveMap.on('app:ready', function (e) { + interactiveMap.addButton('help', { + label: 'Help', + href: 'https://google.co.uk', + iconSvgContent: '', + mobile: { slot: 'right-top', showLabel: false }, + tablet: { slot: 'right-top', showLabel: false, order: 1 }, + desktop: { slot: 'right-top', showLabel: false, order: 1 } + }) interactiveMap.addButton('menu', { label: 'Menu', panelId: 'menu', diff --git a/docs/plugins/plugin-descriptor.md b/docs/plugins/plugin-descriptor.md index 03fb7495..91ff2e0a 100644 --- a/docs/plugins/plugin-descriptor.md +++ b/docs/plugins/plugin-descriptor.md @@ -69,3 +69,40 @@ Async function that loads and returns a [PluginManifest](./plugin-manifest.md). **Type:** `Partial` Optional manifest overrides. Allows overriding properties of the loaded [PluginManifest](./plugin-manifest.md). + +Use when you need to customise the UI of a plugin at registration time — particularly for predefined or third-party plugins where you cannot modify the original manifest directly. + +Only the properties you provide are merged into the loaded manifest. Overrides are matched by `id`. + +#### Example + +This example: + +- Moves the `mapStyles` button to the `right-top` slot on desktop. +- Hides the button label. +- Positions the related panel so it opens from the `map-styles-button` slot. +- Sets the panel width to `400px`. +- Makes the panel modal. + +```js +manifest: { + buttons: [ + { + id: 'mapStyles', + desktop: { + slot: 'right-top', + showLabel: false + } + } + ], + panels: [ + { + id: 'mapStyles', + desktop: { + slot: 'map-styles-button', + width: '400px', + modal: true + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index 1a80ed2c..10b5b139 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "tslib": "^2.8.1" }, "devDependencies": { - "@arcgis/core": "^4.34.8", + "@arcgis/core": "^5.0.9", "@babel/core": "^7.28.0", "@babel/plugin-transform-runtime": "^7.29.0", "@babel/preset-env": "^7.28.0", @@ -90,9 +90,6 @@ "webpack-merge": "^6.0.1", "webpack-remove-empty-scripts": "^1.1.1" }, - "peerDependencies": { - "@arcgis/core": "^4.34.8" - }, "peerDependenciesMeta": { "@arcgis/core": { "optional": true @@ -132,7 +129,9 @@ "license": "MIT" }, "node_modules/@amcharts/amcharts5": { - "version": "5.14.4", + "version": "5.15.6", + "resolved": "https://registry.npmjs.org/@amcharts/amcharts5/-/amcharts5-5.15.6.tgz", + "integrity": "sha512-6gVWngHgkMN+v6dJhZ4XJE3fcHjvD5hyjgyNnfvVE1H0ukmHpfFmhI7cCX0cgy0NRyZc4fwgxDMZsiNA7yYKjA==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { @@ -164,32 +163,36 @@ } }, "node_modules/@arcgis/core": { - "version": "4.34.8", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@arcgis/core/-/core-5.0.9.tgz", + "integrity": "sha512-z9LNHKKH+denjz8Ko5csj4QbKBldBXLie3cx3bGC4py+b6NNGK1i5iNAiPPGQ3IyxcotrA76j6BnQG0zuwK8HQ==", "dev": true, - "license": "SEE LICENSE IN copyright.txt", + "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@amcharts/amcharts5": "~5.14.1", - "@arcgis/toolkit": "^4.34.0", + "@amcharts/amcharts5": "~5.15.5", + "@arcgis/toolkit": "^5.0.0", "@esri/arcgis-html-sanitizer": "~4.1.0", - "@esri/calcite-components": "^3.3.2", - "@vaadin/grid": "~24.9.1", - "@zip.js/zip.js": "~2.8.7", + "@esri/calcite-components": "^5.0.2", + "@vaadin/grid": "~25.0.3", + "@zip.js/zip.js": "~2.8.16", "luxon": "~3.7.2", - "marked": "~16.3.0", + "marked": "~17.0.3", "tslib": "^2.8.1" } }, "node_modules/@arcgis/lumina": { - "version": "4.34.9", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@arcgis/lumina/-/lumina-5.0.9.tgz", + "integrity": "sha512-6lvzfi7BKEUehRUdixEsm0r90pB9znE2AmdFkzKeKl3Eav2viFE/Eca4m8rYB4KWowYBxAZX1EyrRLUvDET+Tw==", "dev": true, "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@arcgis/toolkit": "~4.34.9", + "@arcgis/toolkit": "~5.0.9", "csstype": "^3.1.3", "tslib": "^2.8.1" }, "peerDependencies": { - "@lit/context": "^1.1.5", + "@lit/context": "^1.1.6", "lit": "^3.3.0" }, "peerDependenciesMeta": { @@ -199,7 +202,9 @@ } }, "node_modules/@arcgis/toolkit": { - "version": "4.34.9", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@arcgis/toolkit/-/toolkit-5.0.9.tgz", + "integrity": "sha512-D8M0k/SWZZme4FkQav773s+85deqnY3Cxm7u9Tryuvgq0E1t/SoFs/XepYzcO4H5YG18j6hyDHGlXrd+kdKBtA==", "dev": true, "license": "SEE LICENSE IN LICENSE.md", "dependencies": { @@ -4737,6 +4742,8 @@ }, "node_modules/@esri/arcgis-html-sanitizer": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@esri/arcgis-html-sanitizer/-/arcgis-html-sanitizer-4.1.0.tgz", + "integrity": "sha512-einEveDJ/k1180NOp78PB/4Hje9eBy3dyOGLLtLn6bSkizpUfCwuYBIXOA7Y3F/k/BsTQXgKqUVwQ0eiscWMdA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4777,17 +4784,19 @@ } }, "node_modules/@esri/calcite-components": { - "version": "3.3.3", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@esri/calcite-components/-/calcite-components-5.0.2.tgz", + "integrity": "sha512-AE8AQBsdpWWAPJEBc/nabJbdN+H+iuVBJv215mm8xjlyqpHd6BLsD8nG/K8IywDFHeB9TyHLQdYCk/sNiyQo7w==", "dev": true, "license": "SEE LICENSE.md", "dependencies": { - "@arcgis/lumina": ">=4.34.0-next.158 <4.35.0", - "@arcgis/toolkit": ">=4.34.0-next.158 <4.35.0", - "@esri/calcite-ui-icons": "4.3.0", + "@arcgis/lumina": ">=5.0.0-next.144 <6.0.0", + "@arcgis/toolkit": ">=5.0.0-next.144 <6.0.0", + "@esri/calcite-ui-icons": "4.4.0", "@floating-ui/dom": "^1.6.12", "@floating-ui/utils": "^0.2.8", "@types/sortablejs": "^1.15.8", - "color": "^5.0.0", + "color": "^5.0.3", "composed-offset-position": "^0.0.6", "es-toolkit": "^1.39.8", "focus-trap": "^7.6.5", @@ -4799,7 +4808,9 @@ } }, "node_modules/@esri/calcite-ui-icons": { - "version": "4.3.0", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@esri/calcite-ui-icons/-/calcite-ui-icons-4.4.0.tgz", + "integrity": "sha512-PcCGId6vKBysRuuoCIYrVsaC+YVv1lFMqVUQn3Qna0BHOIyf7Mursf3NStELNjYdmL0MRYfmLDEDYQwnAJ/tSA==", "dev": true, "license": "SEE LICENSE.md", "bin": { @@ -4807,29 +4818,37 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.7.4", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.10" + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.5", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.4", - "@floating-ui/utils": "^0.2.10" + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/utils": { - "version": "0.2.10", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "dev": true, "license": "MIT" }, "node_modules/@foliojs-fork/fontkit": { "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.2.tgz", + "integrity": "sha512-IfB5EiIb+GZk+77TRB86AHroVaqfq8JRFlUbz0WEwsInyCG0epX2tCPOy+UfaWPju30DeVoUAXfzWXmhn753KA==", "dev": true, "license": "MIT", "dependencies": { @@ -4845,6 +4864,8 @@ }, "node_modules/@foliojs-fork/linebreak": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.2.tgz", + "integrity": "sha512-ZPohpxxbuKNE0l/5iBJnOAfUaMACwvUIKCvqtWGKIMv1lPYoNjYXRfhi9FeeV9McBkBLxsMFWTVVhHJA8cyzvg==", "dev": true, "license": "MIT", "dependencies": { @@ -4854,6 +4875,8 @@ }, "node_modules/@foliojs-fork/pdfkit": { "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@foliojs-fork/pdfkit/-/pdfkit-0.15.3.tgz", + "integrity": "sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==", "dev": true, "license": "MIT", "dependencies": { @@ -4866,6 +4889,8 @@ }, "node_modules/@foliojs-fork/restructure": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@foliojs-fork/restructure/-/restructure-2.0.2.tgz", + "integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==", "dev": true, "license": "MIT" }, @@ -4919,6 +4944,8 @@ }, "node_modules/@interactjs/types": { "version": "1.10.27", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.27.tgz", + "integrity": "sha512-BUdv0cvs4H5ODuwft2Xp4eL8Vmi3LcihK42z0Ft/FbVJZoRioBsxH+LlsBdK4tAie7PqlKGy+1oyOncu1nQ6eA==", "dev": true, "license": "MIT" }, @@ -5977,11 +6004,15 @@ }, "node_modules/@lit-labs/ssr-dom-shim": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", + "integrity": "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/@lit/reactive-element": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7698,6 +7729,8 @@ }, "node_modules/@open-wc/dedupe-mixin": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@open-wc/dedupe-mixin/-/dedupe-mixin-1.4.0.tgz", + "integrity": "sha512-Sj7gKl1TLcDbF7B6KUhtvr+1UCxdhMbNY5KxdU5IfMFWqL8oy1ZeAcCANjoB1TL0AJTcPmcCFsCbHf8X2jGDUA==", "dev": true, "license": "MIT" }, @@ -8182,14 +8215,6 @@ "version": "1.0.0-next.29", "license": "MIT" }, - "node_modules/@polymer/polymer": { - "version": "3.5.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@webcomponents/shadycss": "^1.9.1" - } - }, "node_modules/@react-foundry/anchor": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/@react-foundry/anchor/-/anchor-0.1.7.tgz", @@ -9780,6 +9805,8 @@ }, "node_modules/@types/d3": { "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", "dev": true, "license": "MIT", "dependencies": { @@ -9817,11 +9844,15 @@ }, "node_modules/@types/d3-array": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-axis": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", "dev": true, "license": "MIT", "dependencies": { @@ -9830,6 +9861,8 @@ }, "node_modules/@types/d3-brush": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", "dev": true, "license": "MIT", "dependencies": { @@ -9838,16 +9871,22 @@ }, "node_modules/@types/d3-chord": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-color": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-contour": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", "dev": true, "license": "MIT", "dependencies": { @@ -9857,16 +9896,22 @@ }, "node_modules/@types/d3-delaunay": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-dispatch": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-drag": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9875,16 +9920,22 @@ }, "node_modules/@types/d3-dsv": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-ease": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-fetch": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", "dev": true, "license": "MIT", "dependencies": { @@ -9893,16 +9944,22 @@ }, "node_modules/@types/d3-force": { "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-format": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-geo": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9911,11 +9968,15 @@ }, "node_modules/@types/d3-hierarchy": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz", + "integrity": "sha512-QwjxA3+YCKH3N1Rs3uSiSy1bdxlLB1uUiENXeJudBoAFvtDuswUxLcanoOaR2JYn1melDTuIXR8VhnVyI3yG/A==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "dev": true, "license": "MIT", "dependencies": { @@ -9924,26 +9985,36 @@ }, "node_modules/@types/d3-path": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-polygon": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-quadtree": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-random": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-sankey": { "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.11.2.tgz", + "integrity": "sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9952,11 +10023,15 @@ }, "node_modules/@types/d3-sankey/node_modules/@types/d3-path": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.11.tgz", + "integrity": "sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-sankey/node_modules/@types/d3-shape": { "version": "1.3.12", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.12.tgz", + "integrity": "sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9965,6 +10040,8 @@ }, "node_modules/@types/d3-scale": { "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", "dev": true, "license": "MIT", "dependencies": { @@ -9973,16 +10050,22 @@ }, "node_modules/@types/d3-scale-chromatic": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-selection": { "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-shape": { "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", "dev": true, "license": "MIT", "dependencies": { @@ -9991,21 +10074,29 @@ }, "node_modules/@types/d3-time": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-time-format": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-timer": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "dev": true, "license": "MIT" }, "node_modules/@types/d3-transition": { "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", "dev": true, "license": "MIT", "dependencies": { @@ -10014,6 +10105,8 @@ }, "node_modules/@types/d3-zoom": { "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", "dev": true, "license": "MIT", "dependencies": { @@ -10210,6 +10303,8 @@ }, "node_modules/@types/polylabel": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/polylabel/-/polylabel-1.1.3.tgz", + "integrity": "sha512-9Zw2KoDpi+T4PZz2G6pO2xArE0m/GSMTW1MIxF2s8ZY8x9XDO6fv9um0ydRGvcbkFLlaq8yNK6eZxnmMZtDgWQ==", "dev": true, "license": "MIT" }, @@ -10319,6 +10414,8 @@ }, "node_modules/@types/sortablejs": { "version": "1.15.9", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.9.tgz", + "integrity": "sha512-7HP+rZGE2p886PKV9c9OJzLBI6BBJu1O7lJGYnPyG3fS4/duUCcngkNCjsLwIMV+WMqANe3tt4irrXHSIe68OQ==", "dev": true, "license": "MIT" }, @@ -10336,6 +10433,8 @@ }, "node_modules/@types/svg-arc-to-cubic-bezier": { "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.3.tgz", + "integrity": "sha512-UNOnbTtl0nVTm8hwKaz5R5VZRvSulFMGojO5+Q7yucKxBoCaTtS4ibSQVRHo5VW5AaRo145U8p1Vfg5KrYe9Bg==", "dev": true, "license": "MIT" }, @@ -10346,6 +10445,8 @@ }, "node_modules/@types/trusted-types": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "dev": true, "license": "MIT" }, @@ -10388,102 +10489,91 @@ "license": "ISC" }, "node_modules/@vaadin/a11y-base": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/a11y-base/-/a11y-base-25.0.5.tgz", + "integrity": "sha512-yE7p9pk1PrQUfur/0rR/jKb5uodYmpn9BXPUb8rfH92CSzOo92QHTO3tC3j7XEIY2UqCMUQo4qI7PQ5EURmSYg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.10", + "@vaadin/component-base": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/checkbox": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/checkbox/-/checkbox-25.0.5.tgz", + "integrity": "sha512-DcHbkxZdUzw9/kDwJ4aJw7hFK61d16kCWyKfyqhcr9klL2AjPlUMt7IcKGugw83gvAtS4MaSD/KvtHappYIr5Q==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.10", - "@vaadin/component-base": "~24.9.10", - "@vaadin/field-base": "~24.9.10", - "@vaadin/vaadin-lumo-styles": "~24.9.10", - "@vaadin/vaadin-material-styles": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10", + "@vaadin/a11y-base": "~25.0.5", + "@vaadin/component-base": "~25.0.5", + "@vaadin/field-base": "~25.0.5", + "@vaadin/vaadin-themable-mixin": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/component-base": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/component-base/-/component-base-25.0.5.tgz", + "integrity": "sha512-iKQ+haAZkAz3HGFN8pxk03DF15XxYRksqkQlvOHUCWDBTSp/pvtJmL1oaXNkjzoZCJdeIYZTWsrqQB9GXIRWeg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", "@vaadin/vaadin-development-mode-detector": "^2.0.0", "@vaadin/vaadin-usage-statistics": "^2.1.0", "lit": "^3.0.0" } }, "node_modules/@vaadin/field-base": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/field-base/-/field-base-25.0.5.tgz", + "integrity": "sha512-2oBmGgDB7DEhMpBnhW408MsRwetrMN0oDHFOzpI1iHvu9YOGBQUznZNCWKIgBPbGfIJv35epoS4wW/g6/ChHRQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.10", - "@vaadin/component-base": "~24.9.10", + "@vaadin/a11y-base": "~25.0.5", + "@vaadin/component-base": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/grid": { - "version": "24.9.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.10", - "@vaadin/checkbox": "~24.9.10", - "@vaadin/component-base": "~24.9.10", - "@vaadin/lit-renderer": "~24.9.10", - "@vaadin/text-field": "~24.9.10", - "@vaadin/vaadin-lumo-styles": "~24.9.10", - "@vaadin/vaadin-material-styles": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10", - "lit": "^3.0.0" - } - }, - "node_modules/@vaadin/icon": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/grid/-/grid-25.0.5.tgz", + "integrity": "sha512-HIzRSTbtdRu/f9keZ++vPtHa49zHbXPvmWKFNp0Tyle05zprhcde5je3+rQukr+YIZfSJyB3gnPOolPRt51uDw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.10", - "@vaadin/vaadin-lumo-styles": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10", + "@vaadin/a11y-base": "~25.0.5", + "@vaadin/checkbox": "~25.0.5", + "@vaadin/component-base": "~25.0.5", + "@vaadin/lit-renderer": "~25.0.5", + "@vaadin/text-field": "~25.0.5", + "@vaadin/vaadin-themable-mixin": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/input-container": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/input-container/-/input-container-25.0.5.tgz", + "integrity": "sha512-mozENjFDmIehVLjgA59njaLgxjo9uSFN2vwxK8wOavxlDBhR2PzxBCQXS0WAZq2rwxUyDIFP6cCavi1WMb2UFg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.10", - "@vaadin/vaadin-lumo-styles": "~24.9.10", - "@vaadin/vaadin-material-styles": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10", + "@vaadin/component-base": "~25.0.5", + "@vaadin/vaadin-themable-mixin": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/lit-renderer": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/lit-renderer/-/lit-renderer-25.0.5.tgz", + "integrity": "sha512-j/7fsXUSUif57G/bDvn7wNhtBtK8Th6IeCwYfbd17KEDc7asVSdEJO1Y6rwQ+sKJijiGdkNRe12FODB3lwc7Aw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -10491,60 +10581,44 @@ } }, "node_modules/@vaadin/text-field": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/text-field/-/text-field-25.0.5.tgz", + "integrity": "sha512-EzwXpXgBOd8EcLJUIszyIP4VAKKR9+3sL2fwQpVpezqsDb3aN+WiOKT9+LF+N51evbXmFs2uenmyBRpngU3Qyw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "@polymer/polymer": "^3.0.0", - "@vaadin/a11y-base": "~24.9.10", - "@vaadin/component-base": "~24.9.10", - "@vaadin/field-base": "~24.9.10", - "@vaadin/input-container": "~24.9.10", - "@vaadin/vaadin-lumo-styles": "~24.9.10", - "@vaadin/vaadin-material-styles": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10", + "@vaadin/a11y-base": "~25.0.5", + "@vaadin/component-base": "~25.0.5", + "@vaadin/field-base": "~25.0.5", + "@vaadin/input-container": "~25.0.5", + "@vaadin/vaadin-themable-mixin": "~25.0.5", "lit": "^3.0.0" } }, "node_modules/@vaadin/vaadin-development-mode-detector": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-development-mode-detector/-/vaadin-development-mode-detector-2.0.7.tgz", + "integrity": "sha512-9FhVhr0ynSR3X2ao+vaIEttcNU5XfzCbxtmYOV8uIRnUCtNgbvMOIcyGBvntsX9I5kvIP2dV3cFAOG9SILJzEA==", "dev": true, "license": "Apache-2.0" }, - "node_modules/@vaadin/vaadin-lumo-styles": { - "version": "24.9.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.10", - "@vaadin/icon": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10" - } - }, - "node_modules/@vaadin/vaadin-material-styles": { - "version": "24.9.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@polymer/polymer": "^3.0.0", - "@vaadin/component-base": "~24.9.10", - "@vaadin/vaadin-themable-mixin": "~24.9.10" - } - }, "node_modules/@vaadin/vaadin-themable-mixin": { - "version": "24.9.10", + "version": "25.0.5", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-themable-mixin/-/vaadin-themable-mixin-25.0.5.tgz", + "integrity": "sha512-U9pGUa8n+BgmJsEoCtFYTnUPLLFE/mty8aplue8FtCQ6NQGGWE0rmlEGQwMCO/H8//OBEFI1VqGGa5ceFKtvaw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@open-wc/dedupe-mixin": "^1.3.0", - "lit": "^3.0.0", - "style-observer": "^0.0.8" + "@vaadin/component-base": "~25.0.5", + "lit": "^3.0.0" } }, "node_modules/@vaadin/vaadin-usage-statistics": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vaadin/vaadin-usage-statistics/-/vaadin-usage-statistics-2.1.3.tgz", + "integrity": "sha512-8r4TNknD7OJQADe3VygeofFR7UNAXZ2/jjBFP5dgI8+2uMfnuGYgbuHivasKr9WSQ64sPej6m8rDoM1uSllXjQ==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -10692,11 +10766,6 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webcomponents/shadycss": { - "version": "1.11.2", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@webpack-cli/configtest": { "version": "3.0.1", "dev": true, @@ -10747,7 +10816,9 @@ "license": "Apache-2.0" }, "node_modules/@zip.js/zip.js": { - "version": "2.8.16", + "version": "2.8.22", + "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.8.22.tgz", + "integrity": "sha512-0KlzbVR6r8irIX2o3zvUlosBDef62VDl47oUfa1U/qgEs67h4/eGBrX/6HWa1RQbt+J6sAeVmtyFKbTHNdF8qQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -11442,6 +11513,8 @@ }, "node_modules/base64-js": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true, "license": "MIT" }, @@ -11655,6 +11728,8 @@ }, "node_modules/brotli": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "dev": true, "license": "MIT", "dependencies": { @@ -12272,6 +12347,8 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", "engines": { @@ -12335,6 +12412,8 @@ }, "node_modules/color": { "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", "dev": true, "license": "MIT", "dependencies": { @@ -12347,6 +12426,8 @@ }, "node_modules/color-convert": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -12358,6 +12439,8 @@ }, "node_modules/color-name": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "dev": true, "license": "MIT", "engines": { @@ -12366,6 +12449,8 @@ }, "node_modules/color-string": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", "dev": true, "license": "MIT", "dependencies": { @@ -12428,6 +12513,8 @@ }, "node_modules/composed-offset-position": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.6.tgz", + "integrity": "sha512-Q7dLompI6lUwd7LWyIcP66r4WcS9u7AL2h8HaeipiRfCRPLMWqRx8fYsjb4OHi6UQFifO7XtNC2IlEJ1ozIFxw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -12729,6 +12816,8 @@ }, "node_modules/crypto-js": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "dev": true, "license": "MIT" }, @@ -13012,6 +13101,8 @@ }, "node_modules/cssfilter": { "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", "dev": true, "license": "MIT" }, @@ -13163,6 +13254,8 @@ }, "node_modules/d3": { "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", "dev": true, "license": "ISC", "dependencies": { @@ -13203,6 +13296,8 @@ }, "node_modules/d3-array": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", "dev": true, "license": "ISC", "dependencies": { @@ -13214,6 +13309,8 @@ }, "node_modules/d3-axis": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", "dev": true, "license": "ISC", "engines": { @@ -13222,6 +13319,8 @@ }, "node_modules/d3-brush": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", "dev": true, "license": "ISC", "dependencies": { @@ -13237,6 +13336,8 @@ }, "node_modules/d3-chord": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", "dev": true, "license": "ISC", "dependencies": { @@ -13248,6 +13349,8 @@ }, "node_modules/d3-color": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", "dev": true, "license": "ISC", "engines": { @@ -13256,6 +13359,8 @@ }, "node_modules/d3-contour": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", "dev": true, "license": "ISC", "dependencies": { @@ -13267,6 +13372,8 @@ }, "node_modules/d3-delaunay": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", "dev": true, "license": "ISC", "dependencies": { @@ -13278,6 +13385,8 @@ }, "node_modules/d3-dispatch": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", "dev": true, "license": "ISC", "engines": { @@ -13286,6 +13395,8 @@ }, "node_modules/d3-drag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", "dev": true, "license": "ISC", "dependencies": { @@ -13298,6 +13409,8 @@ }, "node_modules/d3-dsv": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", "dev": true, "license": "ISC", "dependencies": { @@ -13322,6 +13435,8 @@ }, "node_modules/d3-ease": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -13330,6 +13445,8 @@ }, "node_modules/d3-fetch": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", "dev": true, "license": "ISC", "dependencies": { @@ -13341,6 +13458,8 @@ }, "node_modules/d3-force": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", "dev": true, "license": "ISC", "dependencies": { @@ -13354,6 +13473,8 @@ }, "node_modules/d3-format": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", "dev": true, "license": "ISC", "engines": { @@ -13362,6 +13483,8 @@ }, "node_modules/d3-geo": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", "dev": true, "license": "ISC", "dependencies": { @@ -13373,6 +13496,8 @@ }, "node_modules/d3-hierarchy": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", "dev": true, "license": "ISC", "engines": { @@ -13381,6 +13506,8 @@ }, "node_modules/d3-interpolate": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", "dev": true, "license": "ISC", "dependencies": { @@ -13392,6 +13519,8 @@ }, "node_modules/d3-path": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", "dev": true, "license": "ISC", "engines": { @@ -13400,6 +13529,8 @@ }, "node_modules/d3-polygon": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", "dev": true, "license": "ISC", "engines": { @@ -13408,6 +13539,8 @@ }, "node_modules/d3-quadtree": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", "dev": true, "license": "ISC", "engines": { @@ -13416,6 +13549,8 @@ }, "node_modules/d3-random": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", "dev": true, "license": "ISC", "engines": { @@ -13424,6 +13559,8 @@ }, "node_modules/d3-sankey": { "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13433,6 +13570,8 @@ }, "node_modules/d3-sankey/node_modules/d3-array": { "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13441,11 +13580,15 @@ }, "node_modules/d3-sankey/node_modules/d3-path": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/d3-sankey/node_modules/d3-shape": { "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13454,11 +13597,15 @@ }, "node_modules/d3-sankey/node_modules/internmap": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", "dev": true, "license": "ISC" }, "node_modules/d3-scale": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", "dev": true, "license": "ISC", "dependencies": { @@ -13474,6 +13621,8 @@ }, "node_modules/d3-scale-chromatic": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", "dev": true, "license": "ISC", "dependencies": { @@ -13486,6 +13635,8 @@ }, "node_modules/d3-selection": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "dev": true, "license": "ISC", "engines": { @@ -13494,6 +13645,8 @@ }, "node_modules/d3-shape": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "dev": true, "license": "ISC", "dependencies": { @@ -13505,6 +13658,8 @@ }, "node_modules/d3-time": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "dev": true, "license": "ISC", "dependencies": { @@ -13516,6 +13671,8 @@ }, "node_modules/d3-time-format": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", "dev": true, "license": "ISC", "dependencies": { @@ -13527,6 +13684,8 @@ }, "node_modules/d3-timer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "dev": true, "license": "ISC", "engines": { @@ -13535,6 +13694,8 @@ }, "node_modules/d3-transition": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", "dev": true, "license": "ISC", "dependencies": { @@ -13553,6 +13714,8 @@ }, "node_modules/d3-voronoi-map": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-voronoi-map/-/d3-voronoi-map-2.1.1.tgz", + "integrity": "sha512-mCXfz/kD9IQxjHaU2IMjkO8fSo4J6oysPR2iL+omDsCy1i1Qn6BQ/e4hEAW8C6ms2kfuHwqtbNom80Hih94YsA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13564,21 +13727,29 @@ }, "node_modules/d3-voronoi-map/node_modules/d3-dispatch": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz", + "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/d3-voronoi-map/node_modules/d3-polygon": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", + "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/d3-voronoi-map/node_modules/d3-timer": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/d3-voronoi-treemap": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi-treemap/-/d3-voronoi-treemap-1.1.2.tgz", + "integrity": "sha512-7odu9HdG/yLPWwzDteJq4yd9Q/NwgQV7IE/u36VQtcCK7k1sZwDqbkHCeMKNTBsq5mQjDwolTsrXcU0j8ZEMCA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13587,6 +13758,8 @@ }, "node_modules/d3-weighted-voronoi": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/d3-weighted-voronoi/-/d3-weighted-voronoi-1.1.3.tgz", + "integrity": "sha512-C3WdvSKl9aqhAy+f3QT3PPsQG6V+ajDfYO3BSclQDSD+araW2xDBFIH67aKzsSuuuKaX8K2y2dGq1fq/dWTVig==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13596,6 +13769,8 @@ }, "node_modules/d3-weighted-voronoi/node_modules/d3-array": { "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13604,16 +13779,22 @@ }, "node_modules/d3-weighted-voronoi/node_modules/d3-polygon": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz", + "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/d3-weighted-voronoi/node_modules/internmap": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", "dev": true, "license": "ISC" }, "node_modules/d3-zoom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "dev": true, "license": "ISC", "dependencies": { @@ -13770,6 +13951,8 @@ }, "node_modules/deep-equal": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", "dev": true, "license": "MIT", "dependencies": { @@ -13880,6 +14063,8 @@ }, "node_modules/delaunator": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", "dev": true, "license": "ISC", "dependencies": { @@ -13959,6 +14144,8 @@ }, "node_modules/dfa": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", "dev": true, "license": "MIT" }, @@ -14423,7 +14610,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.44.0", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", + "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", "dev": true, "license": "MIT", "workspaces": [ @@ -15795,6 +15984,8 @@ }, "node_modules/flatpickr": { "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", "dev": true, "license": "MIT" }, @@ -15805,6 +15996,8 @@ }, "node_modules/focus-trap": { "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", "dev": true, "license": "MIT", "dependencies": { @@ -17191,6 +17384,8 @@ }, "node_modules/interactjs": { "version": "1.10.27", + "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.27.tgz", + "integrity": "sha512-y/8RcCftGAF24gSp76X2JS3XpHiUvDQyhF8i7ujemBz77hwiHDuJzftHx7thY8cxGogwGiPJ+o97kWB6eAXnsA==", "dev": true, "license": "MIT", "dependencies": { @@ -17212,6 +17407,8 @@ }, "node_modules/internmap": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", "dev": true, "license": "ISC", "engines": { @@ -17266,6 +17463,8 @@ }, "node_modules/is-arguments": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", "dev": true, "license": "MIT", "dependencies": { @@ -18974,6 +19173,9 @@ }, "node_modules/jpeg-exif": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz", + "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "license": "MIT" }, @@ -19428,6 +19630,8 @@ }, "node_modules/lit": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", + "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -19438,6 +19642,8 @@ }, "node_modules/lit-element": { "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -19448,6 +19654,8 @@ }, "node_modules/lit-html": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz", + "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -19626,6 +19834,8 @@ }, "node_modules/luxon": { "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", "dev": true, "license": "MIT", "engines": { @@ -19917,7 +20127,9 @@ } }, "node_modules/marked": { - "version": "16.3.0", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.4.tgz", + "integrity": "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==", "dev": true, "license": "MIT", "bin": { @@ -19929,6 +20141,8 @@ }, "node_modules/markerjs2": { "version": "2.32.7", + "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.7.tgz", + "integrity": "sha512-HeFRZjmc43DOG3lSQp92z49cq2oCYpYn2pX++SkJAW1Dij4xJtRquVRf+cXeSZQWDX3ufns1Ry/bGk+zveP7rA==", "dev": true, "license": "SEE LICENSE IN LICENSE" }, @@ -24929,6 +25143,8 @@ }, "node_modules/object-is": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -25281,6 +25497,8 @@ }, "node_modules/pako": { "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "dev": true, "license": "MIT" }, @@ -25495,6 +25713,8 @@ }, "node_modules/pdfmake": { "version": "0.2.23", + "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.23.tgz", + "integrity": "sha512-A/IksoKb/ikOZH1edSDJ/2zBbqJKDghD4+fXn3rT7quvCJDlsZMs3NmIB3eajLMMFU9Bd3bZPVvlUMXhvFI+bQ==", "dev": true, "license": "MIT", "dependencies": { @@ -25509,6 +25729,8 @@ }, "node_modules/pdfmake/node_modules/iconv-lite": { "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", "dependencies": { @@ -25824,6 +26046,8 @@ }, "node_modules/png-js": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==", "dev": true }, "node_modules/point-in-polygon-hao": { @@ -25883,6 +26107,8 @@ }, "node_modules/polylabel": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/polylabel/-/polylabel-1.1.0.tgz", + "integrity": "sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==", "dev": true, "license": "ISC", "dependencies": { @@ -25891,6 +26117,8 @@ }, "node_modules/polylabel/node_modules/tinyqueue": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", + "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", "dev": true, "license": "ISC" }, @@ -29689,7 +29917,9 @@ } }, "node_modules/sax": { - "version": "1.4.4", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -29748,6 +29978,8 @@ }, "node_modules/seedrandom": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", "dev": true, "license": "MIT" }, @@ -30212,7 +30444,9 @@ } }, "node_modules/sortablejs": { - "version": "1.15.6", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", "dev": true, "license": "MIT" }, @@ -30667,21 +30901,6 @@ "webpack": "^5.27.0" } }, - "node_modules/style-observer": { - "version": "0.0.8", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/LeaVerou" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/leaverou" - } - ], - "license": "MIT" - }, "node_modules/style-to-js": { "version": "1.1.21", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", @@ -31015,6 +31234,8 @@ }, "node_modules/svg-arc-to-cubic-bezier": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", "dev": true, "license": "ISC" }, @@ -31155,6 +31376,8 @@ }, "node_modules/tabbable": { "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "dev": true, "license": "MIT" }, @@ -31307,6 +31530,8 @@ }, "node_modules/timezone-groups": { "version": "0.10.4", + "resolved": "https://registry.npmjs.org/timezone-groups/-/timezone-groups-0.10.4.tgz", + "integrity": "sha512-AnkJYrbb7uPkDCEqGeVJiawZNiwVlSkkeX4jZg1gTEguClhyX+/Ezn07KB6DT29tG3UN418ldmS/W6KqGOTDjg==", "dev": true, "license": "MIT", "engines": { @@ -31315,6 +31540,8 @@ }, "node_modules/tiny-inflate": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "dev": true, "license": "MIT" }, @@ -31815,6 +32042,8 @@ }, "node_modules/unicode-properties": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", "dev": true, "license": "MIT", "dependencies": { @@ -31831,6 +32060,8 @@ }, "node_modules/unicode-trie": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -33250,6 +33481,8 @@ }, "node_modules/xmldoc": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-2.0.3.tgz", + "integrity": "sha512-6gRk4NY/Jvg67xn7OzJuxLRsGgiXBaPUQplVJ/9l99uIugxh4FTOewYz5ic8WScj7Xx/2WvhENiQKwkK9RpE4w==", "dev": true, "license": "MIT", "dependencies": { @@ -33261,6 +33494,8 @@ }, "node_modules/xss": { "version": "1.0.13", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.13.tgz", + "integrity": "sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -33276,6 +33511,8 @@ }, "node_modules/xss/node_modules/commander": { "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index e99a92d9..409a941b 100755 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ ] }, "peerDependencies": { - "@arcgis/core": "^4.34.8" + "@arcgis/core": "^5.0.9" }, "peerDependenciesMeta": { "@arcgis/core": { @@ -118,7 +118,7 @@ } }, "devDependencies": { - "@arcgis/core": "^4.34.8", + "@arcgis/core": "^5.0.9", "@babel/core": "^7.28.0", "@babel/plugin-transform-runtime": "^7.29.0", "@babel/preset-env": "^7.28.0", diff --git a/plugins/beta/draw-ml/src/events.js b/plugins/beta/draw-ml/src/events.js index 78027f8e..ecd59247 100755 --- a/plugins/beta/draw-ml/src/events.js +++ b/plugins/beta/draw-ml/src/events.js @@ -33,28 +33,18 @@ export function attachEvents({ pluginState, mapProvider, buttonConfig, eventBus disableSnap() mapProvider.undoStack?.clear() - const features = draw.getAll().features - if (mode === 'edit_vertex') { map.fire('draw.editfinish', { features: [draw.get(tempFeature.id)] }) return } - if (!['draw_polygon', 'draw_line'].includes(mode) || features.length === 0) { + if (!['draw_polygon', 'draw_line'].includes(mode)) { return } - const feature = features?.[0] - const geom = feature.geometry - - if (geom.type === 'Polygon') { - const ring = geom.coordinates[0] - geom.coordinates[0] = [...ring.slice(0, -2), ring[0]] - } else { - geom.coordinates = geom.coordinates.slice(0, -1) - } - - map.fire('draw.create', { features: [feature] }) + // Trigger onStop → ParentMode.onStop, which strips the rubber-band vertex + // and fires draw.create once with the correct geometry. + draw.changeMode('disabled') } const handleCancel = () => { diff --git a/plugins/beta/draw-ml/src/modes/createDrawMode.js b/plugins/beta/draw-ml/src/modes/createDrawMode.js index 44ebfb62..52372359 100644 --- a/plugins/beta/draw-ml/src/modes/createDrawMode.js +++ b/plugins/beta/draw-ml/src/modes/createDrawMode.js @@ -137,9 +137,7 @@ export const createDrawMode = (ParentMode, config) => { // For lines: clicking same spot (like double-click) should finish the line if (finishOnInvalidClick && coords.length > 1) { coords.pop() - this.map.fire('draw.create', { - features: [feature.toGeoJSON()] - }) + this.map.fire('draw.create', { features: [feature.toGeoJSON()] }) this.changeMode('simple_select', { featureIds: [feature.id] }) } return diff --git a/plugins/interact/src/InteractInit.jsx b/plugins/interact/src/InteractInit.jsx index 66aba4c7..e17988cb 100755 --- a/plugins/interact/src/InteractInit.jsx +++ b/plugins/interact/src/InteractInit.jsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react' +import { useEffect, useRef } from 'react' import { useInteractionHandlers } from './hooks/useInteractionHandlers.js' import { useHighlightSync } from './hooks/useHighlightSync.js' import { attachEvents } from './events.js' @@ -27,6 +27,27 @@ export const InteractInit = ({ mapProvider, }) + // Refs updated synchronously each render — keeps callbacks fresh without re-attaching events + const handleInteractionRef = useRef(handleInteraction) + handleInteractionRef.current = handleInteraction + + const pluginStateRef = useRef(pluginState) + pluginStateRef.current = pluginState + + const appStateRef = useRef(appState) + appStateRef.current = appState + + // Defer click handling by one macrotask so any click that triggered the enable + // (e.g. finishing a draw gesture) fires before this handler is live. + // Managed separately from attachEvents so re-runs of that effect don't reset it — + // only resets when enabled actually changes. + const clickReadyRef = useRef(false) + useEffect(() => { + clickReadyRef.current = false + const timer = setTimeout(() => { clickReadyRef.current = true }, 0) + return () => clearTimeout(timer) + }, [pluginState.enabled]) + // Highlight features and sync state selectedBounds from mapProvider useHighlightSync({ mapProvider, @@ -54,18 +75,19 @@ export const InteractInit = ({ } const cleanupEvents = attachEvents({ - appState, - pluginState, + getAppState: () => appStateRef.current, mapState, + getPluginState: () => pluginStateRef.current, buttonConfig, events, eventBus, - handleInteraction, + handleInteraction: (e) => handleInteractionRef.current(e), + clickReadyRef, closeApp }) - + return cleanupEvents - }, [appState, mapState, pluginState, buttonConfig, eventBus, handleInteraction]) + }, [pluginState.enabled, buttonConfig, events, eventBus, closeApp]) return null diff --git a/plugins/interact/src/InteractInit.test.js b/plugins/interact/src/InteractInit.test.js index aea5d68c..5c57c608 100644 --- a/plugins/interact/src/InteractInit.test.js +++ b/plugins/interact/src/InteractInit.test.js @@ -1,4 +1,4 @@ -import { render } from '@testing-library/react' +import { act, render } from '@testing-library/react' import { InteractInit } from './InteractInit.jsx' import { useInteractionHandlers } from './hooks/useInteractionHandlers.js' import { useHighlightSync } from './hooks/useHighlightSync.js' @@ -70,9 +70,9 @@ describe('InteractInit', () => { it('attaches events and returns cleanup', () => { const { unmount } = render() expect(attachEvents).toHaveBeenCalledWith(expect.objectContaining({ - handleInteraction: handleInteractionMock, - appState: props.appState, - pluginState: props.pluginState, + getAppState: expect.any(Function), + getPluginState: expect.any(Function), + handleInteraction: expect.any(Function), mapState: props.mapState, buttonConfig: props.buttonConfig, events: props.services.events, @@ -80,11 +80,25 @@ describe('InteractInit', () => { closeApp: props.services.closeApp })) - // simulate unmount + const { getAppState, getPluginState, handleInteraction } = attachEvents.mock.calls.at(-1)[0] + expect(getAppState()).toMatchObject(props.appState) + expect(getPluginState()).toMatchObject({ enabled: props.pluginState.enabled }) + + const event = { point: {}, coords: [] } + handleInteraction(event) + expect(handleInteractionMock).toHaveBeenCalledWith(event) + unmount() expect(cleanupMock).toHaveBeenCalled() }) + it('enables click handling after a macrotask', () => { + jest.useFakeTimers() + render() + act(() => jest.runAllTimers()) + jest.useRealTimers() + }) + it('does not attach events if plugin not enabled', () => { const disabledProps = { ...props, diff --git a/plugins/interact/src/events.js b/plugins/interact/src/events.js index 599d18c1..eb14edab 100755 --- a/plugins/interact/src/events.js +++ b/plugins/interact/src/events.js @@ -1,5 +1,6 @@ // Helper for feature toggling logic -const createFeatureHandler = (mapState, pluginState) => (args, addToExisting) => { +const createFeatureHandler = (mapState, getPluginState) => (args, addToExisting) => { + const pluginState = getPluginState() mapState.markers.remove('location') pluginState.dispatch({ type: 'TOGGLE_SELECTED_FEATURES', @@ -12,17 +13,18 @@ const createFeatureHandler = (mapState, pluginState) => (args, addToExisting) => } export function attachEvents ({ - appState, + getAppState, mapState, - pluginState, + getPluginState, buttonConfig, events, eventBus, handleInteraction, + clickReadyRef, closeApp }) { const { selectDone, selectAtTarget, selectCancel } = buttonConfig - const { viewportRef } = appState.layoutRefs + const { viewportRef } = getAppState().layoutRefs // Keyboard Logic let enterOnViewport = false @@ -35,23 +37,20 @@ export function attachEvents ({ } // Interaction Handlers - // Defer click handling by one macrotask so any click that triggered the enable - // (e.g. finishing a draw gesture) fires before this handler is live. - let clickReady = false - const clickReadyTimer = setTimeout(() => { clickReady = true }, 0) const handleMapClick = (e) => { - if (clickReady) { + if (clickReadyRef.current) { handleInteraction(e) } } const handleSelectAtTarget = () => handleInteraction(mapState.crossHair.getDetail()) const handleSelectDone = () => { + const pluginState = getPluginState() const marker = mapState.markers.getMarker('location') const { coords } = marker || {} const { selectionBounds, selectedFeatures } = pluginState - - if (appState.disabledButtons.has('selectDone')) { + + if (getAppState().disabledButtons.has('selectDone')) { return } @@ -68,12 +67,12 @@ export function attachEvents ({ const handleSelectCancel = () => { eventBus.emit('interact:cancel') - if (pluginState.closeOnAction ?? true) { + if (getPluginState().closeOnAction ?? true) { closeApp() } } - const toggleFeature = createFeatureHandler(mapState, pluginState) + const toggleFeature = createFeatureHandler(mapState, getPluginState) const handleSelect = (args) => toggleFeature(args, true) const handleUnselect = (args) => toggleFeature(args, false) @@ -88,7 +87,6 @@ export function attachEvents ({ selectCancel.onClick = handleSelectCancel return () => { - clearTimeout(clickReadyTimer) selectDone.onClick = null selectAtTarget.onClick = null selectCancel.onClick = null @@ -98,4 +96,4 @@ export function attachEvents ({ eventBus.off('interact:selectFeature', handleSelect) eventBus.off('interact:unselectFeature', handleUnselect) } -} \ No newline at end of file +} diff --git a/plugins/interact/src/events.test.js b/plugins/interact/src/events.test.js index 1ebcadf5..9b317478 100644 --- a/plugins/interact/src/events.test.js +++ b/plugins/interact/src/events.test.js @@ -6,19 +6,27 @@ describe('attachEvents', () => { beforeEach(() => { jest.useFakeTimers() // factory function to create fresh params for each test - createParams = () => ({ - appState: { layoutRefs: { viewportRef: { current: document.body } }, disabledButtons: new Set() }, - mapState: { - markers: { remove: jest.fn(), getMarker: jest.fn(() => null) }, - crossHair: { getDetail: jest.fn(() => ({ point: { x: 0, y: 0 }, coords: [0,0] })) } - }, - pluginState: { dispatch: jest.fn(), selectionBounds: null, selectedFeatures: [], closeOnAction: true, multiSelect: false }, - buttonConfig: { selectDone: {}, selectAtTarget: {}, selectCancel: {} }, - events: { MAP_CLICK: 'map:click' }, - eventBus: { on: jest.fn(), off: jest.fn(), emit: jest.fn() }, - handleInteraction: jest.fn(), - closeApp: jest.fn() - }) + createParams = () => { + const appState = { layoutRefs: { viewportRef: { current: document.body } }, disabledButtons: new Set() } + const pluginState = { dispatch: jest.fn(), selectionBounds: null, selectedFeatures: [], closeOnAction: true, multiSelect: false } + const clickReadyRef = { current: false } + return { + appState, + pluginState, + clickReadyRef, + getAppState: () => appState, + getPluginState: () => pluginState, + mapState: { + markers: { remove: jest.fn(), getMarker: jest.fn(() => null) }, + crossHair: { getDetail: jest.fn(() => ({ point: { x: 0, y: 0 }, coords: [0,0] })) } + }, + buttonConfig: { selectDone: {}, selectAtTarget: {}, selectCancel: {} }, + events: { MAP_CLICK: 'map:click' }, + eventBus: { on: jest.fn(), off: jest.fn(), emit: jest.fn() }, + handleInteraction: jest.fn(), + closeApp: jest.fn() + } + } }) afterEach(() => { @@ -65,10 +73,10 @@ describe('attachEvents', () => { expect(params.handleInteraction).not.toHaveBeenCalled() }) - it('map click triggers interaction after timer fires', () => { + it('map click triggers interaction when clickReadyRef is true', () => { const params = createParams() + params.clickReadyRef.current = true cleanup = attachEvents(params) - jest.runAllTimers() const handler = params.eventBus.on.mock.calls.find(c => c[0]==='map:click')[1] handler({ point:{x:1,y:2}, coords:[3,4] }) @@ -76,8 +84,9 @@ describe('attachEvents', () => { expect(params.handleInteraction).toHaveBeenCalledWith({ point:{x:1,y:2}, coords:[3,4] }) }) - it('map click is suppressed immediately after enable before timer fires', () => { + it('map click is suppressed when clickReadyRef is false', () => { const params = createParams() + params.clickReadyRef.current = false cleanup = attachEvents(params) const handler = params.eventBus.on.mock.calls.find(c => c[0]==='map:click')[1] diff --git a/providers/beta/esri/src/esriProvider.js b/providers/beta/esri/src/esriProvider.js index 2e6a8803..09712b53 100644 --- a/providers/beta/esri/src/esriProvider.js +++ b/providers/beta/esri/src/esriProvider.js @@ -1,6 +1,7 @@ // src/plugins/mapStyles/EsriProvider.jsx import './esriProvider.scss' import esriConfig from '@arcgis/core/config.js' +import TileInfo from '@arcgis/core/layers/support/TileInfo.js' import EsriMap from '@arcgis/core/Map.js' import MapView from '@arcgis/core/views/MapView.js' import VectorTileLayer from '@arcgis/core/layers/VectorTileLayer.js' @@ -50,6 +51,7 @@ export default class EsriProvider { center: getPointFromFlatCoords(config.center), maxExtent: maxExtent, constraints: { + lods: TileInfo.create({ spatialReference: { wkid: 27700 } }).lods, snapToZoom: false, minZoom: config.minZoom, maxZoom: config.maxZoom, diff --git a/providers/beta/esri/src/mapEvents.js b/providers/beta/esri/src/mapEvents.js index 6bfe8399..a790113d 100644 --- a/providers/beta/esri/src/mapEvents.js +++ b/providers/beta/esri/src/mapEvents.js @@ -105,10 +105,41 @@ export function attachMapEvents ({ updating => !updating && emitDataChange() )) - // click - handlers.push(view.on('click', e => { - const mapPoint = e.mapPoint + // Click + // handlers.push(view.on('click', e => { + // const mapPoint = e.mapPoint + // const screenPoint = { x: e.x, y: e.y } + // eventBus.emit(events.MAP_CLICK, { point: screenPoint, coords: [mapPoint.x, mapPoint.y] }) + // })) + + // Using pointer-up instead of click/immediate-click — significantly more responsive as it + // bypasses ArcGIS's internal hit-testing pipeline. Track pointer-down position to suppress + // pointer-up after a drag/pan. Also suppress when SketchViewModel is active so draw/edit + // vertex clicks don't leak through to the map click handler. + const DRAG_TOLERANCE = 6 + let pointerDownX = null + let pointerDownY = null + + handlers.push(view.on('pointer-down', e => { + pointerDownX = e.x + pointerDownY = e.y + })) + + handlers.push(view.on('pointer-up', e => { + if (e.button !== 0) { + return + } + if (Math.hypot(e.x - pointerDownX, e.y - pointerDownY) > DRAG_TOLERANCE) { + return + } + if (mapProvider.sketchViewModel?.state === 'active') { + return + } const screenPoint = { x: e.x, y: e.y } + const mapPoint = view.toMap(screenPoint) + if (!mapPoint) { + return + } eventBus.emit(events.MAP_CLICK, { point: screenPoint, coords: [mapPoint.x, mapPoint.y] }) })) diff --git a/src/App/hooks/useMarkersAPI.js b/src/App/hooks/useMarkersAPI.js index 71dff898..4fb5e705 100755 --- a/src/App/hooks/useMarkersAPI.js +++ b/src/App/hooks/useMarkersAPI.js @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef } from 'react' +import { useCallback, useEffect, useLayoutEffect, useRef } from 'react' import { useConfig } from '../store/configContext.js' import { useMap } from '../store/mapContext.js' import { useService } from '../store/serviceContext.js' @@ -99,8 +99,10 @@ export const useMarkers = () => { const { markers, dispatch, mapSize, isMapReady } = useMap() const markerRefs = useRef(new Map()) - // Attach add, remove, and getMarker methods to the markers store object - useEffect(() => { + // Attach add, remove, and getMarker methods to the markers store object. + // useLayoutEffect ensures these are assigned before paint so rapid clicks can't + // arrive between a render (new markers object) and the async useEffect assignment. + useLayoutEffect(() => { if (!mapProvider) { return } diff --git a/src/App/hooks/useModalPanelBehaviour.js b/src/App/hooks/useModalPanelBehaviour.js index 49d217af..4b7408a5 100755 --- a/src/App/hooks/useModalPanelBehaviour.js +++ b/src/App/hooks/useModalPanelBehaviour.js @@ -75,11 +75,28 @@ export function useModalPanelBehaviour ({ const dividerGap = Number.parseInt(getComputedStyle(root).getPropertyValue('--divider-gap'), 10) useResizeObserver([mainRef], () => { - if (!isModal || !buttonContainerEl || !mainRef.current) { + if (!isModal || !mainRef.current) { return } + + // buttonContainerEl is only defined for button-slot panels (bpConfig.slot ends with '-button'). + // Skip positioning for all other modal types. + if (buttonContainerEl === undefined) { + return + } + + // Dynamically query the current controlling button via aria-controls to handle the case + // where the button has remounted after a breakpoint change (stale triggeringElement). + const panelElId = panelRef.current?.id + const currentButtonEl = panelElId ? document.querySelector(`[aria-controls="${panelElId}"]`) : null + const effectiveContainer = currentButtonEl?.parentElement ?? (buttonContainerEl?.isConnected ? buttonContainerEl : null) + + if (!effectiveContainer) { + return + } + const mainRect = mainRef.current.getBoundingClientRect() - const buttonRect = buttonContainerEl.getBoundingClientRect() + const buttonRect = effectiveContainer.getBoundingClientRect() const offsetTop = buttonRect.top - mainRect.top const offsetRight = Math.round(mainRect.right - buttonRect.right + buttonRect.width + dividerGap) root.style.setProperty('--modal-inset', `${offsetTop}px ${offsetRight}px auto auto`) diff --git a/src/App/hooks/useModalPanelBehaviour.test.js b/src/App/hooks/useModalPanelBehaviour.test.js index 8117382d..31dc643b 100644 --- a/src/App/hooks/useModalPanelBehaviour.test.js +++ b/src/App/hooks/useModalPanelBehaviour.test.js @@ -17,12 +17,17 @@ describe('useModalPanelBehaviour', () => { main: { current: document.createElement('div') }, panel: { current: document.createElement('div') } } + // Give panel an ID for aria-controls tests + refs.panel.current.id = 'modal-panel-id' + elements = { buttonContainer: document.createElement('div'), root: document.createElement('div') } + elements.root.appendChild(refs.panel.current) document.body.appendChild(elements.root) + handleClose = jest.fn() jest.clearAllMocks() document.documentElement.style.setProperty('--modal-inset', '') @@ -32,13 +37,17 @@ describe('useModalPanelBehaviour', () => { document.body.innerHTML = '' }) - const TestComponent = ({ isModal = true }) => { + const TestComponent = ({ + isModal = true, + buttonContainerEl, + rootEl = elements.root + }) => { useModalPanelBehaviour({ mainRef: refs.main, panelRef: refs.panel, isModal, - rootEl: elements.root, - buttonContainerEl: elements.buttonContainer, + rootEl, + buttonContainerEl, handleClose }) return null @@ -63,66 +72,51 @@ describe('useModalPanelBehaviour', () => { ) }) - it('updates --modal-inset on resize', () => { - useResizeObserverModule.useResizeObserver.mockImplementation((_, cb) => cb()) - Object.defineProperty(refs.main.current, 'getBoundingClientRect', { - value: () => ({ top: 0, right: 100, bottom: 50, left: 0, width: 100, height: 50 }) + describe('positioning (--modal-inset)', () => { + beforeEach(() => { + // Force ResizeObserver to run the callback immediately + useResizeObserverModule.useResizeObserver.mockImplementation((_, cb) => cb()) + + Object.defineProperty(refs.main.current, 'getBoundingClientRect', { + value: () => ({ top: 0, right: 100, bottom: 50, left: 0, width: 100, height: 50 }), + configurable: true + }) + Object.defineProperty(elements.buttonContainer, 'getBoundingClientRect', { + value: () => ({ top: 10, right: 80, bottom: 40, left: 20, width: 60, height: 30 }), + configurable: true + }) }) - Object.defineProperty(elements.buttonContainer, 'getBoundingClientRect', { - value: () => ({ top: 10, right: 80, bottom: 40, left: 20, width: 60, height: 30 }) - }) - - render() - - const inset = getComputedStyle(document.documentElement).getPropertyValue('--modal-inset') - expect(inset).toContain('10px') - }) - - describe('backdrop clicks', () => { - const createBackdrop = (appendTo) => { - const backdrop = document.createElement('div') - backdrop.className = 'im-o-app__modal-backdrop' - appendTo.appendChild(backdrop) - return backdrop - } - it('calls handleClose when backdrop inside rootEl is clicked', () => { - const backdrop = createBackdrop(elements.root) + it('hits the buttonContainerEl === undefined branch', () => { + refs.main.current = document.createElement('div') // mainRef must exist render() - fireEvent.click(backdrop) - expect(handleClose).toHaveBeenCalled() - }) - it('does not call handleClose when backdrop outside rootEl is clicked', () => { - const backdrop = createBackdrop(document.body) - render() - fireEvent.click(backdrop) - expect(handleClose).not.toHaveBeenCalled() - }) + // Manually trigger ResizeObserver callback (if mocked) + const callback = useResizeObserverModule.useResizeObserver.mock.calls[0][1] + callback() - it('does not call handleClose when non-backdrop element is clicked', () => { - elements.root.appendChild(document.createElement('div')) - render() - fireEvent.click(elements.root.firstChild) - expect(handleClose).not.toHaveBeenCalled() + // Expect CSS variable not set, just to assert callback ran + const inset = document.documentElement.style.getPropertyValue('--modal-inset') + expect(inset).toBe('') }) - }) - it('toggles inert elements on mount and cleanup', () => { - const { unmount } = render() + it('updates --modal-inset via aria-controls when buttonContainerEl is stale', () => { + const button = document.createElement('button') + button.setAttribute('aria-controls', 'modal-panel-id') + elements.buttonContainer.appendChild(button) + document.body.appendChild(elements.buttonContainer) - expect(toggleInertModule.toggleInertElements).toHaveBeenCalledWith({ - containerEl: refs.panel.current, - isFullscreen: true, - boundaryEl: elements.root - }) + const staleEl = document.createElement('div') // detached + render() - unmount() + const inset = document.documentElement.style.getPropertyValue('--modal-inset') + expect(inset).toContain('10px') + }) - expect(toggleInertModule.toggleInertElements).toHaveBeenCalledWith({ - containerEl: refs.panel.current, - isFullscreen: false, - boundaryEl: elements.root + it('skips update when effectiveContainer cannot be resolved', () => { + render() + const inset = document.documentElement.style.getPropertyValue('--modal-inset') + expect(inset).toBe('') }) }) @@ -138,6 +132,20 @@ describe('useModalPanelBehaviour', () => { expect(refs.panel.current.focus).toHaveBeenCalled() }) + // COVERS LINE 44 (The early return branch) + it('does not redirect focus when focus moves completely outside the app root', () => { + refs.panel.current.focus = jest.fn() + render() + + const externalEl = document.createElement('button') + document.body.appendChild(externalEl) // Outside elements.root + + dispatchFocusIn(externalEl) + + // Since isInsideApp is false, it should hit the "return" and not call focus() + expect(refs.panel.current.focus).not.toHaveBeenCalled() + }) + it('does not redirect focus when focus is already inside panel', () => { refs.panel.current.focus = jest.fn() render() @@ -149,23 +157,39 @@ describe('useModalPanelBehaviour', () => { expect(refs.panel.current.focus).not.toHaveBeenCalled() }) - it('handles edge cases gracefully', () => { + it('handles null focus targets gracefully', () => { render() - dispatchFocusIn(null) + expect(true).toBe(true) + }) + }) + + describe('backdrop and inert', () => { + it('calls handleClose when backdrop inside rootEl is clicked', () => { + const backdrop = document.createElement('div') + backdrop.className = 'im-o-app__modal-backdrop' + elements.root.appendChild(backdrop) - refs.panel.current = null - dispatchFocusIn(document.body) + render() + fireEvent.click(backdrop) + expect(handleClose).toHaveBeenCalled() + }) - expect(true).toBe(true) // No errors thrown + it('toggles inert elements on mount and cleanup', () => { + const { unmount } = render() + expect(toggleInertModule.toggleInertElements).toHaveBeenCalledWith( + expect.objectContaining({ isFullscreen: true }) + ) + unmount() + expect(toggleInertModule.toggleInertElements).toHaveBeenCalledWith( + expect.objectContaining({ isFullscreen: false }) + ) }) }) it('does nothing when isModal is false', () => { render() - fireEvent.keyDown(refs.panel.current, { key: 'Escape' }) expect(handleClose).not.toHaveBeenCalled() - expect(toggleInertModule.toggleInertElements).not.toHaveBeenCalled() }) }) diff --git a/src/App/layout/Layout.jsx b/src/App/layout/Layout.jsx index eb4e39c2..85919ef3 100755 --- a/src/App/layout/Layout.jsx +++ b/src/App/layout/Layout.jsx @@ -70,7 +70,7 @@ export const Layout = () => {
-
+
diff --git a/src/App/layout/layout.module.scss b/src/App/layout/layout.module.scss index deddb1b5..70c35ae8 100755 --- a/src/App/layout/layout.module.scss +++ b/src/App/layout/layout.module.scss @@ -322,10 +322,7 @@ } [class*="im-c-panel--"][class*="-button"] { // Adjacent to button - top: var(--modal-inset); - right: var(--modal-inset); - bottom: var(--modal-inset); - left: var(--modal-inset); + inset: var(--modal-inset); } } diff --git a/src/App/renderer/HtmlElementHost.jsx b/src/App/renderer/HtmlElementHost.jsx index 9b92b52b..52820756 100644 --- a/src/App/renderer/HtmlElementHost.jsx +++ b/src/App/renderer/HtmlElementHost.jsx @@ -18,6 +18,7 @@ export const getSlotRef = (slot, layoutRefs) => { inset: layoutRefs.insetRef, middle: layoutRefs.middleRef, bottom: layoutRefs.bottomRef, + 'right-bottom': layoutRefs.rightBottomRef, actions: layoutRefs.actionsRef, modal: layoutRefs.modalRef } diff --git a/src/App/renderer/pluginWrapper.js b/src/App/renderer/pluginWrapper.js index 47cccc3e..4a290fd7 100755 --- a/src/App/renderer/pluginWrapper.js +++ b/src/App/renderer/pluginWrapper.js @@ -1,4 +1,5 @@ // src/core/renderers/pluginWrapper.js +import { useMemo } from 'react' import { useConfig } from '../store/configContext.js' import { useApp } from '../store/appContext.js' import { useMap } from '../store/mapContext.js' @@ -59,11 +60,11 @@ export function withPluginContexts (Component, { pluginId, pluginConfig }) { services={services} mapProvider={appConfig.mapProvider} iconRegistry={getIconRegistry()} - buttonConfig={Object.fromEntries( + buttonConfig={useMemo(() => Object.fromEntries( Object.entries(appState.buttonConfig).filter( ([_, btn]) => btn.pluginId === pluginId ) - )} + ), [appState.buttonConfig])} /> ) }) diff --git a/src/App/renderer/slots.js b/src/App/renderer/slots.js index 0df0a29d..8d302ea5 100755 --- a/src/App/renderer/slots.js +++ b/src/App/renderer/slots.js @@ -30,10 +30,10 @@ export const allowedSlots = Object.freeze({ layoutSlots.SIDE, layoutSlots.BANNER, layoutSlots.INSET, + layoutSlots.RIGHT_BOTTOM, layoutSlots.MIDDLE, layoutSlots.BOTTOM, layoutSlots.ACTIONS, - layoutSlots.DRAWER, layoutSlots.MODAL ], button: [ diff --git a/src/App/store/AppProvider.jsx b/src/App/store/AppProvider.jsx index 390108ca..10345ab8 100755 --- a/src/App/store/AppProvider.jsx +++ b/src/App/store/AppProvider.jsx @@ -21,6 +21,7 @@ export const AppProvider = ({ options, children }) => { topRightColRef: useRef(null), insetRef: useRef(null), rightRef: useRef(null), + rightBottomRef: useRef(null), middleRef: useRef(null), bottomRef: useRef(null), footerRef: useRef(null),