diff --git a/.github/workflows/list-storybook-branches.sh b/.github/workflows/list-storybook-branches.sh index d2d5c9eed..a28b2a405 100755 --- a/.github/workflows/list-storybook-branches.sh +++ b/.github/workflows/list-storybook-branches.sh @@ -1,7 +1,7 @@ #!/bin/bash # Number of days to check -DAYS=10 +DAYS=30 # Get the current date in seconds since epoch CURRENT_DATE=$(date +%s) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a29a7671..3d8e36d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,154 @@ +# [16.0.0-rc.20](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.19...react-16.0.0-rc.20) (2026-02-26) + + +### Bug Fixes + +* **separator:** fix custom size application [#535](https://github.com/TEDI-Design-System/react/issues/535) ([#536](https://github.com/TEDI-Design-System/react/issues/536)) ([130edcd](https://github.com/TEDI-Design-System/react/commit/130edcd158944b90c62788e76fc97e015f1f228c)) + +# [16.0.0-rc.19](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.18...react-16.0.0-rc.19) (2026-02-25) + + +### Bug Fixes + +* **text-field:** fix small textfield right area padding, fix small textfield font size [#527](https://github.com/TEDI-Design-System/react/issues/527) ([#528](https://github.com/TEDI-Design-System/react/issues/528)) ([bd8bd16](https://github.com/TEDI-Design-System/react/commit/bd8bd1640c40be40199d881efead665ce45bd0a3)) + +# [16.0.0-rc.18](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.17...react-16.0.0-rc.18) (2026-02-25) + + +### Features + +* **separator:** redesign with new spacing API, dotPosition and dotStyle support [#30](https://github.com/TEDI-Design-System/react/issues/30) ([#525](https://github.com/TEDI-Design-System/react/issues/525)) ([93e9e11](https://github.com/TEDI-Design-System/react/commit/93e9e118aab73d40347029089c5370851a7b551c)) + + +### BREAKING CHANGES + +* **separator:** legacy spacing props removed, dotSize enum changed, variant values simplified + +# [16.0.0-rc.17](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.16...react-16.0.0-rc.17) (2026-02-25) + + +### Bug Fixes + +* **checkbox,radio:** show pointer on label hover [#532](https://github.com/TEDI-Design-System/react/issues/532) ([#533](https://github.com/TEDI-Design-System/react/issues/533)) ([097627d](https://github.com/TEDI-Design-System/react/commit/097627db68e23afaa27dd288319b34ccba3e5888)) + +# [16.0.0-rc.16](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.15...react-16.0.0-rc.16) (2026-02-20) + + +### Bug Fixes + +* **number-field:** fix variables [#516](https://github.com/TEDI-Design-System/react/issues/516) ([#522](https://github.com/TEDI-Design-System/react/issues/522)) ([dcf6240](https://github.com/TEDI-Design-System/react/commit/dcf62404afa9543c13277623a9aaa6daed1b93df)) + +# [16.0.0-rc.15](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.14...react-16.0.0-rc.15) (2026-02-19) + + +### Bug Fixes + +* **choice-group:** segmented item borders and focus behaviour [#101](https://github.com/TEDI-Design-System/react/issues/101) ([#513](https://github.com/TEDI-Design-System/react/issues/513)) ([455c491](https://github.com/TEDI-Design-System/react/commit/455c491a753dbfc35d7c996fb94aa15639bbdc51)) + +# [16.0.0-rc.14](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.13...react-16.0.0-rc.14) (2026-02-19) + + +### Features + +* **closing-button:** add brand and inverted color [#6](https://github.com/TEDI-Design-System/react/issues/6) ([#519](https://github.com/TEDI-Design-System/react/issues/519)) ([cfeb5f2](https://github.com/TEDI-Design-System/react/commit/cfeb5f206b9137041b581c610c577e8e600b4fd7)) + +# [16.0.0-rc.13](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.12...react-16.0.0-rc.13) (2026-02-19) + + +### Bug Fixes + +* **feedback-text:** fix error/success text color variables [#517](https://github.com/TEDI-Design-System/react/issues/517) ([#521](https://github.com/TEDI-Design-System/react/issues/521)) ([c019e79](https://github.com/TEDI-Design-System/react/commit/c019e793c5126baba67c516255f3ad3ecfcb2fd7)) + +# [16.0.0-rc.12](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.11...react-16.0.0-rc.12) (2026-02-19) + + +### Features + +* **sidenav:** subheading as ReactNode, fix mobile sidenav items padding [#421](https://github.com/TEDI-Design-System/react/issues/421) ([#512](https://github.com/TEDI-Design-System/react/issues/512)) ([bb7fbe8](https://github.com/TEDI-Design-System/react/commit/bb7fbe8637895adfd5f331bbdbca5e3853d807ef)) + +# [16.0.0-rc.11](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.10...react-16.0.0-rc.11) (2026-02-19) + + +### Bug Fixes + +* **link:** fix link icon sizes in relation to figma design [#46](https://github.com/TEDI-Design-System/react/issues/46) ([#520](https://github.com/TEDI-Design-System/react/issues/520)) ([f32bd83](https://github.com/TEDI-Design-System/react/commit/f32bd83b549b195ecb70b4f9191dd8ef9f6b0a42)) + +# [16.0.0-rc.10](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.9...react-16.0.0-rc.10) (2026-02-19) + + +### Features + +* **button-group:** add size prop, add small example, fix examples on storybook [#14](https://github.com/TEDI-Design-System/react/issues/14) ([#511](https://github.com/TEDI-Design-System/react/issues/511)) ([73cd4f1](https://github.com/TEDI-Design-System/react/commit/73cd4f11348e4cccc9dfbfd84b7a333ce59f2023)) + +# [16.0.0-rc.9](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.8...react-16.0.0-rc.9) (2026-02-19) + + +### Features + +* **alert:** new size prop with default and small values [#11](https://github.com/TEDI-Design-System/react/issues/11) ([#509](https://github.com/TEDI-Design-System/react/issues/509)) ([35c4962](https://github.com/TEDI-Design-System/react/commit/35c4962ec56612c5e5b727a27f813eb96fd7fb1e)) + +# [16.0.0-rc.8](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.7...react-16.0.0-rc.8) (2026-02-16) + + +### Bug Fixes + +* **tooltip,overlay:** wcag improvements [#468](https://github.com/TEDI-Design-System/react/issues/468) ([#491](https://github.com/TEDI-Design-System/react/issues/491)) ([fa60e46](https://github.com/TEDI-Design-System/react/commit/fa60e46c2492734c29d3af2ac3d7cb4df9779c69)) + +# [16.0.0-rc.7](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.6...react-16.0.0-rc.7) (2026-02-13) + + +### Bug Fixes + +* **choice-group:** selected disabled choice-group item fixes [#27](https://github.com/TEDI-Design-System/react/issues/27) ([#510](https://github.com/TEDI-Design-System/react/issues/510)) ([be8884e](https://github.com/TEDI-Design-System/react/commit/be8884e83e0fb26925b155e13143061ba485aa82)) + +# [16.0.0-rc.6](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.5...react-16.0.0-rc.6) (2026-02-13) + + +### Bug Fixes + +* **sidenav:** apply linkAs for flyout items [#40](https://github.com/TEDI-Design-System/react/issues/40) ([#501](https://github.com/TEDI-Design-System/react/issues/501)) ([6007ede](https://github.com/TEDI-Design-System/react/commit/6007ede51b75c6382db9ee3caf689f2a51a04bc3)) + +# [16.0.0-rc.5](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.4...react-16.0.0-rc.5) (2026-02-13) + + +### Features + +* **info-button:** added inverted variant and new color prop [#420](https://github.com/TEDI-Design-System/react/issues/420) ([#508](https://github.com/TEDI-Design-System/react/issues/508)) ([6ca2d7f](https://github.com/TEDI-Design-System/react/commit/6ca2d7fb3b5f609f3f51b884db074ee30fae457a)) + +# [16.0.0-rc.4](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.3...react-16.0.0-rc.4) (2026-02-10) + + +### Bug Fixes + +* **choice-group:** prevent calling onchange twice on card variant [#484](https://github.com/TEDI-Design-System/react/issues/484) ([#502](https://github.com/TEDI-Design-System/react/issues/502)) ([27799cc](https://github.com/TEDI-Design-System/react/commit/27799cc2c4db6381f911ada2697e1bd0b53d2a4d)) +* **choice-group:** prevent double change events and unify card click behavior [#504](https://github.com/TEDI-Design-System/react/issues/504) ([#505](https://github.com/TEDI-Design-System/react/issues/505)) ([7ea1fed](https://github.com/TEDI-Design-System/react/commit/7ea1fedf754e4828df7b508f8cd9ab4428ad3fe6)) + +# [16.0.0-rc.3](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.2...react-16.0.0-rc.3) (2026-02-02) + + +### Bug Fixes + +* **checkbox,radio:** pass required prop to label [#115](https://github.com/TEDI-Design-System/react/issues/115) ([#498](https://github.com/TEDI-Design-System/react/issues/498)) ([a569636](https://github.com/TEDI-Design-System/react/commit/a569636453c865b142ec53761949b97afd436546)), closes [#486](https://github.com/TEDI-Design-System/react/issues/486) + +# [16.0.0-rc.2](https://github.com/TEDI-Design-System/react/compare/react-16.0.0-rc.1...react-16.0.0-rc.2) (2026-02-02) + + +### Features + +* **form-label:** update label prop type to ReactNode [#486](https://github.com/TEDI-Design-System/react/issues/486) ([#490](https://github.com/TEDI-Design-System/react/issues/490)) ([2c1152a](https://github.com/TEDI-Design-System/react/commit/2c1152a549aef92cb3225f092b0519c13440b756)) + +# [16.0.0-rc.1](https://github.com/TEDI-Design-System/react/compare/react-15.0.0...react-16.0.0-rc.1) (2026-01-30) + + +### Features + +* **closing-button:** align size and icon behavior with the design [#43](https://github.com/TEDI-Design-System/react/issues/43) ([#481](https://github.com/TEDI-Design-System/react/issues/481)) ([cdd92a8](https://github.com/TEDI-Design-System/react/commit/cdd92a88115f9ba5b6a5265bf495640178f02b9c)) + + +### BREAKING CHANGES + +* **closing-button:** size, iconSize changes, new default values + # [15.0.0](https://github.com/TEDI-Design-System/react/compare/react-14.3.0...react-15.0.0) (2026-01-29) diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..f05362f4a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 TEDI Design System + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/package-lock.json b/package-lock.json index 1604a4dfe..6268efb2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@mui/material": "^5.15.13", "@mui/x-date-pickers": "^5.0.20", "@tanstack/react-table": "^8.13.2", - "@tedi-design-system/core": "3.0.1", + "@tedi-design-system/core": "3.2.0", "classnames": "^2.5.1", "draft-js": "^0.11.7", "draftjs-md-converter": "^1.5.2", @@ -33,7 +33,7 @@ "@babel/preset-env": "^7.26.0", "@babel/preset-react": "^7.26.3", "@babel/preset-typescript": "^7.26.0", - "@commitlint/cli": "^19.8.1", + "@commitlint/cli": "^20.4.0", "@commitlint/config-conventional": "^20.0.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -2131,17 +2131,17 @@ } }, "node_modules/@commitlint/cli": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.1.tgz", - "integrity": "sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.4.0.tgz", + "integrity": "sha512-2lqrFrYNxjKxgMqeYiO3zNM14XN9v72/5xIJyvdLw7sHEGlfg6sweW01PGNWiqZa6/AuZwsb0uzkgWJy6F4N2w==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/format": "^19.8.1", - "@commitlint/lint": "^19.8.1", - "@commitlint/load": "^19.8.1", - "@commitlint/read": "^19.8.1", - "@commitlint/types": "^19.8.1", + "@commitlint/format": "^20.4.0", + "@commitlint/lint": "^20.4.0", + "@commitlint/load": "^20.4.0", + "@commitlint/read": "^20.4.0", + "@commitlint/types": "^20.4.0", "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, @@ -2166,28 +2166,14 @@ "node": ">=v18" } }, - "node_modules/@commitlint/config-conventional/node_modules/@commitlint/types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.0.0.tgz", - "integrity": "sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/conventional-commits-parser": "^5.0.0", - "chalk": "^5.3.0" - }, - "engines": { - "node": ">=v18" - } - }, "node_modules/@commitlint/config-validator": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.8.1.tgz", - "integrity": "sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.4.0.tgz", + "integrity": "sha512-zShmKTF+sqyNOfAE0vKcqnpvVpG0YX8F9G/ZIQHI2CoKyK+PSdladXMSns400aZ5/QZs+0fN75B//3Q5CHw++w==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.1", + "@commitlint/types": "^20.4.0", "ajv": "^8.11.0" }, "engines": { @@ -2195,27 +2181,23 @@ } }, "node_modules/@commitlint/ensure": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.8.1.tgz", - "integrity": "sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.4.0.tgz", + "integrity": "sha512-F3qwnanJUisFWwh44GYYmMOxfgJL1FKV73FCB5zxo8pw1CHkxXadGfDfzNkN8B3iqgSGusDN2+oDH6upBmLszA==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.1", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" + "@commitlint/types": "^20.4.0", + "kasi": "^2.0.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/execute-rule": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.8.1.tgz", - "integrity": "sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", "dev": true, "license": "MIT", "engines": { @@ -2223,27 +2205,27 @@ } }, "node_modules/@commitlint/format": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.8.1.tgz", - "integrity": "sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.4.0.tgz", + "integrity": "sha512-i3ki3WR0rgolFVX6r64poBHXM1t8qlFel1G1eCBvVgntE3fCJitmzSvH5JD/KVJN/snz6TfaX2CLdON7+s4WVQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.1", - "chalk": "^5.3.0" + "@commitlint/types": "^20.4.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/is-ignored": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.8.1.tgz", - "integrity": "sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.4.0.tgz", + "integrity": "sha512-E8AHpedEfuf+lZatFvFiJXA4TtZgBZ10+A7HzFudaEmTPPE5o6MGswxbxUIGAciaHAFj/oTTmyFc6A5tcvxE3Q==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.1", + "@commitlint/types": "^20.4.0", "semver": "^7.6.0" }, "engines": { @@ -2264,47 +2246,59 @@ } }, "node_modules/@commitlint/lint": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.8.1.tgz", - "integrity": "sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.4.0.tgz", + "integrity": "sha512-W90YCbm5h3Yg+btF5/X+cxsY6vd/H3tsFt6U7WBmDQSkKV8NmitYg89zeoSQyYEiQCwAsH0dcA+99aQtLZiSnw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^19.8.1", - "@commitlint/parse": "^19.8.1", - "@commitlint/rules": "^19.8.1", - "@commitlint/types": "^19.8.1" + "@commitlint/is-ignored": "^20.4.0", + "@commitlint/parse": "^20.4.0", + "@commitlint/rules": "^20.4.0", + "@commitlint/types": "^20.4.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.8.1.tgz", - "integrity": "sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.4.0.tgz", + "integrity": "sha512-Dauup/GfjwffBXRJUdlX/YRKfSVXsXZLnINXKz0VZkXdKDcaEILAi9oflHGbfydonJnJAbXEbF3nXPm9rm3G6A==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.8.1", - "@commitlint/execute-rule": "^19.8.1", - "@commitlint/resolve-extends": "^19.8.1", - "@commitlint/types": "^19.8.1", - "chalk": "^5.3.0", + "@commitlint/config-validator": "^20.4.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.4.0", + "@commitlint/types": "^20.4.0", "cosmiconfig": "^9.0.0", "cosmiconfig-typescript-loader": "^6.1.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0" + "is-plain-obj": "^4.1.0", + "lodash.mergewith": "^4.6.2", + "picocolors": "^1.1.1" }, "engines": { "node": ">=v18" } }, + "node_modules/@commitlint/load/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@commitlint/message": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.8.1.tgz", - "integrity": "sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.0.tgz", + "integrity": "sha512-B5lGtvHgiLAIsK5nLINzVW0bN5hXv+EW35sKhYHE8F7V9Uz1fR4tx3wt7mobA5UNhZKUNgB/+ldVMQE6IHZRyA==", "dev": true, "license": "MIT", "engines": { @@ -2312,29 +2306,29 @@ } }, "node_modules/@commitlint/parse": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.8.1.tgz", - "integrity": "sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.4.0.tgz", + "integrity": "sha512-NcRkqo/QUnuc1RgxRCIKTqobKzF0BKJ8h3i1jRyeZ+SEy5rO9dPNOh4BqrFsSznb5mnwETYB7ph9tUcthNkwAQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^19.8.1", - "conventional-changelog-angular": "^7.0.0", - "conventional-commits-parser": "^5.0.0" + "@commitlint/types": "^20.4.0", + "conventional-changelog-angular": "^8.1.0", + "conventional-commits-parser": "^6.2.1" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/read": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.8.1.tgz", - "integrity": "sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.4.0.tgz", + "integrity": "sha512-QfpFn6/I240ySEGv7YWqho4vxqtPpx40FS7kZZDjUJ+eHxu3azfhy7fFb5XzfTqVNp1hNoI3tEmiEPbDB44+cg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/top-level": "^19.8.1", - "@commitlint/types": "^19.8.1", + "@commitlint/top-level": "^20.4.0", + "@commitlint/types": "^20.4.0", "git-raw-commits": "^4.0.0", "minimist": "^1.2.8", "tinyexec": "^1.0.0" @@ -2344,14 +2338,14 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.8.1.tgz", - "integrity": "sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.4.0.tgz", + "integrity": "sha512-ay1KM8q0t+/OnlpqXJ+7gEFQNlUtSU5Gxr8GEwnVf2TPN3+ywc5DzL3JCxmpucqxfHBTFwfRMXxPRRnR5Ki20g==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^19.8.1", - "@commitlint/types": "^19.8.1", + "@commitlint/config-validator": "^20.4.0", + "@commitlint/types": "^20.4.0", "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", @@ -2362,25 +2356,25 @@ } }, "node_modules/@commitlint/rules": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.8.1.tgz", - "integrity": "sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.4.0.tgz", + "integrity": "sha512-E+UoAA7WA4xrre9lDyX2vL4Df26I+vqMN4D8JoW/L2xE/VRDvn533/ibhgSlGYDltB9nm2S+1lti3PagEwO0ag==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^19.8.1", - "@commitlint/message": "^19.8.1", - "@commitlint/to-lines": "^19.8.1", - "@commitlint/types": "^19.8.1" + "@commitlint/ensure": "^20.4.0", + "@commitlint/message": "^20.4.0", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.4.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/to-lines": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.8.1.tgz", - "integrity": "sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", + "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", "dev": true, "license": "MIT", "engines": { @@ -2388,27 +2382,27 @@ } }, "node_modules/@commitlint/top-level": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.8.1.tgz", - "integrity": "sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.0.tgz", + "integrity": "sha512-NDzq8Q6jmFaIIBC/GG6n1OQEaHdmaAAYdrZRlMgW6glYWGZ+IeuXmiymDvQNXPc82mVxq2KiE3RVpcs+1OeDeA==", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^7.0.0" + "escalade": "^3.2.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/types": { - "version": "19.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.8.1.tgz", - "integrity": "sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.4.0.tgz", + "integrity": "sha512-aO5l99BQJ0X34ft8b0h7QFkQlqxC6e7ZPVmBKz13xM9O8obDaM1Cld4sQlJDXXU/VFuUzQ30mVtHjVz74TuStw==", "dev": true, "license": "MIT", "dependencies": { - "@types/conventional-commits-parser": "^5.0.0", - "chalk": "^5.3.0" + "conventional-commits-parser": "^6.2.1", + "picocolors": "^1.1.1" }, "engines": { "node": ">=v18" @@ -6110,48 +6104,6 @@ "semantic-release": ">=20.1.0" } }, - "node_modules/@semantic-release/commit-analyzer/node_modules/conventional-changelog-angular": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", - "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@semantic-release/commit-analyzer/node_modules/conventional-commits-parser": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.2.0.tgz", - "integrity": "sha512-uLnoLeIW4XaoFtH37qEcg/SXMJmKF4vi7V0H2rnPueg+VEtFGA/asSCNTcq4M/GQ6QmlzchAEtOoDTtKqWeHag==", - "dev": true, - "license": "MIT", - "dependencies": { - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@semantic-release/commit-analyzer/node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@semantic-release/error": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", @@ -6607,35 +6559,6 @@ "semantic-release": ">=20.1.0" } }, - "node_modules/@semantic-release/release-notes-generator/node_modules/conventional-changelog-angular": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", - "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@semantic-release/release-notes-generator/node_modules/conventional-commits-parser": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.2.0.tgz", - "integrity": "sha512-uLnoLeIW4XaoFtH37qEcg/SXMJmKF4vi7V0H2rnPueg+VEtFGA/asSCNTcq4M/GQ6QmlzchAEtOoDTtKqWeHag==", - "dev": true, - "license": "MIT", - "dependencies": { - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", @@ -6649,19 +6572,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@semantic-release/release-notes-generator/node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -7979,9 +7889,9 @@ } }, "node_modules/@tedi-design-system/core": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@tedi-design-system/core/-/core-3.0.1.tgz", - "integrity": "sha512-ioet8RlFmWjg8fic4WUuYeavLiqUsKx3vFGZzzXkL91xNNjHexNVKhhtMLLkpCywzOc2tKXMx3AYdDhu2dsbwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@tedi-design-system/core/-/core-3.2.0.tgz", + "integrity": "sha512-R9gpmprRT8qCGeJ8Frhz2yiJQ9bJM1Yp3mvWHeX2a6600hWh3mKXvhARSLFAF6im83FEFmOoKwdIOr4nfy8Qbg==", "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" @@ -8504,16 +8414,6 @@ "@babel/types": "^7.28.2" } }, - "node_modules/@types/conventional-commits-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", - "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/css-modules": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/css-modules/-/css-modules-1.0.5.tgz", @@ -8738,15 +8638,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -9494,43 +9385,6 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@volar/source-map": "1.11.1" - } - }, - "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "muggle-string": "^0.3.1" - } - }, - "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" - } - }, "node_modules/@vue/compiler-core": { "version": "3.5.22", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", @@ -9567,34 +9421,6 @@ "he": "^1.2.0" } }, - "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", - "computeds": "^0.0.1", - "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@vue/shared": { "version": "3.5.22", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", @@ -10033,18 +9859,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -10655,38 +10469,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001749", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz", @@ -11275,15 +11057,6 @@ "dev": true, "license": "MIT" }, - "node_modules/computeds": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -11317,16 +11090,16 @@ "license": "ISC" }, "node_modules/conventional-changelog-angular": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", - "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.1.0.tgz", + "integrity": "sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==", "dev": true, "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/conventional-changelog-conventionalcommits": { @@ -11398,32 +11171,29 @@ } }, "node_modules/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.2.1.tgz", + "integrity": "sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==", "dev": true, "license": "MIT", "dependencies": { - "is-text-path": "^2.0.0", - "JSONStream": "^1.3.5", - "meow": "^12.0.1", - "split2": "^4.0.0" + "meow": "^13.0.0" }, "bin": { - "conventional-commits-parser": "cli.mjs" + "conventional-commits-parser": "dist/cli/index.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/conventional-commits-parser/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16.10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11933,49 +11703,6 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", @@ -14228,24 +13955,6 @@ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, - "node_modules/find-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", - "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^7.2.0", - "path-exists": "^5.0.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/find-up-simple": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", @@ -14953,18 +14662,6 @@ "node": ">=0.10.0" } }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -16007,19 +15704,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-text-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", - "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "text-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", @@ -17732,33 +17416,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -17775,6 +17432,13 @@ "node": ">=4.0" } }, + "node_modules/kasi": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kasi/-/kasi-2.0.1.tgz", + "integrity": "sha512-8qhiHZ1BN26ig1+jQ9fWEk6dj8T1wuxs00QRJfXIANI4scto1EuPUgqj+mxHls52WBfdTNJGQ8yYw9rDpWUcgQ==", + "dev": true, + "license": "MIT" + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -18149,22 +17813,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -18219,13 +17867,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -18247,20 +17888,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -18268,13 +17895,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", @@ -18282,13 +17902,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -18462,21 +18075,6 @@ "tmpl": "1.0.5" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/map-or-similar": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", @@ -19216,134 +18814,6 @@ "map-or-similar": "^1.5.0" } }, - "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -20087,35 +19557,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -20164,15 +19605,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -23462,51 +22894,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-map": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", @@ -23661,16 +23048,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -24460,18 +23837,6 @@ ], "license": "MIT" }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -24733,180 +24098,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/read-pkg/node_modules/parse-json": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", @@ -28069,19 +27260,6 @@ "node": "*" } }, - "node_modules/text-extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", - "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -28112,13 +27290,6 @@ "node": ">=0.8" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -28166,11 +27337,14 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinyglobby": { "version": "0.2.15", @@ -28281,18 +27455,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -30270,54 +29432,6 @@ "dev": true, "license": "MIT" }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" - }, - "bin": { - "vue-tsc": "bin/vue-tsc.js" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/vue-tsc/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/package.json b/package.json index 6fcde260d..33819bf54 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@mui/material": "^5.15.13", "@mui/x-date-pickers": "^5.0.20", "@tanstack/react-table": "^8.13.2", - "@tedi-design-system/core": "3.0.1", + "@tedi-design-system/core": "3.2.0", "classnames": "^2.5.1", "draft-js": "^0.11.7", "draftjs-md-converter": "^1.5.2", @@ -67,7 +67,7 @@ "@babel/preset-env": "^7.26.0", "@babel/preset-react": "^7.26.3", "@babel/preset-typescript": "^7.26.0", - "@commitlint/cli": "^19.8.1", + "@commitlint/cli": "^20.4.0", "@commitlint/config-conventional": "^20.0.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", diff --git a/src/community/components/layout/header/components/header-modal/header-modal.tsx b/src/community/components/layout/header/components/header-modal/header-modal.tsx index df3b57160..5794e99ae 100644 --- a/src/community/components/layout/header/components/header-modal/header-modal.tsx +++ b/src/community/components/layout/header/components/header-modal/header-modal.tsx @@ -55,7 +55,7 @@ export const HeaderModal = (props: HeaderModalProps) => { diff --git a/src/community/components/map-components/directions/direction-item.tsx b/src/community/components/map-components/directions/direction-item.tsx index 6ce1b16a3..18696e06e 100644 --- a/src/community/components/map-components/directions/direction-item.tsx +++ b/src/community/components/map-components/directions/direction-item.tsx @@ -61,6 +61,7 @@ export const DirectionItem = (props: DirectionItemProps): JSX.Element => { className={styles['tedi-directions__remove']} onClick={onDelete} aria-label={getLabel('remove')} + iconSize={18} /> )} diff --git a/src/community/components/map-components/left-panel/left-panel-footer.tsx b/src/community/components/map-components/left-panel/left-panel-footer.tsx index 526f38fc9..f3d725cbc 100644 --- a/src/community/components/map-components/left-panel/left-panel-footer.tsx +++ b/src/community/components/map-components/left-panel/left-panel-footer.tsx @@ -7,7 +7,7 @@ const LeftPanelFooter = () => {
Tume režiim} /> - +
diff --git a/src/community/components/map-components/right-panel/right-panel.tsx b/src/community/components/map-components/right-panel/right-panel.tsx index 65a2be2b2..d6b47b2c8 100644 --- a/src/community/components/map-components/right-panel/right-panel.tsx +++ b/src/community/components/map-components/right-panel/right-panel.tsx @@ -69,7 +69,7 @@ type DefaultCloseButtonProps = { id: string; isSingleItem: boolean; onClose: (id export const DefaultCloseButton = ({ id, isSingleItem, onClose }: DefaultCloseButtonProps): JSX.Element => ( onClose(id)} title="Sulge aken" /> diff --git a/src/community/components/map-components/sheet/sheet.tsx b/src/community/components/map-components/sheet/sheet.tsx index 4e6215294..cf64b65be 100644 --- a/src/community/components/map-components/sheet/sheet.tsx +++ b/src/community/components/map-components/sheet/sheet.tsx @@ -229,7 +229,7 @@ export const Sheet = (props: SheetProps): JSX.Element | null => {
{actions} diff --git a/src/community/components/modal/modal.tsx b/src/community/components/modal/modal.tsx index 2948f7dc1..122ac4b7d 100644 --- a/src/community/components/modal/modal.tsx +++ b/src/community/components/modal/modal.tsx @@ -109,7 +109,7 @@ export const Modal = (props: ModalProps): JSX.Element | null => { children: ( <> - + {child.props.children} diff --git a/src/community/docs/scale-layout/development.mdx b/src/community/docs/scale-layout/development.mdx deleted file mode 100644 index a413dfb5c..000000000 --- a/src/community/docs/scale-layout/development.mdx +++ /dev/null @@ -1,12 +0,0 @@ -import { Meta, Title, Subtitle, Unstyled } from '@storybook/blocks'; - - - -# Grid in development - -Every layout in design is makeable with `` and `` components.
-All examples of Grid usage are under [Grid docs](/docs/components-grid--docs) - -To create vertical spacing between elements use `` [component](/docs/components-vertical-spacing--docs). - -{/* TODO: Need more information how to use Row, Col, VerticalSpacing and Card correctly */} diff --git a/src/tedi/components/buttons/button-content/button-content.module.scss b/src/tedi/components/buttons/button-content/button-content.module.scss index 27c5ab3c1..15a153cd0 100644 --- a/src/tedi/components/buttons/button-content/button-content.module.scss +++ b/src/tedi/components/buttons/button-content/button-content.module.scss @@ -399,11 +399,16 @@ $btn-width-large: 3.72rem; height: auto; min-height: auto; padding: 0; + font-size: var(--body-link-size-regular); text-align: left; text-decoration: none; background: none; border: none; + &.tedi-btn--small { + font-size: var(--body-link-size-responsive); + } + @include link-variant( var(--link-primary-default), var(--link-primary-hover), @@ -411,12 +416,22 @@ $btn-width-large: 3.72rem; var(--link-primary-focus) ); - .tedi-btn__icon--left { - margin-right: var(--button-sm-inner-spacing); + .tedi-btn__inner { + .tedi-btn__icon--left { + display: inline; + margin-right: var(--button-sm-inner-spacing); + vertical-align: middle; + } + + .tedi-btn__icon--right { + display: inline; + margin-left: var(--button-sm-inner-spacing); + vertical-align: middle; + } } - .tedi-btn__icon--right { - margin-left: var(--button-sm-inner-spacing); + .tedi-btn__icon-responsive { + font-size: var(--link-icon-responsive); } } diff --git a/src/tedi/components/buttons/button-content/button-content.tsx b/src/tedi/components/buttons/button-content/button-content.tsx index dff0edabc..604d47c7a 100644 --- a/src/tedi/components/buttons/button-content/button-content.tsx +++ b/src/tedi/components/buttons/button-content/button-content.tsx @@ -144,14 +144,12 @@ const InternalButtonContent = forwardRef( const getIcon = (location: string, icon: string | IconWithoutBackgroundProps): JSX.Element => { const iconBEM = cn(styles['tedi-btn__icon'], styles[`tedi-btn__icon--${location}`], { [styles['tedi-btn__spinner']]: isLoading, + [styles['tedi-btn__icon-responsive']]: Component === 'a' && size === 'small', }); - const isLink = visualType === 'link'; - const defaultIconProps: Partial = { size: size === 'large' ? 24 : 18, className: iconBEM, - ...(isLink ? { display: 'inline' } : {}), }; const iconProps: IconWithoutBackgroundProps = diff --git a/src/tedi/components/buttons/button-group/button-group.module.scss b/src/tedi/components/buttons/button-group/button-group.module.scss index fe4ab8aee..61910972d 100644 --- a/src/tedi/components/buttons/button-group/button-group.module.scss +++ b/src/tedi/components/buttons/button-group/button-group.module.scss @@ -11,8 +11,6 @@ align-items: center; justify-content: center; height: auto; - min-height: 2.5rem; - padding: calc(var(--button-md-padding-y) - 1px) var(--button-md-padding-x); text-align: center; cursor: pointer; border-radius: 0; @@ -38,6 +36,17 @@ @include breakpoints.media-breakpoint-down(md) { flex: 1; } + + &--size-default { + min-height: var(--button-md-height); + padding: calc(var(--button-md-padding-y) - 1px) var(--button-md-padding-x); + } + + &--size-small { + min-height: var(--button-sm-height); + padding: calc(var(--button-sm-padding-y) - 1px) var(--button-sm-padding-x); + font-size: var(--button-text-size-sm); + } } } @@ -65,6 +74,12 @@ background-color: var(--button-group-primary-selected-background); border-color: var(--button-group-primary-selected-border); } + + &:focus-visible:not(:disabled, .tedi-button-group__item--active) { + color: var(--button-group-primary-inactive-text); + background-color: var(--button-group-primary-inactive-background); + border: 1px solid var(--button-group-primary-inactive-border); + } } } @@ -93,6 +108,12 @@ outline: 2px solid var(--button-group-secondary-selected-border); outline-offset: -2px; } + + &:focus-visible:not(:disabled, .tedi-button-group__item--active) { + color: var(--button-group-secondary-inactive-text); + background-color: var(--button-group-secondary-inactive-background); + border: 1px solid var(--button-group-secondary-inactive-border); + } } } diff --git a/src/tedi/components/buttons/button-group/button-group.stories.tsx b/src/tedi/components/buttons/button-group/button-group.stories.tsx index d3b692e0d..14adb9282 100644 --- a/src/tedi/components/buttons/button-group/button-group.stories.tsx +++ b/src/tedi/components/buttons/button-group/button-group.stories.tsx @@ -1,6 +1,7 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react'; import { useState } from 'react'; +import { Text } from '../../base/typography/text/text'; import { Col, Row } from '../../layout/grid'; import { VerticalSpacing } from '../../layout/vertical-spacing'; import { Button } from '../button/button'; @@ -24,7 +25,8 @@ const meta: Meta = { export default meta; type Story = StoryObj; -const buttonStates = ['Default', 'Hover', 'Active', 'Disabled']; +const buttonStates = ['Default', 'Hover', 'Active', 'Focus', 'Disabled']; +const sizeArray: ButtonGroupProps['size'][] = ['default', 'small']; const Template: StoryFn = (args) => ( @@ -36,6 +38,40 @@ const Template: StoryFn = (args) => ( ); +interface TemplateMultipleProps extends ButtonGroupProps { + array: Type[]; + property: keyof ButtonGroupProps; +} + +const TemplateSizes: StoryFn = (args) => { + const { array, property, ...buttonGroupProps } = args; + + return ( +
+ {array.map((value, key) => { + return ( + + + {value ? value.charAt(0).toUpperCase() + value.slice(1) : ''} + + + + + + + + + + + + ); + })} +
+ ); +}; + const TemplateTypes: StoryFn = (args) => { return ( @@ -73,6 +109,14 @@ export const Default: Story = { }, }; +export const Sizes: StoryObj = { + render: TemplateSizes, + args: { + property: 'size', + array: sizeArray, + }, +}; + export const Types: StoryObj = { render: TemplateTypes, }; @@ -130,7 +174,7 @@ export const Primary: StoryObj<{ states: string[] }> = { pseudo: { hover: ['#Hover-primary'], active: ['#Active-primary'], - focus: ['#Focus-primary'], + focusVisible: ['#Focus-primary'], }, }, }; @@ -144,7 +188,7 @@ export const Secondary: StoryObj<{ states: string[] }> = { pseudo: { hover: ['#Hover-secondary'], active: ['#Active-secondary'], - focus: ['#Focus-secondary'], + focusVisible: ['#Focus-secondary'], }, }, }; diff --git a/src/tedi/components/buttons/button-group/button-group.tsx b/src/tedi/components/buttons/button-group/button-group.tsx index b2e0ecbaa..f830c304c 100644 --- a/src/tedi/components/buttons/button-group/button-group.tsx +++ b/src/tedi/components/buttons/button-group/button-group.tsx @@ -36,10 +36,22 @@ export type ButtonGroupProps = { * Additional custom CSS classes to apply to the ButtonGroup container */ className?: string; + /** + * Size of the buttons in ButtonGroup + */ + size?: 'default' | 'small'; }; export const ButtonGroup = (props: ButtonGroupProps): JSX.Element => { - const { children, className, type = 'primary', onSelectionChange, stretch = false, ariaLabel } = props; + const { + children, + className, + type = 'primary', + onSelectionChange, + stretch = false, + ariaLabel, + size = 'default', + } = props; return (
{ className: cn(styles['tedi-button-group__item'], { [styles['tedi-button-group__item--active']]: child.props.isActive, [styles['tedi-button-group__item--disabled']]: child.props.disabled, + [styles[`tedi-button-group__item--size-${size}`]]: size, }), - noStyle: true, + size: size, onClick: () => { if (!child.props.disabled) { child.props.onClick?.(); diff --git a/src/tedi/components/buttons/closing-button/closing-button.module.scss b/src/tedi/components/buttons/closing-button/closing-button.module.scss index 16f010cfb..628e9b58e 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.module.scss +++ b/src/tedi/components/buttons/closing-button/closing-button.module.scss @@ -1,36 +1,78 @@ .tedi-closing-button { - --general-icon-primary: var(--button-close-text-default); - display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; - background-color: var(--button-close-background-default); - border: 1px solid var(--button-close-background-default); + border: 0; border-radius: var(--button-radius-default); - transition: background 0.5s ease; + transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; - @each $state in hover, active { - &:#{ $state } { - --general-icon-primary: var(--button-close-text-#{$state}); + &--default { + width: var(--button-sm-icon-size); + height: var(--button-sm-icon-size); + } - background-color: var(--button-close-background-#{$state}); - } + &--small { + width: var(--button-xs-icon-size); + height: var(--button-xs-icon-size); } - &:focus-visible { - outline: 2px solid var(--button-main-primary-border-focus); - outline-offset: -2px; + &--color-primary { + color: var(--button-close-text-default); + background-color: var(--button-close-background-default); + + &:hover { + color: var(--button-close-text-hover); + background-color: var(--button-close-background-hover); + } + + &:active { + color: var(--button-close-text-active); + background-color: var(--button-close-background-active); + } + + &:focus-visible { + color: var(--button-close-text-focus); + outline: 2px solid var(--button-main-primary-border-focus); + } } - &--medium { - width: var(--button-xs-icon-size); - height: var(--button-xs-icon-size); + &--color-brand { + color: var(--button-main-neutral-text-default); + background-color: var(--button-main-neutral-icon-only-background-default); + + &:hover { + color: var(--button-main-neutral-text-hover); + background-color: var(--button-main-neutral-icon-only-background-hover); + } + + &:active { + color: var(--button-main-neutral-text-active); + background-color: var(--button-main-neutral-icon-only-background-active); + } + + &:focus-visible { + outline: 2px solid var(--button-main-primary-border-focus); + } } - &--large { - width: var(--button-sm-icon-size); - height: var(--button-sm-icon-size); + &--color-white { + color: var(--button-neutral-inverted-text-default); + background-color: var(--button-neutral-inverted-icon-only-background-default); + + &:hover { + color: var(--button-neutral-inverted-text-hover); + background-color: var(--button-main-neutral-inverted-icon-only-background-hover); + } + + &:active { + color: var(--button-neutral-inverted-text-active); + background-color: var(--button-main-neutral-inverted-icon-only-background-hover); + } + + &:focus-visible { + outline: 2px solid var(--button-main-neutral-inverted-text-focus); + } } } diff --git a/src/tedi/components/buttons/closing-button/closing-button.spec.tsx b/src/tedi/components/buttons/closing-button/closing-button.spec.tsx index 8bc45184d..9e27d065a 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.spec.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.spec.tsx @@ -10,72 +10,94 @@ jest.mock('../../../providers/label-provider', () => ({ describe('ClosingButton component', () => { it('renders the ClosingButton with default props', () => { - render( - { - console.log('Button pressed'); - }} - /> - ); + render(); const button = screen.getByRole('button', { name: /close/i }); expect(button).toBeInTheDocument(); - expect(button).toHaveClass('tedi-closing-button'); + expect(button).toHaveClass('tedi-closing-button tedi-closing-button--default tedi-closing-button--color-primary'); const icon = button.querySelector('span[data-name="icon"]'); expect(icon).toBeInTheDocument(); - expect(icon).toHaveClass('tedi-icon--size-18'); + expect(icon).toHaveClass('tedi-icon--size-24'); }); - it('renders with the correct large size class and icon size', () => { + it('renders with the correct small size class and icon size', () => { + render(); + + const button = screen.getByRole('button', { name: /close/i }); + expect(button).toHaveClass('tedi-closing-button tedi-closing-button--small tedi-closing-button--color-primary'); render( { console.log('Button pressed'); }} /> ); - const button = screen.getByRole('button', { name: /close/i }); expect(button).toBeInTheDocument(); - expect(button).toHaveClass('tedi-closing-button tedi-closing-button--large'); + expect(button).toHaveClass('tedi-closing-button'); + expect(button).toHaveClass('tedi-closing-button--small'); const icon = button.querySelector('span[data-name="icon"]'); - expect(icon).toBeInTheDocument(); expect(icon).toHaveClass('tedi-icon--size-24'); }); + it('forces small size when iconSize is 18', () => { + render(); + + const button = screen.getByRole('button', { name: /close/i }); + expect(button).toHaveClass('tedi-closing-button--small'); + + const icon = button.querySelector('span[data-name="icon"]'); + expect(icon).toBeInTheDocument(); + expect(icon).toHaveClass('tedi-icon--size-18'); + }); + it('applies custom class names', () => { - render(); + render(); - const button = screen.getByRole('button', { name: /Close/i }); - expect(button).toHaveClass('tedi-closing-button tedi-closing-button--large custom-class'); + const button = screen.getByRole('button', { name: /close/i }); + expect(button).toHaveClass( + 'tedi-closing-button tedi-closing-button--default tedi-closing-button--color-primary custom-class' + ); + const customButton = screen.getByRole('button', { name: /Close/i }); + expect(customButton).toHaveClass('tedi-closing-button'); + expect(customButton).toHaveClass('tedi-closing-button--default'); + expect(customButton).toHaveClass('custom-class'); }); it('triggers onClick handler when clicked', () => { const onClickMock = jest.fn(); - render(); + render(); - const button = screen.getByRole('button', { name: /Close/i }); + const button = screen.getByRole('button', { name: /close/i }); fireEvent.click(button); expect(onClickMock).toHaveBeenCalledTimes(1); }); it('uses fallback label from label provider when title is not provided', () => { - render(); + render(); - const button = screen.getByRole('button', { name: /Close/i }); + const button = screen.getByRole('button', { name: /close/i }); expect(button).toHaveAttribute('title', 'Close'); expect(button).toHaveAttribute('aria-label', 'Close'); }); it('uses custom title if provided', () => { - render(); + render(); const button = screen.getByRole('button', { name: /Custom Close/i }); expect(button).toHaveAttribute('title', 'Custom Close'); expect(button).toHaveAttribute('aria-label', 'Custom Close'); }); + + it('applies the correct color classes', () => { + const colors: Array<'primary' | 'brand' | 'white'> = ['primary', 'brand', 'white']; + + colors.forEach((color) => { + const { container } = render(); + const button = container.querySelector('button[data-name="closing-button"]'); + expect(button).toHaveClass(`tedi-closing-button--color-${color}`); + }); + }); }); diff --git a/src/tedi/components/buttons/closing-button/closing-button.stories.tsx b/src/tedi/components/buttons/closing-button/closing-button.stories.tsx index 69528a74f..d2e0a084b 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.stories.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.stories.tsx @@ -1,5 +1,6 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react'; +import { Text } from '../../base/typography/text/text'; import { Col, Row } from '../../layout/grid'; import ClosingButton, { ClosingButtonProps } from './closing-button'; @@ -19,7 +20,8 @@ const meta: Meta = { }, }; -const sizeArray: ClosingButtonProps['size'][] = ['medium', 'large']; +const sizeArray: ClosingButtonProps['size'][] = ['default', 'small']; +const iconSizeArray: ClosingButtonProps['iconSize'][] = [18, 24]; export default meta; type Story = StoryObj; @@ -41,16 +43,43 @@ const SizeTemplate: StoryFn = () => { const stateArray = ['Default', 'Hover', 'Active', 'Focus']; -const StatesTemplate: StoryFn = () => { +const StatesTemplate: StoryFn = (args) => { return (
{stateArray.map((state) => ( - {state} + + {state} + - + + + + ))} +
+ ); +}; + +const IconSizeTemplate: StoryFn = () => { + return ( +
+ {iconSizeArray.map((iconSize, key) => ( + + {`${iconSize}px`} + + alert(`${iconSize}px icon clicked`)} className="hover" /> + {iconSize === 24 && ( +
+ alert(`${iconSize}px icon clicked`)} + className="hover" + /> +
+ )}
))} @@ -61,7 +90,6 @@ const StatesTemplate: StoryFn = () => { export const Default: Story = { args: { title: 'close', - size: 'medium', }, }; @@ -69,6 +97,18 @@ export const Size: Story = { render: SizeTemplate, }; +/** + * Hover state is shown on all buttons for size preview. + */ +export const IconSizes: Story = { + render: IconSizeTemplate, + parameters: { + pseudo: { + hover: '.hover', + }, + }, +}; + export const States: Story = { render: StatesTemplate, parameters: { @@ -79,3 +119,32 @@ export const States: Story = { }, }, }; + +export const ColorBrand: Story = { + render: StatesTemplate, + args: { + color: 'brand', + }, + parameters: { + pseudo: { + hover: '#Hover', + active: '#Active', + focusVisible: '#Focus', + }, + }, +}; + +export const ColorInverted: Story = { + render: StatesTemplate, + args: { + color: 'white', + }, + parameters: { + pseudo: { + hover: '#Hover', + active: '#Active', + focusVisible: '#Focus', + }, + backgrounds: { default: 'brand' }, + }, +}; diff --git a/src/tedi/components/buttons/closing-button/closing-button.tsx b/src/tedi/components/buttons/closing-button/closing-button.tsx index b718964f6..0eb7c77a5 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.tsx @@ -6,7 +6,9 @@ import { useLabels } from '../../../providers/label-provider'; import { Icon } from '../../base/icon/icon'; import styles from './closing-button.module.scss'; -type ClosingButtonSize = 'medium' | 'large'; +type ClosingButtonColor = 'primary' | 'brand' | 'white'; +export type ClosingButtonSize = 'default' | 'small'; +export type ClosingButtonIconSize = 18 | 24; export interface ClosingButtonProps extends ButtonHTMLAttributes { /** @@ -15,7 +17,7 @@ export interface ClosingButtonProps extends ButtonHTMLAttributes { const { getLabel } = useLabels(); - const { title = getLabel('close'), onClick, size = 'medium', className, ...rest } = props; + const { + title = getLabel('close'), + onClick, + size = 'default', + iconSize = 24, + color = 'primary', + className, + ...rest + } = props; + + const resolvedSize: ClosingButtonSize = iconSize === 18 ? 'small' : size; const buttonClass = cn( styles['tedi-closing-button'], { [styles[`tedi-closing-button--${size}`]]: size, + [styles[`tedi-closing-button--color-${color}`]]: color, + [styles[`tedi-closing-button--${resolvedSize}`]]: resolvedSize, }, className ); - const iconSize = size === 'large' ? 24 : 18; + const resolvedIconSize: ClosingButtonIconSize = iconSize ?? 24; return ( ); }; diff --git a/src/tedi/components/buttons/info-button/info-button.module.scss b/src/tedi/components/buttons/info-button/info-button.module.scss index 6f2fc8dbf..8a7ac2a79 100644 --- a/src/tedi/components/buttons/info-button/info-button.module.scss +++ b/src/tedi/components/buttons/info-button/info-button.module.scss @@ -3,4 +3,12 @@ height: var(--button-xs-icon-size); min-height: var(--button-xs-icon-size); vertical-align: bottom; + + &[data-variant='inverted']:hover:not(:disabled) { + background-color: var(--button-main-neutral-inverted-icon-only-background-hover); + } + + &[data-variant='inverted']:active:not(:disabled) { + background-color: var(--button-main-neutral-inverted-icon-only-background-active); + } } diff --git a/src/tedi/components/buttons/info-button/info-button.spec.tsx b/src/tedi/components/buttons/info-button/info-button.spec.tsx index b450f9a3c..ad642916e 100644 --- a/src/tedi/components/buttons/info-button/info-button.spec.tsx +++ b/src/tedi/components/buttons/info-button/info-button.spec.tsx @@ -66,4 +66,30 @@ describe('InfoButton Component', () => { expect(button).toHaveAttribute('title', 'Info button'); expect(button).toHaveAttribute('id', 'info-button-id'); }); + + it('applies default color variant correctly', () => { + render(Info); + const button = screen.getByRole('button'); + expect(button).not.toHaveAttribute('data-variant'); + }); + + it('applies inverted color variant correctly', () => { + render(Info); + const button = screen.getByRole('button'); + expect(button).toHaveAttribute('data-variant', 'inverted'); + }); + + it('applies the inverted variant and still renders children', () => { + render( + + Child content + + ); + const button = screen.getByRole('button'); + expect(button).toHaveAttribute('data-variant', 'inverted'); + + const child = screen.getByTestId('child'); + expect(child).toBeInTheDocument(); + expect(child).toHaveTextContent('Child content'); + }); }); diff --git a/src/tedi/components/buttons/info-button/info-button.stories.tsx b/src/tedi/components/buttons/info-button/info-button.stories.tsx index 6cf4a3cb0..2f5f1869e 100644 --- a/src/tedi/components/buttons/info-button/info-button.stories.tsx +++ b/src/tedi/components/buttons/info-button/info-button.stories.tsx @@ -28,20 +28,29 @@ const buttonStateArray = ['Default', 'Hover', 'Active', 'Focus']; type TemplateMultipleProps = { array: typeof buttonStateArray; + color?: 'default' | 'inverted'; }; const TemplateColumn: StoryFn = (args) => { - const { array, ...buttonProps } = args; + const { array, color = 'default', ...buttonProps } = args; return ( {array.map((state, index) => ( - {state} + + {state} + - + Info button @@ -57,7 +66,7 @@ export const Default: Story = { }, }; -export const InfoButtonStates: StoryObj = { +export const States: StoryObj = { render: TemplateColumn, args: { array: buttonStateArray, @@ -70,3 +79,19 @@ export const InfoButtonStates: StoryObj = { }, }, }; + +export const Inverted: StoryObj = { + render: TemplateColumn, + args: { + array: buttonStateArray, + color: 'inverted', + }, + parameters: { + pseudo: { + hover: '#Hover', + active: '#Active', + focusVisible: '#Focus', + }, + backgrounds: { default: 'brand' }, + }, +}; diff --git a/src/tedi/components/buttons/info-button/info-button.tsx b/src/tedi/components/buttons/info-button/info-button.tsx index 69d524cef..0669f1288 100644 --- a/src/tedi/components/buttons/info-button/info-button.tsx +++ b/src/tedi/components/buttons/info-button/info-button.tsx @@ -4,27 +4,33 @@ import React from 'react'; import { Button, ButtonProps } from '../button/button'; import styles from './info-button.module.scss'; -export interface InfoButtonProps extends Omit { +export interface InfoButtonProps extends Omit { /** - * If true, applies a small size to the InfoButton. + * If true, applies a small size to the InfoButton * @default false */ isSmall?: boolean; /** - * Children elements to be rendered inside the InfoButton. + * Children elements to be rendered inside the InfoButton */ children?: React.ReactNode; + /* + * Color variant of the InfoButton + * @default 'default' + */ + color?: 'default' | 'inverted'; } export const InfoButton = React.forwardRef( - ({ isSmall, children, ...props }, ref): JSX.Element => ( + ({ isSmall, children, color = 'default', ...props }, ref): JSX.Element => ( ) : ( - + )} diff --git a/src/tedi/components/form/form-label/form-label.spec.tsx b/src/tedi/components/form/form-label/form-label.spec.tsx index 9c470d5aa..f3fbf6fb5 100644 --- a/src/tedi/components/form/form-label/form-label.spec.tsx +++ b/src/tedi/components/form/form-label/form-label.spec.tsx @@ -61,4 +61,21 @@ describe('FormLabel component', () => { expect(getByText('Form Label Text')).toBeInTheDocument(); }); + + it('renders a ReactNode label correctly', () => { + const { getByTestId } = render( + + Custom Node + + } + /> + ); + + const customLabel = getByTestId('custom-label'); + expect(customLabel).toBeInTheDocument(); + expect(customLabel).toHaveTextContent('Custom Node'); + }); }); diff --git a/src/tedi/components/form/form-label/form-label.tsx b/src/tedi/components/form/form-label/form-label.tsx index 287c92d6b..593316eb8 100644 --- a/src/tedi/components/form/form-label/form-label.tsx +++ b/src/tedi/components/form/form-label/form-label.tsx @@ -13,7 +13,7 @@ export interface FormLabelProps { /** * The text content of the label that describes the input field. */ - label: string; + label: React.ReactNode; /** * Controls the visibility of the label. * Use `true` to hide the label visually while maintaining its space in the layout, diff --git a/src/tedi/components/form/number-field/number-field.module.scss b/src/tedi/components/form/number-field/number-field.module.scss index dea9571ea..2e5ebd7ef 100644 --- a/src/tedi/components/form/number-field/number-field.module.scss +++ b/src/tedi/components/form/number-field/number-field.module.scss @@ -1,11 +1,5 @@ @use '@tedi-design-system/core/bootstrap-utility/breakpoints'; -$input-height: 2.5rem; -$small-input-height: 2rem; -$input-height-mobile: 2.75rem; -$border-radius: 0.25rem; -$border-width: 1px; - .tedi-number-field { display: flex; @@ -17,30 +11,30 @@ $border-width: 1px; } .tedi-number-field__button { - width: $input-height; - border: $border-width solid var(--form-input-border-default); + width: var(--button-md-icon-size); + height: var(--button-md-icon-size); + min-height: var(--button-md-height); + border: 1px solid var(--button-main-secondary-border-default); &__disabled, &:disabled { background-color: var(--form-input-background-disabled); - border: $border-width solid var(--form-input-border-disabled); + border: 1px solid var(--form-input-border-disabled); opacity: 0.5; } &--decrement { - margin-right: -$border-width; - border-radius: $border-radius 0 0 $border-radius; + margin-right: -1px; + border-radius: var(--button-radius-sm) 0 0 var(--button-radius-sm); } &--increment { - margin-left: -$border-width; - border-radius: 0 $border-radius $border-radius 0; + margin-left: -1px; + border-radius: 0 var(--button-radius-sm) var(--button-radius-sm) 0; } @include breakpoints.media-breakpoint-down(md) { flex: none; - width: $input-height-mobile; - height: $input-height-mobile; } } @@ -64,10 +58,6 @@ $border-width: 1px; outline: none; } } - - @include breakpoints.media-breakpoint-down(md) { - height: $input-height-mobile; - } } &--disabled { @@ -91,11 +81,8 @@ $border-width: 1px; &--small { .tedi-number-field__input-wrapper, .tedi-number-field__button { - height: $small-input-height; - - @include breakpoints.media-breakpoint-down(md) { - height: $input-height-mobile; - } + height: var(--button-sm-height); + min-height: var(--form-field-height-sm); } @include breakpoints.media-breakpoint-down(md) { @@ -110,18 +97,18 @@ $border-width: 1px; gap: var(--form-field-inner-spacing-sm); align-items: stretch; width: 5rem; - height: $input-height; + height: var(--form-field-height); padding-right: var(--form-field-padding-y-3-default); padding-left: var(--form-field-padding-y-3-default); background-color: var(--form-input-background-default); - border: $border-width solid var(--form-input-border-default); + border: 1px solid var(--form-input-border-default); &:focus-within { z-index: 1; border-color: var(--form-input-border-active); - border-radius: $border-radius; - outline: calc(2 * $border-width) solid var(--form-input-border-active); - outline-offset: -$border-width; + border-radius: var(--button-radius-sm); + outline: calc(2 * 1px) solid var(--form-input-border-active); + outline-offset: -1px; } &:active { @@ -148,9 +135,12 @@ $border-width: 1px; } } + &__feedback { + margin-top: var(--form-field-outer-spacing); + } + @include breakpoints.media-breakpoint-down(md) { width: 100%; - height: $input-height-mobile; } } @@ -159,6 +149,7 @@ $border-width: 1px; width: 100%; min-width: 2rem; font-size: var(--heading-h6-size); + color: var(--form-input-text-filled); text-align: center; background-color: var(--form-input-background-default); border: 0; diff --git a/src/tedi/components/form/number-field/number-field.tsx b/src/tedi/components/form/number-field/number-field.tsx index c9d79fd21..a9778b38c 100644 --- a/src/tedi/components/form/number-field/number-field.tsx +++ b/src/tedi/components/form/number-field/number-field.tsx @@ -244,7 +244,7 @@ export const NumberField = (props: NumberFieldProps) => { {renderInputElement()} {renderButton('increment')}
- {helper && } + {helper && } {inputUpdated && (
{inputUpdated} diff --git a/src/tedi/components/form/radio/radio.module.scss b/src/tedi/components/form/radio/radio.module.scss index 4c4aa6cc4..bca07f7dc 100644 --- a/src/tedi/components/form/radio/radio.module.scss +++ b/src/tedi/components/form/radio/radio.module.scss @@ -6,12 +6,13 @@ @include mixins.print-grayscale; - &:hover:not(.tedi-radio--disabled) { + &:hover:not(.tedi-radio--disabled) label { cursor: pointer; } &--disabled { color: var(--general-text-disabled); + cursor: not-allowed; } &__input { diff --git a/src/tedi/components/form/radio/radio.spec.tsx b/src/tedi/components/form/radio/radio.spec.tsx index 9021d7256..8581dbd9a 100644 --- a/src/tedi/components/form/radio/radio.spec.tsx +++ b/src/tedi/components/form/radio/radio.spec.tsx @@ -222,4 +222,10 @@ describe('Radio component', () => { expect(label.click).toHaveBeenCalled(); }); + + it('renders required indicator when required prop is true', () => { + render(); + + expect(screen.getByText('*')).toBeInTheDocument(); + }); }); diff --git a/src/tedi/components/form/radio/radio.stories.tsx b/src/tedi/components/form/radio/radio.stories.tsx index ec0eb4ed2..7a1772ef4 100644 --- a/src/tedi/components/form/radio/radio.stories.tsx +++ b/src/tedi/components/form/radio/radio.stories.tsx @@ -131,6 +131,14 @@ export const States = () => { /> + + + Required + + + + + diff --git a/src/tedi/components/form/radio/radio.tsx b/src/tedi/components/form/radio/radio.tsx index 639c54161..d49a6cda6 100644 --- a/src/tedi/components/form/radio/radio.tsx +++ b/src/tedi/components/form/radio/radio.tsx @@ -26,6 +26,7 @@ export const Radio = (props: RadioProps): JSX.Element => { tooltip, size = 'default', invalid, + required, ...rest } = props; @@ -46,10 +47,14 @@ export const Radio = (props: RadioProps): JSX.Element => { const helperId = helper ? helper.id ?? `${id}-helper` : undefined; const tooltipId = tooltip ? `${id}-tooltip` : undefined; - const LabelBEM = cn(styles['tedi-radio'], { [styles['tedi-radio--disabled']]: disabled }); + const LabelBEM = cn(styles['tedi-radio__label'], { [styles['tedi-radio--disabled']]: disabled }); return ( -
+
@@ -78,8 +83,8 @@ export const Radio = (props: RadioProps): JSX.Element => { />
- - {label && typeof label === 'string' ? ( + {label && ( + { hideLabel={hideLabel} label={label} tooltip={tooltip} + required={required} /> - ) : ( - - )} - + + )}
{helper && ( diff --git a/src/tedi/components/form/select/components/select-clear-indicator.tsx b/src/tedi/components/form/select/components/select-clear-indicator.tsx index 7f1d24767..368284589 100644 --- a/src/tedi/components/form/select/components/select-clear-indicator.tsx +++ b/src/tedi/components/form/select/components/select-clear-indicator.tsx @@ -17,7 +17,7 @@ export const SelectClearIndicator = ({ return isClearIndicatorVisible ? ( <> - + {getLabel('clear')} diff --git a/src/tedi/components/form/select/components/select-multi-value-remove.tsx b/src/tedi/components/form/select/components/select-multi-value-remove.tsx index 8ed9a4e08..828e3a88b 100644 --- a/src/tedi/components/form/select/components/select-multi-value-remove.tsx +++ b/src/tedi/components/form/select/components/select-multi-value-remove.tsx @@ -28,6 +28,7 @@ export const SelectMultiValueRemove = ({ innerProps, data }: MultiValueRemovePro onClick={handleClick} onKeyDown={handleKeyDown} className={styles['tedi-select__multi-value-clear']} + iconSize={18} title={`${getLabel('clear')} ${data.label}`} /> diff --git a/src/tedi/components/form/textfield/textfield.module.scss b/src/tedi/components/form/textfield/textfield.module.scss index 850f10a8f..fa91f068c 100644 --- a/src/tedi/components/form/textfield/textfield.module.scss +++ b/src/tedi/components/form/textfield/textfield.module.scss @@ -1,7 +1,32 @@ @use '@tedi-design-system/core/bootstrap-utility/breakpoints'; @use '@tedi-design-system/core/mixins'; +@use 'sass:map'; $input-height-large: 3.5rem; +$input-padding-right-map: ( + default: ( + normal: 2rem, + both: 4rem, + ), + small: ( + normal: 2rem, + both: 4rem, + ), + large: ( + normal: 3.5rem, + both: 6rem, + ), +); + +@function get-padding-right($size, $clearable, $icon) { + @if $clearable and $icon { + @return map.get(map.get($input-padding-right-map, $size), both); + } @else if $clearable or $icon { + @return map.get(map.get($input-padding-right-map, $size), normal); + } @else { + @return null; + } +} @mixin textfield-focus($border-color: null) { @if $border-color { @@ -69,29 +94,45 @@ $input-height-large: 3.5rem; @include textfield-focus(var(--form-general-feedback-success-border)); } - .tedi-textfield--clearable &, - .tedi-textfield--with-icon & { - padding-right: 2rem; - } - - .tedi-textfield--clearable.tedi-textfield--with-icon & { - padding-right: 4rem; - } - &::placeholder { color: var(--form-input-text-placeholder); opacity: 1; } } -// hide arrows on number inputs -.tedi-textfield__input--hidden-arrows[type='number'] { - appearance: textfield; // for Firefox +@each $size in default, small, large { + $selector: if($size == default, '.tedi-textfield', '.tedi-textfield--#{$size}'); + #{$selector} { + $padding: get-padding-right($size, true, false); - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - margin: 0; - appearance: none; + &.tedi-textfield--clearable .tedi-textfield__input { + padding-right: get-padding-right($size, true, false); + } + + &.tedi-textfield--with-icon .tedi-textfield__input { + padding-right: get-padding-right($size, false, true); + } + + &.tedi-textfield--clearable.tedi-textfield--with-icon .tedi-textfield__input { + padding-right: get-padding-right($size, true, true); + } + + @if $size == small { + .tedi-textfield__input { + height: var(--form-field-height-sm); + padding: var(--form-field-padding-y-sm) var(--form-field-padding-x-md-default); + font-size: var(--body-regular-size); + } + } @else if $size == large { + .tedi-textfield__input { + height: $input-height-large; + padding: var(--form-field-padding-y-lg) var(--form-field-padding-x-lg); + + @include breakpoints.media-breakpoint-down(md) { + height: var(--form-field-height); + } + } + } } } @@ -100,26 +141,24 @@ $input-height-large: 3.5rem; top: 0; right: 0; display: flex; + gap: var(--layout-grid-gutters-04); align-items: center; height: 100%; - padding: 0.75rem 0.5rem; + padding: var(--form-field-padding-y-md-default) var(--form-field-padding-x-md-default); .tedi-textfield--small & { - padding: 0.25rem 0.5rem; + padding: var(--form-field-padding-y-sm) var(--form-field-padding-x-md-default); } .tedi-textfield--large & { - padding: 1rem; + padding: var(--form-field-padding-y-lg) var(--form-field-padding-x-lg); } } -.tedi-textfield__separator { - margin-right: 0.5rem; - margin-left: 0.25rem; -} - .tedi-textfield__icon-wrapper { display: flex; + justify-content: center; + width: var(--icon-04); color: var(--form-input-text-filled); transition: color 0.2s ease; @@ -150,50 +189,6 @@ div.tedi-textfield__icon-wrapper { vertical-align: text-top; } -/* Small */ -.tedi-textfield--small { - .tedi-textfield__input { - height: var(--form-field-height-sm); - padding: var(--form-field-padding-y-sm) var(--form-field-padding-x-md-default); - font-size: var(--body-small-regular-size); - } - - &.tedi-textfield--clearable &, - &.tedi-textfield--with-icon & { - padding-right: 2rem; - } - - &.tedi-textfield--clearable.tedi-textfield--with-icon & { - padding-right: 4rem; - } -} - -/* Large */ -.tedi-textfield--large { - .tedi-textfield__input { - height: $input-height-large; - padding: 1rem; - - @include breakpoints.media-breakpoint-down(md) { - height: var(--form-field-height); - } - } - - .tedi-textfield__separator { - margin-right: 0.5rem; - margin-left: 0.5rem; - } - - &.tedi-textfield--clearable .tedi-textfield__input, - &.tedi-textfield--with-icon .tedi-textfield__input { - padding-right: 3.5rem; - } - - &.tedi-textfield--clearable.tedi-textfield--with-icon .tedi-textfield__input { - padding-right: 6rem; - } -} - .tedi-textfield__feedback-wrapper { display: flex; } diff --git a/src/tedi/components/form/textfield/textfield.tsx b/src/tedi/components/form/textfield/textfield.tsx index f94f5acb3..ff1de6a5c 100644 --- a/src/tedi/components/form/textfield/textfield.tsx +++ b/src/tedi/components/form/textfield/textfield.tsx @@ -10,6 +10,11 @@ import { FeedbackText, FeedbackTextProps } from '../feedback-text/feedback-text' import FormLabel, { FormLabelProps } from '../form-label/form-label'; import styles from './textfield.module.scss'; +const iconSizes = { + large: 24, + default: 18, +} as const; + type TextFieldBreakpointProps = { /** * Input field size @@ -333,7 +338,7 @@ export const TextField = forwardRef((props, const renderClearButton = React.useMemo(() => { const clearButtonProps = { - size: (size === 'large' ? 'large' : 'medium') as 'medium' | 'large', + iconSize: iconSizes[size === 'large' ? 'large' : 'default'], onClick: disabled ? () => {} : clearInput, disabled, 'aria-disabled': disabled || undefined, diff --git a/src/tedi/components/layout/grid/col.stories.tsx b/src/tedi/components/layout/grid/col.stories.tsx new file mode 100644 index 000000000..b2ea48bf9 --- /dev/null +++ b/src/tedi/components/layout/grid/col.stories.tsx @@ -0,0 +1,59 @@ +import { Meta, StoryFn, StoryObj } from '@storybook/react'; + +import { Heading } from '../../base/typography/heading/heading'; +import { VerticalSpacing } from '../vertical-spacing'; +import { Col } from './col'; +import { Row } from './row'; + +/** + * Zeroheight ↗
+ * Bootstrap docs ↗
+ * Row and Col components are inspired by Bootstrap V5 Grid System.
You can use different Bootstrap grid classes + * through component props. + */ + +const meta: Meta = { + title: 'Tedi-Ready/Layout/Grid/Col', + component: Col, + subcomponents: { Row } as never, + parameters: { + status: { type: 'devComponent' }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: StoryFn = () => ( + + + Label/Value pairs + + +
+ + + Label + + Value + + + + Label + + Value + +
+ +
+
+ + + Lists + + Item 1 + Item 2 + + +
+); diff --git a/src/tedi/components/layout/grid/grid.stories.tsx b/src/tedi/components/layout/grid/grid.stories.tsx deleted file mode 100644 index 78ec8ed9d..000000000 --- a/src/tedi/components/layout/grid/grid.stories.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { Meta, StoryFn, StoryObj } from '@storybook/react'; - -import { Heading } from '../../base/typography/heading/heading'; -import { VerticalSpacing } from '../vertical-spacing'; -import { Col } from './col'; -import { Row, RowProps } from './row'; - -/** - * Zeroheight ↗
- * Boostrap docs ↗
- * Row and Col components are inspired by Bootstrap V5 Grid System.
You can use different Bootstrap grid classes - * through component props. - */ -const meta: Meta = { - title: 'Tedi-Ready/Components/Helpers/Grid', - component: Row, - subcomponents: { Col: Col } as never, - parameters: { - status: { - type: 'devComponent', - }, - }, -}; - -export default meta; -type Story = StoryObj; - -const Template: StoryFn = (args) => ( -
- - Col-1 - Col-2 - Col-3 - - - - Col-1 - - - Col-2 - - - Col-3 - - - - - Col-1 - - - Col-2 - - - Col-3 - - - - Col-1 - Col-2 - Col-3 - -
-); - -export const Default: Story = { - render: Template, -}; - -export const CustomTags: StoryFn = () => ( - - - Label/Value pairs - - - {/* Grouped rows */} -
- - - Label - - Value - - - - Label - - Value - -
- - - {/* Non grouped rows */} - - - - Label - - - Value - - - Label - - - Value - - - -
-
- - - Lists - - Item 1 - Item 2 - - -
-); diff --git a/src/tedi/components/layout/grid/row.stories.tsx b/src/tedi/components/layout/grid/row.stories.tsx new file mode 100644 index 000000000..1904bb382 --- /dev/null +++ b/src/tedi/components/layout/grid/row.stories.tsx @@ -0,0 +1,59 @@ +import { Meta, StoryFn, StoryObj } from '@storybook/react'; + +import { Col } from './col'; +import { Row, RowProps } from './row'; + +/** + * Zeroheight ↗
+ * Bootstrap docs ↗
+ * Row and Col components are inspired by Bootstrap V5 Grid System.
You can use different Bootstrap grid classes + * through component props. + */ + +const meta: Meta = { + title: 'Tedi-Ready/Layout/Grid/Row', + component: Row, + subcomponents: { Col } as never, + parameters: { + status: { type: 'devComponent' }, + }, +}; + +export default meta; +type Story = StoryObj; + +const Template: StoryFn = (args) => ( +
+ + Col-1 + Col-2 + Col-3 + + + + + Col-1 + + + Col-2 + + + Col-3 + + + + + + Col-1 + + + Col-2 + + + Col-3 + + +
+); + +export const Default: Story = { render: Template }; diff --git a/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.spec.tsx b/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.spec.tsx index 3b6b1f33d..be299eef3 100644 --- a/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.spec.tsx +++ b/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.spec.tsx @@ -144,7 +144,7 @@ describe('SideNavDropdown', () => { const parentItem = screen.getByRole('menuitem', { name: /parent/i }); expect(parentItem).toHaveAttribute('aria-haspopup', 'true'); - expect(parentItem).toHaveAttribute('aria-expanded', 'false'); + expect(parentItem).toHaveAttribute('aria-expanded', 'true'); }); it('calls onOpenChange when closing', () => { diff --git a/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.tsx b/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.tsx index 6a2fe9e67..ce1f65895 100644 --- a/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.tsx +++ b/src/tedi/components/layout/sidenav/components/sidenav-dropdown/sidenav-dropdown.tsx @@ -22,10 +22,11 @@ type SideNavDropdownProps = { trigger: React.ReactNode; groups: Group[]; onOpenChange?: (isOpen: boolean) => void; + as?: C; }; type Group = { - subHeading?: string; + subHeading?: React.ReactNode; subItems: SideNavItemProps[]; }; @@ -33,6 +34,7 @@ export const SideNavDropdown = ({ trigger, groups, onOpenChange, + as, }: SideNavDropdownProps) => { const { getLabel } = useLabels(); const [open, setOpen] = useState(false); @@ -68,7 +70,7 @@ export const SideNavDropdown = ({ {...item} role="menuitem" aria-haspopup={hasChildren ? 'true' : undefined} - aria-expanded={hasChildren ? false : undefined} + aria-expanded={hasChildren ? open : undefined} aria-controls={hasChildren ? `${id}-submenu` : undefined} className={styles['tedi-sidenav-dropdown__link']} data-active={item.isActive} @@ -78,6 +80,7 @@ export const SideNavDropdown = ({ item.onClick?.(e); setOpen(false); }} + as={item.as ?? as} > {item.children} {hasChildren && } diff --git a/src/tedi/components/layout/sidenav/components/sidenav-item/sidenav-item.tsx b/src/tedi/components/layout/sidenav/components/sidenav-item/sidenav-item.tsx index ae95b7d5f..fd6472309 100644 --- a/src/tedi/components/layout/sidenav/components/sidenav-item/sidenav-item.tsx +++ b/src/tedi/components/layout/sidenav/components/sidenav-item/sidenav-item.tsx @@ -23,7 +23,7 @@ export type SideNavItemProps = LinkProps & * Grouped submenu items (preferred for headings) */ subItemGroups?: { - subHeading?: string; + subHeading?: React.ReactNode; subItems: SideNavItemProps[]; }[]; /** @@ -73,6 +73,7 @@ export const SideNavItem = ( const groupsToRender = subItemGroups ?? (subItems ? [{ subItems }] : null); const hasChildren = !!groupsToRender; + const hasTreeIndicator = level > 1 && hasChildren; const SideNavItemBEM = cn( styles['tedi-sidenav__item'], @@ -81,6 +82,7 @@ export const SideNavItem = ( [styles[`tedi-sidenav__item--level-${level}`]]: level > 1, [styles['tedi-sidenav__item--current']]: isActive, [styles['tedi-sidenav__item--has-children']]: hasChildren, + [styles['tedi-sidenav__item--with-tree']]: hasTreeIndicator, }, className ); @@ -186,6 +188,7 @@ export const SideNavItem = ( } + as={as} groups={groupsToRender} onOpenChange={setIsDropdownOpen} /> @@ -264,7 +267,7 @@ export const SideNavItem = ( ); return level === 1 && isCollapsed ? ( - + {children} {content} diff --git a/src/tedi/components/layout/sidenav/components/sidenav-toggle/sidenav-toggle.module.scss b/src/tedi/components/layout/sidenav/components/sidenav-toggle/sidenav-toggle.module.scss index 1830947fe..fac53cbac 100644 --- a/src/tedi/components/layout/sidenav/components/sidenav-toggle/sidenav-toggle.module.scss +++ b/src/tedi/components/layout/sidenav/components/sidenav-toggle/sidenav-toggle.module.scss @@ -1,8 +1,9 @@ @use '@tedi-design-system/core/bootstrap-utility/breakpoints'; .tedi-sidenav-toggle { - width: 3.5rem; - height: 3.5rem; + z-index: var(--z-index-sidenav); + width: var(--button-sm-height); + height: var(--button-sm-height); margin: 0; border-radius: 0; diff --git a/src/tedi/components/layout/sidenav/examples.ts b/src/tedi/components/layout/sidenav/examples.tsx similarity index 78% rename from src/tedi/components/layout/sidenav/examples.ts rename to src/tedi/components/layout/sidenav/examples.tsx index 152583eff..0bb8ac52e 100644 --- a/src/tedi/components/layout/sidenav/examples.ts +++ b/src/tedi/components/layout/sidenav/examples.tsx @@ -1,4 +1,6 @@ /* istanbul ignore file */ +import { Text } from '../../base/typography/text/text'; +import { InfoButton } from '../../buttons/info-button/info-button'; import { SideNavItemProps } from './components/sidenav-item/sidenav-item'; export const exampleNavItems: SideNavItemProps[] = [ @@ -248,3 +250,63 @@ export const exampleThirdLevelMenuItemsLinks: SideNavItemProps[] = [ { href: '#', children: 'Inventory Management', icon: 'inventory' }, { href: '#', children: 'Billing & Finance', icon: 'payments' }, ]; + +export const exampleThirdLevelMenuItemsLinksWithSubTitles: SideNavItemProps[] = [ + { href: '#', children: 'Dashboard', icon: 'dashboard' }, + { href: '#', children: 'Patient Records', icon: 'people' }, + { + children: 'Clinical Management', + icon: 'medical_services', + subItemGroups: [ + { + subHeading: ( + + Minu tervise ajalugu Lorem ipsum + + ), + subItems: [ + { href: '#', children: 'Active Treatments' }, + { href: '#', children: 'Treatment History' }, + { href: '#', children: 'Treatment Plans' }, + { href: '#', children: 'Clinical Protocols' }, + ], + }, + ], + subItems: [ + { href: '#', children: 'Vital Signs' }, + { href: '#', children: 'Assessments' }, + { + href: '#', + children: 'Treatments', + subItems: [ + { href: '#', children: 'Active Treatments' }, + { href: '#', children: 'Treatment History' }, + { href: '#', children: 'Treatment Plans' }, + { href: '#', children: 'Clinical Protocols' }, + ], + }, + { + href: '#', + children: 'Documentation', + subItems: [ + { href: '#', children: 'Clinical Notes' }, + { href: '#', children: 'Medical Forms' }, + { href: '#', children: 'Consent Forms' }, + { href: '#', children: 'Reports' }, + ], + }, + ], + isDefaultOpen: true, + }, + { + href: '#', + children: 'Administration', + icon: 'admin_panel_settings', + subItems: [ + { href: '#', children: 'Staff Management' }, + { href: '#', children: 'Scheduling' }, + ], + }, + { href: '#', children: 'Inventory Management', icon: 'inventory' }, + { href: '#', children: 'Billing & Finance', icon: 'payments' }, +]; diff --git a/src/tedi/components/layout/sidenav/sidenav.module.scss b/src/tedi/components/layout/sidenav/sidenav.module.scss index 194aa458c..bc48c812f 100644 --- a/src/tedi/components/layout/sidenav/sidenav.module.scss +++ b/src/tedi/components/layout/sidenav/sidenav.module.scss @@ -197,7 +197,8 @@ } } -.tedi-sidenav__item.tedi-sidenav__sub-item .tedi-sidenav__link { +.tedi-sidenav__item--with-tree .tedi-sidenav__item.tedi-sidenav__sub-item .tedi-sidenav__link, +.tedi-sidenav__item--level-2 .tedi-sidenav__link { min-height: var(--navigation-vertical-item-min-height-medium); padding-top: var(--navigation-vertical-item-padding-y); padding-bottom: var(--navigation-vertical-item-padding-y); @@ -208,11 +209,21 @@ ); } +.tedi-sidenav__item:not(.tedi-sidenav__item--with-tree) .tedi-sidenav__sub-item.tedi-sidenav__item .tedi-sidenav__link, +.tedi-sidenav__item--level-2 .tedi-sidenav__link, +.tedi-sidenav__item--with-tree.tedi-sidenav__item--level-2 .tedi-sidenav__link.tedi-sidenav__link--has-children-link { + @include breakpoints.media-breakpoint-down(md) { + padding-left: var(--navigation-vertical-item-padding-right); + } +} + .tedi-sidenav__item .tedi-sidenav__link--has-children-link { padding-right: calc(var(--navigation-vertical-item-padding-right) + var(--button-xs-icon-size)); @include breakpoints.media-breakpoint-down(md) { + z-index: 1; margin-left: calc(var(--navigation-vertical-item-padding-right) + var(--button-xs-icon-size)); + background-color: var(--navigation-vertical-item-background-default); } } @@ -227,7 +238,7 @@ + .tedi-sidenav__link-collapse-wrapper [data-name='collapse-trigger'] { position: absolute; - top: calc(var(--navigation-vertical-item-min-height-medium) / 3); + top: calc((var(--navigation-vertical-item-min-height-large) - var(--button-xs-icon-size)) / 2); right: var(--navigation-vertical-item-padding-right); display: flex; align-items: center; @@ -359,7 +370,7 @@ button.tedi-sidenav__link.tedi-sidenav__back-button { .tedi-sidenav__subheading { padding: var(--layout-grid-gutters-02) var(--navigation-vertical-item-padding-left-level-1) var(--layout-grid-gutters-04) var(--navigation-vertical-item-padding-right); - font-size: var(--size-00); + font-size: var(--body-extra-small-bold-size); color: var(--navigation-vertical-group-title-text); text-transform: uppercase; diff --git a/src/tedi/components/layout/sidenav/sidenav.stories.tsx b/src/tedi/components/layout/sidenav/sidenav.stories.tsx index 0648731f3..30537b06e 100644 --- a/src/tedi/components/layout/sidenav/sidenav.stories.tsx +++ b/src/tedi/components/layout/sidenav/sidenav.stories.tsx @@ -11,6 +11,7 @@ import { exampleNavItems, exampleThirdLevelMenuItems, exampleThirdLevelMenuItemsLinks, + exampleThirdLevelMenuItemsLinksWithSubTitles, } from './examples'; import { SideNav } from './sidenav'; @@ -278,3 +279,10 @@ export const SmallSideNavItems: Story = { sideNavItemSize: 'small', }, }; + +export const SubTitles: Story = { + render: Template, + args: { + navItems: exampleThirdLevelMenuItemsLinksWithSubTitles, + }, +}; diff --git a/src/tedi/components/layout/vertical-spacing/vertical-spacing.stories.tsx b/src/tedi/components/layout/vertical-spacing/vertical-spacing.stories.tsx index 4af447580..a3fcaffe9 100644 --- a/src/tedi/components/layout/vertical-spacing/vertical-spacing.stories.tsx +++ b/src/tedi/components/layout/vertical-spacing/vertical-spacing.stories.tsx @@ -11,7 +11,7 @@ import { VerticalSpacing, VerticalSpacingProps } from './vertical-spacing'; const meta: Meta = { component: VerticalSpacing, - title: 'Tedi-Ready/Components/Helpers/VerticalSpacing', + title: 'Tedi-Ready/Layout/VerticalSpacing', subcomponents: { 'VerticalSpacing.Item': VerticalSpacing.Item, } as never, diff --git a/src/tedi/components/misc/separator/separator.module.scss b/src/tedi/components/misc/separator/separator.module.scss index 0e17b456e..85741e1e7 100644 --- a/src/tedi/components/misc/separator/separator.module.scss +++ b/src/tedi/components/misc/separator/separator.module.scss @@ -1,24 +1,21 @@ @use '@tedi-design-system/core/mixins'; -$sizes: ( - '0': 0, - '0-25': 0.25rem, - '0-5': 0.5rem, - '0-75': 0.75rem, - '1': 1rem, - '1-25': 1.25rem, - '1-5': 1.5rem, - '1-75': 1.75rem, - '2': 2rem, - '2-5': 2.5rem, - '5': 5rem, +$thicknesses: ( + '1': 1px, + '2': 2px, +); +$dot-colors: ( + 'primary': var(--general-border-primary), + 'secondary': var(--general-border-secondary), + 'accent': var(--general-border-accent), ); .tedi-separator { --vertical-separator-height: 100%; position: relative; - margin: 0; + margin: var(--separator-margin-top) var(--separator-margin-right) var(--separator-margin-bottom) + var(--separator-margin-left); border: 0; border-top: 1px solid var(--general-border-primary); @@ -30,12 +27,8 @@ $sizes: ( border-left: 1px solid var(--general-border-primary); } - &--secondary { - border-color: var(--general-border-secondary); - } - - &--accent { - border-color: var(--general-border-accent); + &--horizontal { + display: block; } &--block { @@ -45,84 +38,38 @@ $sizes: ( &--inline { display: inline; } -} - -.tedi-separator--dotted, -.tedi-separator--dotted-small { - &::before { - position: absolute; - top: 1.25rem; - width: var(--separator-dotted-dot-lg); - height: var(--separator-dotted-dot-lg); - content: ''; - background-color: var(--general-border-primary); - border-radius: 100%; - transform: translateX(-8px); - - @include mixins.print-grayscale; - } - &.tedi-separator--secondary::before { - background-color: var(--general-border-secondary); + &--secondary { + border-color: var(--general-border-secondary); } - &.tedi-separator--accent::before { - background-color: var(--general-border-accent); + &--accent { + border-color: var(--general-border-accent); } -} - -.tedi-separator--dotted-small::before { - top: 1.5rem; - width: var(--separator-dotted-dot-md); - height: var(--separator-dotted-dot-md); - transform: translateX(-5px); -} -.tedi-separator--is-stretched { - margin-right: calc(var(--card-content-padding-right) * -1); - margin-left: calc(var(--card-content-padding-left) * -1); + &--is-stretched { + margin-right: calc(var(--card-content-padding-right) * -1); + margin-left: calc(var(--card-content-padding-left) * -1); - &.tedi-separator--vertical { - height: calc(100% + (var(--card-content-padding-top) + var(--card-content-padding-bottom))); - margin: calc(var(--card-content-padding-top) * -1) 0 calc(var(--card-content-padding-bottom) * -1); + &.tedi-separator--vertical { + height: calc(100% + (var(--card-content-padding-top) + var(--card-content-padding-bottom))); + margin: calc(var(--card-content-padding-top) * -1) 0 calc(var(--card-content-padding-bottom) * -1); + } } } -@each $size, $value in $sizes { - .tedi-separator--horizontal.tedi-separator--top-#{$size} { - margin-top: #{$value}; - } - - .tedi-separator--horizontal.tedi-separator--bottom-#{$size} { - margin-bottom: #{$value}; - } - - .tedi-separator--horizontal.tedi-separator--spacing-#{$size}:not(.tedi-separator--dot-only) { - margin-top: #{$value}; - margin-bottom: #{$value}; - } +.tedi-separator--dotted { + &::before { + position: absolute; + content: ''; + background-color: var(--general-border-primary); + border-radius: 50%; - .tedi-separator--horizontal.tedi-separator--dot-only.tedi-separator--spacing-#{$size}, - .tedi-separator--vertical.tedi-separator--spacing-#{$size} { - margin-right: #{$value}; - margin-left: #{$value}; + @include mixins.print-grayscale; } -} - -$thicknesses: ( - '1': 1px, - '2': 2px, -); -@each $thickness, $value in $thicknesses { - .tedi-separator { - &.tedi-separator--thickness-#{$thickness} { - border-top-width: #{$value}; - } - - &--vertical.tedi-separator--thickness-#{$thickness} { - border-left-width: #{$value}; - } + &.tedi-separator--vertical { + min-height: 3rem; } } @@ -138,58 +85,115 @@ $thicknesses: ( width: var(--separator-dotted-dot-sm); height: var(--separator-dotted-dot-sm); content: ''; - border-radius: 100%; + border-radius: 50%; @include mixins.print-grayscale; } - &.tedi-separator--dot-only-extra-small::before { - width: var(--separator-dotted-dot-xs); - height: var(--separator-dotted-dot-xs); + &.tedi-separator--dot-style-outlined::before { + background: transparent; } +} - &.tedi-separator--dot-only-small::before { - width: var(--separator-dotted-dot-sm); - height: var(--separator-dotted-dot-sm); - } +@each $name, $color in $dot-colors { + .tedi-separator--#{$name} { + border-color: $color; - &.tedi-separator--dot-only-medium::before { - width: var(--separator-dotted-dot-md); - height: var(--separator-dotted-dot-md); - } + &::before { + background-color: $color; + } - &.tedi-separator--dot-only-large::before { - width: var(--separator-dotted-dot-lg); - height: var(--separator-dotted-dot-lg); + &.tedi-separator--dot-style-outlined:not(.tedi-separator--dot-only)::before { + border-color: $color; + } } +} - &.tedi-separator--primary::before { - background-color: var(--general-border-primary); +@each $size, $var in (extra-small: xs, small: sm, medium: md, large: lg) { + .tedi-separator--dot-only-#{$size}::before, + .tedi-separator--dotted-#{$size}::before, + .tedi-separator--dot-style-outlined.tedi-separator--dotted-#{$size}::before { + width: var(--separator-dot-size-#{$var}); + height: var(--separator-dot-size-#{$var}); } +} - &.tedi-separator--secondary::before { - background-color: var(--general-border-secondary); +@each $axis in (horizontal, vertical) { + @each $pos in (start, center, end) { + .tedi-separator--#{$axis}.tedi-separator--dot-position-#{$pos}::before { + @if $axis == horizontal { + @if $pos == start { + right: auto; + left: 0; + } @else if $pos == center { + right: 0; + left: 0; + margin: auto; + } @else { + right: 0; + left: auto; + } + } @else { + @if $pos == start { + top: 0; + bottom: auto; + } @else if $pos == center { + top: 0; + bottom: 0; + margin: auto 0; + } @else { + top: auto; + bottom: 0; + } + } + } } +} + +.tedi-separator--horizontal.tedi-separator--dot-position-custom::before { + right: auto; + left: var(--separator-dot-position); +} + +.tedi-separator--vertical.tedi-separator--dot-position-custom::before { + top: var(--separator-dot-position); + bottom: auto; +} - &.tedi-separator--accent::before { - background-color: var(--general-border-accent); +@each $thickness, $value in $thicknesses { + .tedi-separator--thickness-#{$thickness} { + border-top-width: $value; + } + .tedi-separator--vertical.tedi-separator--thickness-#{$thickness} { + border-left-width: $value; } } -.tedi-separator--horizontal { - &.tedi-separator--dotted::before, - &.tedi-separator--dotted-small::before { - right: 0; - left: 0; - margin: 0 auto; - transform: initial; +@each $axis in (horizontal, vertical) { + @each $size, $var in (extra-small: xs, small: sm, medium: md, large: lg) { + .tedi-separator--#{$axis}.tedi-separator--dotted-#{$size}::before, + .tedi-separator--#{$axis}.tedi-separator--dot-style-outlined.tedi-separator--dotted-#{$size}::before { + @if $axis == horizontal { + top: calc((var(--separator-dot-size-#{$var}) / 2 + var(--separator-thickness)) * -1); + } @else { + left: calc((var(--separator-dot-size-#{$var}) / 2 + var(--separator-thickness) / 2) * -1); + } + } } +} - &.tedi-separator--dotted::before { - top: calc(var(--separator-dotted-dot-lg) / 2 * -1); +.tedi-separator--dot-style-outlined { + &::before { + background-color: var(--general-surface-primary); + border-style: solid; + border-width: var(--separator-thickness); } - &.tedi-separator--dotted-small::before { - top: calc(var(--separator-dotted-dot-md) / 2 * -1); + @each $name, $color in $dot-colors { + &.tedi-separator--#{$name}::before, + &.tedi-separator--dotted-#{$name}::before { + z-index: 10; + border-color: $color; + } } } diff --git a/src/tedi/components/misc/separator/separator.spec.tsx b/src/tedi/components/misc/separator/separator.spec.tsx index 65d9c7e20..0f465e37e 100644 --- a/src/tedi/components/misc/separator/separator.spec.tsx +++ b/src/tedi/components/misc/separator/separator.spec.tsx @@ -17,132 +17,148 @@ describe('Separator Component', () => { }); }); - const renderComponent = (props: SeparatorProps) => render(); + const renderComponent =

(props: P) => + render(); - it('should render a div element by default', () => { - const { getByTestId } = renderComponent({}); + it('renders a div by default', () => { + const { getByTestId } = renderComponent({ element: 'div' }); expect(getByTestId('separator').tagName).toBe('DIV'); }); - it('should render the specified element', () => { + it('renders the specified element', () => { const { getByTestId } = renderComponent({ element: 'hr' }); expect(getByTestId('separator').tagName).toBe('HR'); }); - it('should apply default classes', () => { - const { getByTestId } = renderComponent({}); - const separator = getByTestId('separator'); - expect(separator).toHaveClass(styles['tedi-separator']); - expect(separator).toHaveClass(styles['tedi-separator--thickness-1']); - expect(separator).toHaveClass(styles['tedi-separator--horizontal']); - }); - - it('should apply additional classes from className prop', () => { - const { getByTestId } = renderComponent({ className: 'custom-class' }); - expect(getByTestId('separator')).toHaveClass('custom-class'); - }); - - it('should apply correct spacing class', () => { - const { getByTestId } = renderComponent({ spacing: 1.25 }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--spacing-1-25']); - }); + it('applies base and default classes', () => { + const { getByTestId } = renderComponent({ axis: 'horizontal' }); + const el = getByTestId('separator'); - it('should apply correct top and bottom spacing classes', () => { - const { getByTestId } = renderComponent({ topSpacing: 0.5, bottomSpacing: 1 }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--top-0-5']); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--bottom-1']); + expect(el).toHaveClass(styles['tedi-separator']); + expect(el).toHaveClass(styles['tedi-separator--horizontal']); + expect(el).toHaveClass(styles['tedi-separator--thickness-1']); }); - it('should apply axis specific class', () => { - const { getByTestId } = renderComponent({ axis: 'vertical' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--vertical']); + it('applies custom className', () => { + const { getByTestId } = renderComponent({ className: 'my-extra-class' }); + expect(getByTestId('separator')).toHaveClass('my-extra-class'); }); - it('should apply color class', () => { + it('applies color modifier', () => { const { getByTestId } = renderComponent({ color: 'accent' }); expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--accent']); }); - it('should apply variant class', () => { - const { getByTestId } = renderComponent({ variant: 'dotted' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dotted']); + it('applies vertical axis class and allows height', () => { + const { getByTestId } = renderComponent({ axis: 'vertical', height: 5.5 }); + const el = getByTestId('separator'); + + expect(el).toHaveClass(styles['tedi-separator--vertical']); + expect(el).toHaveStyle('--vertical-separator-height: 5.5rem'); }); - it('should apply thickness class when no variant is used', () => { - const { getByTestId } = renderComponent({ thickness: 2 }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--thickness-2']); + it('applies spacing — number value', () => { + const { getByTestId } = renderComponent({ spacing: 1.5 }); + const el = getByTestId('separator'); + + expect(el).toHaveStyle({ + '--separator-margin-top': '1.5rem', + '--separator-margin-bottom': '1.5rem', + '--separator-margin-left': '0rem', + '--separator-margin-right': '0rem', + }); }); - it('should not apply thickness class when variant is used', () => { - const { getByTestId } = renderComponent({ variant: 'dotted', thickness: 2 }); - expect(getByTestId('separator')).not.toHaveClass(styles['tedi-separator--thickness-2']); + it('applies spacing — object value', () => { + const { getByTestId } = renderComponent({ + spacing: { top: 2, bottom: 0.5, left: 1 }, + axis: 'horizontal', + }); + const el = getByTestId('separator'); + + expect(el).toHaveStyle({ + '--separator-margin-top': '2rem', + '--separator-margin-bottom': '0.5rem', + '--separator-margin-left': '1rem', + '--separator-margin-right': '0rem', + }); }); - it('should apply isStretched class', () => { + it('applies isStretched class', () => { const { getByTestId } = renderComponent({ isStretched: true }); expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--is-stretched']); }); - it('should set height CSS variable for vertical separator', () => { - const { getByTestId } = renderComponent({ axis: 'vertical', height: 2 }); - expect(getByTestId('separator')).toHaveStyle('--vertical-separator-height: 2rem'); + it('applies thickness class when no variant', () => { + const { getByTestId } = renderComponent({ thickness: 2 }); + expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--thickness-2']); }); + it('applies dotted class and dot size', () => { + const { getByTestId } = renderComponent({ + variant: 'dotted', + dotSize: 'small', + dotPosition: 'center', + }); + const el = getByTestId('separator'); - it('should apply dot-only variant class', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only']); + expect(el).toHaveClass(styles['tedi-separator--dotted']); + expect(el).toHaveClass(styles['tedi-separator--dotted-small']); + expect(el).toHaveClass(styles['tedi-separator--dot-position-center']); }); - it('should apply correct dot size class when variant is dot-only and dotSize is extra small', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only', dotSize: 'extra-small' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only-extra-small']); + it('applies custom dot position via CSS var', () => { + const { getByTestId } = renderComponent({ + variant: 'dotted', + dotPosition: 2.75, + }); + expect(getByTestId('separator')).toHaveStyle('--separator-dot-position: 2.75rem'); + expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-position-custom']); }); - it('should apply correct dot size class when variant is dot-only and dotSize is small', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only', dotSize: 'small' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only-small']); - }); + it('applies dot-only and dot size class', () => { + const { getByTestId } = renderComponent({ + variant: 'dot-only', + dotSize: 'large', + dotStyle: 'filled', + }); + const el = getByTestId('separator'); - it('should apply correct dot size class when variant is dot-only and dotSize is medium', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only', dotSize: 'medium' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only-medium']); + expect(el).toHaveClass(styles['tedi-separator--dot-only']); + expect(el).toHaveClass(styles['tedi-separator--dot-only-large']); + expect(el).not.toHaveClass(styles['tedi-separator--dot-style-outlined']); }); - it('should apply correct dot size class when variant is dot-only and dotSize is large', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only', dotSize: 'large' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only-large']); - }); + it('applies outlined style and thickness var when outlined', () => { + const { getByTestId } = renderComponent({ + variant: 'dot-only', + dotSize: 'medium', + dotStyle: 'outlined', + thickness: 2, + }); + const el = getByTestId('separator'); - it('should not apply dot size class when variant is not dot-only', () => { - const { getByTestId } = renderComponent({ variant: 'dotted', dotSize: 'large' }); - expect(getByTestId('separator')).not.toHaveClass(styles['tedi-separator--dot-only-large']); + expect(el).toHaveClass(styles['tedi-separator--dot-style-outlined']); + expect(el).toHaveStyle('--separator-thickness: 2px'); + expect(el).toHaveClass(styles['tedi-separator--thickness-2']); }); - it('should default vertical separator display to block', () => { + it('requires dotSize (but test fallback/default)', () => { + const { getByTestId } = renderComponent({ + variant: 'dot-only', + dotSize: 'large', + }); + expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--dot-only-large']); + }); + it('defaults to block display in vertical mode', () => { const { getByTestId } = renderComponent({ axis: 'vertical' }); expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--block']); }); - it('should apply inline display class to vertical separator when specified', () => { - const { getByTestId } = renderComponent({ axis: 'vertical', display: 'inline' }); - expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--inline']); - }); - - it('should not apply inline display class to horizontal separator', () => { - const { getByTestId } = renderComponent({ axis: 'horizontal', display: 'block' }); - expect(getByTestId('separator')).not.toHaveClass(styles['tedi-separator--inline']); - }); - it('should apply dotSize class when variant is dot-only', () => { - const { getByTestId } = renderComponent({ variant: 'dot-only', dotSize: 'medium' }); - const separator = getByTestId('separator'); - expect(separator).toHaveClass(styles['tedi-separator--dot-only']); - expect(separator).toHaveClass(styles['tedi-separator--dot-only-medium']); - }); - - it('should ignore dotSize when variant is not dot-only', () => { - const { getByTestId } = renderComponent({ variant: 'dotted', dotSize: 'medium' }); - const separator = getByTestId('separator'); - expect(separator).toHaveClass(styles['tedi-separator--dotted']); - expect(separator).not.toHaveClass(styles['tedi-separator--dot-only-medium']); + it('applies inline display when specified (vertical)', () => { + const { getByTestId } = renderComponent({ + axis: 'vertical', + display: 'inline-block', + }); + expect(getByTestId('separator')).toHaveClass(styles['tedi-separator--inline-block']); }); }); diff --git a/src/tedi/components/misc/separator/separator.stories.tsx b/src/tedi/components/misc/separator/separator.stories.tsx index 5d5a4f6f5..385b2a01d 100644 --- a/src/tedi/components/misc/separator/separator.stories.tsx +++ b/src/tedi/components/misc/separator/separator.stories.tsx @@ -1,11 +1,10 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react'; -import { Fragment } from 'react/jsx-runtime'; import { Text } from '../../base/typography/text/text'; import { Card, CardContent } from '../../cards/card'; import { Col, Row } from '../../layout/grid'; import { VerticalSpacing } from '../../layout/vertical-spacing'; -import Separator, { SeparatorProps } from './separator'; +import Separator, { DotSize, SeparatorProps } from './separator'; /** * Figma ↗
@@ -32,86 +31,254 @@ const meta: Meta = { export default meta; type Story = StoryObj; -const colorArray: SeparatorProps['color'][] = ['primary', 'secondary', 'accent']; +const spacingArray: SeparatorProps['spacing'][] = [0, 0.5, 1, 1.5, 2, 2.5]; +const sizeArray: SeparatorProps['dotSize'][] = ['large', 'medium']; +type TemplateMultipleProps = SeparatorProps & { + array: Type[]; + property: keyof SeparatorProps; +}; +const Template: StoryFn = (args) => ; -const Template: StoryFn = (args) => ( - <> - Some content - - Other content - -); +const SizesTemplate: StoryFn = (args) => { + const { array } = args; -const ColorsAndThickness: StoryFn = (args) => ( - <> - {colorArray.map((color) => ( - - - - + return ( +

+ {array.map((value, key) => ( + + + {value === 'large' ? 'Large' : 'Medium'} - - - - + + + + + - - ))} - -); + ))} +
+ ); +}; -const VerticalColorTemplate: StoryFn = (args) => ( +const ColorsAndThickness: StoryFn = (args) => ( - {colorArray.map((color) => ( - - - - - - - - - - - ))} + + + + ); -const DotOnlyTemplate: StoryFn = (args) => ( +const SpacingHorizontal: StoryFn = (args) => ( - - - - + {spacingArray.map((spacing, index) => ( + + ))} ); +const SpacingVertical: StoryFn = (args) => ( + + {spacingArray.map((spacing, index) => ( + + + + ))} + +); + export const Default: Story = { render: Template, args: { spacing: 1 }, }; -export const HorizontalColors: Story = { +export const HorizontalSpacings: Story = { + render: SpacingHorizontal, + args: { + axis: 'horizontal', + }, +}; + +export const HorizontalThickness: Story = { render: ColorsAndThickness, - args: { spacing: 1 }, }; -export const VerticalColors: Story = { - render: VerticalColorTemplate, - args: { axis: 'vertical', height: 5 }, +export const Vertical: Story = { + render: Template, + args: { axis: 'vertical', height: 3 }, +}; + +export const VerticalSpacings: Story = { + render: SpacingVertical, + args: { + axis: 'vertical', + height: 3, + display: 'inline-block', + }, +}; + +export const VerticalThickness: Story = { + render: ColorsAndThickness, + args: { axis: 'vertical', height: 3, display: 'inline' }, }; -export const PaddedEven: Story = { +export const DottedLineHorizontal: Story = { render: Template, - args: { spacing: 1 }, + args: { axis: 'horizontal', variant: 'dotted', color: 'accent', dotPosition: 'center' }, }; -export const PaddedUneven: Story = { +export const DottedLineVertical: Story = { render: Template, - args: { topSpacing: 2.5, bottomSpacing: 0.5 }, + args: { axis: 'vertical', variant: 'dotted', color: 'accent', height: 5, dotPosition: 'center' }, +}; + +export const Sizes: StoryObj = { + render: SizesTemplate, + + args: { + property: 'dotSize', + array: sizeArray, + }, +}; + +export const SpacingTopDefault: Story = { + render: () => { + return ( + + + + + + + + + ); + }, +}; + +export const SpacingTopSmall: Story = { + render: () => { + return ( + + + + + + + + + ); + }, +}; + +export const Position: Story = { + render: () => { + return ( + <> + + + + Start + + +
+ +
+ + + + +
+
+ + + + Center + + + + + + + + + + + + + End + + + + + + + + + + +
+ + ); + }, }; const TemplateVertical: StoryFn = (args) => ( @@ -137,88 +304,132 @@ const TemplateVertical: StoryFn = (args) => ( ); -export const VerticalThick: Story = { - render: TemplateVertical, +export const DotFilled: Story = { + render: () => { + return ( + <> + + + ); + }, +}; + +export const DotOutlined: Story = { + render: () => { + return ( + <> + + + ); + }, +}; + +const dotSizeToPxMap: Record = { + xs: '2px', + sm: '4px', + md: '8px', + lg: '15px', +}; + +const DottedSizesTemplate: StoryFn = (args) => { + const { array } = args; + + return ( +
+ {array.map((value, key) => ( + + + {value !== undefined ? dotSizeToPxMap[value] || value : '—'} + + + + + + + + + ))} +
+ ); +}; + +export const DottedSizes: StoryObj = { + render: DottedSizesTemplate, args: { - axis: 'horizontal', - thickness: 1, - isStretched: true, - topSpacing: 1, - bottomSpacing: 1, - md: { axis: 'vertical', thickness: 1 }, + property: 'dotSize', + array: ['extra-small', 'small', 'medium', 'large'], }, }; -export const VerticalDotted: Story = { +const InlineSeparatorTemplate: StoryFn = (args) => { + const { dotPosition, ...safeArgs } = args; + + return ( + <> + + Lorem ipsum dolor sit, amet + + consectetur adipisicing elit. + + + Lorem ipsum dolor sit, amet + + consectetur adipisicing elit. + + + Lorem ipsum dolor sit, amet + + consectetur adipisicing elit. + + + Lorem ipsum dolor sit, amet + + consectetur adipisicing elit. + + + ); +}; + +export const InlineSeparatorUsage: Story = { + render: InlineSeparatorTemplate, + args: { axis: 'vertical', display: 'inline' }, +}; + +export const VerticalDottedCardExample: Story = { render: TemplateVertical, args: { axis: 'horizontal', variant: 'dotted', color: 'accent', - topSpacing: 1, - bottomSpacing: 1, + spacing: 1, isStretched: true, + dotPosition: 1.25, md: { axis: 'vertical' }, }, }; -export const VerticalDottedSmall: Story = { +export const VerticalDottedSmallCardExample: Story = { render: TemplateVertical, args: { axis: 'horizontal', - topSpacing: 1, - bottomSpacing: 1, - variant: 'dotted-small', + spacing: 1, + variant: 'dotted', + dotSize: 'medium', color: 'accent', isStretched: true, + dotPosition: 1.25, md: { axis: 'vertical' }, }, }; - -export const HorizontalDottedSeparator: Story = { - render: () => ( - - - - - - - - - ), -}; - -export const DotOnly: Story = { - render: DotOnlyTemplate, - args: { spacing: 0.5 }, -}; - -const InlineSeparatorTemplate: StoryFn = (args) => ( - - - Lorem ipsum dolor sit, amet - - consectetur adipisicing elit. - - - Lorem ipsum dolor sit, amet - - consectetur adipisicing elit. - - - Lorem ipsum dolor sit, amet - - consectetur adipisicing elit. - - - Lorem ipsum dolor sit, amet - - consectetur adipisicing elit. - - -); - -export const InlineSeparatorUsedInText: Story = { - render: InlineSeparatorTemplate, - args: { axis: 'vertical', display: 'inline' }, -}; diff --git a/src/tedi/components/misc/separator/separator.tsx b/src/tedi/components/misc/separator/separator.tsx index bcf4f7682..d343f08b3 100644 --- a/src/tedi/components/misc/separator/separator.tsx +++ b/src/tedi/components/misc/separator/separator.tsx @@ -4,154 +4,201 @@ import { CSSProperties } from 'react'; import { BreakpointSupport, useBreakpointProps } from '../../../helpers'; import styles from './separator.module.scss'; -export type SeparatorSpacing = 0 | 0.25 | 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2 | 2.5 | 5; +export type SeparatorVariant = 'dotted' | 'dot-only'; +export type DotSize = 'large' | 'medium' | 'small' | 'extra-small'; +export type DotStyle = 'filled' | 'outlined'; +export type DotPosition = 'start' | 'center' | 'end' | number; + +/** + * Margin/padding-like spacing around the separator + * - number → uniform spacing on main axis + * - object → fine-grained control (top/bottom/left/right) + */ +export type SeparatorSpacing = + | number + | { + top?: number; + bottom?: number; + left?: number; + right?: number; + }; export interface SeparatorSharedProps { /** - * Additional class. + * Additional class names */ className?: string; /** - * Rendered HTML element. - * @default div + * HTML element to render — most common are 'hr', 'div', 'span' */ element?: 'hr' | 'div' | 'span'; /** - * Whether the separator should stretch to fill the full spacing inside cardContent. + * When true, the separator stretches to fill available space (100%) */ isStretched?: boolean; - /* - * Color of separator - * @default default + /** + * Semantic color token + * @default primary */ color?: 'primary' | 'secondary' | 'accent'; - /* - * Separator style variant. - */ - variant?: 'dotted' | 'dotted-small' | 'dot-only'; - /* - * Dot size. - * Only used when variant="dot-only" + /** + * Visual style — line with dots vs standalone centered dot(s) */ - dotSize?: 'large' | 'medium' | 'small' | 'extra-small'; - /* - * Thickness in pixels (ignored if variant is used). - * @default 1 + variant?: SeparatorVariant; + /** + * Line thickness in pixels (1 or 2) — affects outlined & solid lines */ thickness?: 1 | 2; /** - * Spacing applied based on the axis: - * - For horizontal axis, spacing is applied to top and bottom of the separator. - * - For vertical axis, spacing is applied to left and right of the separator. + * Spacing (margin) around the separator + * @example + * spacing={16} // 16px top & bottom (horizontal) or left & right (vertical) + * spacing={{ top: 24, bottom: 8 }} */ spacing?: SeparatorSpacing; } - export interface SeparatorVerticalProps extends SeparatorSharedProps { /** - * Height of separator. Use with vertical axis, when full-width separator is not needed. - * Height can be number in rem units. It's customizable to allow for more flexibility around X components. + * Must be set to 'vertical' + */ + axis: 'vertical'; + /** + * Height of the vertical separator in rem units */ height?: number; /** - * Axis of separator, vertical and horizontal separators support different props + * CSS display value — usually 'block' or 'inline-block' */ - axis: 'vertical'; - topSpacing?: undefined; - bottomSpacing?: undefined; - display?: 'block' | 'inline'; + display?: 'block' | 'inline' | 'inline-block'; } - export interface SeparatorHorizontalProps extends SeparatorSharedProps { /** - * Spacing on top of separator. Ignored when spacing is also used. Only for horizontal axis. + * Must be set to 'horizontal' or left undefined (defaults to horizontal) */ - topSpacing?: SeparatorSpacing; + axis?: 'horizontal'; /** - * Spacing on bottom of separator. Ignored when spacing is also used. Only for horizontal axis. - */ - bottomSpacing?: SeparatorSpacing; + Vertical height is not used in horizontal mode + */ + height?: undefined; /** - * Axis of separator, vertical and horizontal separators support different props + * Display is forced to 'block' in horizontal mode */ - axis?: 'horizontal'; - height?: undefined; display?: 'block'; } -export type SeparatorBreakpointProps = { - /** - * Spacing values based on breakpoints. - */ - spacing?: Omit; +type DottedSeparatorProps = { + variant?: 'dotted'; + dotSize?: DotSize; + dotStyle?: DotStyle; /** - * Height values based on breakpoints (for vertical separators). + * Position of the single dot + * @example + * 'center' | 'start' | 'end' | 2.5 // 2.5rem from start */ - height?: Omit; + dotPosition?: DotPosition; +}; + +type DotOnlySeparatorProps = { + variant: 'dot-only'; + dotSize: DotSize; + dotStyle?: DotStyle; + dotPosition?: never; +}; + +export type SeparatorBreakpointProps = { + spacing?: SeparatorSpacing; + height?: number; axis?: 'horizontal' | 'vertical'; }; export type SeparatorProps = BreakpointSupport< - | ( - | SeparatorHorizontalProps - | (SeparatorVerticalProps & { - variant?: 'dotted' | 'dotted-small'; - dotSize?: undefined; - }) - ) - | ( - | SeparatorHorizontalProps - | (SeparatorVerticalProps & { - variant: 'dot-only'; - dotSize: 'large' | 'medium' | 'small' | 'extra-small'; - }) - ) + | (SeparatorHorizontalProps & (DottedSeparatorProps | DotOnlySeparatorProps)) + | (SeparatorVerticalProps & (DottedSeparatorProps | DotOnlySeparatorProps)) > & SeparatorBreakpointProps; export const Separator = (props: SeparatorProps): JSX.Element => { const { getCurrentBreakpointProps } = useBreakpointProps(props.defaultServerBreakpoint); + const { className, element: Element = 'div', isStretched, spacing, - topSpacing, - bottomSpacing, axis = 'horizontal', - color = 'default', + color = 'primary', variant, thickness = 1, height, - dotSize, + dotSize = 'large', + dotStyle = 'filled', + dotPosition, display = 'block', ...rest } = getCurrentBreakpointProps(props); + const isNumericDotPosition = typeof dotPosition === 'number'; + const resolvedDotPosition = variant !== 'dot-only' && !isNumericDotPosition ? dotPosition : undefined; + + let top = 0; + let bottom = 0; + let left = 0; + let right = 0; + + if (typeof spacing === 'number') { + if (axis === 'horizontal') { + top = bottom = spacing; + } else { + left = right = spacing; + } + } + + if (typeof spacing === 'object' && spacing !== null) { + top = spacing.top ?? top; + bottom = spacing.bottom ?? bottom; + left = spacing.left ?? left; + right = spacing.right ?? right; + } + const SeparatorBEM = cn( styles['tedi-separator'], className, - { [styles[`tedi-separator--${color}`]]: color }, - { [styles[`tedi-separator--${axis}`]]: axis }, - { [styles[`tedi-separator--${variant}`]]: variant }, - { [styles[`tedi-separator--${display}`]]: display }, - { [styles[`tedi-separator--${variant}-${dotSize}`]]: variant && dotSize }, - { [styles[`tedi-separator--thickness-${thickness}`]]: thickness && !variant }, - { [styles['tedi-separator--is-stretched']]: isStretched }, - { [styles[`tedi-separator--spacing-${spacing}`.replace('.', '-')]]: spacing }, - { [styles[`tedi-separator--top-${topSpacing}`.replace('.', '-')]]: !spacing && topSpacing }, - { [styles[`tedi-separator--bottom-${bottomSpacing}`.replace('.', '-')]]: !spacing && bottomSpacing } + styles[`tedi-separator--${axis}`], + styles[`tedi-separator--${color}`], + { + [styles[`tedi-separator--${variant}`]]: variant, + [styles[`tedi-separator--${display}`]]: display, + [styles[`tedi-separator--dotted-${dotSize}`]]: variant === 'dotted', + [styles[`tedi-separator--dot-only-${dotSize}`]]: variant === 'dot-only', + [styles[`tedi-separator--dot-style-${dotStyle}`]]: variant, + [styles[`tedi-separator--dot-position-${resolvedDotPosition}`]]: + typeof resolvedDotPosition === 'string' && variant !== 'dot-only', + [styles['tedi-separator--dot-position-custom']]: isNumericDotPosition, + [styles['tedi-separator--is-stretched']]: isStretched, + [styles[`tedi-separator--thickness-${thickness}`]]: thickness || dotStyle === 'outlined' ? thickness : undefined, + } ); - const getCssVars = () => { - const cssvars: CSSProperties = {}; + const cssVars: CSSProperties = { + '--separator-margin-top': `${top}rem`, + '--separator-margin-bottom': `${bottom}rem`, + '--separator-margin-left': `${left}rem`, + '--separator-margin-right': `${right}rem`, + } as CSSProperties; + + if (height) { + cssVars['--vertical-separator-height'] = `${height}rem`; + } - if (height) cssvars['--vertical-separator-height'] = `${height}rem`; + if (thickness) { + cssVars['--separator-thickness'] = `${thickness}px`; + } - return cssvars; - }; + if (variant === 'dotted' && isNumericDotPosition) { + cssVars['--separator-dot-position'] = `${dotPosition}rem`; + } - return ; + return ; }; export default Separator; diff --git a/src/tedi/components/notifications/alert/alert.module.scss b/src/tedi/components/notifications/alert/alert.module.scss index e84a27354..ba7710e83 100644 --- a/src/tedi/components/notifications/alert/alert.module.scss +++ b/src/tedi/components/notifications/alert/alert.module.scss @@ -5,8 +5,6 @@ } .tedi-alert { - padding: var(--alert-default-padding-y) var(--alert-default-padding-x); - font-size: var(--body-regular-size); border: 1px solid; border-radius: var(--alert-radius); @@ -14,14 +12,32 @@ &__content { display: flex; - gap: var(--layout-grid-gutters-08); - align-items: flex-start; + align-self: center; .tedi-alert__icon { line-height: var(--body-regular-line-height); } } + &--size-default { + padding: var(--alert-default-padding-y) var(--alert-default-padding-x); + font-size: var(--body-regular-size); + + .tedi-alert__content { + gap: var(--layout-grid-gutters-08); + } + } + + &--size-small { + padding: var(--alert-default-padding-y-sm) var(--alert-default-padding-x-sm); + font-size: var(--body-small-regular-size); + line-height: var(--body-small-regular-line-height); + + .tedi-alert__content { + gap: var(--layout-grid-gutters-04); + } + } + &--info { @include alert-variant(var(--alert-default-background-info), var(--alert-default-border-info)); } diff --git a/src/tedi/components/notifications/alert/alert.spec.tsx b/src/tedi/components/notifications/alert/alert.spec.tsx index 336858a85..ae944d37d 100644 --- a/src/tedi/components/notifications/alert/alert.spec.tsx +++ b/src/tedi/components/notifications/alert/alert.spec.tsx @@ -118,4 +118,23 @@ describe('Alert component', () => { const title = screen.getByText(text); expect(title.tagName).toBe(level.toUpperCase()); }); + + it('renders with small size and applies correct size class', () => { + render(Small Alert); + + const alert = screen.getByRole('alert'); + expect(alert).toHaveClass('tedi-alert--size-small'); + }); + + it('renders danger alert with small size', () => { + render( + + Danger Small Alert + + ); + + const alert = screen.getByRole('alert'); + expect(alert).toHaveClass('tedi-alert--danger'); + expect(alert).toHaveClass('tedi-alert--size-small'); + }); }); diff --git a/src/tedi/components/notifications/alert/alert.stories.tsx b/src/tedi/components/notifications/alert/alert.stories.tsx index ca3d894ff..51d7a59f4 100644 --- a/src/tedi/components/notifications/alert/alert.stories.tsx +++ b/src/tedi/components/notifications/alert/alert.stories.tsx @@ -1,5 +1,7 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react'; +import { Text } from '../../base/typography/text/text'; +import { Col, Row } from '../../layout/grid'; import { VerticalSpacing } from '../../layout/vertical-spacing'; import Link from '../../navigation/link/link'; import Alert, { AlertProps } from '../alert/alert'; @@ -36,6 +38,8 @@ const alertTypes: { type: AlertProps['type']; icon: string }[] = [ { type: 'danger', icon: 'error' }, ]; +const sizeArray: AlertProps['size'][] = ['default', 'small']; + const TypesTemplate: StoryFn = (args) => ( {alertTypes.map(({ type, icon }) => ( @@ -46,6 +50,31 @@ const TypesTemplate: StoryFn = (args) => ( ); +interface TemplateMultipleProps extends AlertProps { + array: Type[]; +} + +const TemplateColumn: StoryFn = (args) => { + const { array, ...alertProps } = args; + + return ( +
+ {array.map((value, key) => ( + + + {value ? value.charAt(0).toUpperCase() + value.slice(1) : ''} + + + + Content description + + + + ))} +
+ ); +}; + const Template: StoryFn = (args) => ; export const Default: Story = { args: { @@ -69,6 +98,15 @@ const WithAndWithoutHeading: StoryFn = (args) => { ); }; +export const Sizes: StoryObj = { + render: TemplateColumn, + args: { + array: sizeArray, + type: 'info', + children: 'Content description', + onClose: () => null, + }, +}; export const Headless: Story = { render: Template, args: { diff --git a/src/tedi/components/notifications/alert/alert.tsx b/src/tedi/components/notifications/alert/alert.tsx index a926d0aa6..911e5826c 100644 --- a/src/tedi/components/notifications/alert/alert.tsx +++ b/src/tedi/components/notifications/alert/alert.tsx @@ -29,6 +29,13 @@ type AlertBreakpointProps = { * @default false */ noSideBorders?: boolean; + /** + * Alert size variant. + * - 'default': Standard alert size with padding and border radius. + * - 'small': More compact alert size with reduced padding. + * @default default + */ + size?: 'default' | 'small'; }; export interface AlertProps extends BreakpointSupport { @@ -79,7 +86,7 @@ export interface AlertProps extends BreakpointSupport { * // For secondary notifications * titleElement="h4" * - * @default 'h3' + * @default h3 */ titleElement?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } @@ -97,12 +104,14 @@ export const Alert = (props: AlertProps): JSX.Element | null => { isGlobal = false, noSideBorders = false, titleElement = 'h3', + size = 'default', ...rest } = getCurrentBreakpointProps(props); const alertBEM = cn( styles['tedi-alert'], styles[`tedi-alert--${type}`], + styles[`tedi-alert--size-${size}`], { [styles['tedi-alert--global']]: isGlobal, [styles['tedi-alert--no-side-borders']]: noSideBorders, @@ -149,7 +158,7 @@ export const Alert = (props: AlertProps): JSX.Element | null => { {onClose && ( - + )} diff --git a/src/tedi/components/overlays/overlay/overlay-content.tsx b/src/tedi/components/overlays/overlay/overlay-content.tsx index 9b49ec2b8..0008458c6 100644 --- a/src/tedi/components/overlays/overlay/overlay-content.tsx +++ b/src/tedi/components/overlays/overlay/overlay-content.tsx @@ -61,6 +61,7 @@ export const OverlayContent = (props: OverlayContentProps) => { context, arrow, scrollLock, + contentId, } = useContext(OverlayContext); useEffect(() => { @@ -88,6 +89,7 @@ export const OverlayContent = (props: OverlayContentProps) => { {...getFloatingProps({ ref: floating, tabIndex: -1, + id: contentId, 'aria-labelledby': labelledBy, 'aria-describedby': describedBy, style: { diff --git a/src/tedi/components/overlays/overlay/overlay-trigger.spec.tsx b/src/tedi/components/overlays/overlay/overlay-trigger.spec.tsx new file mode 100644 index 000000000..d82fb26e3 --- /dev/null +++ b/src/tedi/components/overlays/overlay/overlay-trigger.spec.tsx @@ -0,0 +1,126 @@ +import { render, screen } from '@testing-library/react'; + +import { useLabels } from '../../../providers/label-provider'; +import { Icon } from '../../base/icon/icon'; +import Button from '../../buttons/button/button'; +import Overlay from './overlay'; +import { OverlayTrigger } from './overlay-trigger'; + +jest.mock('../../../providers/label-provider', () => ({ + useLabels: jest.fn(() => ({ + getLabel: jest.fn((key) => `Mocked Label for ${key}`), + })), +})); + +jest.mock('../../../helpers', () => ({ + ...jest.requireActual('../../../helpers'), + useIsTouchDevice: jest.fn(), + useIsMounted: jest.fn(() => true), +})); + +describe('Overlay.Trigger', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('applies correct class names when children is text', () => { + render( + + Click me + Content + + ); + + const trigger = screen.getByText('Click me'); + + expect(trigger).toHaveClass('tedi-overlay__trigger'); + expect(trigger).toHaveClass('tedi-overlay__trigger--text'); + expect(trigger).toHaveClass('my-extra-class'); + }); + + it('applies correct aria attributes when child is an Icon', () => { + const { getLabel } = useLabels(); + + render( + + + + + Content + + ); + + const icon = screen.getByTestId('icon-child'); + expect(icon).toHaveAttribute('aria-label', getLabel('tooltip.icon-trigger')); + }); + + it('does NOT apply aria-label when child is not an Icon', () => { + const { getLabel } = useLabels(); + + render( + + + + + Content + + ); + + const btn = screen.getByTestId('btn-child'); + expect(btn).not.toHaveAttribute('aria-label', getLabel('tooltip.icon-trigger')); + }); + + it('adds tabindex=0 to non-Icon valid elements (cloneElement path)', () => { + render( + + + Hover me + + Content + + ); + + const span = screen.getByTestId('span-child'); + expect(span).toHaveAttribute('tabindex', '0'); + }); + + it('does NOT add aria-describedby when role is not "tooltip"', () => { + render( + + +
Trigger
+
+ Dialog content +
+ ); + + const trigger = screen.getByTestId('trigger-dialog'); + expect(trigger).not.toHaveAttribute('aria-describedby'); + }); + + it.each([ + { role: 'tooltip' as const, open: true, expectDescribedBy: true }, + { role: 'tooltip' as const, open: false, expectDescribedBy: false }, + { role: 'dialog' as const, open: true, expectDescribedBy: false }, + ])('aria-describedby behavior - role=$role open=$open → $expectDescribedBy', ({ role, open, expectDescribedBy }) => { + const onToggle = jest.fn(); + + render( + + +
Trigger
+
+ Content +
+ ); + + const trigger = screen.getByTestId('trigger'); + + if (expectDescribedBy) { + const content = screen.getByTestId('overlay-content'); + expect(trigger).toHaveAttribute('aria-describedby', content.id); + } else { + expect(trigger).not.toHaveAttribute('aria-describedby'); + } + }); +}); diff --git a/src/tedi/components/overlays/overlay/overlay-trigger.tsx b/src/tedi/components/overlays/overlay/overlay-trigger.tsx index 9fb4dc97e..936305cba 100644 --- a/src/tedi/components/overlays/overlay/overlay-trigger.tsx +++ b/src/tedi/components/overlays/overlay/overlay-trigger.tsx @@ -21,9 +21,15 @@ export interface OverlayTriggerProps { export const OverlayTrigger = (props: OverlayTriggerProps) => { const { children, className } = props; const { getLabel } = useLabels(); - const { getReferenceProps, reference, openWith } = useContext(OverlayContext); + const { getReferenceProps, reference, openWith, open, role, contentId } = useContext(OverlayContext); // eslint-disable-next-line @typescript-eslint/no-explicit-any const refs = useMergeRefs([reference, (children as React.ComponentPropsWithRef).ref]); + const extraProps = + role === 'tooltip' + ? { + 'aria-describedby': open ? contentId : undefined, + } + : {}; if (isValidElement(children)) { return cloneElement( @@ -31,6 +37,7 @@ export const OverlayTrigger = (props: OverlayTriggerProps) => { getReferenceProps({ ref: refs, tabIndex: 0, + ...extraProps, label: children.type === Icon ? getLabel('tooltip.icon-trigger') : undefined, ...children.props, }) @@ -50,6 +57,7 @@ export const OverlayTrigger = (props: OverlayTriggerProps) => { }, className ), + ...extraProps, })} > {children} diff --git a/src/tedi/components/overlays/overlay/overlay.spec.tsx b/src/tedi/components/overlays/overlay/overlay.spec.tsx index c9c38bf48..34ef8eef7 100644 --- a/src/tedi/components/overlays/overlay/overlay.spec.tsx +++ b/src/tedi/components/overlays/overlay/overlay.spec.tsx @@ -207,4 +207,49 @@ describe('Overlay component', () => { expect(document.body.style.overflow).toBe(''); }); }); + + it('does NOT add aria-label when child is valid element but NOT an Icon (cloneElement path)', () => { + const { getLabel } = useLabels(); + + render( + + + Hover me + + Content + + ); + + const span = screen.getByTestId('span-child'); + + expect(span).toHaveAttribute('tabindex', '0'); + expect(span).not.toHaveAttribute('aria-label'); + expect(span).not.toHaveAttribute('aria-label', getLabel('tooltip.icon-trigger')); + }); + + it('removes aria-describedby when tooltip is closed', async () => { + render( + + +
Trigger div
+
+ Hidden tooltip +
+ ); + + const trigger = screen.getByTestId('div-trigger'); + expect(trigger).not.toHaveAttribute('aria-describedby'); + + await act(async () => { + fireEvent.mouseEnter(trigger); + }); + + expect(trigger).toHaveAttribute('aria-describedby'); + + await act(async () => { + fireEvent.mouseLeave(trigger); + }); + + expect(trigger).not.toHaveAttribute('aria-describedby'); + }); }); diff --git a/src/tedi/components/overlays/overlay/overlay.tsx b/src/tedi/components/overlays/overlay/overlay.tsx index 279258685..338062c87 100644 --- a/src/tedi/components/overlays/overlay/overlay.tsx +++ b/src/tedi/components/overlays/overlay/overlay.tsx @@ -20,7 +20,7 @@ import { useRole, UseRoleProps, } from '@floating-ui/react'; -import { ComponentProps, createContext, ReactNode, useCallback, useMemo, useRef, useState } from 'react'; +import { ComponentProps, createContext, ReactNode, useCallback, useId, useMemo, useRef, useState } from 'react'; import { useIsMounted, useIsTouchDevice } from '../../../helpers'; import { OverlayContent } from './overlay-content'; @@ -117,6 +117,8 @@ export interface OverlayContextType { placement: Placement; context: FloatingContext; scrollLock?: boolean; + role?: UseRoleProps['role']; + contentId: string; } export const OverlayContext = createContext({ @@ -143,6 +145,7 @@ export const OverlayContext = createContext({ placement: 'top', context: {} as FloatingContext, scrollLock: undefined, + contentId: '', }); export const Overlay = (props: OverlayProps) => { @@ -220,42 +223,70 @@ export const Overlay = (props: OverlayProps) => { }), ]); - return ( - - {children} - + const contentId = useId(); + const contextValue = useMemo( + () => ({ + open: isOpen, + onOpenChange, + isMounted, + openWith, + focusManager: focusManager + ? { + order, + modal, + initialFocus: resolvedInitialFocus, + ...restFocusManager, + } + : undefined, + reference: refs.setReference, + floating: refs.setFloating, + arrowRef, + x, + y, + strategy, + getReferenceProps, + getFloatingProps, + arrow: { + width: arrowDimensions?.width, + height: arrowDimensions?.height, + ...middlewareData.arrow, + }, + context, + placement, + scrollLock, + role, + contentId, + }), + [ + isOpen, + onOpenChange, + isMounted, + openWith, + focusManager, + refs.setReference, + refs.setFloating, + arrowRef, + x, + y, + strategy, + getReferenceProps, + getFloatingProps, + arrowDimensions?.width, + arrowDimensions?.height, + middlewareData.arrow, + context, + placement, + scrollLock, + role, + contentId, + modal, + order, + resolvedInitialFocus, + restFocusManager, + ] ); + + return {children}; }; Overlay.Trigger = OverlayTrigger; diff --git a/src/tedi/components/overlays/popover/popover-content.tsx b/src/tedi/components/overlays/popover/popover-content.tsx index 1086962e4..0dedfac18 100644 --- a/src/tedi/components/overlays/popover/popover-content.tsx +++ b/src/tedi/components/overlays/popover/popover-content.tsx @@ -45,7 +45,7 @@ export const PopoverContent = (props: PopoverContentProps) => { title, titleProps = { element: 'h4' }, close, - closeProps = { size: 'large' }, + closeProps = { size: 'default' }, } = props; const { onOpenChange } = useContext(OverlayContext); const titleId = useId(); diff --git a/src/tedi/components/overlays/tooltip/tooltip.tsx b/src/tedi/components/overlays/tooltip/tooltip.tsx index 916df9ef9..554435b69 100644 --- a/src/tedi/components/overlays/tooltip/tooltip.tsx +++ b/src/tedi/components/overlays/tooltip/tooltip.tsx @@ -22,7 +22,7 @@ export interface TooltipProps } export const Tooltip = (props: TooltipProps) => { - const { openWith = 'hover', ...rest } = props; + const { openWith = 'hover', focusManager, ...rest } = props; return ( { height: ARROW_HEIGHT, }} openWith={openWith} + role="tooltip" + focusManager={{ + modal: false, + order: ['reference', 'content'], + returnFocus: true, + ...focusManager, + }} {...rest} /> ); diff --git a/src/tedi/components/tags/tag/tag.tsx b/src/tedi/components/tags/tag/tag.tsx index 61405973e..ed1194a15 100644 --- a/src/tedi/components/tags/tag/tag.tsx +++ b/src/tedi/components/tags/tag/tag.tsx @@ -71,7 +71,7 @@ export const Tag = (props: TagProps): JSX.Element => {
)} - {!isLoading && onClose && } + {!isLoading && onClose && }
); }; diff --git a/src/community/docs/scale-layout/breaking-points.tsx b/src/tedi/docs/scale-layout/breaking-points.tsx similarity index 96% rename from src/community/docs/scale-layout/breaking-points.tsx rename to src/tedi/docs/scale-layout/breaking-points.tsx index 174567782..ccb5c4244 100644 --- a/src/community/docs/scale-layout/breaking-points.tsx +++ b/src/tedi/docs/scale-layout/breaking-points.tsx @@ -1,7 +1,7 @@ import { ColumnDef, createColumnHelper } from '@tanstack/react-table'; -import { Text } from '../../../tedi/components/base/typography/text/text'; -import { Breakpoint, CustomizeTableCell, getBackgroundColorClass, Table } from '../../index'; +import { Breakpoint, CustomizeTableCell, getBackgroundColorClass, Table } from '../../../community/index'; +import { Text } from '../../components/base/typography/text/text'; interface BreakpointRow { type: 'mobile' | 'tablet' | 'desktop'; diff --git a/src/community/docs/scale-layout/grid.mdx b/src/tedi/docs/scale-layout/grid.mdx similarity index 59% rename from src/community/docs/scale-layout/grid.mdx rename to src/tedi/docs/scale-layout/grid.mdx index 907fc622f..6d4bb22fd 100644 --- a/src/community/docs/scale-layout/grid.mdx +++ b/src/tedi/docs/scale-layout/grid.mdx @@ -1,7 +1,7 @@ import { Meta, Title, Subtitle, Unstyled } from '@storybook/blocks'; import Grid from './grid.tsx'; - + diff --git a/src/community/docs/scale-layout/grid.tsx b/src/tedi/docs/scale-layout/grid.tsx similarity index 92% rename from src/community/docs/scale-layout/grid.tsx rename to src/tedi/docs/scale-layout/grid.tsx index e89db1d09..04998c322 100644 --- a/src/community/docs/scale-layout/grid.tsx +++ b/src/tedi/docs/scale-layout/grid.tsx @@ -1,9 +1,9 @@ import { Title } from '@storybook/blocks'; -import { Heading } from '../../../tedi/components/base/typography/heading/heading'; -import { Col, Row } from '../../../tedi/components/layout/grid'; -import { VerticalSpacing } from '../../../tedi/components/layout/vertical-spacing'; -import { Separator } from '../../../tedi/components/misc/separator/separator'; +import { Heading } from '../../components/base/typography/heading/heading'; +import { Col, Row } from '../../components/layout/grid'; +import { VerticalSpacing } from '../../components/layout/vertical-spacing'; +import { Separator } from '../../components/misc/separator/separator'; import BreakingpointsTable from './breaking-points'; const Grid = () => { diff --git a/src/community/docs/scale-layout/spacing.mdx b/src/tedi/docs/scale-layout/spacing.mdx similarity index 60% rename from src/community/docs/scale-layout/spacing.mdx rename to src/tedi/docs/scale-layout/spacing.mdx index 547603667..4dd24520b 100644 --- a/src/community/docs/scale-layout/spacing.mdx +++ b/src/tedi/docs/scale-layout/spacing.mdx @@ -2,7 +2,7 @@ import { Meta, Unstyled } from '@storybook/blocks'; import Spacing from './spacing.tsx'; - + diff --git a/src/community/docs/scale-layout/spacing.tsx b/src/tedi/docs/scale-layout/spacing.tsx similarity index 88% rename from src/community/docs/scale-layout/spacing.tsx rename to src/tedi/docs/scale-layout/spacing.tsx index f22458635..03fe96afa 100644 --- a/src/community/docs/scale-layout/spacing.tsx +++ b/src/tedi/docs/scale-layout/spacing.tsx @@ -1,11 +1,11 @@ import { Title } from '@storybook/blocks'; import { ColumnDef, createColumnHelper } from '@tanstack/react-table'; -import { Heading } from '../../../tedi/components/base/typography/heading/heading'; -import { Col, Row } from '../../../tedi/components/layout/grid'; -import { VerticalSpacing } from '../../../tedi/components/layout/vertical-spacing'; -import { Separator } from '../../../tedi/components/misc/separator/separator'; -import { Table } from '../../index'; +import { Table } from '../../../community/index'; +import { Heading } from '../../components/base/typography/heading/heading'; +import { Col, Row } from '../../components/layout/grid'; +import { VerticalSpacing } from '../../components/layout/vertical-spacing'; +import { Separator } from '../../components/misc/separator/separator'; const Spacing = () => { return (