diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..b782dbeec
Binary files /dev/null and b/.DS_Store differ
diff --git a/.changeset/sharp-bees-grin.md b/.changeset/sharp-bees-grin.md
new file mode 100644
index 000000000..e55b47f2e
--- /dev/null
+++ b/.changeset/sharp-bees-grin.md
@@ -0,0 +1,5 @@
+---
+"@ebay/ebayui-core": patch
+---
+
+TS fix for combobox
diff --git a/.changeset/sixty-experts-marry.md b/.changeset/sixty-experts-marry.md
new file mode 100644
index 000000000..dc3b97d2c
--- /dev/null
+++ b/.changeset/sixty-experts-marry.md
@@ -0,0 +1,5 @@
+---
+"@ebay/ebayui-core": minor
+---
+
+Add area chart
diff --git a/.changeset/slimy-items-change.md b/.changeset/slimy-items-change.md
new file mode 100644
index 000000000..e56e08676
--- /dev/null
+++ b/.changeset/slimy-items-change.md
@@ -0,0 +1,5 @@
+---
+"@ebay/ebayui-core": patch
+---
+
+fix(table): replaced column-type of "row-header" with boolean row-header
diff --git a/.changeset/thirty-walls-notice.md b/.changeset/thirty-walls-notice.md
new file mode 100644
index 000000000..96a359a6f
--- /dev/null
+++ b/.changeset/thirty-walls-notice.md
@@ -0,0 +1,5 @@
+---
+"@ebay/ebayui-core": patch
+---
+
+Upgrade dependencies
diff --git a/.changeset/wet-wombats-roll.md b/.changeset/wet-wombats-roll.md
new file mode 100644
index 000000000..2e10ba609
--- /dev/null
+++ b/.changeset/wet-wombats-roll.md
@@ -0,0 +1,5 @@
+---
+"@ebay/ebayui-core": patch
+---
+
+Updated the component-browser.ts file to reference shared attributes from tags-html.d.ts and added the Textbox class implementation.
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
index 7dcbef084..c16543b18 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/node.js.yml
@@ -51,7 +51,7 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: coverage/lcov.info
- name: Upload artifact
- uses: actions/upload-pages-artifact@v1
+ uses: actions/upload-pages-artifact@v3
# Deployment job
deploy:
diff --git a/.gitignore b/.gitignore
index 5b22ef625..256eb9667 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@ yarn.lock
.env
_cdn
__screenshots__
+.DS_Store
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 1c4632b33..0e11df6a8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,10 +41,10 @@
"@commitlint/config-conventional": "^19",
"@ebay/browserslist-config": "^2.10.0",
"@ebay/skin": "~18.6.0",
- "@marko/compiler": "^5.37.23",
+ "@marko/compiler": "^5.39.10",
"@marko/prettyprint": "^3.0.1",
"@marko/testing-library": "^6",
- "@marko/type-check": "^1.2.4",
+ "@marko/type-check": "^1.3.12",
"@marko/vite": "^4.1.20",
"@storybook/addon-a11y": "^8.3.6",
"@storybook/addon-docs": "^8.3.6",
@@ -72,7 +72,7 @@
"libphonenumber-js": "^1.11.17",
"lint-staged": "^15.2.11",
"lintspaces-cli": "^1.0.0",
- "marko": "^5.35.32",
+ "marko": "^5.37.10",
"playwright": "^1.49.1",
"postcss-less": "^6.0.0",
"prettier": "^3.4.2",
@@ -215,12 +215,13 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
- "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz",
+ "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==",
+ "license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.2",
- "@babel/types": "^7.26.0",
+ "@babel/parser": "^7.26.5",
+ "@babel/types": "^7.26.5",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -383,9 +384,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
- "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
+ "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -426,19 +427,6 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-simple-access": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
- "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
@@ -508,11 +496,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
- "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz",
+ "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.0"
+ "@babel/types": "^7.26.5"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1086,14 +1075,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
- "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
+ "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-simple-access": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1560,14 +1548,14 @@
}
},
"node_modules/@babel/plugin-transform-typescript": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz",
- "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.5.tgz",
+ "integrity": "sha512-GJhPO0y8SD5EYVCy2Zr+9dSZcEgaSmq5BLR0Oc25TOEhC+ba49vUAGZFjy8v79z9E1mdldq4x9d1xgh4L1d5dQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.25.9",
"@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.26.5",
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
"@babel/plugin-syntax-typescript": "^7.25.9"
},
@@ -1825,16 +1813,16 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
- "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz",
+ "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/generator": "^7.25.9",
- "@babel/parser": "^7.25.9",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.5",
+ "@babel/parser": "^7.26.5",
"@babel/template": "^7.25.9",
- "@babel/types": "^7.25.9",
+ "@babel/types": "^7.26.5",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1843,9 +1831,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
- "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz",
+ "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
@@ -3760,55 +3748,62 @@
"marko": "^4.12.4 || ^5"
}
},
- "node_modules/@marko/babel-utils": {
- "version": "6.5.10",
- "resolved": "https://registry.npmjs.org/@marko/babel-utils/-/babel-utils-6.5.10.tgz",
- "integrity": "sha512-ziaYtREMoFCpUp2GByDz2ELj5n5SrO9ATlhuBt5TPYAKElHWck1pqq71WVnHvJ9qqRhT92bWQ6N1eyWjTDNy/Q==",
- "dependencies": {
- "@babel/runtime": "^7.26.0",
- "jsesc": "^3.0.2",
- "relative-import-path": "^1.0.0"
- }
- },
"node_modules/@marko/compiler": {
- "version": "5.37.23",
- "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.37.23.tgz",
- "integrity": "sha512-LRaRheDcCzZrARINcQtbMEUokfXM8ia4itcQbBWok/pIScSwAD8ahGjqneHaS6Y3H07vilflSqjHzBqSzS1SGw==",
+ "version": "5.39.10",
+ "resolved": "https://registry.npmjs.org/@marko/compiler/-/compiler-5.39.10.tgz",
+ "integrity": "sha512-bq1mLsyi1swyb2mJOuqOlHCUCBN/SnbtL13fZvYftmVvHMT2sd/U2uBfW1AAJwoWyOww1jcwdyiM8Bd2IvCzZA==",
+ "license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/core": "^7.26.0",
- "@babel/generator": "^7.26.2",
- "@babel/parser": "^7.26.2",
+ "@babel/generator": "^7.26.3",
+ "@babel/parser": "^7.26.3",
"@babel/plugin-syntax-typescript": "^7.25.9",
- "@babel/plugin-transform-modules-commonjs": "^7.25.9",
- "@babel/plugin-transform-typescript": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.26.3",
+ "@babel/plugin-transform-typescript": "^7.26.3",
"@babel/runtime": "^7.26.0",
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.26.0",
+ "@babel/traverse": "^7.26.4",
+ "@babel/types": "^7.26.3",
"@luxass/strip-json-comments": "^1.3.2",
- "@marko/babel-utils": "^6.5.10",
"complain": "^1.6.1",
"he": "^1.2.0",
- "htmljs-parser": "^5.5.2",
- "jsesc": "^3.0.2",
+ "htmljs-parser": "^5.5.3",
+ "jsesc": "^3.1.0",
"kleur": "^4.1.5",
"lasso-package-root": "^1.0.1",
"raptor-regexp": "^1.0.1",
"raptor-util": "^3.2.0",
+ "relative-import-path": "^1.0.0",
"resolve-from": "^5.0.0",
"self-closing-tags": "^1.0.1",
"source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@marko/compiler/node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/@marko/language-tools": {
- "version": "2.4.5",
- "resolved": "https://registry.npmjs.org/@marko/language-tools/-/language-tools-2.4.5.tgz",
- "integrity": "sha512-8nYK1KFUaDn9O6FWe9Ueq7PkQm0zfjilpvf9qChxrl43ftJ/23mtDkXBX3bizbSc+1REFuuiVyE+VQqDJCGePA==",
+ "version": "2.5.12",
+ "resolved": "https://registry.npmjs.org/@marko/language-tools/-/language-tools-2.5.12.tgz",
+ "integrity": "sha512-fftw8n5kpknSpZT/mQLpl6IG8bHVFh/q6lxpARxlhIQkgnwSU88d7BsnZ7OyA8CRMg1xI4+MfbyJpKg/l/7flQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.2",
+ "@babel/parser": "^7.26.3",
"@luxass/strip-json-comments": "^1.3.2",
- "htmljs-parser": "^5.5.2",
+ "htmljs-parser": "^5.5.3",
"relative-import-path": "^1.0.0"
},
"peerDependencies": {
@@ -3975,33 +3970,19 @@
"marko": "^3 || ^4 || ^5"
}
},
- "node_modules/@marko/translator-default": {
- "version": "6.0.23",
- "resolved": "https://registry.npmjs.org/@marko/translator-default/-/translator-default-6.0.23.tgz",
- "integrity": "sha512-F7IuNidVbOcZnir29EkYhGu+pfR9Fz1RE2MFtE0HOhghkAFTUnY2XUcx+6iVkCRZbgEq54ROl+3xsr7ORWLJWA==",
- "dependencies": {
- "@babel/runtime": "^7.26.0",
- "@marko/babel-utils": "^6.5.10",
- "magic-string": "^0.30.12",
- "self-closing-tags": "^1.0.1"
- },
- "peerDependencies": {
- "@marko/compiler": "^5.16.1",
- "marko": "^5.17.2"
- }
- },
"node_modules/@marko/type-check": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@marko/type-check/-/type-check-1.2.4.tgz",
- "integrity": "sha512-nMq5c8NxvfKSPUfzIXj6TJ+7gJJdBDMvqWHY3icsvGb7Nfoj2ojXQXJ+T2C/00A133zvUvnDrRK1VGBbmSRyww==",
+ "version": "1.3.12",
+ "resolved": "https://registry.npmjs.org/@marko/type-check/-/type-check-1.3.12.tgz",
+ "integrity": "sha512-SWVQ+vf7w0vG0JAOwRxGX6Ot6J8kSDhtSpxx08zkC/rc9bq1q2Yptcc5xvy8X1vWzPKexqh7EqvGtC/8IXB9uA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@luxass/strip-json-comments": "^1.3.2",
- "@marko/language-tools": "^2.4.5",
+ "@marko/language-tools": "^2.5.12",
"arg": "^5.0.2",
"kleur": "^4.1.5",
- "typescript": "^5.6.3"
+ "typescript": "^5.7.2"
},
"bin": {
"marko-type-check": "dist/cli.js",
@@ -9877,9 +9858,9 @@
}
},
"node_modules/htmljs-parser": {
- "version": "5.5.2",
- "resolved": "https://registry.npmjs.org/htmljs-parser/-/htmljs-parser-5.5.2.tgz",
- "integrity": "sha512-5pNHk0dSIFLA0ucC2NJv4ikhOdAFKT2X3zo69uAd5fqt3AX4kaXD9F17k/98LKCn5u4Dd9PXeso2iJ0bFw0X+Q==",
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/htmljs-parser/-/htmljs-parser-5.5.3.tgz",
+ "integrity": "sha512-uX5BWkdIJV2qfxTVMcFJGPSqx9EYZGfZQv7THtNfA3cIr2zfwlzjojqO7jHDntO3cJUQauRSjBETBkiaCi3wtA==",
"license": "MIT"
},
"node_modules/htmlparser2": {
@@ -11798,9 +11779,9 @@
}
},
"node_modules/magic-string": {
- "version": "0.30.12",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
- "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
@@ -11950,12 +11931,13 @@
}
},
"node_modules/marko": {
- "version": "5.35.32",
- "resolved": "https://registry.npmjs.org/marko/-/marko-5.35.32.tgz",
- "integrity": "sha512-LuzveiXXQZoiRqdoRdlWXrC/JxZWMItfMixnHZ8T3XY2FPAFa8f8UwscIXsu8BSFD3Vzi60hCL1RHHf7W6nFtw==",
+ "version": "5.37.10",
+ "resolved": "https://registry.npmjs.org/marko/-/marko-5.37.10.tgz",
+ "integrity": "sha512-UUBDJNG1VzGAWRUiLqxG5R91OkJnYKvnUsFRFKE9/xkfO1Sp0eP2mWOwfcRbhaQtfj1DvUkR+Q9pxtoaF7/fUg==",
+ "license": "MIT",
"dependencies": {
- "@marko/compiler": "^5.37.23",
- "@marko/translator-default": "^6.0.23",
+ "@babel/runtime": "^7.26.0",
+ "@marko/compiler": "^5.39.9",
"app-module-path": "^2.2.0",
"argly": "^1.2.0",
"browser-refresh-client": "1.1.4",
@@ -11963,6 +11945,7 @@
"csstype": "^3.1.3",
"events-light": "^1.0.5",
"listener-tracker": "^2.0.0",
+ "magic-string": "^0.30.17",
"minimatch": "^9.0.5",
"raptor-util": "^3.2.0",
"resolve-from": "^5.0.0",
@@ -11971,6 +11954,9 @@
},
"bin": {
"markoc": "bin/markoc"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
}
},
"node_modules/marko/node_modules/brace-expansion": {
@@ -15784,9 +15770,9 @@
}
},
"node_modules/typescript": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
- "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
+ "version": "5.7.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
+ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/package.json b/package.json
index 797cba9b0..0080de007 100644
--- a/package.json
+++ b/package.json
@@ -101,10 +101,10 @@
"@commitlint/config-conventional": "^19",
"@ebay/browserslist-config": "^2.10.0",
"@ebay/skin": "~18.6.0",
- "@marko/compiler": "^5.37.23",
+ "@marko/compiler": "^5.39.10",
"@marko/prettyprint": "^3.0.1",
"@marko/testing-library": "^6",
- "@marko/type-check": "^1.2.4",
+ "@marko/type-check": "^1.3.12",
"@marko/vite": "^4.1.20",
"@storybook/addon-a11y": "^8.3.6",
"@storybook/addon-docs": "^8.3.6",
@@ -132,7 +132,7 @@
"libphonenumber-js": "^1.11.17",
"lint-staged": "^15.2.11",
"lintspaces-cli": "^1.0.0",
- "marko": "^5.35.32",
+ "marko": "^5.37.10",
"playwright": "^1.49.1",
"postcss-less": "^6.0.0",
"prettier": "^3.4.2",
diff --git a/src/common/charts/shared.ts b/src/common/charts/shared.ts
index 46b7351a0..e4c689c87 100644
--- a/src/common/charts/shared.ts
+++ b/src/common/charts/shared.ts
@@ -1,8 +1,8 @@
export const chartFontFamily = '"Market Sans", Arial, sans-serif',
backgroundColor = "var(--color-background-primary)",
gridColor = "var(--color-data-viz-grid)",
- labelsColor = "var(--color-data-viz-labels)",
- legendColor = "var(--color-data-viz-legend)",
+ labelsColor = "var(--color-foreground-secondary)",
+ legendColor = "var(--color-foreground-primary)",
legendInactiveColor = "var(--color-data-viz-legend-inactive)",
legendHoverColor = "var(--color-data-viz-legend-hover)",
tooltipBackgroundColor = "var(--color-background-primary)",
@@ -79,6 +79,7 @@ export const chartFontFamily = '"Market Sans", Arial, sans-serif',
const color = strokeColorMapping[i % strokeColorMapping.length];
series[i].lineColor = color;
series[i].borderColor = color;
+ series[i].fillOpacity = 1;
}
},
setDonutColors = function (series: any) {
@@ -110,4 +111,25 @@ export const chartFontFamily = '"Market Sans", Arial, sans-serif',
});
return colors.map((color: any) => color.lineColor);
+ },
+ setSeriesMarkerStyles = function (series: Highcharts.PlotAreaOptions[]) {
+ series.forEach((s, i) => {
+ s.zIndex = series.length - i;
+ s.marker = {
+ symbol: "circle",
+ lineWidth: 1,
+ fillColor: "black",
+ lineColor: "white",
+ states: {
+ hover: {
+ animation: { duration: 0 },
+ radius: 4,
+ lineWidth: 2,
+ },
+ normal: {
+ animation: false,
+ },
+ },
+ };
+ });
};
diff --git a/src/components/ebay-area-chart/README.md b/src/components/ebay-area-chart/README.md
index 779c8170d..396a18cd5 100644
--- a/src/components/ebay-area-chart/README.md
+++ b/src/components/ebay-area-chart/README.md
@@ -8,3 +8,9 @@
The area chart displays one to five series of data points as an interactive stacked area chart
+
+## Examples and Documentation
+
+- [Storybook](https://ebay.github.io/ebayui-core/?path=/docs/charts-ebay-area-chart)
+- [Storybook Docs](https://ebay.github.io/ebayui-core/?path=/docs/charts-ebay-area-chart)
+- [Code Examples](https://github.com/eBay/ebayui-core/tree/master/src/components/ebay-area-chart/examples)
diff --git a/src/components/ebay-area-chart/area-chart.stories-ignore.ts b/src/components/ebay-area-chart/area-chart.stories-ignore.ts
deleted file mode 100644
index 4ba576e1c..000000000
--- a/src/components/ebay-area-chart/area-chart.stories-ignore.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-import { tagToString } from "../../common/storybook/storybook-code-source";
-import { addRenderBodies } from "../../common/storybook/utils";
-import Readme from "./README.md";
-import Component from "./index.marko";
-import sampleSeriesData from "./examples/data.json";
-import { Story } from "@storybook/marko";
-import type { Input } from "./component";
-
-const Template: Story = (args) => ({
- input: addRenderBodies(args),
-});
-
-export default {
- title: "charts/ebay-area-chart",
- excludeStories: ".*",
- component: Component,
- parameters: {
- docs: {
- description: {
- component: Readme,
- },
- },
- },
- argTypes: {
- title: {
- type: { name: "string", required: false },
- description: "A title displayed above the graph",
- },
- description: {
- type: { name: "string", required: true },
- description: "A description of what the chart is displaying",
- },
- series: {
- type: { name: "object", required: true },
- description:
- "The series is an array of one to five arrays of point objects, each point contains an `x`, `y`, and `label`. `x` is an epoch/unix time code, `y` is a numeric value, `label` is what is displayed for the `y` value in the tool tip",
- },
- xAxisLabelFormat: {
- type: { name: "string", required: false },
- description:
- "Used to modify the display of the x-axis labels. Accepts a string like `{value:%Y-%m-%d}`. Refer to https://api.highcharts.com/class-reference/Highcharts.Time#dateFormat for available format keys",
- table: {
- defaultValue: {
- summary: "{value:%b %e}",
- },
- },
- },
- xAxisPositioner: {
- type: { name: "function", required: false },
- description:
- "A custom function that returns an array of epoch/unix time values where x-axis labels will be displayed. You can access `this.dataMin` and `this.dataMax` from the function to help determine positions.",
- },
- yAxisLabels: {
- type: { name: "array", required: false },
- description:
- "An array of labels to use on the y-axis. Use in conjunction with yAxisPositioner. Make sure the length of the yAxisLabels match the length of the positions array returned by the yAxisPositioner function",
- },
- yAxisPositioner: {
- type: { name: "function", required: false },
- description:
- "A custom function that returns an array of numeric values where y-axis labels will be displayed. You can access `this.dataMin` and `this.dataMax` from the function to help determine positions",
- },
- class: {
- type: { name: "string", require: false },
- description:
- "A class name that will be added to the main chart container",
- },
- },
-};
-
-export const Standard = Template.bind({});
-Standard.args = {
- title: "Single series sample area chart",
- description: "this chart displays 30 days of sample values",
- series: sampleSeriesData.slice(0, 1) as any,
-};
-Standard.parameters = {
- docs: {
- source: {
- code: tagToString("bar-chart", Standard.args),
- },
- },
-};
-
-export const TwoSeries = Template.bind({});
-TwoSeries.args = {
- title: "Two series sample area chart",
- description:
- "this chart displays 30 days of values for sample1 and sample2",
- series: sampleSeriesData.slice(0, 2) as any,
-};
-TwoSeries.parameters = {
- docs: {
- source: {
- code: tagToString("bar-chart", TwoSeries.args),
- },
- },
-};
-
-export const ThreeSeries = Template.bind({});
-ThreeSeries.args = {
- title: "Three series sample area chart",
- description:
- "this chart displays 30 days of values for sample1, sample2 and sample3",
- series: sampleSeriesData.slice(0, 3) as any,
-};
-ThreeSeries.parameters = {
- docs: {
- source: {
- code: tagToString("bar-chart", ThreeSeries.args),
- },
- },
-};
-
-export const FourSeries = Template.bind({});
-FourSeries.args = {
- title: "Four series sample area chart",
- description:
- "this chart displays 30 days of values for sample1, sample2, sample3, and sample4",
- series: sampleSeriesData.slice(0, 4) as any,
-};
-FourSeries.parameters = {
- docs: {
- source: {
- code: tagToString("bar-chart", FourSeries.args),
- },
- },
-};
-
-export const FiveSeries = Template.bind({});
-FiveSeries.args = {
- title: "Five series sample area chart",
- description:
- "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
- series: sampleSeriesData as any,
-};
-FiveSeries.parameters = {
- docs: {
- source: {
- code: tagToString("bar-chart", FiveSeries.args),
- },
- },
-};
diff --git a/src/components/ebay-area-chart/area-chart.stories.ts b/src/components/ebay-area-chart/area-chart.stories.ts
new file mode 100644
index 000000000..918c61e47
--- /dev/null
+++ b/src/components/ebay-area-chart/area-chart.stories.ts
@@ -0,0 +1,229 @@
+import { tagToString } from "../../common/storybook/storybook-code-source";
+import { addRenderBodies } from "../../common/storybook/utils";
+import Readme from "./README.md";
+import Component from "./index.marko";
+import sampleSeriesData from "./examples/data.json";
+import { Story } from "@storybook/marko";
+import type { Input } from "./component";
+
+const Template: Story = (args) => ({
+ input: addRenderBodies(args),
+});
+
+const seriesDataWithoutLabels = sampleSeriesData.map((series) => {
+ const { data, ...rest } = series;
+ return {
+ ...rest,
+ data: data.map((point) => {
+ const { label, ...rest } = point;
+ return rest;
+ }),
+ };
+})
+
+export default {
+ title: "charts/ebay-area-chart",
+ component: Component,
+ parameters: {
+ docs: {
+ description: {
+ component: Readme,
+ },
+ },
+ },
+ argTypes: {
+ title: {
+ type: { name: "string", required: false },
+ description: "A title displayed above the graph",
+ },
+ description: {
+ type: { name: "string", required: true },
+ description: "A description of what the chart is displaying",
+ },
+ series: {
+ type: { name: "object", required: true },
+ description:
+ "The series is an array of one to five arrays of point objects, each point contains an `x`, `y`, and `label`. `x` is an epoch/unix time code, `y` is a numeric value, `label` is what is displayed for the `y` value in the tool tip",
+ },
+ highchartOptions: {
+ type: { name: "object", required: false },
+ description:
+ "A highcharts options object that will be merged with the default options",
+ },
+ xLabelFormatter: {
+ type: { name: "function", required: false },
+ description:
+ "A function that will be used to format the x-axis labels. Provides the value and a date formatter function. By default is formatted as `MMM dd`. Refer to https://api.highcharts.com/class-reference/Highcharts.Time#dateFormat for available format keys",
+ },
+ yLabelFormatter: {
+ type: { name: "function", required: false },
+ description:
+ "A function that will be used to format the y-axis labels. By default is formatted as USD currency.",
+ },
+ tooltipValueFormatter: {
+ type: { name: "function", required: false },
+ description:
+ "A function that will be used to format the tooltip series values and total. By default is formatted as USD currency.",
+ },
+ areaType: {
+ type: { name: "string", required: false },
+ description:
+ "The type of area chart to display. By default is `spline`. Options are `spline` and `area`",
+ },
+ class: {
+ type: { name: "string", require: false },
+ description:
+ "A class name that will be added to the main chart container",
+ },
+ },
+};
+
+export const Standard = Template.bind({});
+Standard.args = {
+ title: "Single series sample area chart",
+ description: "this chart displays 30 days of sample values",
+ series: sampleSeriesData.slice(0, 1) as Highcharts.SeriesAreaOptions[],
+};
+Standard.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", Standard.args),
+ },
+ },
+};
+
+export const TwoSeries = Template.bind({});
+TwoSeries.args = {
+ title: "Two series sample area chart",
+ description:
+ "this chart displays 30 days of values for sample1 and sample2",
+ series: sampleSeriesData.slice(0, 2) as Highcharts.SeriesAreaOptions[],
+};
+TwoSeries.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", TwoSeries.args),
+ },
+ },
+};
+
+export const ThreeSeries = Template.bind({});
+ThreeSeries.args = {
+ title: "Three series sample area chart",
+ description:
+ "this chart displays 30 days of values for sample1, sample2 and sample3",
+ series: sampleSeriesData.slice(0, 3) as Highcharts.SeriesAreaOptions[],
+};
+ThreeSeries.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", ThreeSeries.args),
+ },
+ },
+};
+
+export const FourSeries = Template.bind({});
+FourSeries.args = {
+ title: "Four series sample area chart",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, and sample4",
+ series: sampleSeriesData.slice(0, 4) as Highcharts.SeriesAreaOptions[],
+};
+FourSeries.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", FourSeries.args),
+ },
+ },
+};
+
+export const FiveSeries = Template.bind({});
+FiveSeries.args = {
+ title: "Five series sample area chart",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
+ series: sampleSeriesData as Highcharts.SeriesAreaOptions[],
+};
+FiveSeries.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", FiveSeries.args),
+ },
+ },
+};
+
+export const WithUnitlessYFormat = Template.bind({});
+WithUnitlessYFormat.args = {
+ title: "Custom y-axis label and tooltip value format",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
+ series: seriesDataWithoutLabels as Highcharts.SeriesAreaOptions[],
+ yLabelFormatter: (value) => `${value}`,
+ tooltipValueFormatter: (value) => `${value}`,
+};
+WithUnitlessYFormat.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", WithUnitlessYFormat.args),
+ },
+ },
+};
+
+export const WithXLabelFormat = Template.bind({});
+WithXLabelFormat.args = {
+ title: "Custom x-axis label format",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
+ series: sampleSeriesData as Highcharts.SeriesAreaOptions[],
+ xLabelFormatter: (value, dateFormat) => {
+ if (typeof value !== "number") {
+ return value;
+ }
+ return dateFormat("%A", value);
+ },
+ tooltipTitleFormatter(value, dateFormat) {
+ if (typeof value !== "number") {
+ return value;
+ }
+ return dateFormat("%A", value);
+ },
+};
+
+WithXLabelFormat.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", WithXLabelFormat.args),
+ },
+ },
+};
+
+export const NonSpline = Template.bind({});
+NonSpline.args = {
+ title: "Area chart with non-spline type",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
+ series: sampleSeriesData.slice(0, 1) as Highcharts.SeriesAreaOptions[],
+ areaType: "area",
+};
+
+NonSpline.parameters = {
+ docs: {
+ source: {
+ code: tagToString("ebay-area-chart", NonSpline.args),
+ },
+ },
+};
+
+export const CustomHighchartOptions = Template.bind({});
+CustomHighchartOptions.args = {
+ title: "Custom highchart options",
+ description:
+ "this chart displays 30 days of values for sample1, sample2, sample3, sample4, and sample5",
+ series: sampleSeriesData.slice(0, 1) as Highcharts.SeriesAreaOptions[],
+ highchartOptions: {
+ yAxis: {
+ ceiling: 45000,
+ tickAmount: 4,
+ },
+ },
+};
\ No newline at end of file
diff --git a/src/components/ebay-area-chart/component.ts b/src/components/ebay-area-chart/component.ts
index 18217f339..4106caeda 100644
--- a/src/components/ebay-area-chart/component.ts
+++ b/src/components/ebay-area-chart/component.ts
@@ -11,41 +11,49 @@ import {
tooltipShadows,
setSeriesColors,
colorMapping,
+ setSeriesMarkerStyles,
} from "../../common/charts/shared";
-import { debounce } from "../../common/event-utils";
import { ebayLegend } from "../../common/charts/legend";
import type { WithNormalizedProps } from "../../global";
+import tooltipTemplate from "./tooltip.marko";
+import type { Input as TooltipInput } from "./tooltip.marko";
import type HighchartsTypes from "highcharts";
declare const Highcharts: typeof HighchartsTypes;
+// Extend highcharts series data with a label property
+declare module "highcharts" {
+ export interface Point {
+ label?: string;
+ }
+}
+
interface AreaChartInput extends Omit, `on${string}`> {
- title: Highcharts.TitleOptions["text"];
- /**
- * input.xAxisLabelFormat allows overriding the default short month / day label.
- * refer to https://api.highcharts.com/class-reference/Highcharts.Time#dateFormat to customize
- **/
- "x-axis-label-format"?: Highcharts.XAxisLabelsOptions["format"];
- "x-axis-positioner"?: Highcharts.XAxisOptions["tickPositioner"];
- "y-axis-labels"?: Highcharts.YAxisLabelsOptions["format"];
- "y-axis-positioner"?: Highcharts.YAxisOptions["tickPositioner"];
+ title?: Highcharts.TitleOptions["text"];
description?: Highcharts.SeriesAccessibilityOptionsObject["description"];
+ series: Highcharts.SeriesAreaOptions | Highcharts.SeriesAreaOptions[];
+ tooltipValueFormatter?: (value: string | number) => string;
+ tooltipTitleFormatter?: (
+ value: string | number,
+ dateFormat: typeof Highcharts.dateFormat,
+ ) => string;
+ xLabelFormatter?: (
+ value: string | number,
+ dateFormat: typeof Highcharts.dateFormat,
+ ) => string;
+ yLabelFormatter?: (value: string | number) => string;
+ areaType?: "areaspline" | "area";
+ highchartOptions?: Highcharts.Options;
"cdn-highcharts"?: string;
"cdn-highcharts-accessibility"?: string;
"cdn-highcharts-pattern-fill"?: string;
version?: string;
- series: Highcharts.SeriesAreaOptions | Highcharts.SeriesAreaOptions[];
- "on-load-error": (err: Error) => void;
+ "on-load-error"?: (err: Error) => void;
}
export interface Input extends WithNormalizedProps {}
-const pointSize = 1.5;
-
class AreaChart extends Marko.Component {
declare chartRef: Highcharts.Chart;
- declare mouseOut: ReturnType;
- declare mouseOver: ReturnType;
- declare points: Highcharts.Point[];
onInput() {
// if chartRef does not exist do not try to run setupCharts as it may be server side and highcharts only works on the client side
@@ -68,45 +76,35 @@ class AreaChart extends Marko.Component {
handleError(err: Error) {
this.emit("load-error", err);
}
+
handleSuccess() {
this._initializeHighchartExtensions();
- this._setupEvents();
this._setupCharts();
}
+
getContainerId() {
return `ebay-bar-chart-${this.id}`;
}
+
+ /**
+ * Initialize the highchart extensions
+ */
_initializeHighchartExtensions() {
// add custom legend wrapper function
- // eslint-disable-next-line no-undef,new-cap
ebayLegend(Highcharts);
}
- _setupEvents() {
- // bind functions to keep scope and setup debounced versions of function calls
- this.debounce = debounce.bind(this);
- this.handleMouseOver = this.handleMouseOver.bind(this);
- this.handleMouseOut = this.handleMouseOut.bind(this);
- this.mouseOut = this.debounce(() => this.handleMouseOut(), 80); // 80ms delay for debounce
- this.mouseOver = this.debounce(
- (e: Event) => this.handleMouseOver(e),
- 85,
- ); // 85ms delay for debounce so it doesn't colide with mouseOut debounce calls
- }
+
+ /**
+ * Set up the chart with the input data and configuration options.
+ */
_setupCharts() {
// check if a single series was passed in for series and if so add it to a new array
const series = Array.isArray(this.input.series)
? this.input.series
: [this.input.series];
- // update the zIndex of each series object so they render in the correct order
- // and configure the markers that are displayed on hover
- series.forEach((s, i) => {
- s.zIndex = series.length - i;
- s.marker = {
- symbol: "circle",
- lineWidth: 3,
- };
- });
+ setSeriesMarkerStyles(series);
+
setSeriesColors(series);
const config: Highcharts.Options = {
@@ -114,7 +112,7 @@ class AreaChart extends Marko.Component {
chart: this.getChartConfig(),
colors: colorMapping,
xAxis: this.getXAxisConfig(),
- yAxis: this.getYAxisConfig(series),
+ yAxis: this.getYAxisConfig(),
legend: this.getLegendConfig(),
tooltip: this.getTooltipConfig(),
plotOptions: this.getPlotOptions(),
@@ -124,285 +122,265 @@ class AreaChart extends Marko.Component {
},
};
// initialize and keep reference to chart
- // eslint-disable-next-line no-undef,new-cap
- this.chartRef = Highcharts.chart(this.getContainerId(), config);
+ this.chartRef = Highcharts.chart(
+ this.getContainerId(),
+ this._mergeConfigs(config, this.input.highchartOptions ?? {}),
+ );
+ }
+
+ /**
+ * Default format function for the tooltip titles
+ */
+ _tooltipTitleFormatter(
+ value: number | string,
+ dateFormat: typeof Highcharts.dateFormat,
+ ) {
+ if (typeof value === "string") {
+ value = parseFloat(value);
+ }
+ return dateFormat("%b %e, %Y", value);
}
+
+ /**
+ * Default format function for the tooltip values
+ */
+ _tooltipValueFormatter(value: number | string) {
+ if (typeof value === "string") {
+ value = parseFloat(value);
+ }
+ return Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: "USD",
+ }).format(value);
+ }
+
+ /**
+ * Default format function for the yAxis labels
+ */
+ _yLabelFormatter(value: number | string) {
+ if (typeof value === "string") {
+ value = parseFloat(value);
+ }
+ return Intl.NumberFormat("en-US", {
+ notation: "compact",
+ style: "currency",
+ currency: "USD",
+ maximumSignificantDigits: 4,
+ }).format(value);
+ }
+
+ /**
+ * Merge the source Highcharts config into the target Highcharts config
+ *
+ * Allows for custom overrides of ebay default Highcharts configuration settings
+ */
+ _mergeConfigs(
+ source: { [key: string]: any },
+ target: { [key: string]: any },
+ ) {
+ for (const key in source) {
+ if (source[key] instanceof Object)
+ Object.assign(
+ source[key],
+ this._mergeConfigs(target[key], source[key]),
+ );
+ }
+ Object.assign(target || {}, source);
+ return target;
+ }
+
+ /**
+ * Get the title configuration for the chart
+ */
getTitleConfig(): Highcharts.TitleOptions {
return {
text: this.input.title,
align: "left",
useHTML: true,
style: {
- // styles are set in JS since they are rendered in the SVG
fontSize: "18px",
fontWeight: "700",
},
};
}
+
+ /**
+ * Get the chart configuration for the chart
+ */
getChartConfig(): Highcharts.ChartOptions {
+ const type = this.input.areaType ?? "areaspline";
return {
- type: "area",
+ type,
+ animation: false,
backgroundColor: backgroundColor,
style: {
- // styles are set in JS since they are rendered in the SVG
fontFamily: chartFontFamily,
},
};
}
+
+ /**
+ * Get the xAxis configuration for the chart
+ */
getXAxisConfig(): Highcharts.XAxisOptions {
+ const xLabelFormatter = this.input.xLabelFormatter;
return {
// currently setup to support epoch time values for xAxisLabels.
// It is possible to set custom non datetime xAxisLabels but will need changes to this component
type: "datetime",
labels: {
- format: this.input.xAxisLabelFormat
- ? this.input.xAxisLabelFormat
- : "{value:%b %e}",
+ formatter: xLabelFormatter
+ ? function () {
+ return xLabelFormatter?.(
+ this.value,
+ Highcharts.dateFormat,
+ );
+ }
+ : undefined,
+ format: "{value:%b %e}",
align: "center",
style: {
- color: labelsColor, // setting label colors
+ color: labelsColor,
},
},
tickWidth: 0, // hide the vertical tick on xAxis labels
crosshair: {
- zIndex: 3, // make sure the vertical crosshair line on hover shows up on top
+ color: "rgba(0, 0, 0, 0.2)",
+ zIndex: 3,
},
- tickPositioner: this.input.xAxisPositioner, // optional input to allow configuring the position of xAxis tick marks
};
}
- getYAxisConfig(
- series: Highcharts.SeriesAreaOptions[],
- ): Highcharts.YAxisOptions {
- const component = this; // component reference used in formatter functions that don't have the same scope
- let yLabelsIterator = 0; // used when yAxisLabels array is provided in input
- let maxYAxisValue = 0; // use to determine the highest yAxis value
- series.forEach((s) => {
- maxYAxisValue = s.data!.reduce(
- (p: number, c: any) => (c > p ? c : p),
- maxYAxisValue,
- ) as number;
- });
+
+ /**
+ * Get the yAxis configuration for the chart
+ */
+ getYAxisConfig(): Highcharts.YAxisOptions {
+ // Formatter function for the yAxis labels
+ const yLabelFormatter =
+ this.input.yLabelFormatter ?? this._yLabelFormatter;
+
return {
- gridLineColor: gridColor, // sets the horizontal grid line colors
+ gridLineColor: gridColor,
opposite: true, // moves yAxis labels to the right side of the chart
reversedStacks: false, // makes so series one starts at the bottom of the yAxis, by default this is true
labels: {
- // if yAxisLabels are not passed in display the standard label
- format: this.input.yAxisLabels ?? "${text}",
- // if yAxisLabels array is passed in this formatter function is needed to
- // return the proper label for each yAxis tick mark
- formatter: this.input.yAxisLabels
- ? function () {
- if (this.isFirst) {
- yLabelsIterator = -1;
- }
- yLabelsIterator = yLabelsIterator + 1;
- return (
- component.input.yAxisLabels?.[yLabelsIterator] ??
- ""
- );
- }
- : undefined,
+ formatter: function () {
+ return yLabelFormatter(this.value);
+ },
style: {
- color: labelsColor, // setting label colors
+ color: labelsColor,
},
},
- max: maxYAxisValue,
title: {
- enabled: false, // hide the axis label next to the axis
+ enabled: false,
} as Highcharts.YAxisTitleOptions,
- offset: 0, // set to zero for no offset refer to https://api.highcharts.com/highcharts/yAxis.offset
- // passed in function for yAxisPositioner refer to https://api.highcharts.com/highcharts/yAxis.tickPositioner for use
- tickPositioner: this.input.yAxisPositioner,
+ offset: 0,
};
}
- getLegendConfig() {
+
+ /**
+ * Get the legend configuration for the chart
+ */
+ getLegendConfig(): Highcharts.LegendOptions {
return {
- // if only a single series is provided do not display the legend
+ // If only a single series is provided do not display the legend
enabled:
Array.isArray(this.input.series) &&
this.input.series.length > 1,
- symbolRadius: 2, // corner radius on legend identifiers svg element
- symbolWidth: 12, // setting the width of the legend identifiers svg element
- symbolHeight: 12, // setting the height of the legend identifiers svg element
+ symbolRadius: 2,
+ symbolWidth: 12,
+ symbolHeight: 12,
itemStyle: {
- color: legendColor, // set the color of the text in the legend
+ color: legendColor,
+ fontWeight: "normal",
},
+ align: "left",
itemHiddenStyle: {
- color: legendInactiveColor, // set legend text color when legend item has been clicked and hidden
+ color: legendInactiveColor,
},
itemHoverStyle: {
- color: legendHoverColor, // set legend text color on hover of legend element
+ color: legendHoverColor,
},
};
}
- getTooltipConfig() {
- const component = this; // component reference used in formatter functions that don't have the same scope
+ /**
+ * Get the tooltip configuration for the chart
+ */
+ getTooltipConfig(): Highcharts.TooltipOptions {
+ const tooltipValueFormatter =
+ this.input.tooltipValueFormatter ?? this._tooltipValueFormatter;
+
+ const tooltipTitleFormatter =
+ this.input.tooltipTitleFormatter ?? this._tooltipTitleFormatter;
+
return {
- formatter: function (this: any) {
- // refer to https://api.highcharts.com/class-reference/Highcharts.Time#dateFormat for dateFormat variables
- // s is used to compile html string of formatted tooltip data
-
- // TODO need to change this to use a component
- // eslint-disable-next-line no-undef,new-cap
- let s = `${Highcharts.dateFormat(
- "%b %e, %Y",
- this.x,
- false,
- )}`; // sets the displayed date at the top of the tooltip
- if (component.chartRef.series.length > 1) {
- // setup html for multi series tooltip
- component.chartRef.series.forEach((serie) => {
- // cycle through each series
- serie.data.forEach((d) => {
- // cycle through each series data array to match x value with active hovered xAxis position
- if (d.x === this.x) {
- // when the x value matches the hovered xAxis position
- s += `
${serie.name}${d.name}
`;
- }
- });
- });
- } else {
- // setup html for single series tooltip
- // cycle through points of the single series and find the one that matches the active xAxis
- component.points.forEach((d) => {
- if (d.x === this.x) {
- // when the x value matches the hovered xAxis position
- s += `