From a3e63acd0719af28a49dffce7c7e1f7c570c8aad Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 19 Jan 2025 17:36:06 -0800 Subject: [PATCH 01/23] tailwind setup under .tw class wrapper --- .vscode/settings.json | 3 + electron.vite.config.ts | 12 + frontend/app/app.tsx | 1 + package.json | 10 +- postcss.config.cjs | 6 + tailwind.config.js | 12 + yarn.lock | 519 ++++++++++++++++++++++++++++++++++++++-- 7 files changed, 539 insertions(+), 24 deletions(-) create mode 100644 postcss.config.cjs create mode 100644 tailwind.config.js diff --git a/.vscode/settings.json b/.vscode/settings.json index 831ce237f..5be93fed6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,5 +45,8 @@ }, "[md]": { "editor.wordWrap": "on" + }, + "files.associations": { + "*.css": "tailwindcss" } } diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 0077b808d..a80261af7 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -2,8 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 import react from "@vitejs/plugin-react-swc"; +import autoprefixer from "autoprefixer"; import { defineConfig } from "electron-vite"; import flow from "rollup-plugin-flow"; +import tailwindcss from "tailwindcss"; import { ViteImageOptimizer } from "vite-plugin-image-optimizer"; import { viteStaticCopy } from "vite-plugin-static-copy"; import svgr from "vite-plugin-svgr"; @@ -63,6 +65,16 @@ export default defineConfig({ server: { open: false, }, + css: { + preprocessorOptions: { + scss: { + // your existing scss options if any + }, + }, + postcss: { + plugins: [tailwindcss as any, autoprefixer as any], + }, + }, plugins: [ ViteImageOptimizer(), tsconfigPaths(), diff --git a/frontend/app/app.tsx b/frontend/app/app.tsx index 230544282..e18f3e4ed 100644 --- a/frontend/app/app.tsx +++ b/frontend/app/app.tsx @@ -28,6 +28,7 @@ import { CenteredDiv } from "./element/quickelems"; import { NotificationBubbles } from "./notification/notificationbubbles"; import "./app.scss"; +import "./tailwindsetup.css"; const dlog = debug("wave:app"); const focusLog = debug("wave:focus"); diff --git a/package.json b/package.json index 8e12f837b..bf3ff50a9 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,9 @@ "private": true, "main": "./dist/main/index.js", "type": "module", + "browserslist": [ + "Chrome >= 128" + ], "scripts": { "dev": "electron-vite dev", "start": "electron-vite preview", @@ -43,7 +46,7 @@ "@types/css-tree": "^2", "@types/debug": "^4", "@types/electron": "^1.6.12", - "@types/node": "^22.10.2", + "@types/node": "^22.10.7", "@types/papaparse": "^5", "@types/pngjs": "^6.0.5", "@types/prop-types": "^15", @@ -58,11 +61,13 @@ "@types/ws": "^8", "@vitejs/plugin-react-swc": "^3.7.2", "@vitest/coverage-istanbul": "^2.1.8", + "autoprefixer": "^10.4.20", "electron": "^33.2.1", "electron-builder": "^25.1.8", "electron-vite": "^2.3.0", "eslint": "^9.16.0", "eslint-config-prettier": "^9.1.0", + "postcss": "^8.5.1", "prettier": "^3.4.2", "prettier-plugin-jsdoc": "^1.3.0", "prettier-plugin-organize-imports": "^4.1.0", @@ -71,6 +76,8 @@ "semver": "^7.6.3", "storybook": "^8.5.0", "storybook-dark-mode": "^4.0.2", + "tailwindcss": "^3.4.17", + "tailwindcss-animate": "^1.0.7", "ts-node": "^10.9.2", "tslib": "^2.8.1", "tsx": "^4.19.2", @@ -127,6 +134,7 @@ "react-frame-component": "^5.2.7", "react-gauge-chart": "^0.5.1", "react-markdown": "^9.0.1", + "recharts": "^2.15.0", "rehype-highlight": "^7.0.1", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 000000000..67cdf1a55 --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 000000000..dbebd95be --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,12 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./frontend/**/*.{js,ts,jsx,tsx,scss,css}", // adjust this path if your frontend files are elsewhere + ], + theme: { + extend: {}, + }, + corePlugins: { preflight: false }, + plugins: [], +}; diff --git a/yarn.lock b/yarn.lock index c093c6d7b..26986aa53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -362,6 +362,13 @@ __metadata: languageName: node linkType: hard +"@alloc/quick-lru@npm:^5.2.0": + version: 5.2.0 + resolution: "@alloc/quick-lru@npm:5.2.0" + checksum: 10c0/7b878c48b9d25277d0e1a9b8b2f2312a314af806b4129dc902f2bc29ab09b58236e53964689feec187b28c80d2203aff03829754773a707a8a5987f1b7682d92 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" @@ -1599,7 +1606,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.25.9, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.25.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": version: 7.26.0 resolution: "@babel/runtime@npm:7.26.0" dependencies: @@ -4081,6 +4088,17 @@ __metadata: languageName: node linkType: hard +"@jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.8 + resolution: "@jridgewell/gen-mapping@npm:0.3.8" + dependencies: + "@jridgewell/set-array": "npm:^1.2.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/c668feaf86c501d7c804904a61c23c67447b2137b813b9ce03eca82cb9d65ac7006d766c218685d76e3d72828279b6ee26c347aa1119dab23fbaf36aed51585a + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -6162,6 +6180,75 @@ __metadata: languageName: node linkType: hard +"@types/d3-array@npm:^3.0.3": + version: 3.2.1 + resolution: "@types/d3-array@npm:3.2.1" + checksum: 10c0/38bf2c778451f4b79ec81a2288cb4312fe3d6449ecdf562970cc339b60f280f31c93a024c7ff512607795e79d3beb0cbda123bb07010167bce32927f71364bca + languageName: node + linkType: hard + +"@types/d3-color@npm:*": + version: 3.1.3 + resolution: "@types/d3-color@npm:3.1.3" + checksum: 10c0/65eb0487de606eb5ad81735a9a5b3142d30bc5ea801ed9b14b77cb14c9b909f718c059f13af341264ee189acf171508053342142bdf99338667cea26a2d8d6ae + languageName: node + linkType: hard + +"@types/d3-ease@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/d3-ease@npm:3.0.2" + checksum: 10c0/aff5a1e572a937ee9bff6465225d7ba27d5e0c976bd9eacdac2e6f10700a7cb0c9ea2597aff6b43a6ed850a3210030870238894a77ec73e309b4a9d0333f099c + languageName: node + linkType: hard + +"@types/d3-interpolate@npm:^3.0.1": + version: 3.0.4 + resolution: "@types/d3-interpolate@npm:3.0.4" + dependencies: + "@types/d3-color": "npm:*" + checksum: 10c0/066ebb8da570b518dd332df6b12ae3b1eaa0a7f4f0c702e3c57f812cf529cc3500ec2aac8dc094f31897790346c6b1ebd8cd7a077176727f4860c2b181a65ca4 + languageName: node + linkType: hard + +"@types/d3-path@npm:*": + version: 3.1.0 + resolution: "@types/d3-path@npm:3.1.0" + checksum: 10c0/85e8b3aa968a60a5b33198ade06ae7ffedcf9a22d86f24859ff58e014b053ccb7141ec163b78d547bc8215bb12bb54171c666057ab6156912814005b686afb31 + languageName: node + linkType: hard + +"@types/d3-scale@npm:^4.0.2": + version: 4.0.8 + resolution: "@types/d3-scale@npm:4.0.8" + dependencies: + "@types/d3-time": "npm:*" + checksum: 10c0/57de90e4016f640b83cb960b7e3a0ab3ed02e720898840ddc5105264ffcfea73336161442fdc91895377c2d2f91904d637282f16852b8535b77e15a761c8e99e + languageName: node + linkType: hard + +"@types/d3-shape@npm:^3.1.0": + version: 3.1.7 + resolution: "@types/d3-shape@npm:3.1.7" + dependencies: + "@types/d3-path": "npm:*" + checksum: 10c0/38e59771c1c4c83b67aa1f941ce350410522a149d2175832fdc06396b2bb3b2c1a2dd549e0f8230f9f24296ee5641a515eaf10f55ee1ef6c4f83749e2dd7dcfd + languageName: node + linkType: hard + +"@types/d3-time@npm:*, @types/d3-time@npm:^3.0.0": + version: 3.0.4 + resolution: "@types/d3-time@npm:3.0.4" + checksum: 10c0/6d9e2255d63f7a313a543113920c612e957d70da4fb0890931da6c2459010291b8b1f95e149a538500c1c99e7e6c89ffcce5554dd29a31ff134a38ea94b6d174 + languageName: node + linkType: hard + +"@types/d3-timer@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/d3-timer@npm:3.0.2" + checksum: 10c0/c644dd9571fcc62b1aa12c03bcad40571553020feeb5811f1d8a937ac1e65b8a04b759b4873aef610e28b8714ac71c9885a4d6c127a048d95118f7e5b506d9e1 + languageName: node + linkType: hard + "@types/debug@npm:^4, @types/debug@npm:^4.0.0, @types/debug@npm:^4.1.6": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" @@ -6454,12 +6541,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^22.10.2": - version: 22.10.2 - resolution: "@types/node@npm:22.10.2" +"@types/node@npm:^22.10.7": + version: 22.10.7 + resolution: "@types/node@npm:22.10.7" dependencies: undici-types: "npm:~6.20.0" - checksum: 10c0/2c7b71a040f1ef5320938eca8ebc946e6905caa9bbf3d5665d9b3774a8d15ea9fab1582b849a6d28c7fc80756a62c5666bc66b69f42f4d5dafd1ccb193cdb4ac + checksum: 10c0/c941b4689dfc4044b64a5f601306cbcb0c7210be853ba378a5dd44137898c45accedd796ee002ad9407024cac7ecaf5049304951cb1d80ce3d7cebbbae56f20e languageName: node linkType: hard @@ -7654,6 +7741,13 @@ __metadata: languageName: node linkType: hard +"any-promise@npm:^1.0.0": + version: 1.3.0 + resolution: "any-promise@npm:1.3.0" + checksum: 10c0/60f0298ed34c74fef50daab88e8dab786036ed5a7fad02e012ab57e376e0a0b4b29e83b95ea9b5e7d89df762f5f25119b83e00706ecaccb22cfbacee98d74889 + languageName: node + linkType: hard + "anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" @@ -7738,7 +7832,7 @@ __metadata: languageName: node linkType: hard -"arg@npm:^5.0.0": +"arg@npm:^5.0.0, arg@npm:^5.0.2": version: 5.0.2 resolution: "arg@npm:5.0.2" checksum: 10c0/ccaf86f4e05d342af6666c569f844bec426595c567d32a8289715087825c2ca7edd8a3d204e4d2fb2aa4602e09a57d0c13ea8c9eea75aac3dbb4af5514e6800e @@ -7858,7 +7952,7 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.14, autoprefixer@npm:^10.4.19": +"autoprefixer@npm:^10.4.14, autoprefixer@npm:^10.4.19, autoprefixer@npm:^10.4.20": version: 10.4.20 resolution: "autoprefixer@npm:10.4.20" dependencies: @@ -8418,6 +8512,13 @@ __metadata: languageName: node linkType: hard +"camelcase-css@npm:^2.0.1": + version: 2.0.1 + resolution: "camelcase-css@npm:2.0.1" + checksum: 10c0/1a1a3137e8a781e6cbeaeab75634c60ffd8e27850de410c162cce222ea331cd1ba5364e8fb21c95e5ca76f52ac34b81a090925ca00a87221355746d049c6e273 + languageName: node + linkType: hard + "camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" @@ -8597,7 +8698,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.0.0, chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": +"chokidar@npm:^3.0.0, chokidar@npm:^3.4.2, chokidar@npm:^3.5.3, chokidar@npm:^3.6.0": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -8948,6 +9049,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^4.0.0": + version: 4.1.1 + resolution: "commander@npm:4.1.1" + checksum: 10c0/84a76c08fe6cc08c9c93f62ac573d2907d8e79138999312c92d4155bc2325d487d64d13f669b2000c9f8caf70493c1be2dac74fec3c51d5a04f8bc3ae1830bab + languageName: node + linkType: hard + "commander@npm:^5.0.0, commander@npm:^5.1.0": version: 5.1.0 resolution: "commander@npm:5.1.0" @@ -9575,7 +9683,7 @@ __metadata: languageName: node linkType: hard -"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0": +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.1.6, d3-array@npm:^3.2.0": version: 3.2.4 resolution: "d3-array@npm:3.2.4" dependencies: @@ -9676,7 +9784,7 @@ __metadata: languageName: node linkType: hard -"d3-ease@npm:1 - 3, d3-ease@npm:3": +"d3-ease@npm:1 - 3, d3-ease@npm:3, d3-ease@npm:^3.0.1": version: 3.0.1 resolution: "d3-ease@npm:3.0.1" checksum: 10c0/fec8ef826c0cc35cda3092c6841e07672868b1839fcaf556e19266a3a37e6bc7977d8298c0fcb9885e7799bfdcef7db1baaba9cd4dcf4bc5e952cf78574a88b0 @@ -9726,7 +9834,7 @@ __metadata: languageName: node linkType: hard -"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3": +"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3, d3-interpolate@npm:^3.0.1": version: 3.0.1 resolution: "d3-interpolate@npm:3.0.1" dependencies: @@ -9773,7 +9881,7 @@ __metadata: languageName: node linkType: hard -"d3-scale@npm:4": +"d3-scale@npm:4, d3-scale@npm:^4.0.2": version: 4.0.2 resolution: "d3-scale@npm:4.0.2" dependencies: @@ -9793,7 +9901,7 @@ __metadata: languageName: node linkType: hard -"d3-shape@npm:3": +"d3-shape@npm:3, d3-shape@npm:^3.1.0": version: 3.2.0 resolution: "d3-shape@npm:3.2.0" dependencies: @@ -9811,7 +9919,7 @@ __metadata: languageName: node linkType: hard -"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3": +"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3, d3-time@npm:^3.0.0": version: 3.1.0 resolution: "d3-time@npm:3.1.0" dependencies: @@ -9820,7 +9928,7 @@ __metadata: languageName: node linkType: hard -"d3-timer@npm:1 - 3, d3-timer@npm:3": +"d3-timer@npm:1 - 3, d3-timer@npm:3, d3-timer@npm:^3.0.1": version: 3.0.1 resolution: "d3-timer@npm:3.0.1" checksum: 10c0/d4c63cb4bb5461d7038aac561b097cd1c5673969b27cbdd0e87fa48d9300a538b9e6f39b4a7f0e3592ef4f963d858c8a9f0e92754db73116770856f2fc04561a @@ -9928,6 +10036,13 @@ __metadata: languageName: node linkType: hard +"decimal.js-light@npm:^2.4.1": + version: 2.5.1 + resolution: "decimal.js-light@npm:2.5.1" + checksum: 10c0/4fd33f535aac9e5bd832796831b65d9ec7914ad129c7437b3ab991b0c2eaaa5a57e654e6174c4a17f1b3895ea366f0c1ab4955cdcdf7cfdcf3ad5a58b456c020 + languageName: node + linkType: hard + "decode-named-character-reference@npm:^1.0.0": version: 1.0.2 resolution: "decode-named-character-reference@npm:1.0.2" @@ -10160,6 +10275,13 @@ __metadata: languageName: node linkType: hard +"didyoumean@npm:^1.2.2": + version: 1.2.2 + resolution: "didyoumean@npm:1.2.2" + checksum: 10c0/95d0b53d23b851aacff56dfadb7ecfedce49da4232233baecfeecb7710248c4aa03f0aa8995062f0acafaf925adf8536bd7044a2e68316fd7d411477599bc27b + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -10193,6 +10315,13 @@ __metadata: languageName: node linkType: hard +"dlv@npm:^1.1.3": + version: 1.1.3 + resolution: "dlv@npm:1.1.3" + checksum: 10c0/03eb4e769f19a027fd5b43b59e8a05e3fd2100ac239ebb0bf9a745de35d449e2f25cfaf3aa3934664551d72856f4ae8b7822016ce5c42c2d27c18ae79429ec42 + languageName: node + linkType: hard + "dmg-builder@npm:25.1.8": version: 25.1.8 resolution: "dmg-builder@npm:25.1.8" @@ -10281,6 +10410,16 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^5.0.1": + version: 5.2.1 + resolution: "dom-helpers@npm:5.2.1" + dependencies: + "@babel/runtime": "npm:^7.8.7" + csstype: "npm:^3.0.2" + checksum: 10c0/f735074d66dd759b36b158fa26e9d00c9388ee0e8c9b16af941c38f014a37fc80782de83afefd621681b19ac0501034b4f1c4a3bff5caa1b8667f0212b5e124c + languageName: node + linkType: hard + "dom-serializer@npm:^1.0.1": version: 1.4.1 resolution: "dom-serializer@npm:1.4.1" @@ -11345,7 +11484,7 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.0": +"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.1": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" checksum: 10c0/5f6d97cbcbac47be798e6355e3a7639a84ee1f7d9b199a07017f1d2f1e2fe236004d14fa5dfaeba661f94ea57805385e326236a6debbc7145c8877fbc0297c6b @@ -11490,6 +11629,13 @@ __metadata: languageName: node linkType: hard +"fast-equals@npm:^5.0.1": + version: 5.2.2 + resolution: "fast-equals@npm:5.2.2" + checksum: 10c0/2bfeac6317a8959a00e2134749323557e5df6dea3af24e4457297733eace8ce4313fcbca2cf4532f3a6792607461e80442cd8d3af148d5c2e4e98ad996d6e5b5 + languageName: node + linkType: hard + "fast-fifo@npm:^1.2.0, fast-fifo@npm:^1.3.2": version: 1.3.2 resolution: "fast-fifo@npm:1.3.2" @@ -13271,6 +13417,15 @@ __metadata: languageName: node linkType: hard +"is-core-module@npm:^2.16.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" + dependencies: + hasown: "npm:^2.0.2" + checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd + languageName: node + linkType: hard + "is-decimal@npm:^1.0.0": version: 1.0.4 resolution: "is-decimal@npm:1.0.4" @@ -13707,6 +13862,15 @@ __metadata: languageName: node linkType: hard +"jiti@npm:^1.21.6": + version: 1.21.7 + resolution: "jiti@npm:1.21.7" + bin: + jiti: bin/jiti.js + checksum: 10c0/77b61989c758ff32407cdae8ddc77f85e18e1a13fc4977110dbd2e05fc761842f5f71bce684d9a01316e1c4263971315a111385759951080bbfe17cbb5de8f7a + languageName: node + linkType: hard + "joi@npm:^17.9.2": version: 17.13.3 resolution: "joi@npm:17.13.3" @@ -13958,6 +14122,13 @@ __metadata: languageName: node linkType: hard +"lilconfig@npm:^3.0.0, lilconfig@npm:^3.1.3": + version: 3.1.3 + resolution: "lilconfig@npm:3.1.3" + checksum: 10c0/f5604e7240c5c275743561442fbc5abf2a84ad94da0f5adc71d25e31fa8483048de3dcedcb7a44112a942fed305fd75841cdf6c9681c7f640c63f1049e9a5dcc + languageName: node + linkType: hard + "lilconfig@npm:^3.1.1": version: 3.1.2 resolution: "lilconfig@npm:3.1.2" @@ -15226,7 +15397,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -15618,7 +15789,18 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.7": +"mz@npm:^2.7.0": + version: 2.7.0 + resolution: "mz@npm:2.7.0" + dependencies: + any-promise: "npm:^1.0.0" + object-assign: "npm:^4.0.1" + thenify-all: "npm:^1.0.0" + checksum: 10c0/103114e93f87362f0b56ab5b2e7245051ad0276b646e3902c98397d18bb8f4a77f2ea4a2c9d3ad516034ea3a56553b60d3f5f78220001ca4c404bd711bd0af39 + languageName: node + linkType: hard + +"nanoid@npm:^3.3.7, nanoid@npm:^3.3.8": version: 3.3.8 resolution: "nanoid@npm:3.3.8" bin: @@ -15944,7 +16126,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.1.1": +"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 @@ -16502,6 +16684,20 @@ __metadata: languageName: node linkType: hard +"pify@npm:^2.3.0": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 10c0/551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc + languageName: node + linkType: hard + +"pirates@npm:^4.0.1": + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 10c0/00d5fa51f8dded94d7429700fb91a0c1ead00ae2c7fd27089f0c5b63e6eca36197fe46384631872690a66f390c5e27198e99006ab77ae472692ab9c2ca903f36 + languageName: node + linkType: hard + "pkg-dir@npm:^7.0.0": version: 7.0.0 resolution: "pkg-dir@npm:7.0.0" @@ -16826,6 +17022,30 @@ __metadata: languageName: node linkType: hard +"postcss-import@npm:^15.1.0": + version: 15.1.0 + resolution: "postcss-import@npm:15.1.0" + dependencies: + postcss-value-parser: "npm:^4.0.0" + read-cache: "npm:^1.0.0" + resolve: "npm:^1.1.7" + peerDependencies: + postcss: ^8.0.0 + checksum: 10c0/518aee5c83ea6940e890b0be675a2588db68b2582319f48c3b4e06535a50ea6ee45f7e63e4309f8754473245c47a0372632378d1d73d901310f295a92f26f17b + languageName: node + linkType: hard + +"postcss-js@npm:^4.0.1": + version: 4.0.1 + resolution: "postcss-js@npm:4.0.1" + dependencies: + camelcase-css: "npm:^2.0.1" + peerDependencies: + postcss: ^8.4.21 + checksum: 10c0/af35d55cb873b0797d3b42529514f5318f447b134541844285c9ac31a17497297eb72296902967911bb737a75163441695737300ce2794e3bd8c70c13a3b106e + languageName: node + linkType: hard + "postcss-lab-function@npm:^7.0.6": version: 7.0.6 resolution: "postcss-lab-function@npm:7.0.6" @@ -16841,6 +17061,24 @@ __metadata: languageName: node linkType: hard +"postcss-load-config@npm:^4.0.2": + version: 4.0.2 + resolution: "postcss-load-config@npm:4.0.2" + dependencies: + lilconfig: "npm:^3.0.0" + yaml: "npm:^2.3.4" + peerDependencies: + postcss: ">=8.0.9" + ts-node: ">=9.0.0" + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + checksum: 10c0/3d7939acb3570b0e4b4740e483d6e555a3e2de815219cb8a3c8fc03f575a6bde667443aa93369c0be390af845cb84471bf623e24af833260de3a105b78d42519 + languageName: node + linkType: hard + "postcss-loader@npm:^7.3.3": version: 7.3.4 resolution: "postcss-loader@npm:7.3.4" @@ -16996,6 +17234,17 @@ __metadata: languageName: node linkType: hard +"postcss-nested@npm:^6.2.0": + version: 6.2.0 + resolution: "postcss-nested@npm:6.2.0" + dependencies: + postcss-selector-parser: "npm:^6.1.1" + peerDependencies: + postcss: ^8.2.14 + checksum: 10c0/7f9c3f2d764191a39364cbdcec350f26a312431a569c9ef17408021424726b0d67995ff5288405e3724bb7152a4c92f73c027e580ec91e798800ed3c52e2bc6e + languageName: node + linkType: hard + "postcss-nesting@npm:^13.0.1": version: 13.0.1 resolution: "postcss-nesting@npm:13.0.1" @@ -17297,7 +17546,7 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.16, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.16, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2": version: 6.1.2 resolution: "postcss-selector-parser@npm:6.1.2" dependencies: @@ -17351,7 +17600,7 @@ __metadata: languageName: node linkType: hard -"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": +"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161 @@ -17389,6 +17638,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.47, postcss@npm:^8.5.1": + version: 8.5.1 + resolution: "postcss@npm:8.5.1" + dependencies: + nanoid: "npm:^3.3.8" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/c4d90c59c98e8a0c102b77d3f4cac190f883b42d63dc60e2f3ed840f16197c0c8e25a4327d2e9a847b45a985612317dc0534178feeebd0a1cf3eb0eecf75cae4 + languageName: node + linkType: hard + "prebuild-install@npm:^7.1.1": version: 7.1.2 resolution: "prebuild-install@npm:7.1.2" @@ -17910,7 +18170,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.1 || ^18.0.0": +"react-is@npm:^17.0.1 || ^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072 @@ -18018,6 +18278,35 @@ __metadata: languageName: node linkType: hard +"react-smooth@npm:^4.0.0": + version: 4.0.4 + resolution: "react-smooth@npm:4.0.4" + dependencies: + fast-equals: "npm:^5.0.1" + prop-types: "npm:^15.8.1" + react-transition-group: "npm:^4.4.5" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10c0/d94cb27f808721ec040d320ca1927919199495fd212e54eb9dc8ee3f73ff1d808a34be9f4b09fe49b01f411ac2387fdf0e4bee297f18faf56f94bfbef5fd204c + languageName: node + linkType: hard + +"react-transition-group@npm:^4.4.5": + version: 4.4.5 + resolution: "react-transition-group@npm:4.4.5" + dependencies: + "@babel/runtime": "npm:^7.5.5" + dom-helpers: "npm:^5.0.1" + loose-envify: "npm:^1.4.0" + prop-types: "npm:^15.6.2" + peerDependencies: + react: ">=16.6.0" + react-dom: ">=16.6.0" + checksum: 10c0/2ba754ba748faefa15f87c96dfa700d5525054a0141de8c75763aae6734af0740e77e11261a1e8f4ffc08fd9ab78510122e05c21c2d79066c38bb6861a886c82 + languageName: node + linkType: hard + "react-waypoint@npm:^10.3.0": version: 10.3.0 resolution: "react-waypoint@npm:10.3.0" @@ -18052,6 +18341,15 @@ __metadata: languageName: node linkType: hard +"read-cache@npm:^1.0.0": + version: 1.0.0 + resolution: "read-cache@npm:1.0.0" + dependencies: + pify: "npm:^2.3.0" + checksum: 10c0/90cb2750213c7dd7c80cb420654344a311fdec12944e81eb912cd82f1bc92aea21885fa6ce442e3336d9fccd663b8a7a19c46d9698e6ca55620848ab932da814 + languageName: node + linkType: hard + "read-package-json-fast@npm:^3.0.0": version: 3.0.2 resolution: "read-package-json-fast@npm:3.0.2" @@ -18124,6 +18422,34 @@ __metadata: languageName: node linkType: hard +"recharts-scale@npm:^0.4.4": + version: 0.4.5 + resolution: "recharts-scale@npm:0.4.5" + dependencies: + decimal.js-light: "npm:^2.4.1" + checksum: 10c0/64ce1fc4ebe62001787bf4dc4cbb779452d33831619309c71c50277c58e8968ffe98941562d9d0d5ffdb02588ebd62f4fe6548fa826110fd458db9c3cc6dadc1 + languageName: node + linkType: hard + +"recharts@npm:^2.15.0": + version: 2.15.0 + resolution: "recharts@npm:2.15.0" + dependencies: + clsx: "npm:^2.0.0" + eventemitter3: "npm:^4.0.1" + lodash: "npm:^4.17.21" + react-is: "npm:^18.3.1" + react-smooth: "npm:^4.0.0" + recharts-scale: "npm:^0.4.4" + tiny-invariant: "npm:^1.3.1" + victory-vendor: "npm:^36.6.8" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10c0/9dca8003c22c1d91b895add65e85d58bc1e79a5abc739bf0b61e275384f70b6922ad7247c0c39e0f5650174d2d9b1a006dc9c23d33732b7f4016c7df076826d3 + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" @@ -19025,6 +19351,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.1.7": + version: 1.22.10 + resolution: "resolve@npm:1.22.10" + dependencies: + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/8967e1f4e2cc40f79b7e080b4582b9a8c5ee36ffb46041dccb20e6461161adf69f843b43067b4a375de926a2cd669157e29a29578191def399dd5ef89a1b5203 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" @@ -19038,6 +19377,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin": + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/52a4e505bbfc7925ac8f4cd91fd8c4e096b6a89728b9f46861d3b405ac9a1ccf4dcbf8befb4e89a2e11370dacd0160918163885cbc669369590f2f31f4c58939 + languageName: node + linkType: hard + "responselike@npm:^2.0.0": version: 2.0.1 resolution: "responselike@npm:2.0.1" @@ -20398,6 +20750,24 @@ __metadata: languageName: node linkType: hard +"sucrase@npm:^3.35.0": + version: 3.35.0 + resolution: "sucrase@npm:3.35.0" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.2" + commander: "npm:^4.0.0" + glob: "npm:^10.3.10" + lines-and-columns: "npm:^1.1.6" + mz: "npm:^2.7.0" + pirates: "npm:^4.0.1" + ts-interface-checker: "npm:^0.1.9" + bin: + sucrase: bin/sucrase + sucrase-node: bin/sucrase-node + checksum: 10c0/ac85f3359d2c2ecbf5febca6a24ae9bf96c931f05fde533c22a94f59c6a74895e5d5f0e871878dfd59c2697a75ebb04e4b2224ef0bfc24ca1210735c2ec191ef + languageName: node + linkType: hard + "sumchecker@npm:^3.0.1": version: 3.0.1 resolution: "sumchecker@npm:3.0.1" @@ -20480,6 +20850,48 @@ __metadata: languageName: node linkType: hard +"tailwindcss-animate@npm:^1.0.7": + version: 1.0.7 + resolution: "tailwindcss-animate@npm:1.0.7" + peerDependencies: + tailwindcss: "*" + checksum: 10c0/ec7dbd1631076b97d66a1fbaaa06e0725fccfa63119221e8d87a997b02dcede98ad88bb1ef6665b968f5d260fcefb10592e0299ca70208d365b37761edf5e19a + languageName: node + linkType: hard + +"tailwindcss@npm:^3.4.17": + version: 3.4.17 + resolution: "tailwindcss@npm:3.4.17" + dependencies: + "@alloc/quick-lru": "npm:^5.2.0" + arg: "npm:^5.0.2" + chokidar: "npm:^3.6.0" + didyoumean: "npm:^1.2.2" + dlv: "npm:^1.1.3" + fast-glob: "npm:^3.3.2" + glob-parent: "npm:^6.0.2" + is-glob: "npm:^4.0.3" + jiti: "npm:^1.21.6" + lilconfig: "npm:^3.1.3" + micromatch: "npm:^4.0.8" + normalize-path: "npm:^3.0.0" + object-hash: "npm:^3.0.0" + picocolors: "npm:^1.1.1" + postcss: "npm:^8.4.47" + postcss-import: "npm:^15.1.0" + postcss-js: "npm:^4.0.1" + postcss-load-config: "npm:^4.0.2" + postcss-nested: "npm:^6.2.0" + postcss-selector-parser: "npm:^6.1.2" + resolve: "npm:^1.22.8" + sucrase: "npm:^3.35.0" + bin: + tailwind: lib/cli.js + tailwindcss: lib/cli.js + checksum: 10c0/cc42c6e7fdf88a5507a0d7fea37f1b4122bec158977f8c017b2ae6828741f9e6f8cb90282c6bf2bd5951fd1220a53e0a50ca58f5c1c00eb7f5d9f8b80dc4523c + languageName: node + linkType: hard + "tapable@npm:^1.0.0": version: 1.1.3 resolution: "tapable@npm:1.1.3" @@ -20639,6 +21051,24 @@ __metadata: languageName: node linkType: hard +"thenify-all@npm:^1.0.0": + version: 1.6.0 + resolution: "thenify-all@npm:1.6.0" + dependencies: + thenify: "npm:>= 3.1.0 < 4" + checksum: 10c0/9b896a22735e8122754fe70f1d65f7ee691c1d70b1f116fda04fea103d0f9b356e3676cb789506e3909ae0486a79a476e4914b0f92472c2e093d206aed4b7d6b + languageName: node + linkType: hard + +"thenify@npm:>= 3.1.0 < 4": + version: 3.3.1 + resolution: "thenify@npm:3.3.1" + dependencies: + any-promise: "npm:^1.0.0" + checksum: 10c0/f375aeb2b05c100a456a30bc3ed07ef03a39cbdefe02e0403fb714b8c7e57eeaad1a2f5c4ecfb9ce554ce3db9c2b024eba144843cd9e344566d9fcee73b04767 + languageName: node + linkType: hard + "throttle-debounce@npm:^5.0.2": version: 5.0.2 resolution: "throttle-debounce@npm:5.0.2" @@ -20801,6 +21231,13 @@ __metadata: languageName: node linkType: hard +"ts-interface-checker@npm:^0.1.9": + version: 0.1.13 + resolution: "ts-interface-checker@npm:0.1.13" + checksum: 10c0/232509f1b84192d07b81d1e9b9677088e590ac1303436da1e92b296e9be8e31ea042e3e1fd3d29b1742ad2c959e95afe30f63117b8f1bc3a3850070a5142fea7 + languageName: node + linkType: hard + "ts-node@npm:^10.9.2": version: 10.9.2 resolution: "ts-node@npm:10.9.2" @@ -21630,6 +22067,28 @@ __metadata: languageName: node linkType: hard +"victory-vendor@npm:^36.6.8": + version: 36.9.2 + resolution: "victory-vendor@npm:36.9.2" + dependencies: + "@types/d3-array": "npm:^3.0.3" + "@types/d3-ease": "npm:^3.0.0" + "@types/d3-interpolate": "npm:^3.0.1" + "@types/d3-scale": "npm:^4.0.2" + "@types/d3-shape": "npm:^3.1.0" + "@types/d3-time": "npm:^3.0.0" + "@types/d3-timer": "npm:^3.0.0" + d3-array: "npm:^3.1.6" + d3-ease: "npm:^3.0.1" + d3-interpolate: "npm:^3.0.1" + d3-scale: "npm:^4.0.2" + d3-shape: "npm:^3.1.0" + d3-time: "npm:^3.0.0" + d3-timer: "npm:^3.0.1" + checksum: 10c0/bad36de3bf4d406834743c2e99a8281d786af324d7e84b7f7a2fc02c27a3779034fb0c3c4707d4c8e68683334d924a67100cfa13985235565e83b9877f8e2ffd + languageName: node + linkType: hard + "vite-node@npm:2.1.8": version: 2.1.8 resolution: "vite-node@npm:2.1.8" @@ -21979,7 +22438,7 @@ __metadata: "@types/css-tree": "npm:^2" "@types/debug": "npm:^4" "@types/electron": "npm:^1.6.12" - "@types/node": "npm:^22.10.2" + "@types/node": "npm:^22.10.7" "@types/papaparse": "npm:^5" "@types/pngjs": "npm:^6.0.5" "@types/prop-types": "npm:^15" @@ -22000,6 +22459,7 @@ __metadata: "@xterm/addon-web-links": "npm:^0.11.0" "@xterm/addon-webgl": "npm:^0.18.0" "@xterm/xterm": "npm:^5.5.0" + autoprefixer: "npm:^10.4.20" base64-js: "npm:^1.5.1" clsx: "npm:^2.1.1" color: "npm:^4.2.3" @@ -22026,6 +22486,7 @@ __metadata: papaparse: "npm:^5.4.1" parse-srcset: "npm:^1.0.2" pngjs: "npm:^7.0.0" + postcss: "npm:^8.5.1" prettier: "npm:^3.4.2" prettier-plugin-jsdoc: "npm:^1.3.0" prettier-plugin-organize-imports: "npm:^4.1.0" @@ -22037,6 +22498,7 @@ __metadata: react-frame-component: "npm:^5.2.7" react-gauge-chart: "npm:^0.5.1" react-markdown: "npm:^9.0.1" + recharts: "npm:^2.15.0" rehype-highlight: "npm:^7.0.1" rehype-raw: "npm:^7.0.0" rehype-sanitize: "npm:^6.0.0" @@ -22053,6 +22515,8 @@ __metadata: sprintf-js: "npm:^1.1.3" storybook: "npm:^8.5.0" storybook-dark-mode: "npm:^4.0.2" + tailwindcss: "npm:^3.4.17" + tailwindcss-animate: "npm:^1.0.7" throttle-debounce: "npm:^5.0.2" tinycolor2: "npm:^1.6.0" ts-node: "npm:^10.9.2" @@ -22543,6 +23007,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.3.4": + version: 2.7.0 + resolution: "yaml@npm:2.7.0" + bin: + yaml: bin.mjs + checksum: 10c0/886a7d2abbd70704b79f1d2d05fe9fb0aa63aefb86e1cb9991837dced65193d300f5554747a872b4b10ae9a12bc5d5327e4d04205f70336e863e35e89d8f4ea9 + languageName: node + linkType: hard + "yaml@npm:^2.6.1": version: 2.6.1 resolution: "yaml@npm:2.6.1" From 52cc8ab1cdb5f2b223c0918522d07469f18b6ca3 Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 19 Jan 2025 19:34:24 -0800 Subject: [PATCH 02/23] add more files for tailwind --- .storybook/global.css | 6 ++++++ frontend/app/tailwindsetup.css | 9 +++++++++ tailwind.config.js | 5 +---- 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 frontend/app/tailwindsetup.css diff --git a/.storybook/global.css b/.storybook/global.css index 32d95f6e4..8d5fcb577 100644 --- a/.storybook/global.css +++ b/.storybook/global.css @@ -16,3 +16,9 @@ body { background-color: orange; } } + +.tw { + @tailwind base; + @tailwind components; + @tailwind utilities; +} diff --git a/frontend/app/tailwindsetup.css b/frontend/app/tailwindsetup.css new file mode 100644 index 000000000..8aacb8a57 --- /dev/null +++ b/frontend/app/tailwindsetup.css @@ -0,0 +1,9 @@ +/* Copyright 2024, Command Line Inc. + SPDX-License-Identifier: Apache-2.0 */ + +/* added this wrapper while we transition */ +.tw { + @tailwind base; + @tailwind components; + @tailwind utilities; +} diff --git a/tailwind.config.js b/tailwind.config.js index dbebd95be..50434edb1 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,9 +1,6 @@ /** @type {import('tailwindcss').Config} */ export default { - content: [ - "./index.html", - "./frontend/**/*.{js,ts,jsx,tsx,scss,css}", // adjust this path if your frontend files are elsewhere - ], + content: ["./index.html", "./frontend/**/*.{js,ts,jsx,tsx,scss,css}", "./.storybook/**/*.{js,ts,jsx,tsx,scss,css}"], theme: { extend: {}, }, From 8fdd5fe8c43b0f36076438f6d2de54eaaec13ae0 Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 19 Jan 2025 19:34:50 -0800 Subject: [PATCH 03/23] donutchart to use tailwind --- frontend/app/element/donutchart.scss | 20 +++ frontend/app/element/donutchart.stories.tsx | 121 ++++++++++++++++++ frontend/app/element/donutchart.tsx | 130 ++++++++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 frontend/app/element/donutchart.scss create mode 100644 frontend/app/element/donutchart.stories.tsx create mode 100644 frontend/app/element/donutchart.tsx diff --git a/frontend/app/element/donutchart.scss b/frontend/app/element/donutchart.scss new file mode 100644 index 000000000..38c6c7531 --- /dev/null +++ b/frontend/app/element/donutchart.scss @@ -0,0 +1,20 @@ +.donutchart { + width: 100%; + height: 100%; + + &__center-label-value { + fill: #000000; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, + "Helvetica Neue", sans-serif; + font-size: 20px; + font-weight: 500; + } + + &__center-label-text { + fill: #666666; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, + "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: normal; + } +} diff --git a/frontend/app/element/donutchart.stories.tsx b/frontend/app/element/donutchart.stories.tsx new file mode 100644 index 000000000..230d1a4e3 --- /dev/null +++ b/frontend/app/element/donutchart.stories.tsx @@ -0,0 +1,121 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import DonutChart from "./donutchart"; + +const meta = { + title: "Components/DonutChart", + component: DonutChart, + parameters: { + layout: "centered", + docs: { + description: { + component: + "The `DonutChart` component displays data in a donut-style chart with customizable colors, labels, and tooltip. Useful for visualizing proportions or percentages.", + }, + }, + }, + argTypes: { + data: { + description: + "The data for the chart, where each item includes `label`, `value`, and optional `displayvalue`.", + control: { type: "object" }, + }, + colors: { + description: "An array of colors for chart segments.", + control: { type: "object" }, + }, + innerRadius: { + description: "Inner radius of the donut chart.", + control: { type: "number" }, + }, + outerRadius: { + description: "Outer radius of the donut chart.", + control: { type: "number" }, + }, + insideLabel: { + description: "The label displayed inside the donut chart (e.g., percentages).", + control: { type: "text" }, + }, + bottomLabel: { + description: "The label displayed below the donut chart.", + control: { type: "text" }, + }, + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + data: [ + { label: "Chrome", value: 275 }, + { label: "Safari", value: 200 }, + { label: "Firefox", value: 187 }, + ], + insideLabel: "50%", + bottomLabel: "Browser Usage", + }, +}; + +export const WithDisplayValues: Story = { + args: { + data: [ + { label: "Chrome", value: 275, displayvalue: "275 users" }, + { label: "Safari", value: 200, displayvalue: "200 users" }, + { label: "Firefox", value: 187, displayvalue: "187 users" }, + ], + insideLabel: "75%", + bottomLabel: "Total Users", + }, +}; + +export const CustomColors: Story = { + args: { + ...Default.args, + colors: ["#FF6B6B", "#4ECDC4", "#45B7D1"], + insideLabel: "44%\n44/100", + bottomLabel: "Memory", + }, +}; + +export const EmptyData: Story = { + args: { + data: [], + insideLabel: "No Data", + bottomLabel: "Empty Chart", + }, +}; + +export const SingleValue: Story = { + args: { + data: [{ label: "Chrome", value: 275, displayvalue: "275 users" }], + insideLabel: "100%", + bottomLabel: "Single Value", + }, +}; + +export const CustomRadii: Story = { + args: { + ...Default.args, + innerRadius: 50, + outerRadius: 100, + insideLabel: "Custom", + bottomLabel: "Radius", + }, +}; diff --git a/frontend/app/element/donutchart.tsx b/frontend/app/element/donutchart.tsx new file mode 100644 index 000000000..4fbc7b9b7 --- /dev/null +++ b/frontend/app/element/donutchart.tsx @@ -0,0 +1,130 @@ +import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip, TooltipProps } from "recharts"; +import { NameType, ValueType } from "recharts/types/component/DefaultTooltipContent"; + +const DEFAULT_COLORS = [ + "#3498db", // blue + "#2ecc71", // green + "#e74c3c", // red + "#f1c40f", // yellow + "#9b59b6", // purple + "#1abc9c", // turquoise + "#e67e22", // orange + "#34495e", // dark blue +]; + +const NO_DATA_COLOR = "#E0E0E0"; + +const CustomTooltip = ({ active, payload, label }: TooltipProps) => { + if (!active || !payload?.length) return null; + + const data = payload[0].payload; + + return ( +
+
{data.name}
+
+ {data.displayValue} ({data.percentage}%) +
+
+ ); +}; + +const DonutChart = ({ + data = [], + valueKey = "value", + displayValueKey = "displayvalue", + labelKey = "label", + colors = DEFAULT_COLORS, + innerRadius = 60, + outerRadius = 80, + insideLabel = null, + bottomLabel = null, +}) => { + const validData: any[] = data.filter((item) => { + const value = item[valueKey]; + return value != null && !Number.isNaN(value) && value > 0; + }); + + if (colors == null || colors.length === 0) { + colors = DEFAULT_COLORS; + } + + if (validData.length == 0) { + colors = [NO_DATA_COLOR]; + validData.push({ + [valueKey]: 1, + [displayValueKey]: "No data", + [labelKey]: "No data", + }); + } + + const total = validData.reduce((sum, item) => sum + item[valueKey], 0); + const formattedData = validData.map((item) => ({ + value: item[valueKey], + displayValue: item[displayValueKey] || String(item[valueKey]), + name: item[labelKey], + percentage: ((item[valueKey] / total) * 100).toFixed(1), + })); + + const primaryItem = formattedData.reduce((max, item) => (item.value > max.value ? item : max), formattedData[0]); + + return ( +
+ + + } cursor={false} /> + + {formattedData.map((entry, index) => ( + + ))} + + {insideLabel && ( + + {insideLabel.split("\n").map((line, index, lines) => ( + + {line} + + ))} + + )} + + + {bottomLabel &&
{bottomLabel}
} +
+ ); +}; + +export default DonutChart; From 5f31fa80e8cabf4aba7fe28a1235aa723bf3dc2b Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 19 Jan 2025 21:36:58 -0800 Subject: [PATCH 04/23] adding shadcn/chart --- frontend/app/shadcn/chart.tsx | 317 ++++++++++++++++++++++++++++++++++ tsconfig.json | 3 +- 2 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 frontend/app/shadcn/chart.tsx diff --git a/frontend/app/shadcn/chart.tsx b/frontend/app/shadcn/chart.tsx new file mode 100644 index 000000000..96537a47e --- /dev/null +++ b/frontend/app/shadcn/chart.tsx @@ -0,0 +1,317 @@ +"use client"; + +import * as React from "react"; +import * as RechartsPrimitive from "recharts"; + +import cn from "clsx"; + +// Format: { THEME_NAME: CSS_SELECTOR } +const THEMES = { light: "", dark: ".dark" } as const; + +export type ChartConfig = { + [k in string]: { + label?: React.ReactNode; + icon?: React.ComponentType; + } & ({ color?: string; theme?: never } | { color?: never; theme: Record }); +}; + +type ChartContextProps = { + config: ChartConfig; +}; + +const ChartContext = React.createContext(null); + +function useChart() { + const context = React.useContext(ChartContext); + + if (!context) { + throw new Error("useChart must be used within a "); + } + + return context; +} + +const ChartContainer = React.forwardRef< + HTMLDivElement, + React.ComponentProps<"div"> & { + config: ChartConfig; + children: React.ComponentProps["children"]; + } +>(({ id, className, children, config, ...props }, ref) => { + const uniqueId = React.useId(); + const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`; + + return ( + +
+ + {children} +
+
+ ); +}); +ChartContainer.displayName = "Chart"; + +const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { + const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color); + + if (!colorConfig.length) { + return null; + } + + return ( +