diff --git a/CHANGELOG.md b/CHANGELOG.md index 75fff0e..2eab366 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.4.1 +* Packages update +* Fixed tests with measureUnits +* Fixed eslint errors + # 2.4.0 * Update powerbi packages, API to 5.7.0 * Migrate from tslint to eslint diff --git a/README.md b/README.md index 84474b4..9457192 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # powerbi-visuals-bulletchart -![Build](https://github.com/microsoft/powerbi-visuals-bulletchart/workflows/build/badge.svg)[![Coverage Status](https://coveralls.io/repos/github/Microsoft/powerbi-visuals-bulletchart/badge.svg?branch=main)](https://coveralls.io/github/Microsoft/powerbi-visuals-bulletchart?branch=main) +[![build status](https://github.com/microsoft/powerbi-visuals-bulletchart/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/microsoft/powerbi-visuals-bulletchart/actions/workflows/build.yml) > A bullet chart that includes four orientations and a few customization options. Use to feature a single measure against a qualitative range. diff --git a/capabilities.json b/capabilities.json index a5b3b99..0070036 100644 --- a/capabilities.json +++ b/capabilities.json @@ -63,61 +63,43 @@ ], "objects": { "values": { - "displayName": "Data values", - "displayNameKey": "Visual_DataValues", "properties": { "targetValue": { - "displayName": "Target Value", - "displayNameKey": "Visual_DataValues_TargetValue", "type": { "numeric": true } }, "targetValue2": { - "displayName": "Target Value 2", - "displayNameKey": "Visual_DataValues_TargetValue2", "type": { "numeric": true } }, "minimumPercent": { - "displayName": "Minimum %", - "displayNameKey": "Visual_DataValues_MinimumPercent", "type": { "numeric": true } }, "needsImprovementPercent": { - "displayName": "Needs Improvement %", - "displayNameKey": "Visual_DataValues_NeedsImprovementPercent", "type": { "numeric": true } }, "satisfactoryPercent": { - "displayName": "Satisfactory %", - "displayNameKey": "Visual_DataValues_SatisfactoryPercent", "type": { "numeric": true } }, "goodPercent": { - "displayName": "Good %", - "displayNameKey": "Visual_DataValues_GoodPercent", "type": { "numeric": true } }, "veryGoodPercent": { - "displayName": "Very Good %", - "displayNameKey": "Visual_DataValues_VeryGoodPercent", "type": { "numeric": true } }, "maximumPercent": { - "displayName": "Maximum %", - "displayNameKey": "Visual_DataValues_MaximumPercent", "type": { "numeric": true } @@ -125,26 +107,18 @@ } }, "tooltips": { - "displayName": "Tooltips", - "displayNameKey": "Visual_Tooltips", "properties": { "valueCustomName": { - "displayName": "\"Value\" custom name", - "displayNameKey": "Visual_ValueCustomName", "type": { "text": true } }, "targetCustomName": { - "displayName": "\"Target Value\" custom name", - "displayNameKey": "Visual_TargetValueCustomName", "type": { "text": true } }, "target2CustomName": { - "displayName": "\"Target Value 2\" custom name", - "displayNameKey": "Visual_TargetValue2CustomName", "type": { "text": true } @@ -152,21 +126,13 @@ } }, "labels": { - "displayName": "Category labels", - "displayNameKey": "Visual_CategoryLabels", "properties": { "show": { - "displayName": "Show", - "displayNameKey": "Visual_Show", "type": { "bool": true } }, "labelColor": { - "displayName": "color", - "displayNameKey": "Visual_Color", - "description": "Select color for data labels", - "descriptionKey": "Visual_Description_Color", "type": { "fill": { "solid": { @@ -175,61 +141,57 @@ } } }, + "maxWidth": { + "type": { + "numeric": true + } + }, "fontSize": { - "displayName": "Text Size", - "displayNameKey": "Visual_TextSize", "type": { "formatting": { "fontSize": true } } }, - "maxWidth": { - "displayName": "Maximum width", - "displayNameKey": "Visual_MaxWidth", + "fontFamily": { "type": { - "numeric": true + "formatting": { + "fontFamily": true + } + } + }, + "fontBold": { + "type": { + "bool": true + } + }, + "fontItalic": { + "type": { + "bool": true + } + }, + "fontUnderline": { + "type": { + "bool": true } } } }, "orientation": { - "displayName": "Orientation", - "displayNameKey": "Visual_Orientation", "properties": { "orientation": { - "displayName": "Orientation", - "displayNameKey": "Visual_Orientation", "type": { "enumeration": [ - { - "value": "HorizontalLeft", - "displayNameKey": "Visual_Orientation_HorizontalLeft", - "displayName": "Horizontal Left" - }, - { - "value": "HorizontalRight", - "displayNameKey": "Visual_Orientation_HorizontalRight", - "displayName": "Horizontal Right" - }, - { - "value": "VerticalTop", - "displayNameKey": "Visual_Orientation_VerticalTop", - "displayName": "Vertical Top" - }, - { - "value": "VerticalBottom", - "displayNameKey": "Visual_Orientation_VerticalBottom", - "displayName": "Vertical Bottom" - } + { "value": "HorizontalLeft" }, + { "value": "HorizontalRight" }, + { "value": "VerticalTop" }, + { "value": "VerticalBottom" } ] } } } }, "colors": { - "displayName": "Colors", - "displayNameKey": "Visual_Colors", "properties": { "minColor": { "type": { @@ -238,9 +200,7 @@ "color": true } } - }, - "displayName": "Minimum color", - "displayNameKey": "Visual_Colors_MinimumColor" + } }, "needsImprovementColor": { "type": { @@ -249,9 +209,7 @@ "color": true } } - }, - "displayName": "Needs Improvement color", - "displayNameKey": "Visual_Colors_NeedsImprovementColor" + } }, "satisfactoryColor": { "type": { @@ -260,9 +218,7 @@ "color": true } } - }, - "displayName": "Satisfactory color", - "displayNameKey": "Visual_Colors_SatisfactoryColor" + } }, "goodColor": { "type": { @@ -271,9 +227,7 @@ "color": true } } - }, - "displayName": "Good color", - "displayNameKey": "Visual_Colors_GoodColor" + } }, "veryGoodColor": { "type": { @@ -282,9 +236,7 @@ "color": true } } - }, - "displayName": "Very Good color", - "displayNameKey": "Visual_Colors_VeryGoodColor" + } }, "bulletColor": { "type": { @@ -293,19 +245,13 @@ "color": true } } - }, - "displayName": "Bullet color", - "displayNameKey": "Visual_Colors_BulletColor" + } } } }, "axis": { - "displayName": "Axis", - "displayNameKey": "Visual_Axis", "properties": { "axis": { - "displayName": "Axis", - "displayNameKey": "Visual_Axis", "type": { "bool": true } @@ -317,16 +263,12 @@ "color": true } } - }, - "displayName": "Axis color", - "displayNameKey": "Visual_AxisColor" + } }, "measureUnits": { "type": { "text": true - }, - "displayName": "Measure Units", - "displayNameKey": "Visual_MeasureUnits" + } }, "unitsColor": { "type": { @@ -335,9 +277,7 @@ "color": true } } - }, - "displayName": "Units color", - "displayNameKey": "Visual_UnitsColor" + } } } }, @@ -456,6 +396,8 @@ "privileges": [], "supportsHighlight": true, "supportsKeyboardFocus": true, + "supportsOnObjectFormatting": true, + "enablePointerEventsFormatMode": true, "sorting": { "default": {} }, diff --git a/karma.conf.ts b/karma.conf.ts index 3bc0096..ce8f082 100644 --- a/karma.conf.ts +++ b/karma.conf.ts @@ -41,6 +41,12 @@ module.exports = (config) => { mode: "development", browserNoActivityTimeout: 10000, browsers: ["ChromeHeadless"], + customLaunchers: { + ChromeDebugging: { + base: "ChromeHeadless", + flags: ["--remote-debugging-port=9333"] + } + }, colors: true, frameworks: ["jasmine"], reporters: ["progress", "junit"], diff --git a/package-lock.json b/package-lock.json index 3ab31b3..589ca27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "powerbi-visuals-bulletchart", - "version": "2.4.0.0", + "version": "2.4.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "powerbi-visuals-bulletchart", - "version": "2.4.0.0", + "version": "2.4.1.0", "license": "MIT", "dependencies": { "d3-array": "^3.2.4", @@ -25,7 +25,7 @@ "powerbi-visuals-utils-colorutils": "^6.0.3", "powerbi-visuals-utils-dataviewutils": "^6.0.2", "powerbi-visuals-utils-formattingmodel": "^6.0.1", - "powerbi-visuals-utils-formattingutils": "^6.0.3", + "powerbi-visuals-utils-formattingutils": "^6.1.0", "powerbi-visuals-utils-interactivityutils": "^6.0.3", "powerbi-visuals-utils-tooltiputils": "^6.0.3", "regenerator-runtime": "^0.14.1", @@ -48,15 +48,14 @@ "@types/lodash.sumby": "^4.6.6", "@types/lodash.takeright": "^4.1.6", "@types/webpack": "5.28.5", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", - "coveralls": "3.1.1", - "css-loader": "6.9.1", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "css-loader": "6.10.0", + "eslint": "^8.57.0", "eslint-plugin-powerbi-visuals": "^0.8.1", "jasmine": "5.1.0", "jasmine-jquery": "2.1.1", - "karma": "^6.3.4", + "karma": "^6.4.3", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", "karma-jasmine": "5.1.0", @@ -64,20 +63,21 @@ "karma-sourcemap-loader": "0.4.0", "karma-typescript": "5.5.4", "karma-typescript-preprocessor": "0.4.0", - "karma-webpack": "5.0.0", + "karma-webpack": "5.0.1", "less": "4.2.0", - "less-loader": "12.1.0", + "less-loader": "12.2.0", "moment": "^2.29.4", - "playwright-chromium": "^1.41.1", + "playwright-chromium": "^1.41.2", "powerbi-models": "1.14.0", - "powerbi-visuals-api": "~5.7.0", - "powerbi-visuals-tools": "^5.4.0", + "powerbi-visuals-api": "^5.8.0", + "powerbi-visuals-tools": "^5.4.2", + "powerbi-visuals-utils-onobjectutils": "^6.0.1", "powerbi-visuals-utils-testutils": "^6.0.3", "style-loader": "3.3.4", "ts-loader": "9.5.1", "ts-node": "10.9.2", "typescript": "5.3.3", - "webpack": "^5.76.0" + "webpack": "^5.90.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -665,22 +665,22 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -701,9 +701,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -1261,9 +1261,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { @@ -1332,16 +1332,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", - "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", + "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/type-utils": "6.19.0", - "@typescript-eslint/utils": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/type-utils": "7.0.2", + "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1357,8 +1357,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1367,15 +1367,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz", - "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", + "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4" }, "engines": { @@ -1386,7 +1386,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1395,13 +1395,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1412,13 +1412,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", - "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", + "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.0", - "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/utils": "7.0.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1430,7 +1430,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1439,9 +1439,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1452,13 +1452,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1504,17 +1504,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", "semver": "^7.5.4" }, "engines": { @@ -1525,16 +1525,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/types": "7.0.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1871,15 +1871,6 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -1895,15 +1886,6 @@ "node": ">=8" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -1935,27 +1917,12 @@ "util": "^0.12.5" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -1977,21 +1944,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2033,15 +1985,6 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2344,12 +2287,6 @@ } ] }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2494,18 +2431,6 @@ "node": ">=0.10.0" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", @@ -2711,25 +2636,6 @@ "node": ">= 0.10" } }, - "node_modules/coveralls": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", - "integrity": "sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -2816,9 +2722,9 @@ } }, "node_modules/css-loader": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.9.1.tgz", - "integrity": "sha512-OzABOh0+26JKFdMzlK6PY1u5Zx8+Ck7CVRlcGNZoY9qwJjdfu2VWFuprTIpPW+Av5TZTVViYWcFQaEEQURLknQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", @@ -2838,7 +2744,16 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/cssesc": { @@ -2992,18 +2907,6 @@ "d3-selection": "2 - 3" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/date-format": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", @@ -3106,15 +3009,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3260,16 +3154,6 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3410,16 +3294,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -3533,19 +3417,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -3807,15 +3678,6 @@ "schema-utils": "^0.4.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4043,29 +3905,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -4177,15 +4016,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4302,29 +4132,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4570,21 +4377,6 @@ } } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -4942,12 +4734,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, "node_modules/is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", @@ -4990,12 +4776,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -5192,25 +4972,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -5240,12 +5001,6 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5287,21 +5042,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -5345,9 +5085,9 @@ } }, "node_modules/karma": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", - "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", + "integrity": "sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q==", "dev": true, "dependencies": { "@colors/colors": "1.5.0", @@ -5369,7 +5109,7 @@ "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.4.1", + "socket.io": "^4.7.2", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", @@ -5584,22 +5324,46 @@ } }, "node_modules/karma-webpack": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.0.tgz", - "integrity": "sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.1.tgz", + "integrity": "sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ==", "dev": true, "dependencies": { "glob": "^7.1.3", - "minimatch": "^3.0.4", + "minimatch": "^9.0.3", "webpack-merge": "^4.1.5" }, "engines": { - "node": ">= 6" + "node": ">= 18" }, "peerDependencies": { "webpack": "^5.0.0" } }, + "node_modules/karma-webpack/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/karma-webpack/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5619,15 +5383,6 @@ "shell-quote": "^1.8.1" } }, - "node_modules/lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==", - "dev": true, - "bin": { - "lcov-parse": "bin/cli.js" - } - }, "node_modules/less": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", @@ -5655,9 +5410,9 @@ } }, "node_modules/less-loader": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.1.0.tgz", - "integrity": "sha512-N/MRZA9iILOW+TQ9xoDptsSPbtBJDWshOj3LNqL+UJAYDhtoraLECiBa93DeLJUfR4m/VE6bWuxaVs40+wBXYw==", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", + "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", "dev": true, "engines": { "node": ">= 18.12.0" @@ -5667,8 +5422,17 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "less": "^3.5.0 || ^4.0.0", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/less/node_modules/make-dir": { @@ -5852,15 +5616,6 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true, - "engines": { - "node": ">=0.8.6" - } - }, "node_modules/log4js": { "version": "6.9.1", "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", @@ -6306,15 +6061,6 @@ "node": ">=8" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6675,12 +6421,6 @@ "node": ">=0.12" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -6709,13 +6449,13 @@ } }, "node_modules/playwright-chromium": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.41.1.tgz", - "integrity": "sha512-Nr1/rnmRB4QzoAQwCors1Qsa9PLSdipsKiI4FZCQjSDzoBVBzoQqfXGtcIEnoAXEEEpzxuCPqjJNQwCVA66tCw==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-chromium/-/playwright-chromium-1.41.2.tgz", + "integrity": "sha512-1XoW4aGGRbS2BJLldtLcv2QW3deMv8myE5iCtfGRPq99BWqmBLJvJTgY/SyfBCoklwQvl91zUWYWHjCAuvKGkw==", "dev": true, "hasInstallScript": true, "dependencies": { - "playwright-core": "1.41.1" + "playwright-core": "1.41.2" }, "bin": { "playwright": "cli.js" @@ -6725,9 +6465,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz", - "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", + "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -6849,17 +6589,18 @@ "dev": true }, "node_modules/powerbi-visuals-api": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/powerbi-visuals-api/-/powerbi-visuals-api-5.7.0.tgz", - "integrity": "sha512-sPAGYUUkTtbbZXyL8cIJZh6MrZ7BiXPs5li3V7pAa3UUQC3Jih7OS1Hq9AsTp05IKsp94YHXILrcyn4mNAi9qg==", + "version": "5.8.0", + "resolved": "git+ssh://git@github.com/shafeeqz/powerbi-visuals-api.git#55590ff2dc4bc4b4ca7e8f2c023eca51a93ccd44", + "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.3.5" } }, "node_modules/powerbi-visuals-tools": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/powerbi-visuals-tools/-/powerbi-visuals-tools-5.4.0.tgz", - "integrity": "sha512-X0DTH7qqrwHZ92O/yfEFfi3x6vKzNSag8Z1a3DkZ/5lk+vZu+rzdlpU3Tpnbt3k+gs8plpTVVGVh2sXv7pu/gA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/powerbi-visuals-tools/-/powerbi-visuals-tools-5.4.2.tgz", + "integrity": "sha512-5zjyf2ByXIMTmoOuMkweGkOoPC5qkOqa2P3p4gn1fxIGfhmUrkDcH73Ib6y9nbbb6OhcL2zT4OL777Hvzj7Fvg==", "dev": true, "dependencies": { "@typescript-eslint/parser": "^6.17.0", @@ -6921,6 +6662,118 @@ "fsevents": "*" } }, + "node_modules/powerbi-visuals-tools/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/powerbi-visuals-tools/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/powerbi-visuals-tools/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/powerbi-visuals-tools/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/powerbi-visuals-tools/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/powerbi-visuals-tools/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/powerbi-visuals-tools/node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -6986,6 +6839,21 @@ "webpack": "^5.0.0" } }, + "node_modules/powerbi-visuals-tools/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/powerbi-visuals-tools/node_modules/readable-stream": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -7059,10 +6927,18 @@ "powerbi-visuals-api": "~5.7.0" } }, + "node_modules/powerbi-visuals-utils-formattingmodel/node_modules/powerbi-visuals-api": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/powerbi-visuals-api/-/powerbi-visuals-api-5.7.0.tgz", + "integrity": "sha512-sPAGYUUkTtbbZXyL8cIJZh6MrZ7BiXPs5li3V7pAa3UUQC3Jih7OS1Hq9AsTp05IKsp94YHXILrcyn4mNAi9qg==", + "dependencies": { + "semver": "^7.3.5" + } + }, "node_modules/powerbi-visuals-utils-formattingutils": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-formattingutils/-/powerbi-visuals-utils-formattingutils-6.0.3.tgz", - "integrity": "sha512-0YJo2ghqxeb5IJIHIRt3ks3rhZvqnBATbDEsdyySk28QkBjLAjMAJZpFlajHvbROAw70+YHmkVRFoDCwpheXmQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-formattingutils/-/powerbi-visuals-utils-formattingutils-6.1.0.tgz", + "integrity": "sha512-UecuCS1u3LnOBwVem1wESvBz7JX+AO9pzjZxmZR11WHmg4ZSLqPMGXr751Oh/KvNJ1BXaLXg5cA92ioY8axnRg==", "dependencies": { "powerbi-visuals-api": "5.7.0", "powerbi-visuals-utils-dataviewutils": "^6.0.2", @@ -7072,6 +6948,14 @@ "fsevents": "*" } }, + "node_modules/powerbi-visuals-utils-formattingutils/node_modules/powerbi-visuals-api": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/powerbi-visuals-api/-/powerbi-visuals-api-5.7.0.tgz", + "integrity": "sha512-sPAGYUUkTtbbZXyL8cIJZh6MrZ7BiXPs5li3V7pAa3UUQC3Jih7OS1Hq9AsTp05IKsp94YHXILrcyn4mNAi9qg==", + "dependencies": { + "semver": "^7.3.5" + } + }, "node_modules/powerbi-visuals-utils-interactivityutils": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-interactivityutils/-/powerbi-visuals-utils-interactivityutils-6.0.3.tgz", @@ -7088,6 +6972,17 @@ "resolved": "https://registry.npmjs.org/powerbi-models/-/powerbi-models-1.13.0.tgz", "integrity": "sha512-fToQmRqECBJSlHaKNAzFql52ryNnhSm2UwRXfsctcS5Hp//o9sExasVsASv6jZjXE8ACNyKjDUKdGqWsCjRd1Q==" }, + "node_modules/powerbi-visuals-utils-onobjectutils": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-onobjectutils/-/powerbi-visuals-utils-onobjectutils-6.0.1.tgz", + "integrity": "sha512-D7mlH4/6GkhvcDVxmjfqJ9m5yiuRAyTKepJVoMXXoVTo08XabilRgLSPfyWyVyfMGGONObPqiPhmWVhivo3eJg==", + "dev": true, + "dependencies": { + "@types/d3-selection": "^3.0.10", + "d3-selection": "^3.0.0", + "powerbi-visuals-api": "~5.8.0" + } + }, "node_modules/powerbi-visuals-utils-svgutils": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/powerbi-visuals-utils-svgutils/-/powerbi-visuals-utils-svgutils-6.0.3.tgz", @@ -7248,12 +7143,6 @@ "dev": true, "optional": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -7408,47 +7297,6 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8053,37 +7901,6 @@ "wbuf": "^1.7.3" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -8440,19 +8257,6 @@ "node": ">=6" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/ts-api-utils": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", @@ -8549,24 +8353,6 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8759,16 +8545,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -8784,20 +8560,6 @@ "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -8844,18 +8606,18 @@ } }, "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", + "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.15.0", "es-module-lexer": "^1.2.1", @@ -8869,7 +8631,7 @@ "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", + "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, diff --git a/package.json b/package.json index 5175619..190b74a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "powerbi-visuals-bulletchart", "description": "Bullet chart", - "version": "2.4.0.0", + "version": "2.4.1.0", "author": { "name": "Microsoft", "email": "pbicvsupport@microsoft.com" @@ -37,7 +37,7 @@ "powerbi-visuals-utils-colorutils": "^6.0.3", "powerbi-visuals-utils-dataviewutils": "^6.0.2", "powerbi-visuals-utils-formattingmodel": "^6.0.1", - "powerbi-visuals-utils-formattingutils": "^6.0.3", + "powerbi-visuals-utils-formattingutils": "^6.1.0", "powerbi-visuals-utils-interactivityutils": "^6.0.3", "powerbi-visuals-utils-tooltiputils": "^6.0.3", "regenerator-runtime": "^0.14.1", @@ -60,15 +60,14 @@ "@types/lodash.sumby": "^4.6.6", "@types/lodash.takeright": "^4.1.6", "@types/webpack": "5.28.5", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", - "coveralls": "3.1.1", - "css-loader": "6.9.1", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.0.2", + "css-loader": "6.10.0", + "eslint": "^8.57.0", "eslint-plugin-powerbi-visuals": "^0.8.1", "jasmine": "5.1.0", "jasmine-jquery": "2.1.1", - "karma": "^6.3.4", + "karma": "^6.4.3", "karma-chrome-launcher": "3.2.0", "karma-coverage": "2.2.1", "karma-jasmine": "5.1.0", @@ -76,19 +75,20 @@ "karma-sourcemap-loader": "0.4.0", "karma-typescript": "5.5.4", "karma-typescript-preprocessor": "0.4.0", - "karma-webpack": "5.0.0", + "karma-webpack": "5.0.1", "less": "4.2.0", - "less-loader": "12.1.0", + "less-loader": "12.2.0", "moment": "^2.29.4", - "playwright-chromium": "^1.41.1", + "playwright-chromium": "^1.41.2", "powerbi-models": "1.14.0", - "powerbi-visuals-api": "~5.7.0", - "powerbi-visuals-tools": "^5.4.0", + "powerbi-visuals-api": "^5.8.0", + "powerbi-visuals-tools": "^5.4.2", + "powerbi-visuals-utils-onobjectutils": "^6.0.1", "powerbi-visuals-utils-testutils": "^6.0.3", "style-loader": "3.3.4", "ts-loader": "9.5.1", "ts-node": "10.9.2", "typescript": "5.3.3", - "webpack": "^5.76.0" + "webpack": "^5.90.3" } } diff --git a/pbiviz.json b/pbiviz.json index c5dae20..f06b0dc 100644 --- a/pbiviz.json +++ b/pbiviz.json @@ -1,15 +1,15 @@ { "visual": { "name": "BulletChart", - "displayName": "Bullet Chart 2.4.0.0", + "displayName": "Bullet Chart 2.4.1.0", "guid": "BulletChart1443347686880", "visualClassName": "BulletChart", - "version": "2.4.0.0", + "version": "2.4.1.0", "description": "A bullet chart that includes four orientations and a few customization options. Use to feature a single measure against a qualitative range.", "supportUrl": "https://community.powerbi.com", "gitHubUrl": "https://github.com/Microsoft/powerbi-visuals-bulletchart" }, - "apiVersion": "5.7.0", + "apiVersion": "5.8.0", "author": { "name": "Microsoft", "email": "pbicvsupport@microsoft.com" diff --git a/src/BulletChartSettingsModel.ts b/src/BulletChartSettingsModel.ts index a03e37f..25c6822 100644 --- a/src/BulletChartSettingsModel.ts +++ b/src/BulletChartSettingsModel.ts @@ -6,6 +6,141 @@ import {SimpleSlice} from "powerbi-visuals-utils-formattingmodel/lib/FormattingS import IEnumMember = powerbi.IEnumMember; import {BulletChartOrientation} from "./BulletChartOrientation"; import ILocalizationManager = powerbi.extensibility.ILocalizationManager; +import {BarRectType} from "./dataInterfaces"; +import FormattingId = powerbi.visuals.FormattingId; + +const nameof = (name: Extract): string => name; + +export const BulletChartObjectNames = { + Labels: { name: "labels", displayName: "Category labels" }, + Axis: { name: "axis", displayName: "Axis" }, + SyncAxis: { name: "syncAxis", displayName: "Sync axis" }, + Orientation: { name: "orientation", displayName: "Orientation" }, + Colors: { name: "colors", displayName: "Colors" }, + // used for subselection + Minimum: { name: BarRectType.Minimum, displayName: "Minimum" }, + NeedsImprovement: { name: BarRectType.NeedsImprovement, displayName: "Needs Improvement" }, + Satisfactory: { name: BarRectType.Satisfactory, displayName: "Satisfactory" }, + Good: { name: BarRectType.Good, displayName: "Good" }, + VeryGood: { name: BarRectType.VeryGood, displayName: "Very good" }, + Bullet: { name: BarRectType.Bullet, displayName: "Bullet" }, +} as const; + +export const labelsReference: { + cardUid: string; + groupUid: string; + fontFamily: FormattingId; + bold: FormattingId; + italic: FormattingId; + underline: FormattingId; + fontSize: FormattingId; + labelColor: FormattingId; + show: FormattingId; +} = { + cardUid: "Visual-labels-card", + groupUid: "labels-group", + fontFamily: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: "fontFamily" + }, + bold: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: "fontBold" + }, + italic: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: "fontItalic" + }, + underline: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: "fontUnderline" + }, + fontSize: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: "fontSize" + }, + labelColor: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: nameof("labelColor") + }, + show: { + objectName: BulletChartObjectNames.Labels.name, + propertyName: nameof("show") + } +} as const; + +export const axisReference: { + cardUid: string; + groupUid: string; + axis: FormattingId; + axisColor: FormattingId, + syncAxis: FormattingId, + showMainAxis: FormattingId, + orientation: FormattingId, +} = { + cardUid: "Visual-axis-card", + groupUid: "axis-group", + axis: { + objectName: BulletChartObjectNames.Axis.name, + propertyName: nameof("axis") + }, + axisColor: { + objectName: BulletChartObjectNames.Axis.name, + propertyName: nameof("axisColor") + }, + syncAxis: { + objectName: BulletChartObjectNames.SyncAxis.name, + propertyName: nameof("syncAxis") + }, + showMainAxis: { + objectName: BulletChartObjectNames.SyncAxis.name, + propertyName: nameof("showMainAxis") + }, + orientation: { + objectName: BulletChartObjectNames.Orientation.name, + propertyName: nameof("orientation") + }, +} as const; + + +export const colorsReference: { + cardUid: string; + groupUid: string; + minColor: FormattingId; + needsImprovementColor: FormattingId; + satisfactoryColor: FormattingId; + goodColor: FormattingId; + veryGoodColor: FormattingId; + bulletColor: FormattingId; +} = { + cardUid: "Visual-colors-card", + groupUid: "colors-group", + minColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("minColor") + }, + needsImprovementColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("needsImprovementColor") + }, + satisfactoryColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("satisfactoryColor") + }, + goodColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("goodColor") + }, + veryGoodColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("veryGoodColor") + }, + bulletColor: { + objectName: BulletChartObjectNames.Colors.name, + propertyName: nameof("bulletColor") + }, +} as const; + class TextSizeDefaults { public static readonly DefaultSize = 11; @@ -20,6 +155,41 @@ const orientationOptions: IEnumMember[] = [ { value: BulletChartOrientation.VerticalBottom, displayName: "Visual_Orientation_VerticalBottom" }, ]; + +class BaseFontCardSettings extends Card { + font = new formattingSettings.FontControl({ + name: "font", + displayName: "Font", + displayNameKey: "Visual_Font", + fontSize: new formattingSettings.NumUpDown({ + name: "fontSize", + displayName: "Text Size", + displayNameKey: "Visual_TextSize", + value: TextSizeDefaults.DefaultSize, + options: { + minValue: { value: TextSizeDefaults.MinSize, type: powerbi.visuals.ValidatorType.Min }, + maxValue: { value: TextSizeDefaults.MaxSize, type: powerbi.visuals.ValidatorType.Max }, + } + }), + fontFamily: new formattingSettings.FontPicker({ + name: "fontFamily", + value: "Arial, sans-serif", + }), + bold: new formattingSettings.ToggleSwitch({ + name: "fontBold", + value: false, + }), + italic: new formattingSettings.ToggleSwitch({ + name: "fontItalic", + value: false, + }), + underline: new formattingSettings.ToggleSwitch({ + name: "fontUnderline", + value: false, + }), + }); +} + class DataValuesCard extends Card { targetValue = new formattingSettings.NumUpDown({ name: "targetValue", @@ -124,7 +294,7 @@ class TooltipsCard extends Card { slices = [this.valueCustomName, this.targetCustomName, this.target2CustomName]; } -class LabelsCard extends Card { +class LabelsCard extends BaseFontCardSettings { show: SimpleSlice = new formattingSettings.ToggleSwitch({ name: "show", displayName: "Show", @@ -143,17 +313,6 @@ class LabelsCard extends Card { value: { value: "#000000" } }); - fontSize = new formattingSettings.NumUpDown({ - name: "fontSize", - displayName: "Text size", - displayNameKey: "Visual_TextSize", - value: TextSizeDefaults.DefaultSize, - options: { - minValue: { value: TextSizeDefaults.MinSize, type: powerbi.visuals.ValidatorType.Min }, - maxValue: { value: TextSizeDefaults.MaxSize, type: powerbi.visuals.ValidatorType.Max }, - } - }); - maxWidth = new formattingSettings.NumUpDown({ name: "maxWidth", displayName: "Maximum width", @@ -161,10 +320,10 @@ class LabelsCard extends Card { value: 80, }); - name: string = "labels"; - displayName: string = "Category labels"; + name: string = BulletChartObjectNames.Labels.name; + displayName: string = BulletChartObjectNames.Labels.displayName displayNameKey: string = "Visual_CategoryLabels"; - slices = [this.labelColor, this.fontSize, this.maxWidth]; + slices = [this.font, this.labelColor, this.maxWidth]; } class OrientationCard extends Card { @@ -176,8 +335,8 @@ class OrientationCard extends Card { value: orientationOptions[0], }); - name: string = "orientation"; - displayName: string = "Orientation"; + name: string = BulletChartObjectNames.Orientation.name; + displayName: string = BulletChartObjectNames.Orientation.displayName; displayNameKey: string = "Visual_Orientation"; slices = [this.orientation]; } @@ -225,8 +384,8 @@ class ColorsCard extends Card { value: { value: "#000000" } }); - name: string = "colors"; - displayName: string = "Colors"; + name: string = BulletChartObjectNames.Colors.name; + displayName: string = BulletChartObjectNames.Colors.displayName; displayNameKey: string = "Visual_Colors"; slices = [ this.minColor, @@ -270,8 +429,8 @@ class AxisCard extends Card { value: { value: "#808080" }, }); - name: string = "axis"; - displayName: string = "Axis"; + name: string = BulletChartObjectNames.Axis.name; + displayName: string = BulletChartObjectNames.Axis.displayName; displayNameKey: string = "Visual_Axis"; slices = [this.axisColor, this.measureUnits, this.unitsColor]; } @@ -293,8 +452,8 @@ class SyncAxis extends Card { value: false, }); - name: string = "syncAxis"; - displayName: string = "Sync axis"; + name: string = BulletChartObjectNames.SyncAxis.name; + displayName: string = BulletChartObjectNames.SyncAxis.displayName; displayNameKey: string = "Visual_AxisSync"; slices = [this.showMainAxis]; } diff --git a/src/dataInterfaces.ts b/src/dataInterfaces.ts index 33dacbf..45084c5 100644 --- a/src/dataInterfaces.ts +++ b/src/dataInterfaces.ts @@ -60,6 +60,16 @@ export interface BarData { key: string; } +export enum BarRectType { + Minimum = "Minimum", + NeedsImprovement = "NeedsImprovement", + Satisfactory = "Satisfactory", + Good = "Good", + VeryGood = "VeryGood", + Bullet = "Bullet", +} + + export interface BarRect extends SelectableDataPoint { barIndex: number; start: number; @@ -70,6 +80,7 @@ export interface BarRect extends SelectableDataPoint { tooltipInfo?: VisualTooltipDataItem[]; key: string; highlight?: boolean; + type: BarRectType; } export interface TargetValue { @@ -103,4 +114,4 @@ export interface BulletChartTooltipItem { value: any; metadata?: DataViewValueColumn; customName: string; -} \ No newline at end of file +} diff --git a/src/visual.ts b/src/visual.ts index 4815101..d34b5bc 100644 --- a/src/visual.ts +++ b/src/visual.ts @@ -31,63 +31,34 @@ import {select, Selection} from 'd3-selection'; import lodashIsnumber from "lodash.isnumber"; import lodashMax from "lodash.max"; import powerbiVisualsApi from "powerbi-visuals-api"; - -// d3 -type BulletSelection = Selection; import {scaleLinear, ScaleLinear} from "d3-scale"; import {group} from "d3-array" -import IViewport = powerbiVisualsApi.IViewport; -import DataView = powerbiVisualsApi.DataView; -import DataViewCategoryColumn = powerbiVisualsApi.DataViewCategoryColumn; -import DataViewMetadataColumn = powerbiVisualsApi.DataViewMetadataColumn; -import DataViewValueColumns = powerbiVisualsApi.DataViewValueColumns; -import DataViewValueColumn = powerbiVisualsApi.DataViewValueColumn; - -import IVisual = powerbiVisualsApi.extensibility.IVisual; -import IColorPalette = powerbiVisualsApi.extensibility.IColorPalette; -import IVisualHost = powerbiVisualsApi.extensibility.visual.IVisualHost; -import VisualUpdateOptions = powerbiVisualsApi.extensibility.visual.VisualUpdateOptions; -import VisualConstructorOptions = powerbiVisualsApi.extensibility.visual.VisualConstructorOptions; -import VisualTooltipDataItem = powerbiVisualsApi.extensibility.VisualTooltipDataItem; -import ISelectionManager = powerbiVisualsApi.extensibility.ISelectionManager; -import IVisualEventService = powerbiVisualsApi.extensibility.IVisualEventService; - -// powerbi.visuals -import ISelectionId = powerbiVisualsApi.visuals.ISelectionId; -import ISelectionIdBuilder = powerbiVisualsApi.visuals.ISelectionIdBuilder; - // powerbi.extensibility.utils.type import {pixelConverter as PixelConverter} from "powerbi-visuals-utils-typeutils"; // powerbi.extensibility.utils.interactivity import { interactivityBaseService as interactivityService, - interactivitySelectionService, - interactivityBaseService + interactivityBaseService, + interactivitySelectionService } from "powerbi-visuals-utils-interactivityutils"; -import appendClearCatcher = interactivityService.appendClearCatcher; -import IInteractivityService = interactivityService.IInteractivityService; -import createInteractivitySelectionService = interactivitySelectionService.createInteractivitySelectionService; -import BaseDataPoint = interactivityBaseService.BaseDataPoint; // powerbi.extensibility.utils.formatting // import { textMeasurementService as tms, valueFormatter } from "powerbi-visuals-utils-formattingutils"; // import TextProperties = tms.TextProperties; // import TextMeasurementService = tms.textMeasurementService; - import {textMeasurementService as TextMeasurementService} from "powerbi-visuals-utils-formattingutils"; import * as valueFormatter from "powerbi-visuals-utils-formattingutils/lib/src/valueFormatter"; import {TextProperties} from "powerbi-visuals-utils-formattingutils/lib/src/interfaces"; // powerbi.extensibility.utils.chart -import {axisInterfaces, axisScale, axis as AxisHelper} from "powerbi-visuals-utils-chartutils"; -import IAxisProperties = axisInterfaces.IAxisProperties; +import {axis as AxisHelper, axisInterfaces, axisScale} from "powerbi-visuals-utils-chartutils"; // powerbi.extensibility.utils.tooltip import { - ITooltipServiceWrapper, createTooltipServiceWrapper, + ITooltipServiceWrapper, TooltipEnabledDataPoint } from "powerbi-visuals-utils-tooltiputils"; @@ -95,13 +66,77 @@ import { import {ColorHelper} from "powerbi-visuals-utils-colorutils"; import {BulletChartColumns} from "./BulletChartColumns"; -import {BulletChartModel, BulletChartTooltipItem, BarValueRect, BarData, BarRect, TargetValue} from "./dataInterfaces"; +import { + BarData, + BarRect, + BarRectType, + BarValueRect, + BulletChartModel, + BulletChartTooltipItem, + TargetValue +} from "./dataInterfaces"; import {VisualLayout} from "./visualLayout"; import {BulletBehaviorOptions, BulletWebBehavior} from "./behavior"; import {BulletChartOrientation} from "./BulletChartOrientation"; import {FormattingSettingsService} from "powerbi-visuals-utils-formattingmodel"; -import {BulletChartSettingsModel} from "./BulletChartSettingsModel"; +import {BulletChartObjectNames, BulletChartSettingsModel} from "./BulletChartSettingsModel"; + +// OnObject +import { + HtmlSubSelectableClass, + HtmlSubSelectionHelper, + SubSelectableDisplayNameAttribute, + SubSelectableObjectNameAttribute, + SubSelectableTypeAttribute, +} from "powerbi-visuals-utils-onobjectutils" + +// d3 +type BulletSelection = Selection; +import IViewport = powerbiVisualsApi.IViewport; +import DataView = powerbiVisualsApi.DataView; +import DataViewCategoryColumn = powerbiVisualsApi.DataViewCategoryColumn; +import DataViewMetadataColumn = powerbiVisualsApi.DataViewMetadataColumn; +import DataViewValueColumns = powerbiVisualsApi.DataViewValueColumns; +import DataViewValueColumn = powerbiVisualsApi.DataViewValueColumn; + +import IVisual = powerbiVisualsApi.extensibility.IVisual; +import IColorPalette = powerbiVisualsApi.extensibility.IColorPalette; +import IVisualHost = powerbiVisualsApi.extensibility.visual.IVisualHost; +import VisualUpdateOptions = powerbiVisualsApi.extensibility.visual.VisualUpdateOptions; +import VisualConstructorOptions = powerbiVisualsApi.extensibility.visual.VisualConstructorOptions; +import VisualTooltipDataItem = powerbiVisualsApi.extensibility.VisualTooltipDataItem; +import ISelectionManager = powerbiVisualsApi.extensibility.ISelectionManager; +import IVisualEventService = powerbiVisualsApi.extensibility.IVisualEventService; +// powerbi.visuals +import ISelectionId = powerbiVisualsApi.visuals.ISelectionId; +import ISelectionIdBuilder = powerbiVisualsApi.visuals.ISelectionIdBuilder; +import appendClearCatcher = interactivityService.appendClearCatcher; +import IInteractivityService = interactivityService.IInteractivityService; +import createInteractivitySelectionService = interactivitySelectionService.createInteractivitySelectionService; +import BaseDataPoint = interactivityBaseService.BaseDataPoint; +import IAxisProperties = axisInterfaces.IAxisProperties; import ILocalizationManager = powerbi.extensibility.ILocalizationManager; +import CustomVisualSubSelection = powerbi.visuals.CustomVisualSubSelection; +import SubSelectionStyles = powerbi.visuals.SubSelectionStyles; +import VisualSubSelectionShortcuts = powerbi.visuals.VisualSubSelectionShortcuts; +import VisualShortcutType = powerbi.visuals.VisualShortcutType; +import CustomVisualObject = powerbi.visuals.CustomVisualObject; +import SubSelectionStylesType = powerbi.visuals.SubSelectionStylesType; + +import { labelsReference, axisReference, colorsReference } from "./BulletChartSettingsModel"; + +interface ClassAndSelector { + className: string; + selectorName: string; +} + +function CreateClassAndSelector(className: string) { + return { + className: className, + selectorName: "." + className, + }; +} + export class BulletChart implements IVisual { private static ScrollBarSize: number = 22; @@ -123,6 +158,12 @@ export class BulletChart implements IVisual { private static MarkerMarginHorizontalEnd: number = 5 * BulletChart.MarkerMarginHorizontal; private static MarkerMarginVertical: number = BulletChart.BulletSize / 4; private static FontFamily: string = "Segoe UI"; + + private static CategoryLabelsSelector: ClassAndSelector = CreateClassAndSelector("categoryLabel"); + public static MeasureUnitsSelector: ClassAndSelector = CreateClassAndSelector("measureUnits"); + private static AxisSelector: ClassAndSelector = CreateClassAndSelector("axis"); + private static BulletContainerSelector: ClassAndSelector = CreateClassAndSelector("bulletContainer"); + private baselineDelta: number = 0; // Variables private clearCatcher: BulletSelection; @@ -134,6 +175,9 @@ export class BulletChart implements IVisual { private localizationManager: ILocalizationManager; private formattingSettingsService: FormattingSettingsService; private visualSettings: BulletChartSettingsModel; + private subSelectionHelper: HtmlSubSelectionHelper; + private formatMode: boolean = false; + public visualOnObjectFormatting?: powerbi.extensibility.visual.VisualOnObjectFormatting; private behavior: BulletWebBehavior; private interactivityService: IInteractivityService; @@ -196,87 +240,82 @@ export class BulletChart implements IVisual { highlight: any, toolTipItems: BulletChartTooltipItem[], selectionIdBuilder: () => powerbi.visuals.ISelectionIdBuilder, - firstScale: number, - firstFillColor: string, - firstColor: string, - secondScale: number, - secondFillColor: string, - secondColor: string, - thirdScale: number, - thirdFillColor: string, - thirdColor: string, - fourthScale: number, - fourthFillColor: string, - fourthColor: string, - fifthScale: number, - lastScale: number, - lastFillColor: string, - lastColor: string, + minimumScale: number, minFillColor: string, minColor: string, + needsImprovementScale: number, needsImprovementFillColor: string, needsImprovementColor: string, + satisfactoryScale: number, satisfactoryFillColor: string, satisfactoryColor: string, + goodScale: number, goodFillColor: string, goodColor: string, + veryGoodScale: number, veryGoodFillColor: string, veryGoodColor: string, + maximumScale: number, ) { if (anyRangeIsDefined) { BulletChart.addItemToBarArray( bulletModel.barRects, idx, - firstScale, - secondScale, - firstFillColor, - firstColor, + minimumScale, + needsImprovementScale, + minFillColor, + minColor, maxStrokeWidthBars, toolTipItems, selectionIdBuilder(), - highlight + highlight, + BarRectType.Minimum, ); BulletChart.addItemToBarArray( bulletModel.barRects, idx, - secondScale, - thirdScale, - secondFillColor, - secondColor, + needsImprovementScale, + satisfactoryScale, + needsImprovementFillColor, + needsImprovementColor, maxStrokeWidthBars, toolTipItems, selectionIdBuilder(), - highlight + highlight, + BarRectType.NeedsImprovement, ); BulletChart.addItemToBarArray( bulletModel.barRects, idx, - thirdScale, - fourthScale, - thirdFillColor, - thirdColor, + satisfactoryScale, + goodScale, + satisfactoryFillColor, + satisfactoryColor, maxStrokeWidthBars, toolTipItems, selectionIdBuilder(), - highlight + highlight, + BarRectType.Satisfactory, ); BulletChart.addItemToBarArray( bulletModel.barRects, idx, - fourthScale, - fifthScale, - fourthFillColor, - fourthColor, + goodScale, + veryGoodScale, + goodFillColor, + goodColor, maxStrokeWidthBars, toolTipItems, selectionIdBuilder(), - highlight + highlight, + BarRectType.Good, ); BulletChart.addItemToBarArray( bulletModel.barRects, idx, - fifthScale, - lastScale, - lastFillColor, - lastColor, + veryGoodScale, + maximumScale, + veryGoodFillColor, + veryGoodColor, maxStrokeWidthBars, toolTipItems, selectionIdBuilder(), - highlight + highlight, + BarRectType.VeryGood, ); } } @@ -358,7 +397,7 @@ export class BulletChart implements IVisual { if (categorical.Category) { category = valueFormatter.format(categoricalValues.Category[idx], categoryFormatString); category = TextMeasurementService.getTailoredTextOrDefault( - BulletChart.getTextProperties(category, visualSettings.labels.fontSize.value), + BulletChart.getTextProperties(category, visualSettings.labels.font.fontSize.value), isVerticalOrientation ? this.MaxLabelWidth : visualSettings.labels.maxWidth.value ); } @@ -438,8 +477,8 @@ export class BulletChart implements IVisual { viewportLength: BulletChart.zeroValue }; - bulletModel.labelHeight = (visualSettings.labels.show.value || BulletChart.zeroValue) && parseFloat(PixelConverter.fromPoint(visualSettings.labels.fontSize.value)); - bulletModel.labelHeightTop = (visualSettings.labels.show.value || BulletChart.zeroValue) && parseFloat(PixelConverter.fromPoint(visualSettings.labels.fontSize.value)) / BulletChart.value1dot4; + bulletModel.labelHeight = (visualSettings.labels.show.value || BulletChart.zeroValue) && parseFloat(PixelConverter.fromPoint(visualSettings.labels.font.fontSize.value)); + bulletModel.labelHeightTop = (visualSettings.labels.show.value || BulletChart.zeroValue) && parseFloat(PixelConverter.fromPoint(visualSettings.labels.font.fontSize.value)) / BulletChart.value1dot4; bulletModel.spaceRequiredForBarHorizontally = Math.max(visualSettings.axis.axis.value ? BulletChart.value60 : BulletChart.value28, bulletModel.labelHeight + BulletChart.value25); bulletModel.viewportLength = Math.max(0, (isVerticalOrientation ? (viewPortHeight - bulletModel.labelHeightTop - BulletChart.SubtitleMargin - BulletChart.value25 - BulletChart.YMarginVertical * BulletChart.value2) @@ -490,23 +529,23 @@ export class BulletChart implements IVisual { .domain([minimum, maximum]) .range(isVerticalOrientation ? [bulletModel.viewportLength, 0] : [0, bulletModel.viewportLength]); - const firstScale: number = scale(minimum); - const secondScale: number = scale(needsImprovement); - const thirdScale: number = scale(satisfactory); - const fourthScale: number = scale(good); - const fifthScale: number = scale(veryGood); - const lastScale: number = scale(maximum); + const minimumScale: number = scale(minimum); + const needsImprovementScale: number = scale(needsImprovement); + const satisfactoryScale: number = scale(satisfactory); + const goodScale: number = scale(good); + const veryGoodScale: number = scale(veryGood); + const maximumScale: number = scale(maximum); const valueScale: number = scale(categoryValue); - const firstColor: string = visualSettings.colors.minColor.value.value, - secondColor: string = visualSettings.colors.needsImprovementColor.value.value, - thirdColor: string = visualSettings.colors.satisfactoryColor.value.value, - fourthColor: string = visualSettings.colors.goodColor.value.value, - lastColor: string = visualSettings.colors.veryGoodColor.value.value, - firstFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : firstColor, - secondFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : secondColor, - thirdFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : thirdColor, - fourthFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : fourthColor, - lastFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : lastColor; + const minColor: string = visualSettings.colors.minColor.value.value, + needsImprovementColor: string = visualSettings.colors.needsImprovementColor.value.value, + satisfactoryColor: string = visualSettings.colors.satisfactoryColor.value.value, + goodColor: string = visualSettings.colors.goodColor.value.value, + veryGoodColor: string = visualSettings.colors.veryGoodColor.value.value, + minFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : minColor, + needsImprovementFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : needsImprovementColor, + satisfactoryFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : satisfactoryColor, + goodFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : goodColor, + veryGoodFillColor: string = colorHelper.isHighContrast ? colorHelper.getThemeColor() : veryGoodColor; const selectionIdBuilder = () => categorical.Category ? visualHost.createSelectionIdBuilder().withCategory(categorical.Category, idx) @@ -515,19 +554,25 @@ export class BulletChart implements IVisual { const maxStrokeWidthBars: number = 0.5, maxStrokeWidthValues: number = 1.5; BulletChart.addItems( - anyRangeIsDefined, bulletModel, idx, maxStrokeWidthBars, highlight, toolTipItems, selectionIdBuilder, - firstScale, firstFillColor, firstColor, - secondScale, secondFillColor, secondColor, - thirdScale, thirdFillColor, thirdColor, - fourthScale, fourthFillColor, fourthColor, - fifthScale, - lastScale, lastFillColor, lastColor, + anyRangeIsDefined, + bulletModel, + idx, + maxStrokeWidthBars, + highlight, + toolTipItems, + selectionIdBuilder, + minimumScale, minFillColor, minColor, + needsImprovementScale, needsImprovementFillColor, needsImprovementColor, + satisfactoryScale, satisfactoryFillColor, satisfactoryColor, + goodScale, goodFillColor, goodColor, + veryGoodScale, veryGoodFillColor, veryGoodColor, + maximumScale ); const bulletFillColor = colorHelper.isHighContrast ? colorHelper.getThemeColor() : visualSettings.colors.bulletColor.value.value; - BulletChart.addItemToBarArray(bulletModel.valueRects, idx, firstScale, valueScale, bulletFillColor, visualSettings.colors.bulletColor.value.value, - maxStrokeWidthValues, toolTipItems, selectionIdBuilder(), highlight); + BulletChart.addItemToBarArray(bulletModel.valueRects, idx, minimumScale, valueScale, bulletFillColor, visualSettings.colors.bulletColor.value.value, + maxStrokeWidthValues, toolTipItems, selectionIdBuilder(), highlight, BarRectType.Bullet); const scaledTarget: number = scale(targetValue || BulletChart.zeroValue); @@ -662,7 +707,9 @@ export class BulletChart implements IVisual { strokeWidth: number, tooltipInfo: BulletChartTooltipItem[], selectionIdBuilder: ISelectionIdBuilder, - highlight: boolean): void { + highlight: boolean, + barRectType: BarRectType, + ): void { if (!isNaN(start) && !isNaN(end)) collection.push({ @@ -681,6 +728,7 @@ export class BulletChart implements IVisual { .createSelectionId() )).getKey(), highlight: highlight, + type: barRectType, }); } @@ -735,6 +783,16 @@ export class BulletChart implements IVisual { this.selectionManager = options.host.createSelectionManager(); this.localizationManager = options.host.createLocalizationManager(); this.formattingSettingsService = new FormattingSettingsService(this.localizationManager); + this.subSelectionHelper = HtmlSubSelectionHelper.createHtmlSubselectionHelper({ + hostElement: options.element, + subSelectionService: options.host.subSelectionService, + }); + + this.visualOnObjectFormatting = { + getSubSelectionStyles: (subSelections) => this.getSubSelectionStyles(subSelections), + getSubSelectionShortcuts: (subSelections) => this.getSubSelectionShortcuts(subSelections), + getSubSelectables: (filter) => this.getSubSelectables(filter), + }; this.layout = new VisualLayout(null, { top: 0, @@ -776,6 +834,7 @@ export class BulletChart implements IVisual { } const dataView: DataView = options.dataViews[0]; this.layout.viewport = options.viewport; + this.formatMode = options.formatMode ?? false; this.visualSettings = this.formattingSettingsService.populateFormattingSettingsModel(BulletChartSettingsModel, dataView); this.visualSettings.setLocalizedOptions(this.localizationManager); @@ -789,7 +848,7 @@ export class BulletChart implements IVisual { this.data = data; - this.baselineDelta = TextMeasurementHelper.estimateSvgTextBaselineDelta(BulletChart.getTextProperties(BulletChart.oneString, this.data.settings.labels.fontSize.value)); + this.baselineDelta = TextMeasurementHelper.estimateSvgTextBaselineDelta(BulletChart.getTextProperties(BulletChart.oneString, this.data.settings.labels.font.fontSize.value)); if (this.interactivityService) { this.interactivityService.applySelectionStateToData(this.data.barRects); @@ -819,6 +878,15 @@ export class BulletChart implements IVisual { } this.behavior.renderSelection(this.interactivityService.hasSelection()); + + this.subSelectionHelper.setFormatMode(options.formatMode); + const shouldUpdateSubSelection = options.type & (powerbi.VisualUpdateType.Data + | powerbi.VisualUpdateType.Resize + | powerbi.VisualUpdateType.FormattingSubSelectionChange); + if (this.formatMode && shouldUpdateSubSelection) { + this.subSelectionHelper.updateOutlinesFromSubSelections(options.subSelections, true); + } + this.events.renderingFinished(options); } @@ -826,7 +894,7 @@ export class BulletChart implements IVisual { this.labelGraphicsContext.selectAll("text").remove(); this.bulletGraphicsContext.selectAll("rect").remove(); this.bulletGraphicsContext.selectAll("text").remove(); - this.bulletGraphicsContext.selectAll("axis").remove(); + this.bulletGraphicsContext.selectAll(BulletChart.AxisSelector.className).remove(); this.bulletGraphicsContext.selectAll("path").remove(); this.bulletGraphicsContext.selectAll("line").remove(); this.bulletGraphicsContext.selectAll("tick").remove(); @@ -887,7 +955,11 @@ export class BulletChart implements IVisual { if (model.settings.labels.show.value) { barSelection .join("text") - .classed("title", true) + .classed(BulletChart.CategoryLabelsSelector.className, true) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Labels.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Labels.displayName) + .attr(SubSelectableTypeAttribute, SubSelectionStylesType.Text) .attr("x", (d: BarData) => { if (reversed) return ( @@ -904,11 +976,15 @@ export class BulletChart implements IVisual { this.baselineDelta + BulletChart.BulletSize / BulletChart.value2 ) - .attr("fill", model.settings.labels.labelColor.value.value) - .attr( + .style("fill", model.settings.labels.labelColor.value.value) + .style( "font-size", - PixelConverter.fromPoint(model.settings.labels.fontSize.value) + PixelConverter.fromPoint(model.settings.labels.font.fontSize.value) ) + .style("font-family", model.settings.labels.font.fontFamily.value) + .style("font-weight", model.settings.labels.font.bold.value ? "bold" : "normal") + .style("font-style", model.settings.labels.font.italic.value ? "italic" : "normal") + .style("text-decoration", model.settings.labels.font.underline.value ? "underline" : "none") .text((d: BarData) => d.categoryLabel) .append("title") .text((d: BarData) => d.categoryLabel); @@ -927,10 +1003,10 @@ export class BulletChart implements IVisual { const groupedBullets = group(rects, (d: BarRect) => d.barIndex); const groupedBulletsSelection = this.bulletGraphicsContext - .selectAll("g.rect-container") + .selectAll(`g.${BulletChart.BulletContainerSelector.className}`) .data(groupedBullets) .join("g") - .classed("rect-container", true) + .classed(BulletChart.BulletContainerSelector.className, true) .attr("focusable", true) .attr("tabindex", 0); @@ -944,6 +1020,9 @@ export class BulletChart implements IVisual { .attr("width", ((d: BarRect) => Math.max(BulletChart.zeroValue, d.end - d.start))) .attr("height", BulletChart.BulletSize) .classed("range", true) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, (d: BarRect) => d.type) + .attr(SubSelectableDisplayNameAttribute, (d: BarRect) => d.type) .style("fill", (d: BarRect) => d.fillColor) .style("stroke", (d: BarRect) => d.strokeColor) .style("stroke-width", (d: BarRect) => d.strokeWidth); @@ -958,6 +1037,9 @@ export class BulletChart implements IVisual { .attr("width", ((d: BarValueRect) => Math.max(BulletChart.zeroValue, d.end - d.start))) .attr("height", BulletChart.BulletSize * BulletChart.value1 / BulletChart.value4) .classed("value", true) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Bullet.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Bullet.displayName) .style("fill", (d: BarValueRect) => d.fillColor) .style("stroke", (d: BarValueRect) => d.strokeColor) .style("stroke-width", (d: BarValueRect) => d.strokeWidth); @@ -982,6 +1064,7 @@ export class BulletChart implements IVisual { if (model.settings.axis.measureUnits.value) { barSelection .join("text") + .classed(BulletChart.MeasureUnitsSelector.className, true) .attr("x", ((d: BarData) => { if (reversed) return BulletChart.XMarginHorizontalLeft + BulletChart.XMarginHorizontalRight + model.viewportLength + BulletChart.SubtitleMargin; @@ -1010,13 +1093,8 @@ export class BulletChart implements IVisual { this.interactivityService.bind(behaviorOptions); } - this.tooltipServiceWrapper.addTooltip( - valueSelection, - (data: TooltipEnabledDataPoint) => data.tooltipInfo); - this.tooltipServiceWrapper.addTooltip( - bullets, - (data: TooltipEnabledDataPoint) => data.tooltipInfo - ); + this.tooltipServiceWrapper.addTooltip(valueSelection, (data: TooltipEnabledDataPoint) => data.tooltipInfo); + this.tooltipServiceWrapper.addTooltip(bullets, (data: TooltipEnabledDataPoint) => data.tooltipInfo); } private static value3: number = 3; @@ -1066,16 +1144,24 @@ export class BulletChart implements IVisual { if (model.settings.labels.show.value) { barSelection .join("text") - .classed("title", true) + .classed(BulletChart.CategoryLabelsSelector.className, true) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Labels.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Labels.displayName) + .attr(SubSelectableTypeAttribute, SubSelectionStylesType.Text) .attr("x", (d: BarData) => d.x) .attr("y", () => { return labelsStartPosition; }) - .attr("fill", model.settings.labels.labelColor.value.value) - .attr( + .style("fill", model.settings.labels.labelColor.value.value) + .style( "font-size", - PixelConverter.fromPoint(model.settings.labels.fontSize.value) + PixelConverter.fromPoint(model.settings.labels.font.fontSize.value) ) + .style("font-family", model.settings.labels.font.fontFamily.value) + .style("font-weight", model.settings.labels.font.bold.value ? "bold" : "normal") + .style("font-style", model.settings.labels.font.italic.value ? "italic" : "normal") + .style("text-decoration", model.settings.labels.font.underline.value ? "underline" : "none") .text((d: BarData) => d.categoryLabel) .append("title") .text((d: BarData) => d.categoryLabel); @@ -1094,7 +1180,10 @@ export class BulletChart implements IVisual { ); return `translate(${xLocation},${yLocation})`; }) - .classed("axis", true) + .classed(BulletChart.AxisSelector.className, true) + .classed(HtmlSubSelectableClass, this.formatMode && this.visualSettings.axis.axis.value) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Axis.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Axis.displayName) .call(bar.xAxisProperties.axis) .style( "font-size", @@ -1119,7 +1208,10 @@ export class BulletChart implements IVisual { return `translate(${xLocation},${yLocation})`; }) - .classed("axis", true) + .classed(BulletChart.AxisSelector.className, true) + .classed(HtmlSubSelectableClass, this.formatMode && this.visualSettings.axis.axis.value) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Axis.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Axis.displayName) .call(bar.xAxisProperties.axis) .style( "font-size", @@ -1155,10 +1247,10 @@ export class BulletChart implements IVisual { const groupedBullets = group(rects, (d: BarRect) => d.barIndex); const groupedBulletsSelection = this.bulletGraphicsContext - .selectAll("g.rect-container") + .selectAll(`g.${BulletChart.BulletContainerSelector.className}`) .data(groupedBullets) .join("g") - .classed("rect-container", true) + .classed(BulletChart.BulletContainerSelector.className, true) .attr("focusable", true) .attr("tabindex", 0); @@ -1173,6 +1265,9 @@ export class BulletChart implements IVisual { .attr("width", BulletChart.BulletSize) .classed("range", true) .style("fill", (d: BarRect) => d.fillColor) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, (d: BarRect) => d.type) + .attr(SubSelectableDisplayNameAttribute, (d: BarRect) => d.type) .style("stroke", (d: BarRect) => d.strokeColor) .style("stroke-width", (d: BarRect) => d.strokeWidth); @@ -1186,6 +1281,9 @@ export class BulletChart implements IVisual { .attr("height", ((d: BarValueRect) => Math.max(BulletChart.zeroValue, d.start - d.end))) .attr("width", BulletChart.BulletSize * BulletChart.value1 / BulletChart.value4) .classed("value", true) + .classed(HtmlSubSelectableClass, this.formatMode) + .attr(SubSelectableObjectNameAttribute, BulletChartObjectNames.Bullet.name) + .attr(SubSelectableDisplayNameAttribute, BulletChartObjectNames.Bullet.displayName) .style("fill", (d: BarValueRect) => d.fillColor) .attr("stroke", (d: BarRect) => d.strokeColor) .attr("stroke-width", (d: BarRect) => d.strokeWidth); @@ -1212,6 +1310,7 @@ export class BulletChart implements IVisual { if (model.settings.axis.measureUnits.value) { barSelection .join("text") + .classed(BulletChart.MeasureUnitsSelector.className, true) .attr("x", ((d: BarData) => d.x + BulletChart.BulletSize)) .attr("y", () => { return labelsStartPos + BulletChart.SubtitleMargin + BulletChart.value12; @@ -1236,12 +1335,8 @@ export class BulletChart implements IVisual { this.interactivityService.bind(behaviorOptions); } - this.tooltipServiceWrapper.addTooltip( - valueSelectionMerged, - (data: TooltipEnabledDataPoint) => data.tooltipInfo); - this.tooltipServiceWrapper.addTooltip( - bullets, - (data: TooltipEnabledDataPoint) => data.tooltipInfo); + this.tooltipServiceWrapper.addTooltip(valueSelectionMerged, (data: TooltipEnabledDataPoint) => data.tooltipInfo); + this.tooltipServiceWrapper.addTooltip(bullets, (data: TooltipEnabledDataPoint) => data.tooltipInfo); } private drawFirstTargets( @@ -1339,6 +1434,285 @@ export class BulletChart implements IVisual { public getFormattingModel(): powerbi.visuals.FormattingModel { return this.formattingSettingsService.buildFormattingModel(this.visualSettings); } + + private getSubSelectionStyles(subSelections: CustomVisualSubSelection[]) { + const visualObjects = subSelections[0]?.customVisualObjects; + if (!visualObjects) { + return undefined; + } + + let visualObject: CustomVisualObject; + if (visualObjects.length > 0 && visualObjects[0] != null) { + visualObject = visualObjects[0]; + } else { + return undefined; + } + + switch (visualObject.objectName) { + case BulletChartObjectNames.Labels.name: + return this.getLabelsStyles(); + case BulletChartObjectNames.Axis.name: + return this.getAxisStyles(); + // colors + case BulletChartObjectNames.Minimum.name: + return this.getMinimumStyles(); + case BulletChartObjectNames.NeedsImprovement.name: + return this.getNeedsImprovementStyles(); + case BulletChartObjectNames.Satisfactory.name: + return this.getSatisfactoryStyles(); + case BulletChartObjectNames.Good.name: + return this.getGoodStyles(); + case BulletChartObjectNames.VeryGood.name: + return this.getVeryGoodStyles(); + case BulletChartObjectNames.Bullet.name: + return this.getBulletStyles(); + default: + return undefined; + } + } + + private getSubSelectionShortcuts(subSelections: powerbi.visuals.CustomVisualSubSelection[]) { + const visualObjects = subSelections[0]?.customVisualObjects; + if (!visualObjects) { + return undefined; + } + + let visualObject: CustomVisualObject; + if (visualObjects.length > 0 && visualObjects[0] != null) { + visualObject = visualObjects[0]; + } else { + return undefined; + } + + switch (visualObject.objectName) { + case BulletChartObjectNames.Labels.name: + return this.getLabelsShortcuts(); + case BulletChartObjectNames.Axis.name: + return this.getAxisShortcuts(); + case BulletChartObjectNames.Minimum.name: + case BulletChartObjectNames.NeedsImprovement.name: + case BulletChartObjectNames.Satisfactory.name: + case BulletChartObjectNames.Good.name: + case BulletChartObjectNames.VeryGood.name: + case BulletChartObjectNames.Bullet.name: + return this.getColorsShortcuts(); + default: + return undefined; + } + } + + private getSubSelectables(filter?: powerbi.visuals.SubSelectionStylesType): CustomVisualSubSelection[] | undefined { + return this.subSelectionHelper.getAllSubSelectables(filter); + } + + private getLabelsStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Text, + fontFamily: { + reference: { ...labelsReference.fontFamily }, + label: labelsReference.fontFamily.propertyName + }, + bold: { + reference: { ...labelsReference.bold }, + label: labelsReference.bold.propertyName + }, + italic: { + reference: { ...labelsReference.italic }, + label: labelsReference.italic.propertyName + }, + underline: { + reference: { ...labelsReference.underline }, + label: labelsReference.underline.propertyName + }, + fontSize: { + reference: { ...labelsReference.fontSize }, + label: labelsReference.fontSize.propertyName + }, + fontColor: { + reference: { ...labelsReference.labelColor }, + label: labelsReference.labelColor.propertyName + } + }; + } + + private getAxisStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...axisReference.axisColor, + }, + label: this.localizationManager.getDisplayName("Visual_AxisColor"), + }, + } + } + + private getMinimumStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.minColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_MinimumColor"), + } + } + } + + private getNeedsImprovementStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.needsImprovementColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_NeedsImprovementColor"), + } + } + } + + private getSatisfactoryStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.satisfactoryColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_SatisfactoryColor"), + }, + } + } + + private getGoodStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.goodColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_GoodColor") + }, + } + } + + private getVeryGoodStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.veryGoodColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_VeryGoodColor"), + }, + } + } + + private getBulletStyles(): SubSelectionStyles { + return { + type: SubSelectionStylesType.Shape, + fill: { + reference: { + ...colorsReference.bulletColor, + }, + label: this.localizationManager.getDisplayName("Visual_Colors_BulletColor"), + }, + } + } + + + private getLabelsShortcuts(): VisualSubSelectionShortcuts { + return [ + { + type: VisualShortcutType.Reset, + relatedResetFormattingIds: [ + labelsReference.bold, + labelsReference.fontFamily, + labelsReference.fontSize, + labelsReference.italic, + labelsReference.underline, + labelsReference.labelColor + ] + }, + { + type: VisualShortcutType.Toggle, + ...labelsReference.show, + disabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_DeleteLabels"), + enabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_AddLabels"), + }, + { + type: VisualShortcutType.Divider, + }, + { + type: VisualShortcutType.Navigate, + destinationInfo: { cardUid: labelsReference.cardUid }, + label: this.localizationManager.getDisplayName("Visual_OnObject_FormatLabels") + } + ]; + } + + private getAxisShortcuts(): VisualSubSelectionShortcuts { + return [ + { + type: VisualShortcutType.Reset, + relatedResetFormattingIds: [axisReference.axis, axisReference.axisColor, axisReference.syncAxis, axisReference.showMainAxis, axisReference.orientation], + }, + { + type: VisualShortcutType.Toggle, + ...axisReference.axis, + disabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_HideAxis"), + enabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_ShowAxis"), + }, + { + type: VisualShortcutType.Toggle, + ...axisReference.syncAxis, + disabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_DoNotSyncAxis"), + enabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_SyncAxis"), + }, + { + type: VisualShortcutType.Toggle, + ...axisReference.showMainAxis, + disabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_HideMainAxis"), + enabledLabel: this.localizationManager.getDisplayName("Visual_OnObject_ShowMainAxis"), + }, + { + type: VisualShortcutType.Picker, + ...axisReference.orientation, + label: this.localizationManager.getDisplayName("Visual_Orientation"), + }, + { + type: VisualShortcutType.Divider, + }, + { + type: VisualShortcutType.Navigate, + destinationInfo: { cardUid: axisReference.cardUid }, + label: this.localizationManager.getDisplayName("Visual_OnObject_FormatAxis"), + } + ]; + } + + private getColorsShortcuts(): VisualSubSelectionShortcuts { + return [ + { + type: VisualShortcutType.Reset, + relatedResetFormattingIds: [ + colorsReference.minColor, + colorsReference.needsImprovementColor, + colorsReference.satisfactoryColor, + colorsReference.goodColor, + colorsReference.veryGoodColor, + colorsReference.bulletColor + ] + }, + { + type: VisualShortcutType.Divider, + }, + { + type: VisualShortcutType.Navigate, + destinationInfo: { cardUid: colorsReference.cardUid }, + label: this.localizationManager.getDisplayName("Visual_OnObject_FormatColors") + }, + ] + } } diff --git a/stringResources/en-US/resources.resjson b/stringResources/en-US/resources.resjson index 64f8058..841a8e7 100644 --- a/stringResources/en-US/resources.resjson +++ b/stringResources/en-US/resources.resjson @@ -12,7 +12,19 @@ "Visual_DataValues_MaximumPercent": "Maximum %", "Visual_CategoryLabels": "Category labels", "Visual_Show": "Show", - "Visual_Color": "color", + "Visual_Color": "Color", + "Visual_Font": "Font", + "Visual_OnObject_DeleteLabels": "Delete data labels", + "Visual_OnObject_AddLabels": "Add data labels", + "Visual_OnObject_FormatLabels": "Format data labels", + "Visual_OnObject_HideAxis": "Hide axis", + "Visual_OnObject_ShowAxis": "Show axis", + "Visual_OnObject_DoNotSyncAxis": "Do not sync axis", + "Visual_OnObject_SyncAxis": "Sync axis", + "Visual_OnObject_ShowMainAxis": "Show main axis", + "Visual_OnObject_HideMainAxis": "Hide main axis", + "Visual_OnObject_FormatAxis": "Format axis", + "Visual_OnObject_FormatColors": "Format colors", "Visual_Description_Color": "Select color for data labels", "Visual_TextSize": "Text Size", "Visual_Orientation": "Orientation", diff --git a/style/bulletChart.less b/style/bulletChart.less index 6e6ab88..82446b5 100644 --- a/style/bulletChart.less +++ b/style/bulletChart.less @@ -64,7 +64,7 @@ } } - rect.range { + .bulletContainer { &:focus { outline: none; } @@ -73,4 +73,4 @@ outline: -webkit-focus-ring-color auto 4px; } } -} \ No newline at end of file +} diff --git a/test/BulletChartBuilder.ts b/test/BulletChartBuilder.ts index d655a8f..1e32fbb 100644 --- a/test/BulletChartBuilder.ts +++ b/test/BulletChartBuilder.ts @@ -33,7 +33,7 @@ import VisualConstructorOptions = powerbiVisualsApi.extensibility.visual.VisualC // powerbi.extensibility.utils.test import { VisualBuilderBase } from "powerbi-visuals-utils-testutils"; -import { BulletChart as VisualClass } from "../src/visual"; +import {BulletChart, BulletChart as VisualClass} from "../src/visual"; import {BulletChartOrientation} from "../src/BulletChartOrientation"; import {BulletChartSettingsModel} from "../src/BulletChartSettingsModel"; @@ -73,7 +73,7 @@ export class BulletChartBuilder extends VisualBuilderBase { public get measureUnits(): NodeListOf { return this.mainElement .querySelector("g") - .querySelectorAll("text:not(.title)"); + .querySelectorAll(BulletChart.MeasureUnitsSelector.selectorName); } public get rangeRectsGrouped(): SVGElement[][] { diff --git a/test/visualTest.ts b/test/visualTest.ts index a630334..e7bfcb1 100644 --- a/test/visualTest.ts +++ b/test/visualTest.ts @@ -537,15 +537,15 @@ describe("BulletChart", () => { visualBuilder.updateFlushAllD3Transitions(dataView); - expect(visualBuilder.measureUnits).toBeInDOM; + expect(visualBuilder.measureUnits.length).toBeGreaterThan(0); visualBuilder.measureUnits.forEach((e) => - expect(e.innerHTML).toBe(measureUnits) + expect(e.textContent).toBe(measureUnits) ); }); it("units color", () => { let color = "#333333"; - dataView.metadata.objects.axis.measureUnits = "someUnit"; + dataView.metadata.objects.axis.measureUnits = "someUnits"; dataView.metadata.objects.axis.unitsColor = getSolidColorStructuralObject(color);