Write theme JSON files from buildThemes script

Nathan Sobo and Nate Butler created

Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com>

Change summary

script/build-themes            |   7 
styles/buildStyleTree.ts       |  11 
styles/buildThemes.ts          |  17 +
styles/package-lock.json       | 279 +++++++++++++++++++++++
styles/package.json            |   7 
styles/themes/dark.ts          | 432 ++++++++++++++++++------------------
styles/themes/light.ts         | 430 +++++++++++++++++-----------------
styles/tsconfig.json           |  12 +
styles/utils/decamelizeTree.ts |  21 +
9 files changed, 771 insertions(+), 445 deletions(-)

Detailed changes

styles/buildStyleTree.ts 🔗

@@ -1,11 +0,0 @@
-import dark from "./themes/dark";
-import light from "./themes/light";
-import app from "./styleTree/app";
-
-for (let theme of [dark, light]) {
-    let styleTree = app(theme);
-
-    let styleTreeJson = JSON.stringify(styleTree);
-    console.log(styleTreeJson);
-    // TODO: Write style tree json to zed crate assets folder
-}

styles/buildThemes.ts 🔗

@@ -0,0 +1,17 @@
+import * as fs from "fs";
+import * as path from "path";
+import dark from "./themes/dark";
+import light from "./themes/light";
+import app from "./styleTree/app";
+import decamelizeTree from "./utils/decamelizeTree";
+
+const themes = [dark, light];
+for (let theme of themes) {
+  let styleTree = decamelizeTree(app(theme));
+  let styleTreeJSON = JSON.stringify(styleTree, null, 2);
+  let outPath = path.resolve(
+    `${__dirname}/../crates/zed/assets/themes/${theme.name}.json`
+  );
+  fs.writeFileSync(outPath, styleTreeJSON);
+  console.log(`Generated ${outPath}`);
+}

styles/package-lock.json 🔗

@@ -10,30 +10,307 @@
       "license": "ISC",
       "dependencies": {
         "@types/chroma-js": "^2.1.3",
-        "chroma-js": "^2.4.2"
+        "@types/node": "^17.0.23",
+        "case-anything": "^2.1.10",
+        "chroma-js": "^2.4.2",
+        "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/@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/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/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=="
+    },
+    "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=="
+    },
+    "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 🔗

@@ -4,12 +4,15 @@
   "description": "",
   "main": "index.js",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "build": "ts-node buildThemes.ts"
   },
   "author": "",
   "license": "ISC",
   "dependencies": {
     "@types/chroma-js": "^2.1.3",
-    "chroma-js": "^2.4.2"
+    "@types/node": "^17.0.23",
+    "case-anything": "^2.1.10",
+    "chroma-js": "^2.4.2",
+    "ts-node": "^10.7.0"
   }
 }

styles/themes/dark.ts 🔗

