Test using HSL + curves to build a scale

Nate Butler created

Change summary

styles/package-lock.json       | 684 +++++++++++++++++------------------
styles/package.json            |   1 
styles/src/system/algorithm.ts |  87 ++++
styles/src/system/curves.ts    |  12 
styles/src/system/ref/color.ts | 139 +++++++
styles/theme-tool/app/page.tsx |   8 
6 files changed, 579 insertions(+), 352 deletions(-)

Detailed changes

styles/package-lock.json 🔗

@@ -1,356 +1,338 @@
 {
-    "name": "styles",
-    "version": "1.0.0",
-    "lockfileVersion": 2,
-    "requires": true,
-    "packages": {
-        "": {
-            "name": "styles",
-            "version": "1.0.0",
-            "license": "ISC",
-            "dependencies": {
-                "@k-vyn/coloralgorithm": "^1.0.0",
-                "@types/chroma-js": "^2.1.3",
-                "@types/node": "^17.0.23",
-                "case-anything": "^2.1.10",
-                "chroma-js": "^2.4.2",
-                "toml": "^3.0.0",
-                "ts-node": "^10.7.0"
-            }
-        },
-        "node_modules/@cspotcode/source-map-consumer": {
-            "version": "0.8.0",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
-            "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
-            "engines": {
-                "node": ">= 12"
-            }
-        },
-        "node_modules/@cspotcode/source-map-support": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
-            "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
-            "dependencies": {
-                "@cspotcode/source-map-consumer": "0.8.0"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/@k-vyn/coloralgorithm": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/@k-vyn/coloralgorithm/-/coloralgorithm-1.0.0.tgz",
-            "integrity": "sha512-a9aAOXxQ+c2Mw5sMC39elT0wYkPa3qktFjtxVkfY3mQEFBr7NMQEczCARVdkmIKo1dIrgNSx3z12sTXohzSZDg==",
-            "dependencies": {
-                "bezier-easing": "^2.1.0",
-                "chroma-js": "^2.1.0"
-            }
-        },
-        "node_modules/@tsconfig/node10": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
-            "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
-        },
-        "node_modules/@tsconfig/node12": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
-            "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
-        },
-        "node_modules/@tsconfig/node14": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
-            "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
-        },
-        "node_modules/@tsconfig/node16": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
-            "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
-        },
-        "node_modules/@types/chroma-js": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
-            "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
-        },
-        "node_modules/@types/node": {
-            "version": "17.0.23",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
-            "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
-        },
-        "node_modules/acorn": {
-            "version": "8.7.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/acorn-walk": {
-            "version": "8.2.0",
-            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/arg": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
-        },
-        "node_modules/bezier-easing": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
-            "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="
-        },
-        "node_modules/case-anything": {
-            "version": "2.1.10",
-            "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
-            "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==",
-            "engines": {
-                "node": ">=12.13"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/mesqueeb"
-            }
-        },
-        "node_modules/chroma-js": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
-            "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
-        },
-        "node_modules/create-require": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
-        },
-        "node_modules/diff": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/make-error": {
-            "version": "1.3.6",
-            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
-        },
-        "node_modules/toml": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
-            "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
-        },
-        "node_modules/ts-node": {
-            "version": "10.7.0",
-            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
-            "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
-            "dependencies": {
-                "@cspotcode/source-map-support": "0.7.0",
-                "@tsconfig/node10": "^1.0.7",
-                "@tsconfig/node12": "^1.0.7",
-                "@tsconfig/node14": "^1.0.0",
-                "@tsconfig/node16": "^1.0.2",
-                "acorn": "^8.4.1",
-                "acorn-walk": "^8.1.1",
-                "arg": "^4.1.0",
-                "create-require": "^1.1.0",
-                "diff": "^4.0.1",
-                "make-error": "^1.1.1",
-                "v8-compile-cache-lib": "^3.0.0",
-                "yn": "3.1.1"
-            },
-            "bin": {
-                "ts-node": "dist/bin.js",
-                "ts-node-cwd": "dist/bin-cwd.js",
-                "ts-node-esm": "dist/bin-esm.js",
-                "ts-node-script": "dist/bin-script.js",
-                "ts-node-transpile-only": "dist/bin-transpile.js",
-                "ts-script": "dist/bin-script-deprecated.js"
-            },
-            "peerDependencies": {
-                "@swc/core": ">=1.2.50",
-                "@swc/wasm": ">=1.2.50",
-                "@types/node": "*",
-                "typescript": ">=2.7"
-            },
-            "peerDependenciesMeta": {
-                "@swc/core": {
-                    "optional": true
-                },
-                "@swc/wasm": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/typescript": {
-            "version": "4.6.3",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
-            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
-            "peer": true,
-            "bin": {
-                "tsc": "bin/tsc",
-                "tsserver": "bin/tsserver"
-            },
-            "engines": {
-                "node": ">=4.2.0"
-            }
-        },
-        "node_modules/v8-compile-cache-lib": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
-            "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
-        },
-        "node_modules/yn": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-            "engines": {
-                "node": ">=6"
-            }
-        }
+  "name": "styles",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "styles",
+      "version": "1.0.0",
+      "license": "ISC",
+      "dependencies": {
+        "@types/chroma-js": "^2.1.3",
+        "@types/node": "^17.0.23",
+        "bezier-easing": "^2.1.0",
+        "case-anything": "^2.1.10",
+        "chroma-js": "^2.4.2",
+        "toml": "^3.0.0",
+        "ts-node": "^10.7.0"
+      }
     },
