From d4b8b12687cd9cc5e9c9d68aab8b8418de0dd62d Mon Sep 17 00:00:00 2001 From: jeffvli Date: Mon, 29 Sep 2025 03:09:39 -0700 Subject: [PATCH] add color utilities --- package.json | 1 + pnpm-lock.yaml | 80 ++++++++++++++++++++++------- src/shared/utils/is-light-color.ts | 5 ++ src/shared/utils/string-to-color.ts | 11 ++++ 4 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 src/shared/utils/is-light-color.ts create mode 100644 src/shared/utils/string-to-color.ts diff --git a/package.json b/package.json index 2496db656..9bcd61d85 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,7 @@ "react-window-infinite-loader-v2": "npm:react-window-infinite-loader@2.0.0", "react-window-v2": "npm:react-window@^2.1.2", "semver": "^7.5.4", + "string-to-color": "^2.2.2", "swiper": "^9.3.1", "use-sync-external-store": "^1.5.0", "ws": "^8.18.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 299cd8f0c..2739a9327 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -221,6 +221,9 @@ importers: semver: specifier: ^7.5.4 version: 7.7.2 + string-to-color: + specifier: ^2.2.2 + version: 2.2.2 swiper: specifier: ^9.3.1 version: 9.4.1 @@ -2032,11 +2035,12 @@ packages: resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.32.1': - resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' + colornames@1.1.1: + resolution: {integrity: sha512-/pyV40IrsdulWv+wFPmERh9k/mjsPZ64yUMDmWrtj/k1nmgrzzIENWKdaVKyBbvFdQWqkcaRxr+polCo3VMe7A==} + + colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} '@typescript-eslint/utils@8.32.1': resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==} @@ -2833,8 +2837,13 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encoding-sniffer@0.2.0: - resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} + hex-rgb@4.3.0: + resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==} + engines: {node: '>=6'} + + hexy@0.2.11: + resolution: {integrity: sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==} + hasBin: true encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} @@ -3296,13 +3305,20 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@16.1.0: - resolution: {integrity: sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==} - engines: {node: '>=18'} + lodash.padend@4.6.1: + resolution: {integrity: sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==} - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} + lodash.trimstart@4.5.1: + resolution: {integrity: sha512-b/+D6La8tU76L/61/aN0jULWHkT0EeJCmVstPBn/K9MtD2qBW83AsBNrr63dKuWYwVMO7ucv13QNO/Ek/2RKaQ==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash.words@4.2.0: + resolution: {integrity: sha512-mXxqd8Yx9BGPij3lZKFSdOsjOTbL4krbCCp9slEozaN4EMppA2dFmK/f8HeohodprY6W0vOdiQ5WFgPaTI75xQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -4018,8 +4034,13 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + rgb-hex@3.0.0: + resolution: {integrity: sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==} + engines: {node: '>=8'} + + rimraf@2.6.3: + resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true mkdirp@1.0.4: @@ -4347,8 +4368,12 @@ packages: peerDependencies: postcss: ^8.4.20 - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + string-to-color@2.2.2: + resolution: {integrity: sha512-XeA2goP7PNsSlz8RRn6KhYswnMf5Tl+38ajfy8n4oZJyMGC4qqKgHNHsZ/3qwvr42NRIjf9eSr721SyetDeMkA==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} postcss@8.5.3: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} @@ -8143,6 +8168,8 @@ snapshots: colorjs.io@0.5.2: {} + colornames@1.1.1: {} + colors@1.4.0: {} combined-stream@1.0.8: @@ -9303,6 +9330,8 @@ snapshots: dependencies: rsvp: 3.2.1 + hex-rgb@4.3.0: {} + hexy@0.2.11: {} hookified@1.9.1: {} @@ -9745,10 +9774,14 @@ snapshots: lodash.merge@4.6.2: {} - lodash.sortby@4.7.0: {} + lodash.padend@4.6.1: {} + + lodash.trimstart@4.5.1: {} lodash.truncate@4.4.2: {} + lodash.words@4.2.0: {} + lodash@4.17.21: {} log-symbols@4.1.0: @@ -10583,6 +10616,8 @@ snapshots: reusify@1.1.0: {} + rgb-hex@3.0.0: {} + rimraf@2.6.3: dependencies: glob: 7.2.3 @@ -10954,6 +10989,15 @@ snapshots: optionalDependencies: bare-events: 2.5.4 + string-to-color@2.2.2: + dependencies: + colornames: 1.1.1 + hex-rgb: 4.3.0 + lodash.padend: 4.6.1 + lodash.trimstart: 4.5.1 + lodash.words: 4.2.0 + rgb-hex: 3.0.0 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 diff --git a/src/shared/utils/is-light-color.ts b/src/shared/utils/is-light-color.ts new file mode 100644 index 000000000..8173d2e44 --- /dev/null +++ b/src/shared/utils/is-light-color.ts @@ -0,0 +1,5 @@ +import { isLightColor as isLightColorMantine } from '@mantine/core'; + +export const isLightColor = (color: string) => { + return isLightColorMantine(color); +}; diff --git a/src/shared/utils/string-to-color.ts b/src/shared/utils/string-to-color.ts new file mode 100644 index 000000000..37bda2eb8 --- /dev/null +++ b/src/shared/utils/string-to-color.ts @@ -0,0 +1,11 @@ +import stc from 'string-to-color'; + +import { isLightColor } from '/@/shared/utils/is-light-color'; + +const randomSeed = '121212'; + +export const stringToColor = (string: string) => { + const hex = stc({ seed: randomSeed, string }); + + return { color: hex, isLight: isLightColor(hex) }; +};