@@ -4,246 +4,246 @@ import Theme, { NumberToken, Syntax } from "./theme";
 const { color } = core;
 
 const backgroundColor = {
-    100: {
-        base: color.neutral[750],
-        hovered: color.neutral[750],
-        active: color.neutral[750],
-        focused: color.neutral[750],
-    },
-    300: {
-        base: color.neutral[800],
-        hovered: color.neutral[800],
-        active: color.neutral[800],
-        focused: color.neutral[800],
-    },
-    500: {
-        base: color.neutral[900],
-        hovered: color.neutral[900],
-        active: color.neutral[900],
-        focused: color.neutral[900],
-    },
-    ok: {
-        base: color.green[600],
-        hovered: color.green[600],
-        active: color.green[600],
-        focused: color.green[600],
-    },
-    error: {
-        base: color.red[400],
-        hovered: color.red[400],
-        active: color.red[400],
-        focused: color.red[400],
-    },
-    warning: {
-        base: color.amber[300],
-        hovered: color.amber[300],
-        active: color.amber[300],
-        focused: color.amber[300],
-    },
-    info: {
-        base: color.blue[500],
-        hovered: color.blue[500],
-        active: color.blue[500],
-        focused: color.blue[500],
-    },
+  100: {
+    base: color.neutral[750],
+    hovered: color.neutral[750],
+    active: color.neutral[750],
+    focused: color.neutral[750],
+  },
+  300: {
+    base: color.neutral[800],
+    hovered: color.neutral[800],
+    active: color.neutral[800],
+    focused: color.neutral[800],
+  },
+  500: {
+    base: color.neutral[900],
+    hovered: color.neutral[900],
+    active: color.neutral[900],
+    focused: color.neutral[900],
+  },
+  ok: {
+    base: color.green[600],
+    hovered: color.green[600],
+    active: color.green[600],
+    focused: color.green[600],
+  },
+  error: {
+    base: color.red[400],
+    hovered: color.red[400],
+    active: color.red[400],
+    focused: color.red[400],
+  },
+  warning: {
+    base: color.amber[300],
+    hovered: color.amber[300],
+    active: color.amber[300],
+    focused: color.amber[300],
+  },
+  info: {
+    base: color.blue[500],
+    hovered: color.blue[500],
+    active: color.blue[500],
+    focused: color.blue[500],
+  },
 };
 
 const borderColor = {
-    primary: color.neutral[850],
-    secondary: color.neutral[700],
-    muted: color.neutral[750],
-    focused: color.neutral[100],
-    active: color.neutral[500],
-    ok: color.neutral[999],
-    error: color.neutral[999],
-    warning: color.neutral[999],
-    info: color.neutral[999],
+  primary: color.neutral[850],
+  secondary: color.neutral[700],
+  muted: color.neutral[750],
+  focused: color.neutral[100],
+  active: color.neutral[500],
+  ok: color.neutral[1000],
+  error: color.neutral[1000],
+  warning: color.neutral[1000],
+  info: color.neutral[1000],
 };
 
 const textColor = {
-    primary: color.neutral[150],
-    secondary: color.neutral[350],
-    muted: color.neutral[550],
-    placeholder: color.neutral[750],
-    active: color.neutral[0],
-    //TODO: (design) define feature and it's correct value
-    feature: color.sky[500],
-    ok: color.green[600],
-    error: color.red[400],
-    warning: color.amber[300],
-    info: color.blue[500],
+  primary: color.neutral[150],
+  secondary: color.neutral[350],
+  muted: color.neutral[550],
+  placeholder: color.neutral[750],
+  active: color.neutral[0],
+  //TODO: (design) define feature and it's correct value
+  feature: color.sky[500],
+  ok: color.green[600],
+  error: color.red[400],
+  warning: color.amber[300],
+  info: color.blue[500],
 };
 
 const iconColor = {
-    primary: color.neutral[300],
-    secondary: color.neutral[500],
-    muted: color.neutral[600],
-    placeholder: color.neutral[700],
-    active: color.neutral[50],
-    //TODO: (design) define feature and it's correct value
-    feature: color.sky[500],
-    ok: color.green[600],
-    error: color.red[400],
-    warning: color.amber[300],
-    info: color.blue[500],
+  primary: color.neutral[300],
+  secondary: color.neutral[500],
+  muted: color.neutral[600],
+  placeholder: color.neutral[700],
+  active: color.neutral[50],
+  //TODO: (design) define feature and it's correct value
+  feature: color.sky[500],
+  ok: color.green[600],
+  error: color.red[400],
+  warning: color.amber[300],
+  info: color.blue[500],
 };
 
 const player = {
-    1: {
-        baseColor: color.blue[600],
-        cursorColor: color.blue[600],
-        selectionColor: color.blue[600],
-        borderColor: color.blue[600],
-    },
-    2: {
-        baseColor: color.indigo[500],
-        cursorColor: color.indigo[500],
-        selectionColor: color.indigo[500],
-        borderColor: color.indigo[500],
-    },
-    3: {
-        baseColor: color.green[500],
-        cursorColor: color.green[500],
-        selectionColor: color.green[500],
-        borderColor: color.green[500],
-    },
-    4: {
-        baseColor: color.orange[500],
-        cursorColor: color.orange[500],
-        selectionColor: color.orange[500],
-        borderColor: color.orange[500],
-    },
-    5: {
-        baseColor: color.purple[500],
-        cursorColor: color.purple[500],
-        selectionColor: color.purple[500],
-        borderColor: color.purple[500],
-    },
-    6: {
-        baseColor: color.teal[400],
-        cursorColor: color.teal[400],
-        selectionColor: color.teal[400],
-        borderColor: color.teal[400],
-    },
-    7: {
-        baseColor: color.pink[400],
-        cursorColor: color.pink[400],
-        selectionColor: color.pink[400],
-        borderColor: color.pink[400],
-    },
-    8: {
-        baseColor: color.yellow[400],
-        cursorColor: color.yellow[400],
-        selectionColor: color.yellow[400],
-        borderColor: color.yellow[400],
-    },
+  1: {
+    baseColor: color.blue[600],
+    cursorColor: color.blue[600],
+    selectionColor: color.blue[600],
+    borderColor: color.blue[600],
+  },
+  2: {
+    baseColor: color.indigo[500],
+    cursorColor: color.indigo[500],
+    selectionColor: color.indigo[500],
+    borderColor: color.indigo[500],
+  },
+  3: {
+    baseColor: color.green[500],
+    cursorColor: color.green[500],
+    selectionColor: color.green[500],
+    borderColor: color.green[500],
+  },
+  4: {
+    baseColor: color.orange[500],
+    cursorColor: color.orange[500],
+    selectionColor: color.orange[500],
+    borderColor: color.orange[500],
+  },
+  5: {
+    baseColor: color.purple[500],
+    cursorColor: color.purple[500],
+    selectionColor: color.purple[500],
+    borderColor: color.purple[500],
+  },
+  6: {
+    baseColor: color.teal[400],
+    cursorColor: color.teal[400],
+    selectionColor: color.teal[400],
+    borderColor: color.teal[400],
+  },
+  7: {
+    baseColor: color.pink[400],
+    cursorColor: color.pink[400],
+    selectionColor: color.pink[400],
+    borderColor: color.pink[400],
+  },
+  8: {
+    baseColor: color.yellow[400],
+    cursorColor: color.yellow[400],
+    selectionColor: color.yellow[400],
+    borderColor: color.yellow[400],
+  },
 };
 
 // TODO: Fixup
 const editor = {
-    background: backgroundColor[500].base,
-    indent_guide: borderColor.muted,
-    indent_guide_active: borderColor.secondary,
-    line: {
-        active: color.neutral[0],
-        highlighted: color.neutral[0],
-        inserted: backgroundColor.ok.active,
-        deleted: backgroundColor.error.active,
-        modified: backgroundColor.info.active,
-    },
-    highlight: {
-        selection: player[1].selectionColor,
-        occurrence: backgroundColor[500].active,
-        activeOccurrence: color.neutral[0],
-        matchingBracket: color.neutral[0],
-        match: color.neutral[0],
-        activeMatch: color.neutral[0],
-        related: color.neutral[0],
-    },
-    gutter: {
-        primary: color.neutral[0],
-        active: color.neutral[0],
-    },
+  background: backgroundColor[500].base,
+  indent_guide: borderColor.muted,
+  indent_guide_active: borderColor.secondary,
+  line: {
+    active: color.neutral[0],
+    highlighted: color.neutral[0],
+    inserted: backgroundColor.ok.active,
+    deleted: backgroundColor.error.active,
+    modified: backgroundColor.info.active,
+  },
+  highlight: {
+    selection: player[1].selectionColor,
+    occurrence: backgroundColor[500].active,
+    activeOccurrence: color.neutral[0],
+    matchingBracket: color.neutral[0],
+    match: color.neutral[0],
+    activeMatch: color.neutral[0],
+    related: color.neutral[0],
+  },
+  gutter: {
+    primary: color.neutral[0],
+    active: color.neutral[0],
+  },
 };
 
 const syntax: Syntax = {
-    primary: {
-        color: textColor.primary,
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    comment: {
-        color: color.lime[200],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    punctuation: {
-        color: textColor.primary,
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    constant: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    keyword: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    function: {
-        color: color.yellow[200],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    type: {
-        color: color.teal[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    variant: {
-        color: color.teal[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    property: {
-        color: color.sky[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    enum: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    operator: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    string: {
-        color: color.orange[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    number: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    boolean: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    predictive: {
-        color: textColor.muted,
-        weight: { value: "normal", type: "fontWeight" },
-    },
+  primary: {
+    color: textColor.primary,
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  comment: {
+    color: color.lime[200],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  punctuation: {
+    color: textColor.primary,
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  constant: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  keyword: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  function: {
+    color: color.yellow[200],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  type: {
+    color: color.teal[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  variant: {
+    color: color.teal[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  property: {
+    color: color.sky[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  enum: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  operator: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  string: {
+    color: color.orange[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  number: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  boolean: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  predictive: {
+    color: textColor.muted,
+    weight: { value: "normal", type: "fontWeight" },
+  },
 };
 
 const shadowAlpha: NumberToken = {
-    value: 0.32,
-    type: "number"
+  value: 0.32,
+  type: "number",
 };
 
 const theme: Theme = {
-    name: "dark",
-    backgroundColor,
-    borderColor,
-    textColor,
-    iconColor,
-    editor,
-    syntax,
-    player,
-    shadowAlpha,
+  name: "dark",
+  backgroundColor,
+  borderColor,
+  textColor,
+  iconColor,
+  editor,
+  syntax,
+  player,
+  shadowAlpha,
 };
 
-export default theme;
+export default theme;

styles/themes/light.ts 🔗

@@ -6,246 +6,246 @@ const { color } = core;
 // TODO: Replace with light values
 
 const backgroundColor = {
-    100: {
-        base: color.neutral[750],
-        hovered: color.neutral[750],
-        active: color.neutral[750],
-        focused: color.neutral[750],
-    },
-    300: {
-        base: color.neutral[800],
-        hovered: color.neutral[800],
-        active: color.neutral[800],
-        focused: color.neutral[800],
-    },
-    500: {
-        base: color.neutral[900],
-        hovered: color.neutral[900],
-        active: color.neutral[900],
-        focused: color.neutral[900],
-    },
-    ok: {
-        base: color.green[600],
-        hovered: color.green[600],
-        active: color.green[600],
-        focused: color.green[600],
-    },
-    error: {
-        base: color.red[400],
-        hovered: color.red[400],
-        active: color.red[400],
-        focused: color.red[400],
-    },
-    warning: {
-        base: color.amber[300],
-        hovered: color.amber[300],
-        active: color.amber[300],
-        focused: color.amber[300],
-    },
-    info: {
-        base: color.blue[500],
-        hovered: color.blue[500],
-        active: color.blue[500],
-        focused: color.blue[500],
-    },
+  100: {
+    base: color.neutral[750],
+    hovered: color.neutral[750],
+    active: color.neutral[750],
+    focused: color.neutral[750],
+  },
+  300: {
+    base: color.neutral[800],
+    hovered: color.neutral[800],
+    active: color.neutral[800],
+    focused: color.neutral[800],
+  },
+  500: {
+    base: color.neutral[900],
+    hovered: color.neutral[900],
+    active: color.neutral[900],
+    focused: color.neutral[900],
+  },
+  ok: {
+    base: color.green[600],
+    hovered: color.green[600],
+    active: color.green[600],
+    focused: color.green[600],
+  },
+  error: {
+    base: color.red[400],
+    hovered: color.red[400],
+    active: color.red[400],
+    focused: color.red[400],
+  },
+  warning: {
+    base: color.amber[300],
+    hovered: color.amber[300],
+    active: color.amber[300],
+    focused: color.amber[300],
+  },
+  info: {
+    base: color.blue[500],
+    hovered: color.blue[500],
+    active: color.blue[500],
+    focused: color.blue[500],
+  },
 };
 
 const borderColor = {
-    primary: color.neutral[850],
-    secondary: color.neutral[700],
-    muted: color.neutral[750],
-    focused: color.neutral[100],
-    active: color.neutral[500],
-    ok: color.neutral[999],
-    error: color.neutral[999],
-    warning: color.neutral[999],
-    info: color.neutral[999],
+  primary: color.neutral[850],
+  secondary: color.neutral[700],
+  muted: color.neutral[750],
+  focused: color.neutral[100],
+  active: color.neutral[500],
+  ok: color.neutral[1000],
+  error: color.neutral[1000],
+  warning: color.neutral[1000],
+  info: color.neutral[1000],
 };
 
 const textColor = {
-    primary: color.neutral[150],
-    secondary: color.neutral[350],
-    muted: color.neutral[550],
-    placeholder: color.neutral[750],
-    active: color.neutral[0],
-    //TODO: (design) define feature and it's correct value
-    feature: color.sky[500],
-    ok: color.green[600],
-    error: color.red[400],
-    warning: color.amber[300],
-    info: color.blue[500],
+  primary: color.neutral[150],
+  secondary: color.neutral[350],
+  muted: color.neutral[550],
+  placeholder: color.neutral[750],
+  active: color.neutral[0],
+  //TODO: (design) define feature and it's correct value
+  feature: color.sky[500],
+  ok: color.green[600],
+  error: color.red[400],
+  warning: color.amber[300],
+  info: color.blue[500],
 };
 
 const iconColor = {
-    primary: color.neutral[300],
-    secondary: color.neutral[500],
-    muted: color.neutral[600],
-    placeholder: color.neutral[700],
-    active: color.neutral[50],
-    //TODO: (design) define feature and it's correct value
-    feature: color.sky[500],
-    ok: color.green[600],
-    error: color.red[400],
-    warning: color.amber[300],
-    info: color.blue[500],
+  primary: color.neutral[300],
+  secondary: color.neutral[500],
+  muted: color.neutral[600],
+  placeholder: color.neutral[700],
+  active: color.neutral[50],
+  //TODO: (design) define feature and it's correct value
+  feature: color.sky[500],
+  ok: color.green[600],
+  error: color.red[400],
+  warning: color.amber[300],
+  info: color.blue[500],
 };
 
 const player = {
-    1: {
-        baseColor: color.blue[600],
-        cursorColor: color.blue[600],
-        selectionColor: color.blue[600],
-        borderColor: color.blue[600],
-    },
-    2: {
-        baseColor: color.indigo[500],
-        cursorColor: color.indigo[500],
-        selectionColor: color.indigo[500],
-        borderColor: color.indigo[500],
-    },
-    3: {
-        baseColor: color.green[500],
-        cursorColor: color.green[500],
-        selectionColor: color.green[500],
-        borderColor: color.green[500],
-    },
-    4: {
-        baseColor: color.orange[500],
-        cursorColor: color.orange[500],
-        selectionColor: color.orange[500],
-        borderColor: color.orange[500],
-    },
-    5: {
-        baseColor: color.purple[500],
-        cursorColor: color.purple[500],
-        selectionColor: color.purple[500],
-        borderColor: color.purple[500],
-    },
-    6: {
-        baseColor: color.teal[400],
-        cursorColor: color.teal[400],
-        selectionColor: color.teal[400],
-        borderColor: color.teal[400],
-    },
-    7: {
-        baseColor: color.pink[400],
-        cursorColor: color.pink[400],
-        selectionColor: color.pink[400],
-        borderColor: color.pink[400],
-    },
-    8: {
-        baseColor: color.yellow[400],
-        cursorColor: color.yellow[400],
-        selectionColor: color.yellow[400],
-        borderColor: color.yellow[400],
-    },
+  1: {
+    baseColor: color.blue[600],
+    cursorColor: color.blue[600],
+    selectionColor: color.blue[600],
+    borderColor: color.blue[600],
+  },
+  2: {
+    baseColor: color.indigo[500],
+    cursorColor: color.indigo[500],
+    selectionColor: color.indigo[500],
+    borderColor: color.indigo[500],
+  },
+  3: {
+    baseColor: color.green[500],
+    cursorColor: color.green[500],
+    selectionColor: color.green[500],
+    borderColor: color.green[500],
+  },
+  4: {
+    baseColor: color.orange[500],
+    cursorColor: color.orange[500],
+    selectionColor: color.orange[500],
+    borderColor: color.orange[500],
+  },
+  5: {
+    baseColor: color.purple[500],
+    cursorColor: color.purple[500],
+    selectionColor: color.purple[500],
+    borderColor: color.purple[500],
+  },
+  6: {
+    baseColor: color.teal[400],
+    cursorColor: color.teal[400],
+    selectionColor: color.teal[400],
+    borderColor: color.teal[400],
+  },
+  7: {
+    baseColor: color.pink[400],
+    cursorColor: color.pink[400],
+    selectionColor: color.pink[400],
+    borderColor: color.pink[400],
+  },
+  8: {
+    baseColor: color.yellow[400],
+    cursorColor: color.yellow[400],
+    selectionColor: color.yellow[400],
+    borderColor: color.yellow[400],
+  },
 };
 
 // TODO: Fixup
 const editor = {
-    background: backgroundColor[500].base,
-    indent_guide: borderColor.muted,
-    indent_guide_active: borderColor.secondary,
-    line: {
-        active: color.neutral[0],
-        highlighted: color.neutral[0],
-        inserted: backgroundColor.ok.active,
-        deleted: backgroundColor.error.active,
-        modified: backgroundColor.info.active,
-    },
-    highlight: {
-        selection: player[1].selectionColor,
-        occurrence: backgroundColor[500].active,
-        activeOccurrence: color.neutral[0],
-        matchingBracket: color.neutral[0],
-        match: color.neutral[0],
-        activeMatch: color.neutral[0],
-        related: color.neutral[0],
-    },
-    gutter: {
-        primary: color.neutral[0],
-        active: color.neutral[0],
-    },
+  background: backgroundColor[500].base,
+  indent_guide: borderColor.muted,
+  indent_guide_active: borderColor.secondary,
+  line: {
+    active: color.neutral[0],
+    highlighted: color.neutral[0],
+    inserted: backgroundColor.ok.active,
+    deleted: backgroundColor.error.active,
+    modified: backgroundColor.info.active,
+  },
+  highlight: {
+    selection: player[1].selectionColor,
+    occurrence: backgroundColor[500].active,
+    activeOccurrence: color.neutral[0],
+    matchingBracket: color.neutral[0],
+    match: color.neutral[0],
+    activeMatch: color.neutral[0],
+    related: color.neutral[0],
+  },
+  gutter: {
+    primary: color.neutral[0],
+    active: color.neutral[0],
+  },
 };
 
 const syntax: Syntax = {
-    primary: {
-        color: textColor.primary,
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    comment: {
-        color: color.lime[200],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    punctuation: {
-        color: textColor.primary,
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    constant: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    keyword: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    function: {
-        color: color.yellow[200],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    type: {
-        color: color.teal[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    variant: {
-        color: color.teal[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    property: {
-        color: color.sky[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    enum: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    operator: {
-        color: color.sky[400],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    string: {
-        color: color.orange[300],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    number: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    boolean: {
-        color: color.neutral[150],
-        weight: { value: "normal", type: "fontWeight" },
-    },
-    predictive: {
-        color: textColor.muted,
-        weight: { value: "normal", type: "fontWeight" },
-    },
+  primary: {
+    color: textColor.primary,
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  comment: {
+    color: color.lime[200],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  punctuation: {
+    color: textColor.primary,
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  constant: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  keyword: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  function: {
+    color: color.yellow[200],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  type: {
+    color: color.teal[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  variant: {
+    color: color.teal[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  property: {
+    color: color.sky[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  enum: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  operator: {
+    color: color.sky[400],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  string: {
+    color: color.orange[300],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  number: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  boolean: {
+    color: color.neutral[150],
+    weight: { value: "normal", type: "fontWeight" },
+  },
+  predictive: {
+    color: textColor.muted,
+    weight: { value: "normal", type: "fontWeight" },
+  },
 };
 
 const shadowAlpha: NumberToken = {
-    value: 0.32,
-    type: "number"
+  value: 0.32,
+  type: "number",
 };
 
 const theme: Theme = {
-    name: "light",
-    backgroundColor,
-    borderColor,
-    textColor,
-    iconColor,
-    editor,
-    syntax,
-    player,
-    shadowAlpha,
+  name: "light",
+  backgroundColor,
+  borderColor,
+  textColor,
+  iconColor,
+  editor,
+  syntax,
+  player,
+  shadowAlpha,
 };
 
 export default theme;

styles/tsconfig.json 🔗

@@ -0,0 +1,12 @@
+{
+    "compilerOptions": {
+      "target": "es2015",
+      "module": "commonjs",
+      "esModuleInterop": true,
+      "noImplicitAny": true,
+      "removeComments": true,
+      "preserveConstEnums": true,
+      "sourceMap": true
+    },
+    "exclude": ["node_modules"]
+  }

styles/utils/decamelizeTree.ts 🔗

@@ -0,0 +1,21 @@
+import { snakeCase } from "case-anything";
+
+export default function decamelizeTree(object: { [key: string]: any }) {
+  const snakeObject: { [key: string]: any } = {};
+  for (const key in object) {
+    snakeObject[snakeCase(key)] = decamelizeValue(object[key]);
+  }
+  return snakeObject;
+}
+
+function decamelizeValue(value: any): any {
+  if (typeof value === "object") {
+    if (Array.isArray(value)) {
+      return value.map(decamelizeValue);
+    } else {
+      return decamelizeTree(value);
+    }
+  } else {
+    return value;
+  }
+}