-    "dependencies": {
-        "@cspotcode/source-map-consumer": {
-            "version": "0.8.0",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
-            "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg=="
-        },
-        "@cspotcode/source-map-support": {
-            "version": "0.7.0",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
-            "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
-            "requires": {
-                "@cspotcode/source-map-consumer": "0.8.0"
-            }
-        },
-        "@k-vyn/coloralgorithm": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/@k-vyn/coloralgorithm/-/coloralgorithm-1.0.0.tgz",
-            "integrity": "sha512-a9aAOXxQ+c2Mw5sMC39elT0wYkPa3qktFjtxVkfY3mQEFBr7NMQEczCARVdkmIKo1dIrgNSx3z12sTXohzSZDg==",
-            "requires": {
-                "bezier-easing": "^2.1.0",
-                "chroma-js": "^2.1.0"
-            }
-        },
-        "@tsconfig/node10": {
-            "version": "1.0.8",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
-            "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
-        },
-        "@tsconfig/node12": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
-            "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
-        },
-        "@tsconfig/node14": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
-            "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
-        },
-        "@tsconfig/node16": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
-            "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
-        },
-        "@types/chroma-js": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
-            "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
-        },
-        "@types/node": {
-            "version": "17.0.23",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
-            "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
-        },
-        "acorn": {
-            "version": "8.7.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
-            "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
-        },
-        "acorn-walk": {
-            "version": "8.2.0",
-            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
-        },
-        "arg": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
-        },
-        "bezier-easing": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
-            "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="
-        },
-        "case-anything": {
-            "version": "2.1.10",
-            "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
-            "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ=="
-        },
-        "chroma-js": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
-            "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
-        },
-        "create-require": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
-        },
-        "diff": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
-        },
-        "make-error": {
-            "version": "1.3.6",
-            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
-        },
-        "toml": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
-            "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
-        },
-        "ts-node": {
-            "version": "10.7.0",
-            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
-            "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
-            "requires": {
-                "@cspotcode/source-map-support": "0.7.0",
-                "@tsconfig/node10": "^1.0.7",
-                "@tsconfig/node12": "^1.0.7",
-                "@tsconfig/node14": "^1.0.0",
-                "@tsconfig/node16": "^1.0.2",
-                "acorn": "^8.4.1",
-                "acorn-walk": "^8.1.1",
-                "arg": "^4.1.0",
-                "create-require": "^1.1.0",
-                "diff": "^4.0.1",
-                "make-error": "^1.1.1",
-                "v8-compile-cache-lib": "^3.0.0",
-                "yn": "3.1.1"
-            }
-        },
-        "typescript": {
-            "version": "4.6.3",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
-            "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
-            "peer": true
-        },
-        "v8-compile-cache-lib": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
-            "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
-        },
-        "yn": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
+    "node_modules/@cspotcode/source-map-consumer": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
+      "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==",
+      "engines": {
+        "node": ">= 12"
+      }
+    },
+    "node_modules/@cspotcode/source-map-support": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
+      "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+      "dependencies": {
+        "@cspotcode/source-map-consumer": "0.8.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@tsconfig/node10": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
+      "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
+    },
+    "node_modules/@tsconfig/node12": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
+      "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
+    },
+    "node_modules/@tsconfig/node14": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
+      "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
+    },
+    "node_modules/@tsconfig/node16": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
+      "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
+    },
+    "node_modules/@types/chroma-js": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
+      "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
+    },
+    "node_modules/@types/node": {
+      "version": "17.0.23",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
+      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+    },
+    "node_modules/acorn": {
+      "version": "8.7.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+      "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-walk": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+    },
+    "node_modules/bezier-easing": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
+      "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="
+    },
+    "node_modules/case-anything": {
+      "version": "2.1.10",
+      "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
+      "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ==",
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/chroma-js": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
+      "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
+    },
+    "node_modules/create-require": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+    },
+    "node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/make-error": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+    },
+    "node_modules/toml": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
+      "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
+    },
+    "node_modules/ts-node": {
+      "version": "10.7.0",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
+      "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+      "dependencies": {
+        "@cspotcode/source-map-support": "0.7.0",
+        "@tsconfig/node10": "^1.0.7",
+        "@tsconfig/node12": "^1.0.7",
+        "@tsconfig/node14": "^1.0.0",
+        "@tsconfig/node16": "^1.0.2",
+        "acorn": "^8.4.1",
+        "acorn-walk": "^8.1.1",
+        "arg": "^4.1.0",
+        "create-require": "^1.1.0",
+        "diff": "^4.0.1",
+        "make-error": "^1.1.1",
+        "v8-compile-cache-lib": "^3.0.0",
+        "yn": "3.1.1"
+      },
+      "bin": {
+        "ts-node": "dist/bin.js",
+        "ts-node-cwd": "dist/bin-cwd.js",
+        "ts-node-esm": "dist/bin-esm.js",
+        "ts-node-script": "dist/bin-script.js",
+        "ts-node-transpile-only": "dist/bin-transpile.js",
+        "ts-script": "dist/bin-script-deprecated.js"
+      },
+      "peerDependencies": {
+        "@swc/core": ">=1.2.50",
+        "@swc/wasm": ">=1.2.50",
+        "@types/node": "*",
+        "typescript": ">=2.7"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "@swc/wasm": {
+          "optional": true
         }
+      }
+    },
+    "node_modules/typescript": {
+      "version": "4.6.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+      "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+      "peer": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
+    "node_modules/v8-compile-cache-lib": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
+      "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
+    },
+    "node_modules/yn": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+      "engines": {
+        "node": ">=6"
+      }
+    }
+  },
+  "dependencies": {
+    "@cspotcode/source-map-consumer": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz",
+      "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg=="
+    },
+    "@cspotcode/source-map-support": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz",
+      "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==",
+      "requires": {
+        "@cspotcode/source-map-consumer": "0.8.0"
+      }
+    },
+    "@tsconfig/node10": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz",
+      "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg=="
+    },
+    "@tsconfig/node12": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz",
+      "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw=="
+    },
+    "@tsconfig/node14": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz",
+      "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg=="
+    },
+    "@tsconfig/node16": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz",
+      "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA=="
+    },
+    "@types/chroma-js": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz",
+      "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g=="
+    },
+    "@types/node": {
+      "version": "17.0.23",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
+      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+    },
+    "acorn": {
+      "version": "8.7.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+      "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
+    },
+    "acorn-walk": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+      "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA=="
+    },
+    "arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
+    },
+    "bezier-easing": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
+      "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="
+    },
+    "case-anything": {
+      "version": "2.1.10",
+      "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
+      "integrity": "sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ=="
+    },
+    "chroma-js": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz",
+      "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A=="
+    },
+    "create-require": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
+    },
+    "diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+    },
+    "make-error": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
+    },
+    "toml": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
+      "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
+    },
+    "ts-node": {
+      "version": "10.7.0",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz",
+      "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==",
+      "requires": {
+        "@cspotcode/source-map-support": "0.7.0",
+        "@tsconfig/node10": "^1.0.7",
+        "@tsconfig/node12": "^1.0.7",
+        "@tsconfig/node14": "^1.0.0",
+        "@tsconfig/node16": "^1.0.2",
+        "acorn": "^8.4.1",
+        "acorn-walk": "^8.1.1",
+        "arg": "^4.1.0",
+        "create-require": "^1.1.0",
+        "diff": "^4.0.1",
+        "make-error": "^1.1.1",
+        "v8-compile-cache-lib": "^3.0.0",
+        "yn": "3.1.1"
+      }
+    },
+    "typescript": {
+      "version": "4.6.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+      "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+      "peer": true
+    },
+    "v8-compile-cache-lib": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz",
+      "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA=="
+    },
+    "yn": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
     }
+  }
 }

styles/package.json 🔗

@@ -12,6 +12,7 @@
   "dependencies": {
     "@types/chroma-js": "^2.1.3",
     "@types/node": "^17.0.23",
+    "bezier-easing": "^2.1.0",
     "case-anything": "^2.1.10",
     "chroma-js": "^2.4.2",
     "toml": "^3.0.0",

styles/src/system/algorithm.ts 🔗

@@ -1,6 +1,8 @@
 // Adapted from @k-vyn/coloralgorithm
 
+import bezier from "bezier-easing";
 import chroma, { Scale } from "chroma-js";
+import { Curve } from "./curves";
 import { ColorFamily, ColorProps, ColorSet } from "./types";
 
 function validColor(color: string) {
@@ -58,6 +60,91 @@ export function generateColors(props: ColorProps, inverted: boolean) {
   return colors;
 }
 
+export function generateColorsUsingCurve(
+  startColor: string,
+  endColor: string,
+  curve: number[]
+) {
+  const NUM_STEPS = 101;
+
+  const easing = bezier(curve[0], curve[1], curve[2], curve[3]);
+  const curveProgress = [];
+  for (let i = 0; i <= NUM_STEPS; i++) {
+    curveProgress.push(easing(i / NUM_STEPS));
+  }
+
+  const colors: chroma.Color[] = [];
+  for (let i = 0; i < NUM_STEPS; i++) {
+    // Use HSL as an input as it is easier to construct programatically
+    // const color = chroma.hsl();
+    const color = chroma.mix(startColor, endColor, curveProgress[i], "lch");
+    colors.push(color);
+  }
+
+  return colors;
+}
+
+export function generateColors2(
+  hue: {
+    start: number;
+    end: number;
+    curve: Curve;
+  },
+  saturation: {
+    start: number;
+    end: number;
+    curve: Curve;
+  },
+  lightness: {
+    start: number;
+    end: number;
+    curve: Curve;
+  }
+) {
+  const NUM_STEPS = 9;
+
+  const hueEasing = bezier(
+    hue.curve.value[0],
+    hue.curve.value[1],
+    hue.curve.value[2],
+    hue.curve.value[3]
+  );
+  const saturationEasing = bezier(
+    saturation.curve.value[0],
+    saturation.curve.value[1],
+    saturation.curve.value[2],
+    saturation.curve.value[3]
+  );
+  const lightnessEasing = bezier(
+    lightness.curve.value[0],
+    lightness.curve.value[1],
+    lightness.curve.value[2],
+    lightness.curve.value[3]
+  );
+
+  const colors: chroma.Color[] = [];
+  for (let i = 0; i < NUM_STEPS; i++) {
+    const hueValue =
+      hueEasing(i / NUM_STEPS) * (hue.end - hue.start) + hue.start;
+    const saturationValue =
+      saturationEasing(i / NUM_STEPS) * (saturation.end - saturation.start) +
+      saturation.start;
+    const lightnessValue =
+      lightnessEasing(i / NUM_STEPS) * (lightness.end - lightness.start) +
+      lightness.start;
+
+    const color = chroma.hsl(
+      hueValue,
+      saturationValue / 100,
+      lightnessValue / 100
+    );
+    colors.push(color);
+  }
+
+  const scale = chroma.scale(colors).mode("lch");
+  return scale;
+}
+
 /** Generates two color ramps:
  * One for for light, and one for dark.
  * By generating two ramps, rather than two default themes, we can use the same reference palette values for tokens in components.

styles/src/system/curves.ts 🔗

@@ -7,6 +7,8 @@ export interface Curve {
 }
 
 export interface Curves {
+  lightness: Curve;
+  saturation: Curve;
   linear: Curve;
   easeInCubic: Curve;
   easeOutCubic: Curve;
@@ -35,6 +37,16 @@ export interface Curves {
 }
 
 export const curve: Curves = {
+  lightness: {
+    name: "nate",
+    formatted_name: "Nate",
+    value: [0.2, 0, 0.85, 1.1],
+  },
+  saturation: {
+    name: "nate",
+    formatted_name: "Nate",
+    value: [0.67, 0.6, 0.55, 1.0],
+  },
   linear: {
     name: "linear",
     formatted_name: "Linear",

styles/src/system/ref/color.ts 🔗

@@ -1,5 +1,10 @@
 import chroma from "chroma-js";
-import { generateColorSet } from "../algorithm";
+import {
+  generateColors2,
+  generateColorSet,
+  generateColorsUsingCurve,
+} from "../algorithm";
+import { curve } from "../curves";
 import { ColorFamily } from "../types";
 
 // These are the source colors for the color scales in the system.
@@ -59,6 +64,28 @@ const red: ColorFamily = generateColorSet({
 export const redLight = chroma.scale(red.colors).mode("lch");
 export const redDark = chroma.scale(red.invertedColors).mode("lch");
 
+// Red 2 ======================================== //
+
+const red2 = generateColors2(
+  {
+    start: 0,
+    end: 0,
+    curve: curve.linear,
+  },
+  {
+    start: 95,
+    end: 75,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 25,
+    curve: curve.lightness,
+  }
+);
+
+export const red2Light = red2;
+
 // Orange ======================================== //
 
 const orange: ColorFamily = generateColorSet({
@@ -73,6 +100,28 @@ const orange: ColorFamily = generateColorSet({
 export const orangeLight = chroma.scale(orange.colors).mode("lch");
 export const orangeDark = chroma.scale(orange.invertedColors).mode("lch");
 
+// Orange 2 ======================================== //
+
+const orange2 = generateColors2(
+  {
+    start: 25,
+    end: 25,
+    curve: curve.linear,
+  },
+  {
+    start: 100,
+    end: 100,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 25,
+    curve: curve.lightness,
+  }
+);
+
+export const orange2Light = orange2;
+
 // Amber ======================================== //
 
 const amber: ColorFamily = generateColorSet({
@@ -87,6 +136,28 @@ const amber: ColorFamily = generateColorSet({
 export const amberLight = chroma.scale(amber.colors).mode("lch");
 export const amberDark = chroma.scale(amber.invertedColors).mode("lch");
 
+// Amber 2 ======================================== //
+
+const amber2 = generateColors2(
+  {
+    start: 34,
+    end: 34,
+    curve: curve.linear,
+  },
+  {
+    start: 100,
+    end: 100,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 25,
+    curve: curve.lightness,
+  }
+);
+
+export const amber2Light = amber2;
+
 // Yellow ======================================== //
 
 const yellow: ColorFamily = generateColorSet({
@@ -101,6 +172,28 @@ const yellow: ColorFamily = generateColorSet({
 export const yellowLight = chroma.scale(yellow.colors).mode("lch");
 export const yellowDark = chroma.scale(yellow.invertedColors).mode("lch");
 
+// Yellow 2 ======================================== //
+
+const yellow2 = generateColors2(
+  {
+    start: 48,
+    end: 48,
+    curve: curve.linear,
+  },
+  {
+    start: 90,
+    end: 100,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 30,
+    curve: curve.lightness,
+  }
+);
+
+export const yellow2Light = yellow2;
+
 // Lime ======================================== //
 
 const lime: ColorFamily = generateColorSet({
@@ -115,6 +208,50 @@ const lime: ColorFamily = generateColorSet({
 export const limeLight = chroma.scale(lime.colors).mode("lch");
 export const limeDark = chroma.scale(lime.invertedColors).mode("lch");
 
+// Lime 2 ======================================== //
+
+const lime2 = generateColors2(
+  {
+    start: 85,
+    end: 85,
+    curve: curve.linear,
+  },
+  {
+    start: 85,
+    end: 70,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 30,
+    curve: curve.lightness,
+  }
+);
+
+export const lime2Light = lime2;
+
+// Citron 2 ======================================== //
+
+const citron2 = generateColors2(
+  {
+    start: 65,
+    end: 65,
+    curve: curve.linear,
+  },
+  {
+    start: 85,
+    end: 70,
+    curve: curve.saturation,
+  },
+  {
+    start: 97,
+    end: 30,
+    curve: curve.lightness,
+  }
+);
+
+export const citron2Light = citron2;
+
 // Green ======================================== //
 
 const green: ColorFamily = generateColorSet({

styles/theme-tool/app/page.tsx 🔗

@@ -57,6 +57,14 @@ export default function Home() {
                 <ColorChips colorScale={color.pinkLight} />
                 <ColorChips colorScale={color.brownLight} />
             </div>
+            <div style={{ display: 'flex', gap: '1px' }}>
+                <ColorChips colorScale={color.red2Light} />
+                <ColorChips colorScale={color.orange2Light} />
+                <ColorChips colorScale={color.amber2Light} />
+                <ColorChips colorScale={color.yellow2Light} />
+                <ColorChips colorScale={color.citron2Light} />
+                <ColorChips colorScale={color.lime2Light} />
+            </div>
         </main>
     );
 }