Set up vitest and add tests for `interactive`

Nate Butler created

Change summary

styles/.gitignore                                  |    1 
styles/package-lock.json                           | 1192 +++++++++++++++
styles/package.json                                |    9 
styles/src/element/interactive/index.ts            |    3 
styles/src/element/interactive/interactive.test.ts |   59 
styles/src/element/interactive/interactive.ts      |   23 
styles/src/styleTree/assistant.ts                  |  176 +-
styles/src/styleTree/commandPalette.ts             |   60 
styles/src/styleTree/contactList.ts                |  392 ++--
styles/src/styleTree/contactNotification.ts        |   86 
styles/src/styleTree/contextMenu.ts                |   98 
styles/src/styleTree/copilot.ts                    |  522 +++---
styles/src/styleTree/editor.ts                     |  536 +++---
styles/src/styleTree/feedback.ts                   |   84 
styles/src/styleTree/picker.ts                     |  152 +-
styles/src/styleTree/projectPanel.ts               |  212 +-
styles/src/styleTree/search.ts                     |  216 +-
styles/src/styleTree/simpleMessageNotification.ts  |   82 
styles/src/styleTree/statusBar.ts                  |  266 +-
styles/src/styleTree/tabBar.ts                     |  200 +-
styles/src/styleTree/toolbarDropdownMenu.ts        |  100 
styles/src/styleTree/updateNotification.ts         |   60 
styles/src/styleTree/welcome.ts                    |  240 +-
styles/src/styleTree/workspace.ts                  |  704 ++++----
styles/vitest.config.ts                            |    8 
25 files changed, 3,375 insertions(+), 2,106 deletions(-)

Detailed changes

styles/package-lock.json 🔗

@@ -20,9 +20,32 @@
                 "toml": "^3.0.0",
                 "ts-deepmerge": "^6.0.3",
                 "ts-node": "^10.9.1",
-                "utility-types": "^3.10.0"
+                "utility-types": "^3.10.0",
+                "vitest": "^0.32.0"
+            },
+            "devDependencies": {
+                "@vitest/coverage-v8": "^0.32.0"
+            }
+        },
+        "node_modules/@ampproject/remapping": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+            "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+            "dev": true,
+            "dependencies": {
+                "@jridgewell/gen-mapping": "^0.3.0",
+                "@jridgewell/trace-mapping": "^0.3.9"
+            },
+            "engines": {
+                "node": ">=6.0.0"
             }
         },
+        "node_modules/@bcoe/v8-coverage": {
+            "version": "0.2.3",
+            "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+            "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+            "dev": true
+        },
         "node_modules/@cspotcode/source-map-support": {
             "version": "0.8.1",
             "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -34,6 +57,359 @@
                 "node": ">=12"
             }
         },
+        "node_modules/@esbuild/android-arm": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
+            "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
+            "cpu": [
+                "arm"
+            ],
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/android-arm64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
+            "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
+            "cpu": [
+                "arm64"
+            ],
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/android-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
+            "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/darwin-arm64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
+            "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
+            "cpu": [
+                "arm64"
+            ],
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/darwin-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
+            "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/freebsd-arm64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
+            "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
+            "cpu": [
+                "arm64"
+            ],
+            "optional": true,
+            "os": [
+                "freebsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/freebsd-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
+            "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "freebsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-arm": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
+            "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
+            "cpu": [
+                "arm"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-arm64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
+            "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
+            "cpu": [
+                "arm64"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-ia32": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
+            "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
+            "cpu": [
+                "ia32"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-loong64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
+            "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
+            "cpu": [
+                "loong64"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-mips64el": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
+            "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
+            "cpu": [
+                "mips64el"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-ppc64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
+            "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
+            "cpu": [
+                "ppc64"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-riscv64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
+            "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
+            "cpu": [
+                "riscv64"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-s390x": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
+            "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
+            "cpu": [
+                "s390x"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
+            "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/netbsd-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
+            "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "netbsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/openbsd-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
+            "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "openbsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/sunos-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
+            "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "sunos"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-arm64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
+            "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
+            "cpu": [
+                "arm64"
+            ],
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-ia32": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
+            "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
+            "cpu": [
+                "ia32"
+            ],
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-x64": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
+            "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
+            "cpu": [
+                "x64"
+            ],
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@istanbuljs/schema": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+            "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/@jridgewell/gen-mapping": {
+            "version": "0.3.3",
+            "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+            "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+            "dev": true,
+            "dependencies": {
+                "@jridgewell/set-array": "^1.0.1",
+                "@jridgewell/sourcemap-codec": "^1.4.10",
+                "@jridgewell/trace-mapping": "^0.3.9"
+            },
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
         "node_modules/@jridgewell/resolve-uri": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
@@ -42,6 +418,15 @@
                 "node": ">=6.0.0"
             }
         },
+        "node_modules/@jridgewell/set-array": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+            "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+            "dev": true,
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
         "node_modules/@jridgewell/sourcemap-codec": {
             "version": "1.4.14",
             "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
@@ -81,16 +466,124 @@
             "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
             "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ=="
         },
+        "node_modules/@types/chai": {
+            "version": "4.3.5",
+            "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz",
+            "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng=="
+        },
+        "node_modules/@types/chai-subset": {
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz",
+            "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==",
+            "dependencies": {
+                "@types/chai": "*"
+            }
+        },
         "node_modules/@types/chroma-js": {
             "version": "2.4.0",
             "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.0.tgz",
             "integrity": "sha512-JklMxityrwjBTjGY2anH8JaTx3yjRU3/sEHSblLH1ba5lqcSh1LnImXJZO5peJfXyqKYWjHTGy4s5Wz++hARrw=="
         },
+        "node_modules/@types/istanbul-lib-coverage": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
+            "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
+            "dev": true
+        },
         "node_modules/@types/node": {
             "version": "18.14.1",
             "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz",
             "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ=="
         },
+        "node_modules/@vitest/coverage-v8": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.32.0.tgz",
+            "integrity": "sha512-VXXlWq9X/NbsoP/l/CHLBjutsFFww1UY1qEhzGjn/DY7Tqe+z0Nu8XKc8im/XUAmjiWsh2XV7sy/F0IKAl4eaw==",
+            "dev": true,
+            "dependencies": {
+                "@ampproject/remapping": "^2.2.1",
+                "@bcoe/v8-coverage": "^0.2.3",
+                "istanbul-lib-coverage": "^3.2.0",
+                "istanbul-lib-report": "^3.0.0",
+                "istanbul-lib-source-maps": "^4.0.1",
+                "istanbul-reports": "^3.1.5",
+                "magic-string": "^0.30.0",
+                "picocolors": "^1.0.0",
+                "std-env": "^3.3.2",
+                "test-exclude": "^6.0.0",
+                "v8-to-istanbul": "^9.1.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            },
+            "peerDependencies": {
+                "vitest": ">=0.32.0 <1"
+            }
+        },
+        "node_modules/@vitest/expect": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.0.tgz",
+            "integrity": "sha512-VxVHhIxKw9Lux+O9bwLEEk2gzOUe93xuFHy9SzYWnnoYZFYg1NfBtnfnYWiJN7yooJ7KNElCK5YtA7DTZvtXtg==",
+            "dependencies": {
+                "@vitest/spy": "0.32.0",
+                "@vitest/utils": "0.32.0",
+                "chai": "^4.3.7"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            }
+        },
+        "node_modules/@vitest/runner": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.0.tgz",
+            "integrity": "sha512-QpCmRxftHkr72xt5A08xTEs9I4iWEXIOCHWhQQguWOKE4QH7DXSKZSOFibuwEIMAD7G0ERvtUyQn7iPWIqSwmw==",
+            "dependencies": {
+                "@vitest/utils": "0.32.0",
+                "concordance": "^5.0.4",
+                "p-limit": "^4.0.0",
+                "pathe": "^1.1.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            }
+        },
+        "node_modules/@vitest/snapshot": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.0.tgz",
+            "integrity": "sha512-yCKorPWjEnzpUxQpGlxulujTcSPgkblwGzAUEL+z01FTUg/YuCDZ8dxr9sHA08oO2EwxzHXNLjQKWJ2zc2a19Q==",
+            "dependencies": {
+                "magic-string": "^0.30.0",
+                "pathe": "^1.1.0",
+                "pretty-format": "^27.5.1"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            }
+        },
+        "node_modules/@vitest/spy": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.0.tgz",
+            "integrity": "sha512-MruAPlM0uyiq3d53BkwTeShXY0rYEfhNGQzVO5GHBmmX3clsxcWp79mMnkOVcV244sNTeDcHbcPFWIjOI4tZvw==",
+            "dependencies": {
+                "tinyspy": "^2.1.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            }
+        },
+        "node_modules/@vitest/utils": {
+            "version": "0.32.0",
+            "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.0.tgz",
+            "integrity": "sha512-53yXunzx47MmbuvcOPpLaVljHaeSu1G2dHdmy7+9ngMnQIkBQcvwOcoclWFnxDMxFbnq8exAfh3aKSZaK71J5A==",
+            "dependencies": {
+                "concordance": "^5.0.4",
+                "loupe": "^2.3.6",
+                "pretty-format": "^27.5.1"
+            },
+            "funding": {
+                "url": "https://opencollective.com/vitest"
+            }
+        },
         "node_modules/acorn": {
             "version": "8.8.2",
             "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
@@ -110,11 +603,38 @@
                 "node": ">=0.4.0"
             }
         },
+        "node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/ansi-styles": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+            "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
         "node_modules/arg": {
             "version": "4.1.3",
             "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
             "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
         },
+        "node_modules/assertion-error": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+            "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+            "engines": {
+                "node": "*"
+            }
+        },
         "node_modules/ayu": {
             "version": "8.0.1",
             "resolved": "https://registry.npmjs.org/ayu/-/ayu-8.0.1.tgz",
@@ -125,11 +645,40 @@
                 "nonenumerable": "^1.1.1"
             }
         },
+        "node_modules/balanced-match": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+            "dev": true
+        },
         "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/blueimp-md5": {
+            "version": "2.19.0",
+            "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz",
+            "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w=="
+        },
+        "node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/cac": {
+            "version": "6.7.14",
+            "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+            "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/case-anything": {
             "version": "2.1.10",
             "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.10.tgz",
@@ -141,16 +690,109 @@
                 "url": "https://github.com/sponsors/mesqueeb"
             }
         },
+        "node_modules/chai": {
+            "version": "4.3.7",
+            "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
+            "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
+            "dependencies": {
+                "assertion-error": "^1.1.0",
+                "check-error": "^1.0.2",
+                "deep-eql": "^4.1.2",
+                "get-func-name": "^2.0.0",
+                "loupe": "^2.3.1",
+                "pathval": "^1.1.1",
+                "type-detect": "^4.0.5"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/check-error": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+            "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+            "engines": {
+                "node": "*"
+            }
+        },
         "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/concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+            "dev": true
+        },
+        "node_modules/concordance": {
+            "version": "5.0.4",
+            "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz",
+            "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==",
+            "dependencies": {
+                "date-time": "^3.1.0",
+                "esutils": "^2.0.3",
+                "fast-diff": "^1.2.0",
+                "js-string-escape": "^1.0.1",
+                "lodash": "^4.17.15",
+                "md5-hex": "^3.0.1",
+                "semver": "^7.3.2",
+                "well-known-symbols": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14"
+            }
+        },
+        "node_modules/convert-source-map": {
+            "version": "1.9.0",
+            "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+            "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+            "dev": true
+        },
         "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/date-time": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz",
+            "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==",
+            "dependencies": {
+                "time-zone": "^1.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
+        "node_modules/debug": {
+            "version": "4.3.4",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+            "dependencies": {
+                "ms": "2.1.2"
+            },
+            "engines": {
+                "node": ">=6.0"
+            },
+            "peerDependenciesMeta": {
+                "supports-color": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/deep-eql": {
+            "version": "4.1.3",
+            "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+            "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+            "dependencies": {
+                "type-detect": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/deepmerge": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz",
@@ -167,16 +809,564 @@
                 "node": ">=0.3.1"
             }
         },
+        "node_modules/esbuild": {
+            "version": "0.17.19",
+            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
+            "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
+            "hasInstallScript": true,
+            "bin": {
+                "esbuild": "bin/esbuild"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "optionalDependencies": {
+                "@esbuild/android-arm": "0.17.19",
+                "@esbuild/android-arm64": "0.17.19",
+                "@esbuild/android-x64": "0.17.19",
+                "@esbuild/darwin-arm64": "0.17.19",
+                "@esbuild/darwin-x64": "0.17.19",
+                "@esbuild/freebsd-arm64": "0.17.19",
+                "@esbuild/freebsd-x64": "0.17.19",
+                "@esbuild/linux-arm": "0.17.19",
+                "@esbuild/linux-arm64": "0.17.19",
+                "@esbuild/linux-ia32": "0.17.19",
+                "@esbuild/linux-loong64": "0.17.19",
+                "@esbuild/linux-mips64el": "0.17.19",
+                "@esbuild/linux-ppc64": "0.17.19",
+                "@esbuild/linux-riscv64": "0.17.19",
+                "@esbuild/linux-s390x": "0.17.19",
+                "@esbuild/linux-x64": "0.17.19",
+                "@esbuild/netbsd-x64": "0.17.19",
+                "@esbuild/openbsd-x64": "0.17.19",
+                "@esbuild/sunos-x64": "0.17.19",
+                "@esbuild/win32-arm64": "0.17.19",
+                "@esbuild/win32-ia32": "0.17.19",
+                "@esbuild/win32-x64": "0.17.19"
+            }
+        },
+        "node_modules/esutils": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/fast-diff": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+            "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
+        },
+        "node_modules/fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+            "dev": true
+        },
+        "node_modules/fsevents": {
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+            "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+            "hasInstallScript": true,
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+            }
+        },
+        "node_modules/get-func-name": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+            "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/glob": {
+            "version": "7.2.3",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+            "dev": true,
+            "dependencies": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.1.1",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            },
+            "engines": {
+                "node": "*"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/has-flag": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/html-escaper": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+            "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+            "dev": true
+        },
+        "node_modules/inflight": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+            "dev": true,
+            "dependencies": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
+        "node_modules/inherits": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+            "dev": true
+        },
+        "node_modules/istanbul-lib-coverage": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+            "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+            "dev": true,
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/istanbul-lib-report": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+            "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+            "dev": true,
+            "dependencies": {
+                "istanbul-lib-coverage": "^3.0.0",
+                "make-dir": "^3.0.0",
+                "supports-color": "^7.1.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/istanbul-lib-source-maps": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+            "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+            "dev": true,
+            "dependencies": {
+                "debug": "^4.1.1",
+                "istanbul-lib-coverage": "^3.0.0",
+                "source-map": "^0.6.1"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/istanbul-reports": {
+            "version": "3.1.5",
+            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
+            "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+            "dev": true,
+            "dependencies": {
+                "html-escaper": "^2.0.0",
+                "istanbul-lib-report": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/js-string-escape": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
+            "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
+            "engines": {
+                "node": ">= 0.8"
+            }
+        },
+        "node_modules/jsonc-parser": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
+            "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
+        },
+        "node_modules/local-pkg": {
+            "version": "0.4.3",
+            "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz",
+            "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/antfu"
+            }
+        },
+        "node_modules/lodash": {
+            "version": "4.17.21",
+            "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+            "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+        },
+        "node_modules/loupe": {
+            "version": "2.3.6",
+            "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
+            "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
+            "dependencies": {
+                "get-func-name": "^2.0.0"
+            }
+        },
+        "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==",
+            "dependencies": {
+                "yallist": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/magic-string": {
+            "version": "0.30.0",
+            "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
+            "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==",
+            "dependencies": {
+                "@jridgewell/sourcemap-codec": "^1.4.13"
+            },
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/make-dir": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+            "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+            "dev": true,
+            "dependencies": {
+                "semver": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/make-dir/node_modules/semver": {
+            "version": "6.3.0",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+            "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+            "dev": true,
+            "bin": {
+                "semver": "bin/semver.js"
+            }
+        },
         "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/md5-hex": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz",
+            "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==",
+            "dependencies": {
+                "blueimp-md5": "^2.10.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "dev": true,
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/mlly": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz",
+            "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==",
+            "dependencies": {
+                "acorn": "^8.8.2",
+                "pathe": "^1.1.0",
+                "pkg-types": "^1.0.3",
+                "ufo": "^1.1.2"
+            }
+        },
+        "node_modules/ms": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+        },
+        "node_modules/nanoid": {
+            "version": "3.3.6",
+            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+            "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/ai"
+                }
+            ],
+            "bin": {
+                "nanoid": "bin/nanoid.cjs"
+            },
+            "engines": {
+                "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+            }
+        },
         "node_modules/nonenumerable": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/nonenumerable/-/nonenumerable-1.1.1.tgz",
             "integrity": "sha512-ptUD9w9D8WqW6fuJJkZNCImkf+0vdbgUTbRK3i7jsy3olqtH96hYE6Q/S3Tx9NWbcB/ocAjYshXCAUP0lZ9B4Q=="
         },
+        "node_modules/once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+            "dev": true,
+            "dependencies": {
+                "wrappy": "1"
+            }
+        },
+        "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==",
+            "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/path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/pathe": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz",
+            "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q=="
+        },
+        "node_modules/pathval": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+            "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/picocolors": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+            "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+        },
+        "node_modules/pkg-types": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
+            "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==",
+            "dependencies": {
+                "jsonc-parser": "^3.2.0",
+                "mlly": "^1.2.0",
+                "pathe": "^1.1.0"
+            }
+        },
+        "node_modules/postcss": {
+            "version": "8.4.24",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz",
+            "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==",
+            "funding": [
+                {
+                    "type": "opencollective",
+                    "url": "https://opencollective.com/postcss/"
+                },
+                {
+                    "type": "tidelift",
+                    "url": "https://tidelift.com/funding/github/npm/postcss"
+                },
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/ai"
+                }
+            ],
+            "dependencies": {
+                "nanoid": "^3.3.6",
+                "picocolors": "^1.0.0",
+                "source-map-js": "^1.0.2"
+            },
+            "engines": {
+                "node": "^10 || ^12 || >=14"
+            }
+        },
+        "node_modules/pretty-format": {
+            "version": "27.5.1",
+            "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+            "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+            "dependencies": {
+                "ansi-regex": "^5.0.1",
+                "ansi-styles": "^5.0.0",
+                "react-is": "^17.0.1"
+            },
+            "engines": {
+                "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+            }
+        },
+        "node_modules/react-is": {
+            "version": "17.0.2",
+            "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+            "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
+        },
+        "node_modules/rollup": {
+            "version": "3.25.1",
+            "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz",
+            "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==",
+            "bin": {
+                "rollup": "dist/bin/rollup"
+            },
+            "engines": {
+                "node": ">=14.18.0",
+                "npm": ">=8.0.0"
+            },
+            "optionalDependencies": {
+                "fsevents": "~2.3.2"
+            }
+        },
+        "node_modules/semver": {
+            "version": "7.5.2",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+            "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
+            "dependencies": {
+                "lru-cache": "^6.0.0"
+            },
+            "bin": {
+                "semver": "bin/semver.js"
+            },
+            "engines": {
+                "node": ">=10"
+            }
+        },
+        "node_modules/siginfo": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+            "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="
+        },
+        "node_modules/source-map": {
+            "version": "0.6.1",
+            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+            "dev": true,
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/source-map-js": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+            "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/stackback": {
+            "version": "0.0.2",
+            "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+            "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="
+        },
+        "node_modules/std-env": {
+            "version": "3.3.3",
+            "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz",
+            "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg=="
+        },
+        "node_modules/strip-literal": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz",
+            "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==",
+            "dependencies": {
+                "acorn": "^8.8.2"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/antfu"
+            }
+        },
+        "node_modules/supports-color": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+            "dev": true,
+            "dependencies": {
+                "has-flag": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/test-exclude": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+            "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+            "dev": true,
+            "dependencies": {
+                "@istanbuljs/schema": "^0.1.2",
+                "glob": "^7.1.4",
+                "minimatch": "^3.0.4"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/time-zone": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz",
+            "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/tinybench": {
+            "version": "2.5.0",
+            "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz",
+            "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA=="
+        },
+        "node_modules/tinypool": {
+            "version": "0.5.0",
+            "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz",
+            "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==",
+            "engines": {
+                "node": ">=14.0.0"
+            }
+        },
+        "node_modules/tinyspy": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz",
+            "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==",
+            "engines": {
+                "node": ">=14.0.0"
+            }
+        },
         "node_modules/toml": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",

styles/package.json 🔗

@@ -6,7 +6,8 @@
     "scripts": {
         "build": "ts-node ./src/buildThemes.ts",
         "build-licenses": "ts-node ./src/buildLicenses.ts",
-        "build-tokens": "ts-node ./src/buildTokens.ts"
+        "build-tokens": "ts-node ./src/buildTokens.ts",
+        "test": "vitest"
     },
     "author": "",
     "license": "ISC",
@@ -22,12 +23,16 @@
         "toml": "^3.0.0",
         "ts-deepmerge": "^6.0.3",
         "ts-node": "^10.9.1",
-        "utility-types": "^3.10.0"
+        "utility-types": "^3.10.0",
+        "vitest": "^0.32.0"
     },
     "prettier": {
         "semi": false,
         "printWidth": 80,
         "htmlWhitespaceSensitivity": "strict",
         "tabWidth": 4
+    },
+    "devDependencies": {
+        "@vitest/coverage-v8": "^0.32.0"
     }
 }

styles/src/element/interactive/interactive.test.ts 🔗

@@ -0,0 +1,59 @@
+import { NOT_ENOUGH_STATES_ERROR, NO_DEFAULT_OR_BASE_ERROR, interactive } from './interactive'
+import { describe, it, expect } from 'vitest'
+
+describe('interactive', () => {
+
+    it('creates an Interactive<Element> with base properties and states', () => {
+
+        const result = interactive({
+            base: { fontSize: 10, color: '#FFFFFF' },
+            state: {
+                hovered: { color: '#EEEEEE' },
+                clicked: { color: '#CCCCCC' },
+            }
+        })
+
+        expect(result).toEqual({
+            default: { color: '#FFFFFF', fontSize: 10 },
+            hovered: { color: '#EEEEEE', fontSize: 10 },
+            clicked: { color: '#CCCCCC', fontSize: 10 },
+        })
+    })
+
+    it('creates an Interactive<Element> with no base properties', () => {
+
+        const result = interactive({
+            state: {
+                default: { color: '#FFFFFF', fontSize: 10 },
+                hovered: { color: '#EEEEEE' },
+                clicked: { color: '#CCCCCC' },
+            }
+        })
+
+        expect(result).toEqual({
+            default: { color: '#FFFFFF', fontSize: 10 },
+            hovered: { color: '#EEEEEE', fontSize: 10 },
+            clicked: { color: '#CCCCCC', fontSize: 10 },
+        })
+    })
+
+    it('throws error when both default and base are missing', () => {
+        const state = {
+            hovered: { color: 'blue' },
+        }
+
+        expect(() => interactive({ state })).toThrow(
+            NO_DEFAULT_OR_BASE_ERROR
+        )
+    })
+
+    it('throws error when no other state besides default is present', () => {
+        const state = {
+            default: { fontSize: 10 },
+        }
+
+        expect(() => interactive({ state })).toThrow(
+            NOT_ENOUGH_STATES_ERROR
+        )
+    })
+})

styles/src/styleTree/interactive.ts → styles/src/element/interactive/interactive.ts 🔗

@@ -10,24 +10,27 @@ type Interactive<T> = {
     disabled?: T,
 };
 
+export const NO_DEFAULT_OR_BASE_ERROR = "An interactive object must have a default state, or a base property."
+export const NOT_ENOUGH_STATES_ERROR = "An interactive object must have a default and at least one other state."
+
 interface InteractiveProps<T> {
     base?: T,
     state: Partial<Record<InteractiveState, T>>
 }
 
 /**
- * Helper function for creating Interactive<T> objects that works pretty much like Toggle<T>.
- * It takes a object to be used as a value for `default` field and then fills out other fields
- * with fields from either `base` or `modifications`.
- * Notably, it does not touch `hover`, `clicked` and `disabled` if there are no modifications for it.
+ * Helper function for creating Interactive<T> objects that works with Toggle<T>-like behavior.
+ * It takes a default object to be used as the value for `default` field and fills out other fields
+ * with fields from either `base` or from the `state` object which contains values for specific states.
+ * Notably, it does not touch `hover`, `clicked`, `selected` and `disabled` states if there are no modifications for them.
  *
- * @param defaultObj Object to be used as the value for `default` field.
- * @param base Object containing base fields to be included in the resulting object.
- * @param modifications Object containing modified fields to be included in the resulting object.
- * @returns Interactive<T> object with fields from `base` and `modifications`.
+ * @param defaultObj Object to be used as the value for the `default` field.
+ * @param base Optional object containing base fields to be included in the resulting object.
+ * @param state Object containing optional modified fields to be included in the resulting object for each state.
+ * @returns Interactive<T> object with fields from `base` and `state`.
  */
 export function interactive<T extends Object>({ base, state }: InteractiveProps<T>): Interactive<T> {
-    if (!base && !state.default) throw new Error("An interactive object must have a default state, or a base property.");
+    if (!base && !state.default) throw new Error(NO_DEFAULT_OR_BASE_ERROR);
 
     let defaultState: T;
 
@@ -64,7 +67,7 @@ export function interactive<T extends Object>({ base, state }: InteractiveProps<
     }
 
     if (stateCount < 1) {
-        throw new Error("An interactive object must have a default and at least one other state.");
+        throw new Error(NOT_ENOUGH_STATES_ERROR);
     }
 
     return interactiveObj;

styles/src/styleTree/assistant.ts 🔗

@@ -1,94 +1,94 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { text, border, background, foreground } from "./components"
 import editor from "./editor"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function assistant(colorScheme: ColorScheme) {
-  const layer = colorScheme.highest
-  return {
-    container: {
-      background: editor(colorScheme).background,
-      padding: { left: 12 },
-    },
-    header: {
-      border: border(layer, "default", { bottom: true, top: true }),
-      margin: { bottom: 6, top: 6 },
-      background: editor(colorScheme).background,
-    },
-    userSender: {
-      default:
-        { ...text(layer, "sans", "default", { size: "sm", weight: "bold" }) },
-    },
-    assistantSender: {
-      default: {
-        ...text(layer, "sans", "accent", { size: "sm", weight: "bold" })
-      },
-    },
-    systemSender: {
-      default: {
-        ...text(layer, "sans", "variant", { size: "sm", weight: "bold" })
-      },
-    },
-    sentAt: {
-      margin: { top: 2, left: 8 },
-      ...text(layer, "sans", "default", { size: "2xs" }),
-    },
-    modelInfoContainer: {
-      margin: { right: 16, top: 4 },
-    },
-    model: interactive({
-      base: {
-        background: background(layer, "on"),
-        border: border(layer, "on", { overlay: true }),
-        padding: 4,
-        cornerRadius: 4,
-        ...text(layer, "sans", "default", { size: "xs" }),
-      }, state: {
-        hovered: {
-          background: background(layer, "on", "hovered"),
-        }
-      }
-    }),
-    remainingTokens: {
-      background: background(layer, "on"),
-      border: border(layer, "on", { overlay: true }),
-      padding: 4,
-      margin: { left: 4 },
-      cornerRadius: 4,
-      ...text(layer, "sans", "positive", { size: "xs" }),
-    },
-    noRemainingTokens: {
-      background: background(layer, "on"),
-      border: border(layer, "on", { overlay: true }),
-      padding: 4,
-      margin: { left: 4 },
-      cornerRadius: 4,
-      ...text(layer, "sans", "negative", { size: "xs" }),
-    },
-    errorIcon: {
-      margin: { left: 8 },
-      color: foreground(layer, "negative"),
-      width: 12,
-    },
-    apiKeyEditor: {
-      background: background(layer, "on"),
-      cornerRadius: 6,
-      text: text(layer, "mono", "on"),
-      placeholderText: text(layer, "mono", "on", "disabled", {
-        size: "xs",
-      }),
-      selection: colorScheme.players[0],
-      border: border(layer, "on"),
-      padding: {
-        bottom: 4,
-        left: 8,
-        right: 8,
-        top: 4,
-      },
-    },
-    apiKeyPrompt: {
-      padding: 10,
-      ...text(layer, "sans", "default", { size: "xs" }),
-    },
-  }
+    const layer = colorScheme.highest
+    return {
+        container: {
+            background: editor(colorScheme).background,
+            padding: { left: 12 },
+        },
+        header: {
+            border: border(layer, "default", { bottom: true, top: true }),
+            margin: { bottom: 6, top: 6 },
+            background: editor(colorScheme).background,
+        },
+        userSender: {
+            default:
+                { ...text(layer, "sans", "default", { size: "sm", weight: "bold" }) },
+        },
+        assistantSender: {
+            default: {
+                ...text(layer, "sans", "accent", { size: "sm", weight: "bold" })
+            },
+        },
+        systemSender: {
+            default: {
+                ...text(layer, "sans", "variant", { size: "sm", weight: "bold" })
+            },
+        },
+        sentAt: {
+            margin: { top: 2, left: 8 },
+            ...text(layer, "sans", "default", { size: "2xs" }),
+        },
+        modelInfoContainer: {
+            margin: { right: 16, top: 4 },
+        },
+        model: interactive({
+            base: {
+                background: background(layer, "on"),
+                border: border(layer, "on", { overlay: true }),
+                padding: 4,
+                cornerRadius: 4,
+                ...text(layer, "sans", "default", { size: "xs" }),
+            }, state: {
+                hovered: {
+                    background: background(layer, "on", "hovered"),
+                }
+            }
+        }),
+        remainingTokens: {
+            background: background(layer, "on"),
+            border: border(layer, "on", { overlay: true }),
+            padding: 4,
+            margin: { left: 4 },
+            cornerRadius: 4,
+            ...text(layer, "sans", "positive", { size: "xs" }),
+        },
+        noRemainingTokens: {
+            background: background(layer, "on"),
+            border: border(layer, "on", { overlay: true }),
+            padding: 4,
+            margin: { left: 4 },
+            cornerRadius: 4,
+            ...text(layer, "sans", "negative", { size: "xs" }),
+        },
+        errorIcon: {
+            margin: { left: 8 },
+            color: foreground(layer, "negative"),
+            width: 12,
+        },
+        apiKeyEditor: {
+            background: background(layer, "on"),
+            cornerRadius: 6,
+            text: text(layer, "mono", "on"),
+            placeholderText: text(layer, "mono", "on", "disabled", {
+                size: "xs",
+            }),
+            selection: colorScheme.players[0],
+            border: border(layer, "on"),
+            padding: {
+                bottom: 4,
+                left: 8,
+                right: 8,
+                top: 4,
+            },
+        },
+        apiKeyPrompt: {
+            padding: 10,
+            ...text(layer, "sans", "default", { size: "xs" }),
+        },
+    }
 }

styles/src/styleTree/commandPalette.ts 🔗

@@ -2,38 +2,38 @@ import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { text, background } from "./components"
 import { toggleable } from "./toggle"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function commandPalette(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest
-  return {
-    keystrokeSpacing: 8,
-    key:
-      toggleable(interactive({
-        base: {
-          text: text(layer, "mono", "variant", "default", { size: "xs" }),
-          cornerRadius: 2,
-          background: background(layer, "on"),
-          padding: {
-            top: 1,
-            bottom: 1,
-            left: 6,
-            right: 6,
-          },
-          margin: {
-            top: 1,
-            bottom: 1,
-            left: 2,
-          },
-        }, state: { hovered: { cornerRadius: 4, padding: { top: 17 } } }
-      }), {
-        default: {
-          text: text(layer, "mono", "on", "default", { size: "xs" }),
-          background: withOpacity(background(layer, "on"), 0.2),
-        }
+    let layer = colorScheme.highest
+    return {
+        keystrokeSpacing: 8,
+        key:
+            toggleable(interactive({
+                base: {
+                    text: text(layer, "mono", "variant", "default", { size: "xs" }),
+                    cornerRadius: 2,
+                    background: background(layer, "on"),
+                    padding: {
+                        top: 1,
+                        bottom: 1,
+                        left: 6,
+                        right: 6,
+                    },
+                    margin: {
+                        top: 1,
+                        bottom: 1,
+                        left: 2,
+                    },
+                }, state: { hovered: { cornerRadius: 4, padding: { top: 17 } } }
+            }), {
+                default: {
+                    text: text(layer, "mono", "on", "default", { size: "xs" }),
+                    background: withOpacity(background(layer, "on"), 0.2),
+                }
 
-      })
-    ,
+            })
+        ,
 
-  }
+    }
 }

styles/src/styleTree/contactList.ts 🔗

@@ -1,218 +1,218 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, borderColor, foreground, text } from "./components"
 import { toggleable } from "./toggle"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 export default function contactsPanel(colorScheme: ColorScheme) {
-  const nameMargin = 8
-  const sidePadding = 12
+    const nameMargin = 8
+    const sidePadding = 12
 
-  let layer = colorScheme.middle
+    let layer = colorScheme.middle
 
-  const contactButton = {
-    background: background(layer, "on"),
-    color: foreground(layer, "on"),
-    iconWidth: 8,
-    buttonWidth: 16,
-    cornerRadius: 8,
-  }
-  const projectRow = {
-    guestAvatarSpacing: 4,
-    height: 24,
-    guestAvatar: {
-      cornerRadius: 8,
-      width: 14,
-    },
-    name: {
-      ...text(layer, "mono", { size: "sm" }),
-      margin: {
-        left: nameMargin,
-        right: 6,
-      },
-    },
-    guests: {
-      margin: {
-        left: nameMargin,
-        right: nameMargin,
-      },
-    },
-    padding: {
-      left: sidePadding,
-      right: sidePadding,
-    },
-  }
-
-  return {
-    background: background(layer),
-    padding: { top: 12 },
-    userQueryEditor: {
-      background: background(layer, "on"),
-      cornerRadius: 6,
-      text: text(layer, "mono", "on"),
-      placeholderText: text(layer, "mono", "on", "disabled", {
-        size: "xs",
-      }),
-      selection: colorScheme.players[0],
-      border: border(layer, "on"),
-      padding: {
-        bottom: 4,
-        left: 8,
-        right: 8,
-        top: 4,
-      },
-      margin: {
-        left: 6,
-      },
-    },
-    userQueryEditorHeight: 33,
-    addContactButton: {
-      margin: { left: 6, right: 12 },
-      color: foreground(layer, "on"),
-      buttonWidth: 28,
-      iconWidth: 16,
-    },
-    rowHeight: 28,
-    sectionIconSize: 8,
-    headerRow: toggleable(interactive({
-      base: {
-        ...text(layer, "mono", { size: "sm" }),
-        margin: { top: 14 },
-        padding: {
-          left: sidePadding,
-          right: sidePadding,
+    const contactButton = {
+        background: background(layer, "on"),
+        color: foreground(layer, "on"),
+        iconWidth: 8,
+        buttonWidth: 16,
+        cornerRadius: 8,
+    }
+    const projectRow = {
+        guestAvatarSpacing: 4,
+        height: 24,
+        guestAvatar: {
+            cornerRadius: 8,
+            width: 14,
         },
-        background: background(layer, "default"),// posiewic: breaking change
-      }
-      , state: { hovered: { background: background(layer, "default") } } // hack, we want headerRow to be interactive for whatever reason. It probably shouldn't be interactive in the first place.
-    }),
-      {
-        default: {
-          ...text(layer, "mono", "active", { size: "sm" }),
-          background: background(layer, "active"),
+        name: {
+            ...text(layer, "mono", { size: "sm" }),
+            margin: {
+                left: nameMargin,
+                right: 6,
+            },
         },
-      }),
-    leaveCall: interactive({
-      base: {
-        background: background(layer),
-        border: border(layer),
-        cornerRadius: 6,
-        margin: {
-          top: 1,
+        guests: {
+            margin: {
+                left: nameMargin,
+                right: nameMargin,
+            },
         },
         padding: {
-          top: 1,
-          bottom: 1,
-          left: 7,
-          right: 7,
-        },
-        ...text(layer, "sans", "variant", { size: "xs" }),
-      }
-      ,
-      state: {
-        hovered: {
-          ...text(layer, "sans", "hovered", { size: "xs" }),
-          background: background(layer, "hovered"),
-          border: border(layer, "hovered"),
-        }
-      }
-    }
-    ),
-    contactRow: {
-      inactive: {
-        default: {
-          padding: {
             left: sidePadding,
             right: sidePadding,
-          }
         },
-      },
-      active: {
-        default: {
-          background: background(layer, "active"),
-          padding: {
-            left: sidePadding,
-            right: sidePadding,
-          }
+    }
+
+    return {
+        background: background(layer),
+        padding: { top: 12 },
+        userQueryEditor: {
+            background: background(layer, "on"),
+            cornerRadius: 6,
+            text: text(layer, "mono", "on"),
+            placeholderText: text(layer, "mono", "on", "disabled", {
+                size: "xs",
+            }),
+            selection: colorScheme.players[0],
+            border: border(layer, "on"),
+            padding: {
+                bottom: 4,
+                left: 8,
+                right: 8,
+                top: 4,
+            },
+            margin: {
+                left: 6,
+            },
+        },
+        userQueryEditorHeight: 33,
+        addContactButton: {
+            margin: { left: 6, right: 12 },
+            color: foreground(layer, "on"),
+            buttonWidth: 28,
+            iconWidth: 16,
+        },
+        rowHeight: 28,
+        sectionIconSize: 8,
+        headerRow: toggleable(interactive({
+            base: {
+                ...text(layer, "mono", { size: "sm" }),
+                margin: { top: 14 },
+                padding: {
+                    left: sidePadding,
+                    right: sidePadding,
+                },
+                background: background(layer, "default"),// posiewic: breaking change
+            }
+            , state: { hovered: { background: background(layer, "default") } } // hack, we want headerRow to be interactive for whatever reason. It probably shouldn't be interactive in the first place.
+        }),
+            {
+                default: {
+                    ...text(layer, "mono", "active", { size: "sm" }),
+                    background: background(layer, "active"),
+                },
+            }),
+        leaveCall: interactive({
+            base: {
+                background: background(layer),
+                border: border(layer),
+                cornerRadius: 6,
+                margin: {
+                    top: 1,
+                },
+                padding: {
+                    top: 1,
+                    bottom: 1,
+                    left: 7,
+                    right: 7,
+                },
+                ...text(layer, "sans", "variant", { size: "xs" }),
+            }
+            ,
+            state: {
+                hovered: {
+                    ...text(layer, "sans", "hovered", { size: "xs" }),
+                    background: background(layer, "hovered"),
+                    border: border(layer, "hovered"),
+                }
+            }
         }
-      },
-    },
+        ),
+        contactRow: {
+            inactive: {
+                default: {
+                    padding: {
+                        left: sidePadding,
+                        right: sidePadding,
+                    }
+                },
+            },
+            active: {
+                default: {
+                    background: background(layer, "active"),
+                    padding: {
+                        left: sidePadding,
+                        right: sidePadding,
+                    }
+                }
+            },
+        },
 
-    contactAvatar: {
-      cornerRadius: 10,
-      width: 18,
-    },
-    contactStatusFree: {
-      cornerRadius: 4,
-      padding: 4,
-      margin: { top: 12, left: 12 },
-      background: foreground(layer, "positive"),
-    },
-    contactStatusBusy: {
-      cornerRadius: 4,
-      padding: 4,
-      margin: { top: 12, left: 12 },
-      background: foreground(layer, "negative"),
-    },
-    contactUsername: {
-      ...text(layer, "mono", { size: "sm" }),
-      margin: {
-        left: nameMargin,
-      },
-    },
-    contactButtonSpacing: nameMargin,
-    contactButton: interactive({
-      base: { ...contactButton },
-      state: {
-        hovered: {
-          background: background(layer, "hovered"),
+        contactAvatar: {
+            cornerRadius: 10,
+            width: 18,
         },
-      }
-    }),
-    disabledButton: {
-      ...contactButton,
-      background: background(layer, "on"),
-      color: foreground(layer, "on"),
-    },
-    callingIndicator: {
-      ...text(layer, "mono", "variant", { size: "xs" }),
-    },
-    treeBranch: toggleable(interactive({
-      base: {
-        color: borderColor(layer),
-        width: 1,
-      },
-      state: {
-        hovered: {
-          color: borderColor(layer),
+        contactStatusFree: {
+            cornerRadius: 4,
+            padding: 4,
+            margin: { top: 12, left: 12 },
+            background: foreground(layer, "positive"),
         },
-      }
-    }),
-      {
-        default: {
-          color: borderColor(layer),
+        contactStatusBusy: {
+            cornerRadius: 4,
+            padding: 4,
+            margin: { top: 12, left: 12 },
+            background: foreground(layer, "negative"),
         },
-      }
-    ),
-    projectRow: toggleable(interactive({
-      base: {
-        ...projectRow,
-        background: background(layer),
-        icon: {
-          margin: { left: nameMargin },
-          color: foreground(layer, "variant"),
-          width: 12,
+        contactUsername: {
+            ...text(layer, "mono", { size: "sm" }),
+            margin: {
+                left: nameMargin,
+            },
         },
-        name: {
-          ...projectRow.name,
-          ...text(layer, "mono", { size: "sm" }),
+        contactButtonSpacing: nameMargin,
+        contactButton: interactive({
+            base: { ...contactButton },
+            state: {
+                hovered: {
+                    background: background(layer, "hovered"),
+                },
+            }
+        }),
+        disabledButton: {
+            ...contactButton,
+            background: background(layer, "on"),
+            color: foreground(layer, "on"),
         },
-      }, state: {
-        hovered: {
-          background: background(layer, "hovered"),
+        callingIndicator: {
+            ...text(layer, "mono", "variant", { size: "xs" }),
         },
-      }
-    }),
-      {
-        default: { background: background(layer, "active") }
-      })
-  }
+        treeBranch: toggleable(interactive({
+            base: {
+                color: borderColor(layer),
+                width: 1,
+            },
+            state: {
+                hovered: {
+                    color: borderColor(layer),
+                },
+            }
+        }),
+            {
+                default: {
+                    color: borderColor(layer),
+                },
+            }
+        ),
+        projectRow: toggleable(interactive({
+            base: {
+                ...projectRow,
+                background: background(layer),
+                icon: {
+                    margin: { left: nameMargin },
+                    color: foreground(layer, "variant"),
+                    width: 12,
+                },
+                name: {
+                    ...projectRow.name,
+                    ...text(layer, "mono", { size: "sm" }),
+                },
+            }, state: {
+                hovered: {
+                    background: background(layer, "hovered"),
+                },
+            }
+        }),
+            {
+                default: { background: background(layer, "active") }
+            })
+    }
 }

styles/src/styleTree/contactNotification.ts 🔗

@@ -1,54 +1,54 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 const avatarSize = 12
 const headerPadding = 8
 
 export default function contactNotification(colorScheme: ColorScheme): Object {
-  let layer = colorScheme.lowest
-  return {
-    headerAvatar: {
-      height: avatarSize,
-      width: avatarSize,
-      cornerRadius: 6,
-    },
-    headerMessage: {
-      ...text(layer, "sans", { size: "xs" }),
-      margin: { left: headerPadding, right: headerPadding },
-    },
-    headerHeight: 18,
-    bodyMessage: {
-      ...text(layer, "sans", { size: "xs" }),
-      margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
-    },
-    button:
-      interactive({
-        base: {
-          ...text(layer, "sans", "on", { size: "xs" }),
-          background: background(layer, "on"),
-          padding: 4,
-          cornerRadius: 6,
-          margin: { left: 6 }
+    let layer = colorScheme.lowest
+    return {
+        headerAvatar: {
+            height: avatarSize,
+            width: avatarSize,
+            cornerRadius: 6,
         },
+        headerMessage: {
+            ...text(layer, "sans", { size: "xs" }),
+            margin: { left: headerPadding, right: headerPadding },
+        },
+        headerHeight: 18,
+        bodyMessage: {
+            ...text(layer, "sans", { size: "xs" }),
+            margin: { left: avatarSize + headerPadding, top: 6, bottom: 6 },
+        },
+        button:
+            interactive({
+                base: {
+                    ...text(layer, "sans", "on", { size: "xs" }),
+                    background: background(layer, "on"),
+                    padding: 4,
+                    cornerRadius: 6,
+                    margin: { left: 6 }
+                },
 
-        state: {
-          hovered: {
-            background: background(layer, "on", "hovered"),
-          }
-        }
-      }),
+                state: {
+                    hovered: {
+                        background: background(layer, "on", "hovered"),
+                    }
+                }
+            }),
 
-    dismissButton: {
-      default: {
-        color: foreground(layer, "variant"),
-        iconWidth: 8,
-        iconHeight: 8,
-        buttonWidth: 8,
-        buttonHeight: 8,
-        hover: {
-          color: foreground(layer, "hovered"),
+        dismissButton: {
+            default: {
+                color: foreground(layer, "variant"),
+                iconWidth: 8,
+                iconHeight: 8,
+                buttonWidth: 8,
+                buttonHeight: 8,
+                hover: {
+                    color: foreground(layer, "hovered"),
+                },
+            }
         },
-      }
-    },
-  }
+    }
 }

styles/src/styleTree/contextMenu.ts 🔗

@@ -1,56 +1,56 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, borderColor, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 
 export default function contextMenu(colorScheme: ColorScheme) {
-  let layer = colorScheme.middle
-  return {
-    background: background(layer),
-    cornerRadius: 10,
-    padding: 4,
-    shadow: colorScheme.popoverShadow,
-    border: border(layer),
-    keystrokeMargin: 30,
-    item: toggleable(interactive({
-      base: {
-        iconSpacing: 8,
-        iconWidth: 14,
-        padding: { left: 6, right: 6, top: 2, bottom: 2 },
-        cornerRadius: 6,
-        label: text(layer, "sans", { size: "sm" }),
-        keystroke: {
-          ...text(layer, "sans", "variant", {
-            size: "sm",
-            weight: "bold",
-          }),
-          padding: { left: 3, right: 3 },
-        }
-      }, state: {
-        hovered: {
-          background: background(layer, "hovered"),
-          label: text(layer, "sans", "hovered", { size: "sm" }),
-          keystroke: {
-            ...text(layer, "sans", "hovered", {
-              size: "sm",
-              weight: "bold",
-            }),
-            padding: { left: 3, right: 3 },
-          },
-        }
-      }
-    }), {
-      default: {
-        background: background(layer, "active"),
-      },
-      hovered: {
-        background: background(layer, "active"),
-      },
-    }),
+    let layer = colorScheme.middle
+    return {
+        background: background(layer),
+        cornerRadius: 10,
+        padding: 4,
+        shadow: colorScheme.popoverShadow,
+        border: border(layer),
+        keystrokeMargin: 30,
+        item: toggleable(interactive({
+            base: {
+                iconSpacing: 8,
+                iconWidth: 14,
+                padding: { left: 6, right: 6, top: 2, bottom: 2 },
+                cornerRadius: 6,
+                label: text(layer, "sans", { size: "sm" }),
+                keystroke: {
+                    ...text(layer, "sans", "variant", {
+                        size: "sm",
+                        weight: "bold",
+                    }),
+                    padding: { left: 3, right: 3 },
+                }
+            }, state: {
+                hovered: {
+                    background: background(layer, "hovered"),
+                    label: text(layer, "sans", "hovered", { size: "sm" }),
+                    keystroke: {
+                        ...text(layer, "sans", "hovered", {
+                            size: "sm",
+                            weight: "bold",
+                        }),
+                        padding: { left: 3, right: 3 },
+                    },
+                }
+            }
+        }), {
+            default: {
+                background: background(layer, "active"),
+            },
+            hovered: {
+                background: background(layer, "active"),
+            },
+        }),
 
-    separator: {
-      background: borderColor(layer),
-      margin: { top: 2, bottom: 2 },
-    },
-  }
+        separator: {
+            background: borderColor(layer),
+            margin: { top: 2, bottom: 2 },
+        },
+    }
 }

styles/src/styleTree/copilot.ts 🔗

@@ -1,286 +1,286 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, foreground, svg, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 export default function copilot(colorScheme: ColorScheme) {
-  let layer = colorScheme.middle
+    let layer = colorScheme.middle
 
-  let content_width = 264
+    let content_width = 264
 
-  let ctaButton =
-    // Copied from welcome screen. FIXME: Move this into a ZDS component
-    interactive({
-      base: {
-        background: background(layer),
-        border: border(layer, "default"),
-        cornerRadius: 4,
-        margin: {
-          top: 4,
-          bottom: 4,
-          left: 8,
-          right: 8,
-        },
-        padding: {
-          top: 3,
-          bottom: 3,
-          left: 7,
-          right: 7,
-        },
-        ...text(layer, "sans", "default", { size: "sm" })
-      },
-      state: {
-        hovered: {
-          ...text(layer, "sans", "default", { size: "sm" }),
-          background: background(layer, "hovered"),
-          border: border(layer, "active"),
-        },
-      }
-    });
-
-  return {
-    outLinkIcon:
-      interactive({
-        base: {
-          icon: svg(
-            foreground(layer, "variant"),
-            "icons/link_out_12.svg",
-            12,
-            12
-          ),
-          container: {
-            cornerRadius: 6,
-            padding: { left: 6 },
-          },
-        },
-        state: {
-          hovered: {
-            icon: {
-              color:
-                foreground(layer, "hovered")
+    let ctaButton =
+        // Copied from welcome screen. FIXME: Move this into a ZDS component
+        interactive({
+            base: {
+                background: background(layer),
+                border: border(layer, "default"),
+                cornerRadius: 4,
+                margin: {
+                    top: 4,
+                    bottom: 4,
+                    left: 8,
+                    right: 8,
+                },
+                padding: {
+                    top: 3,
+                    bottom: 3,
+                    left: 7,
+                    right: 7,
+                },
+                ...text(layer, "sans", "default", { size: "sm" })
+            },
+            state: {
+                hovered: {
+                    ...text(layer, "sans", "default", { size: "sm" }),
+                    background: background(layer, "hovered"),
+                    border: border(layer, "active"),
+                },
             }
-          },
-        }
-      }),
+        });
 
-    modal: {
-      titleText: {
-        default: {
-          ...text(layer, "sans", { size: "xs", weight: "bold" })
-        }
-      },
-      titlebar: {
-        background: background(colorScheme.lowest),
-        border: border(layer, "active"),
-        padding: {
-          top: 4,
-          bottom: 4,
-          left: 8,
-          right: 8,
-        },
-      },
-      container: {
-        background: background(colorScheme.lowest),
-        padding: {
-          top: 0,
-          left: 0,
-          right: 0,
-          bottom: 8,
-        },
-      },
-      closeIcon: interactive({
-        base:
-        {
-          icon: svg(
-            foreground(layer, "variant"),
-            "icons/x_mark_8.svg",
-            8,
-            8
-          ),
-          container: {
-            cornerRadius: 2,
-            padding: {
-              top: 4,
-              bottom: 4,
-              left: 4,
-              right: 4,
+    return {
+        outLinkIcon:
+            interactive({
+                base: {
+                    icon: svg(
+                        foreground(layer, "variant"),
+                        "icons/link_out_12.svg",
+                        12,
+                        12
+                    ),
+                    container: {
+                        cornerRadius: 6,
+                        padding: { left: 6 },
+                    },
+                },
+                state: {
+                    hovered: {
+                        icon: {
+                            color:
+                                foreground(layer, "hovered")
+                        }
+                    },
+                }
+            }),
+
+        modal: {
+            titleText: {
+                default: {
+                    ...text(layer, "sans", { size: "xs", weight: "bold" })
+                }
             },
-            margin: {
-              right: 0,
+            titlebar: {
+                background: background(colorScheme.lowest),
+                border: border(layer, "active"),
+                padding: {
+                    top: 4,
+                    bottom: 4,
+                    left: 8,
+                    right: 8,
+                },
+            },
+            container: {
+                background: background(colorScheme.lowest),
+                padding: {
+                    top: 0,
+                    left: 0,
+                    right: 0,
+                    bottom: 8,
+                },
+            },
+            closeIcon: interactive({
+                base:
+                {
+                    icon: svg(
+                        foreground(layer, "variant"),
+                        "icons/x_mark_8.svg",
+                        8,
+                        8
+                    ),
+                    container: {
+                        cornerRadius: 2,
+                        padding: {
+                            top: 4,
+                            bottom: 4,
+                            left: 4,
+                            right: 4,
+                        },
+                        margin: {
+                            right: 0,
+                        },
+                    }
+                },
+                state: {
+                    hovered: {
+                        icon: svg(
+                            foreground(layer, "on"),
+                            "icons/x_mark_8.svg",
+                            8,
+                            8
+                        ),
+                    },
+                    clicked: {
+                        icon: svg(
+                            foreground(layer, "base"),
+                            "icons/x_mark_8.svg",
+                            8,
+                            8
+                        ),
+                    },
+                }
+            }),
+            dimensions: {
+                width: 280,
+                height: 280,
             },
-          }
         },
-        state: {
-          hovered: {
-            icon: svg(
-              foreground(layer, "on"),
-              "icons/x_mark_8.svg",
-              8,
-              8
-            ),
-          },
-          clicked: {
-            icon: svg(
-              foreground(layer, "base"),
-              "icons/x_mark_8.svg",
-              8,
-              8
-            ),
-          },
-        }
-      }),
-      dimensions: {
-        width: 280,
-        height: 280,
-      },
-    },
 
-    auth: {
-      content_width,
+        auth: {
+            content_width,
 
-      ctaButton,
+            ctaButton,
 
-      header: {
-        icon: svg(
-          foreground(layer, "default"),
-          "icons/zed_plus_copilot_32.svg",
-          92,
-          32
-        ),
-        container: {
-          margin: {
-            top: 35,
-            bottom: 5,
-            left: 0,
-            right: 0,
-          },
-        },
-      },
+            header: {
+                icon: svg(
+                    foreground(layer, "default"),
+                    "icons/zed_plus_copilot_32.svg",
+                    92,
+                    32
+                ),
+                container: {
+                    margin: {
+                        top: 35,
+                        bottom: 5,
+                        left: 0,
+                        right: 0,
+                    },
+                },
+            },
 
-      prompting: {
-        subheading: {
-          ...text(layer, "sans", { size: "xs" }),
-          margin: {
-            top: 6,
-            bottom: 12,
-            left: 0,
-            right: 0,
-          },
-        },
+            prompting: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
+                    margin: {
+                        top: 6,
+                        bottom: 12,
+                        left: 0,
+                        right: 0,
+                    },
+                },
 
-        hint: {
-          ...text(layer, "sans", { size: "xs", color: "#838994" }),
-          margin: {
-            top: 6,
-            bottom: 2,
-          },
-        },
+                hint: {
+                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
+                    margin: {
+                        top: 6,
+                        bottom: 2,
+                    },
+                },
 
-        deviceCode: {
-          text: text(layer, "mono", { size: "sm" }),
-          cta: {
-            ...ctaButton,
-            background: background(colorScheme.lowest),
-            border: border(colorScheme.lowest, "inverted"),
-            padding: {
-              top: 0,
-              bottom: 0,
-              left: 16,
-              right: 16,
-            },
-            margin: {
-              left: 16,
-              right: 16,
+                deviceCode: {
+                    text: text(layer, "mono", { size: "sm" }),
+                    cta: {
+                        ...ctaButton,
+                        background: background(colorScheme.lowest),
+                        border: border(colorScheme.lowest, "inverted"),
+                        padding: {
+                            top: 0,
+                            bottom: 0,
+                            left: 16,
+                            right: 16,
+                        },
+                        margin: {
+                            left: 16,
+                            right: 16,
+                        },
+                    },
+                    left: content_width / 2,
+                    leftContainer: {
+                        padding: {
+                            top: 3,
+                            bottom: 3,
+                            left: 0,
+                            right: 6,
+                        },
+                    },
+                    right: (content_width * 1) / 3,
+                    rightContainer: interactive({
+                        base: {
+                            border: border(colorScheme.lowest, "inverted", {
+                                bottom: false,
+                                right: false,
+                                top: false,
+                                left: true,
+                            }),
+                            padding: {
+                                top: 3,
+                                bottom: 5,
+                                left: 8,
+                                right: 0,
+                            }
+                        }, state: {
+                            hovered: {
+                                border: border(layer, "active", {
+                                    bottom: false,
+                                    right: false,
+                                    top: false,
+                                    left: true,
+                                }),
+                            },
+                        }
+                    })
+                },
             },
-          },
-          left: content_width / 2,
-          leftContainer: {
-            padding: {
-              top: 3,
-              bottom: 3,
-              left: 0,
-              right: 6,
-            },
-          },
-          right: (content_width * 1) / 3,
-          rightContainer: interactive({
-            base: {
-              border: border(colorScheme.lowest, "inverted", {
-                bottom: false,
-                right: false,
-                top: false,
-                left: true,
-              }),
-              padding: {
-                top: 3,
-                bottom: 5,
-                left: 8,
-                right: 0,
-              }
-            }, state: {
-              hovered: {
-                border: border(layer, "active", {
-                  bottom: false,
-                  right: false,
-                  top: false,
-                  left: true,
-                }),
-              },
-            }
-          })
-        },
-      },
 
-      notAuthorized: {
-        subheading: {
-          ...text(layer, "sans", { size: "xs" }),
+            notAuthorized: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
 
-          margin: {
-            top: 16,
-            bottom: 16,
-            left: 0,
-            right: 0,
-          },
-        },
+                    margin: {
+                        top: 16,
+                        bottom: 16,
+                        left: 0,
+                        right: 0,
+                    },
+                },
 
-        warning: {
-          ...text(layer, "sans", {
-            size: "xs",
-            color: foreground(layer, "warning"),
-          }),
-          border: border(layer, "warning"),
-          background: background(layer, "warning"),
-          cornerRadius: 2,
-          padding: {
-            top: 4,
-            left: 4,
-            bottom: 4,
-            right: 4,
-          },
-          margin: {
-            bottom: 16,
-            left: 8,
-            right: 8,
-          },
-        },
-      },
+                warning: {
+                    ...text(layer, "sans", {
+                        size: "xs",
+                        color: foreground(layer, "warning"),
+                    }),
+                    border: border(layer, "warning"),
+                    background: background(layer, "warning"),
+                    cornerRadius: 2,
+                    padding: {
+                        top: 4,
+                        left: 4,
+                        bottom: 4,
+                        right: 4,
+                    },
+                    margin: {
+                        bottom: 16,
+                        left: 8,
+                        right: 8,
+                    },
+                },
+            },
 
-      authorized: {
-        subheading: {
-          ...text(layer, "sans", { size: "xs" }),
+            authorized: {
+                subheading: {
+                    ...text(layer, "sans", { size: "xs" }),
 
-          margin: {
-            top: 16,
-            bottom: 16,
-          },
-        },
+                    margin: {
+                        top: 16,
+                        bottom: 16,
+                    },
+                },
 
-        hint: {
-          ...text(layer, "sans", { size: "xs", color: "#838994" }),
-          margin: {
-            top: 24,
-            bottom: 4,
-          },
+                hint: {
+                    ...text(layer, "sans", { size: "xs", color: "#838994" }),
+                    margin: {
+                        top: 24,
+                        bottom: 4,
+                    },
+                },
+            },
         },
-      },
-    },
-  }
+    }
 }

styles/src/styleTree/editor.ts 🔗

@@ -4,290 +4,290 @@ import { background, border, borderColor, foreground, text } from "./components"
 import hoverPopover from "./hoverPopover"
 
 import { buildSyntax } from "../theme/syntax"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 
 export default function editor(colorScheme: ColorScheme) {
-  const { isLight } = colorScheme
+    const { isLight } = colorScheme
 
-  let layer = colorScheme.highest
+    let layer = colorScheme.highest
 
-  const autocompleteItem = {
-    cornerRadius: 6,
-    padding: {
-      bottom: 2,
-      left: 6,
-      right: 6,
-      top: 2,
-    },
-  }
+    const autocompleteItem = {
+        cornerRadius: 6,
+        padding: {
+            bottom: 2,
+            left: 6,
+            right: 6,
+            top: 2,
+        },
+    }
 
-  function diagnostic(layer: Layer, styleSet: StyleSets) {
-    return {
-      textScaleFactor: 0.857,
-      header: {
-        border: border(layer, {
-          top: true,
-        }),
-      },
-      message: {
-        text: text(layer, "sans", styleSet, "default", { size: "sm" }),
-        highlightText: text(layer, "sans", styleSet, "default", {
-          size: "sm",
-          weight: "bold",
-        }),
-      },
+    function diagnostic(layer: Layer, styleSet: StyleSets) {
+        return {
+            textScaleFactor: 0.857,
+            header: {
+                border: border(layer, {
+                    top: true,
+                }),
+            },
+            message: {
+                text: text(layer, "sans", styleSet, "default", { size: "sm" }),
+                highlightText: text(layer, "sans", styleSet, "default", {
+                    size: "sm",
+                    weight: "bold",
+                }),
+            },
+        }
     }
-  }
 
-  const syntax = buildSyntax(colorScheme)
+    const syntax = buildSyntax(colorScheme)
 
-  return {
-    textColor: syntax.primary.color,
-    background: background(layer),
-    activeLineBackground: withOpacity(background(layer, "on"), 0.75),
-    highlightedLineBackground: background(layer, "on"),
-    // Inline autocomplete suggestions, Co-pilot suggestions, etc.
-    suggestion: syntax.predictive,
-    codeActions: {
-      indicator: toggleable(interactive({
-        base: {
-          color: foreground(layer, "variant"),
-        }, state: {
-          clicked: {
-            color: foreground(layer, "base"),
-          },
-          hovered: {
-            color: foreground(layer, "on"),
-          },
-        }
-      }),
-        {
-          default: {
-            color: foreground(layer, "on"),
-          }
-        }),
+    return {
+        textColor: syntax.primary.color,
+        background: background(layer),
+        activeLineBackground: withOpacity(background(layer, "on"), 0.75),
+        highlightedLineBackground: background(layer, "on"),
+        // Inline autocomplete suggestions, Co-pilot suggestions, etc.
+        suggestion: syntax.predictive,
+        codeActions: {
+            indicator: toggleable(interactive({
+                base: {
+                    color: foreground(layer, "variant"),
+                }, state: {
+                    clicked: {
+                        color: foreground(layer, "base"),
+                    },
+                    hovered: {
+                        color: foreground(layer, "on"),
+                    },
+                }
+            }),
+                {
+                    default: {
+                        color: foreground(layer, "on"),
+                    }
+                }),
 
-      verticalScale: 0.55,
-    },
-    folds: {
-      iconMarginScale: 2.5,
-      foldedIcon: "icons/chevron_right_8.svg",
-      foldableIcon: "icons/chevron_down_8.svg",
-      indicator: toggleable(interactive({
-        base: {
-          color: foreground(layer, "variant"),
-        }, state: {
-          clicked: {
-            color: foreground(layer, "base"),
-          },
-          hovered: {
-            color: foreground(layer, "on"),
-          },
-        }
-      }),
-        {
-          default: {
-            color: foreground(layer, "on"),
-          }
-        }),
-      ellipses: {
-        textColor: colorScheme.ramps.neutral(0.71).hex(),
-        cornerRadiusFactor: 0.15,
-        background: {
-          // Copied from hover_popover highlight
-          default: { color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex() },
+            verticalScale: 0.55,
+        },
+        folds: {
+            iconMarginScale: 2.5,
+            foldedIcon: "icons/chevron_right_8.svg",
+            foldableIcon: "icons/chevron_down_8.svg",
+            indicator: toggleable(interactive({
+                base: {
+                    color: foreground(layer, "variant"),
+                }, state: {
+                    clicked: {
+                        color: foreground(layer, "base"),
+                    },
+                    hovered: {
+                        color: foreground(layer, "on"),
+                    },
+                }
+            }),
+                {
+                    default: {
+                        color: foreground(layer, "on"),
+                    }
+                }),
+            ellipses: {
+                textColor: colorScheme.ramps.neutral(0.71).hex(),
+                cornerRadiusFactor: 0.15,
+                background: {
+                    // Copied from hover_popover highlight
+                    default: { color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex() },
 
-          hover: {
-            color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
-          },
+                    hover: {
+                        color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
+                    },
 
-          clicked: {
-            color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
-          },
+                    clicked: {
+                        color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
+                    },
+                },
+            },
+            foldBackground: foreground(layer, "variant"),
         },
-      },
-      foldBackground: foreground(layer, "variant"),
-    },
-    diff: {
-      deleted: isLight
-        ? colorScheme.ramps.red(0.5).hex()
-        : colorScheme.ramps.red(0.4).hex(),
-      modified: isLight
-        ? colorScheme.ramps.yellow(0.5).hex()
-        : colorScheme.ramps.yellow(0.5).hex(),
-      inserted: isLight
-        ? colorScheme.ramps.green(0.4).hex()
-        : colorScheme.ramps.green(0.5).hex(),
-      removedWidthEm: 0.275,
-      widthEm: 0.15,
-      cornerRadius: 0.05,
-    },
-    /** Highlights matching occurrences of what is under the cursor
-     * as well as matched brackets
-     */
-    documentHighlightReadBackground: withOpacity(
-      foreground(layer, "accent"),
-      0.1
-    ),
-    documentHighlightWriteBackground: colorScheme.ramps
-      .neutral(0.5)
-      .alpha(0.4)
-      .hex(), // TODO: This was blend * 2
-    errorColor: background(layer, "negative"),
-    gutterBackground: background(layer),
-    gutterPaddingFactor: 3.5,
-    lineNumber: withOpacity(foreground(layer), 0.35),
-    lineNumberActive: foreground(layer),
-    renameFade: 0.6,
-    unnecessaryCodeFade: 0.5,
-    selection: colorScheme.players[0],
-    whitespace: colorScheme.ramps.neutral(0.5).hex(),
-    guestSelections: [
-      colorScheme.players[1],
-      colorScheme.players[2],
-      colorScheme.players[3],
-      colorScheme.players[4],
-      colorScheme.players[5],
-      colorScheme.players[6],
-      colorScheme.players[7],
-    ],
-    autocomplete: {
-      background: background(colorScheme.middle),
-      cornerRadius: 8,
-      padding: 4,
-      margin: {
-        left: -14,
-      },
-      border: border(colorScheme.middle),
-      shadow: colorScheme.popoverShadow,
-      matchHighlight: foreground(colorScheme.middle, "accent"),
-      item: autocompleteItem,
-      hoveredItem: {
-        ...autocompleteItem,
-        matchHighlight: foreground(
-          colorScheme.middle,
-          "accent",
-          "hovered"
-        ),
-        background: background(colorScheme.middle, "hovered"),
-      },
-      selectedItem: {
-        ...autocompleteItem,
-        matchHighlight: foreground(
-          colorScheme.middle,
-          "accent",
-          "active"
+        diff: {
+            deleted: isLight
+                ? colorScheme.ramps.red(0.5).hex()
+                : colorScheme.ramps.red(0.4).hex(),
+            modified: isLight
+                ? colorScheme.ramps.yellow(0.5).hex()
+                : colorScheme.ramps.yellow(0.5).hex(),
+            inserted: isLight
+                ? colorScheme.ramps.green(0.4).hex()
+                : colorScheme.ramps.green(0.5).hex(),
+            removedWidthEm: 0.275,
+            widthEm: 0.15,
+            cornerRadius: 0.05,
+        },
+        /** Highlights matching occurrences of what is under the cursor
+         * as well as matched brackets
+         */
+        documentHighlightReadBackground: withOpacity(
+            foreground(layer, "accent"),
+            0.1
         ),
-        background: background(colorScheme.middle, "active"),
-      },
-    },
-    diagnosticHeader: {
-      background: background(colorScheme.middle),
-      iconWidthFactor: 1.5,
-      textScaleFactor: 0.857,
-      border: border(colorScheme.middle, {
-        bottom: true,
-        top: true,
-      }),
-      code: {
-        ...text(colorScheme.middle, "mono", { size: "sm" }),
-        margin: {
-          left: 10,
+        documentHighlightWriteBackground: colorScheme.ramps
+            .neutral(0.5)
+            .alpha(0.4)
+            .hex(), // TODO: This was blend * 2
+        errorColor: background(layer, "negative"),
+        gutterBackground: background(layer),
+        gutterPaddingFactor: 3.5,
+        lineNumber: withOpacity(foreground(layer), 0.35),
+        lineNumberActive: foreground(layer),
+        renameFade: 0.6,
+        unnecessaryCodeFade: 0.5,
+        selection: colorScheme.players[0],
+        whitespace: colorScheme.ramps.neutral(0.5).hex(),
+        guestSelections: [
+            colorScheme.players[1],
+            colorScheme.players[2],
+            colorScheme.players[3],
+            colorScheme.players[4],
+            colorScheme.players[5],
+            colorScheme.players[6],
+            colorScheme.players[7],
+        ],
+        autocomplete: {
+            background: background(colorScheme.middle),
+            cornerRadius: 8,
+            padding: 4,
+            margin: {
+                left: -14,
+            },
+            border: border(colorScheme.middle),
+            shadow: colorScheme.popoverShadow,
+            matchHighlight: foreground(colorScheme.middle, "accent"),
+            item: autocompleteItem,
+            hoveredItem: {
+                ...autocompleteItem,
+                matchHighlight: foreground(
+                    colorScheme.middle,
+                    "accent",
+                    "hovered"
+                ),
+                background: background(colorScheme.middle, "hovered"),
+            },
+            selectedItem: {
+                ...autocompleteItem,
+                matchHighlight: foreground(
+                    colorScheme.middle,
+                    "accent",
+                    "active"
+                ),
+                background: background(colorScheme.middle, "active"),
+            },
         },
-      },
-      source: {
-        text: text(colorScheme.middle, "sans", {
-          size: "sm",
-          weight: "bold",
-        }),
-      },
-      message: {
-        highlightText: text(colorScheme.middle, "sans", {
-          size: "sm",
-          weight: "bold",
-        }),
-        text: text(colorScheme.middle, "sans", { size: "sm" }),
-      },
-    },
-    diagnosticPathHeader: {
-      background: background(colorScheme.middle),
-      textScaleFactor: 0.857,
-      filename: text(colorScheme.middle, "mono", { size: "sm" }),
-      path: {
-        ...text(colorScheme.middle, "mono", { size: "sm" }),
-        margin: {
-          left: 12,
+        diagnosticHeader: {
+            background: background(colorScheme.middle),
+            iconWidthFactor: 1.5,
+            textScaleFactor: 0.857,
+            border: border(colorScheme.middle, {
+                bottom: true,
+                top: true,
+            }),
+            code: {
+                ...text(colorScheme.middle, "mono", { size: "sm" }),
+                margin: {
+                    left: 10,
+                },
+            },
+            source: {
+                text: text(colorScheme.middle, "sans", {
+                    size: "sm",
+                    weight: "bold",
+                }),
+            },
+            message: {
+                highlightText: text(colorScheme.middle, "sans", {
+                    size: "sm",
+                    weight: "bold",
+                }),
+                text: text(colorScheme.middle, "sans", { size: "sm" }),
+            },
         },
-      },
-    },
-    errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
-    warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
-    informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
-    hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
-    invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
-    invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
-    invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
-    invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
-    hoverPopover: hoverPopover(colorScheme),
-    linkDefinition: {
-      color: syntax.linkUri.color,
-      underline: syntax.linkUri.underline,
-    },
-    jumpIcon: interactive({
-      base: {
-        color: foreground(layer, "on"),
-        iconWidth: 20,
-        buttonWidth: 20,
-        cornerRadius: 6,
-        padding: {
-          top: 6,
-          bottom: 6,
-          left: 6,
-          right: 6,
-        }
-      }, state: {
-        hovered: {
-          background: background(layer, "on", "hovered"),
-        }
-      }
-    }),
+        diagnosticPathHeader: {
+            background: background(colorScheme.middle),
+            textScaleFactor: 0.857,
+            filename: text(colorScheme.middle, "mono", { size: "sm" }),
+            path: {
+                ...text(colorScheme.middle, "mono", { size: "sm" }),
+                margin: {
+                    left: 12,
+                },
+            },
+        },
+        errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
+        warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
+        informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
+        hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
+        invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
+        invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
+        invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
+        invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
+        hoverPopover: hoverPopover(colorScheme),
+        linkDefinition: {
+            color: syntax.linkUri.color,
+            underline: syntax.linkUri.underline,
+        },
+        jumpIcon: interactive({
+            base: {
+                color: foreground(layer, "on"),
+                iconWidth: 20,
+                buttonWidth: 20,
+                cornerRadius: 6,
+                padding: {
+                    top: 6,
+                    bottom: 6,
+                    left: 6,
+                    right: 6,
+                }
+            }, state: {
+                hovered: {
+                    background: background(layer, "on", "hovered"),
+                }
+            }
+        }),
 
-    scrollbar: {
-      width: 12,
-      minHeightFactor: 1.0,
-      track: {
-        border: border(layer, "variant", { left: true }),
-      },
-      thumb: {
-        background: withOpacity(background(layer, "inverted"), 0.3),
-        border: {
-          width: 1,
-          color: borderColor(layer, "variant"),
-          top: false,
-          right: true,
-          left: true,
-          bottom: false,
+        scrollbar: {
+            width: 12,
+            minHeightFactor: 1.0,
+            track: {
+                border: border(layer, "variant", { left: true }),
+            },
+            thumb: {
+                background: withOpacity(background(layer, "inverted"), 0.3),
+                border: {
+                    width: 1,
+                    color: borderColor(layer, "variant"),
+                    top: false,
+                    right: true,
+                    left: true,
+                    bottom: false,
+                },
+            },
+            git: {
+                deleted: isLight
+                    ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
+                modified: isLight
+                    ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
+                inserted: isLight
+                    ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
+                    : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
+            },
+        },
+        compositionMark: {
+            underline: {
+                thickness: 1.0,
+                color: borderColor(layer),
+            },
         },
-      },
-      git: {
-        deleted: isLight
-          ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
-          : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
-        modified: isLight
-          ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
-          : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
-        inserted: isLight
-          ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
-          : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
-      },
-    },
-    compositionMark: {
-      underline: {
-        thickness: 1.0,
-        color: borderColor(layer),
-      },
-    },
-    syntax,
-  }
+        syntax,
+    }
 }

styles/src/styleTree/feedback.ts 🔗

@@ -1,48 +1,48 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function feedback(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest
+    let layer = colorScheme.highest
 
-  return {
-    submit_button: interactive({
-      base: {
-        ...text(layer, "mono", "on"),
-        background: background(layer, "on"),
-        cornerRadius: 6,
-        border: border(layer, "on"),
-        margin: {
-          right: 4,
-        },
-        padding: {
-          bottom: 2,
-          left: 10,
-          right: 10,
-          top: 2,
-        }
-      }, state: {
-        clicked: {
-          ...text(layer, "mono", "on", "pressed"),
-          background: background(layer, "on", "pressed"),
-          border: border(layer, "on", "pressed"),
-        },
-        hovered: {
-          ...text(layer, "mono", "on", "hovered"),
-          background: background(layer, "on", "hovered"),
-          border: border(layer, "on", "hovered"),
-        },
-      }
-    }),
-    button_margin: 8,
-    info_text_default: text(layer, "sans", "default", { size: "xs" }),
-    link_text_default: text(layer, "sans", "default", {
-      size: "xs",
-      underline: true,
-    }),
-    link_text_hover: text(layer, "sans", "hovered", {
-      size: "xs",
-      underline: true,
-    }),
-  }
+    return {
+        submit_button: interactive({
+            base: {
+                ...text(layer, "mono", "on"),
+                background: background(layer, "on"),
+                cornerRadius: 6,
+                border: border(layer, "on"),
+                margin: {
+                    right: 4,
+                },
+                padding: {
+                    bottom: 2,
+                    left: 10,
+                    right: 10,
+                    top: 2,
+                }
+            }, state: {
+                clicked: {
+                    ...text(layer, "mono", "on", "pressed"),
+                    background: background(layer, "on", "pressed"),
+                    border: border(layer, "on", "pressed"),
+                },
+                hovered: {
+                    ...text(layer, "mono", "on", "hovered"),
+                    background: background(layer, "on", "hovered"),
+                    border: border(layer, "on", "hovered"),
+                },
+            }
+        }),
+        button_margin: 8,
+        info_text_default: text(layer, "sans", "default", { size: "xs" }),
+        link_text_default: text(layer, "sans", "default", {
+            size: "xs",
+            underline: true,
+        }),
+        link_text_hover: text(layer, "sans", "hovered", {
+            size: "xs",
+            underline: true,
+        }),
+    }
 }

styles/src/styleTree/picker.ts 🔗

@@ -2,88 +2,88 @@ import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { background, border, text } from "./components"
 import { toggleable } from "./toggle"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function picker(colorScheme: ColorScheme): any {
-  let layer = colorScheme.lowest
-  const container = {
-    background: background(layer),
-    border: border(layer),
-    shadow: colorScheme.modalShadow,
-    cornerRadius: 12,
-    padding: {
-      bottom: 4,
-    },
-  }
-  const inputEditor = {
-    placeholderText: text(layer, "sans", "on", "disabled"),
-    selection: colorScheme.players[0],
-    text: text(layer, "mono", "on"),
-    border: border(layer, { bottom: true }),
-    padding: {
-      bottom: 8,
-      left: 16,
-      right: 16,
-      top: 8,
-    },
-    margin: {
-      bottom: 4,
-    },
-  }
-  const emptyInputEditor: any = { ...inputEditor }
-  delete emptyInputEditor.border
-  delete emptyInputEditor.margin
-
-  return {
-    ...container,
-    emptyContainer: {
-      ...container,
-      padding: {},
-    },
-    item: toggleable(interactive({
-      base: {
+    let layer = colorScheme.lowest
+    const container = {
+        background: background(layer),
+        border: border(layer),
+        shadow: colorScheme.modalShadow,
+        cornerRadius: 12,
+        padding: {
+            bottom: 4,
+        },
+    }
+    const inputEditor = {
+        placeholderText: text(layer, "sans", "on", "disabled"),
+        selection: colorScheme.players[0],
+        text: text(layer, "mono", "on"),
+        border: border(layer, { bottom: true }),
         padding: {
-          bottom: 4,
-          left: 12,
-          right: 12,
-          top: 4,
+            bottom: 8,
+            left: 16,
+            right: 16,
+            top: 8,
         },
         margin: {
-          top: 1,
-          left: 4,
-          right: 4,
+            bottom: 4,
         },
-        cornerRadius: 8,
-        text: text(layer, "sans", "variant"),
-        highlightText: text(layer, "sans", "accent", { weight: "bold" }),
-      }
-      , state: {
-        hovered: {
-          background: withOpacity(background(layer, "hovered"), 0.5),
-        }
-      }
-    }),
-      {
-        default: {
-          background: withOpacity(
-            background(layer, "base", "active"),
-            0.5
-          ),
-          //text: text(layer, "sans", "base", "active"),
-        }
-      }),
+    }
+    const emptyInputEditor: any = { ...inputEditor }
+    delete emptyInputEditor.border
+    delete emptyInputEditor.margin
+
+    return {
+        ...container,
+        emptyContainer: {
+            ...container,
+            padding: {},
+        },
+        item: toggleable(interactive({
+            base: {
+                padding: {
+                    bottom: 4,
+                    left: 12,
+                    right: 12,
+                    top: 4,
+                },
+                margin: {
+                    top: 1,
+                    left: 4,
+                    right: 4,
+                },
+                cornerRadius: 8,
+                text: text(layer, "sans", "variant"),
+                highlightText: text(layer, "sans", "accent", { weight: "bold" }),
+            }
+            , state: {
+                hovered: {
+                    background: withOpacity(background(layer, "hovered"), 0.5),
+                }
+            }
+        }),
+            {
+                default: {
+                    background: withOpacity(
+                        background(layer, "base", "active"),
+                        0.5
+                    ),
+                    //text: text(layer, "sans", "base", "active"),
+                }
+            }),
 
 
-    inputEditor,
-    emptyInputEditor,
-    noMatches: {
-      text: text(layer, "sans", "variant"),
-      padding: {
-        bottom: 8,
-        left: 16,
-        right: 16,
-        top: 8,
-      },
-    },
-  }
+        inputEditor,
+        emptyInputEditor,
+        noMatches: {
+            text: text(layer, "sans", "variant"),
+            padding: {
+                bottom: 8,
+                left: 16,
+                right: 16,
+                top: 8,
+            },
+        },
+    }
 }

styles/src/styleTree/projectPanel.ts 🔗

@@ -1,123 +1,123 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { background, border, foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 export default function projectPanel(colorScheme: ColorScheme) {
-  const { isLight } = colorScheme
+    const { isLight } = colorScheme
 
-  let layer = colorScheme.middle
+    let layer = colorScheme.middle
 
-  let baseEntry = {
-    height: 22,
-    iconColor: foreground(layer, "variant"),
-    iconSize: 7,
-    iconSpacing: 5,
-  }
-
-  let status = {
-    git: {
-      modified: isLight
-        ? colorScheme.ramps.yellow(0.6).hex()
-        : colorScheme.ramps.yellow(0.5).hex(),
-      inserted: isLight
-        ? colorScheme.ramps.green(0.45).hex()
-        : colorScheme.ramps.green(0.5).hex(),
-      conflict: isLight
-        ? colorScheme.ramps.red(0.6).hex()
-        : colorScheme.ramps.red(0.5).hex(),
-    },
-  }
+    let baseEntry = {
+        height: 22,
+        iconColor: foreground(layer, "variant"),
+        iconSize: 7,
+        iconSpacing: 5,
+    }
 
-  let entry = toggleable(interactive({
-    base: {
-      ...baseEntry,
-      text: text(layer, "mono", "variant", { size: "sm" }),
-      status,
-    }, state:
-    {
-      hovered: {
-        background: background(layer, "variant", "hovered"),
-      }
+    let status = {
+        git: {
+            modified: isLight
+                ? colorScheme.ramps.yellow(0.6).hex()
+                : colorScheme.ramps.yellow(0.5).hex(),
+            inserted: isLight
+                ? colorScheme.ramps.green(0.45).hex()
+                : colorScheme.ramps.green(0.5).hex(),
+            conflict: isLight
+                ? colorScheme.ramps.red(0.6).hex()
+                : colorScheme.ramps.red(0.5).hex(),
+        },
     }
-  }),
-    {
-      default: {
-        /*background: colorScheme.isLight
-          ? withOpacity(background(layer, "active"), 0.5)
-          : background(layer, "active") ,*/ // todo posiewic
-        text: text(layer, "mono", "active", { size: "sm" }),
-      },
-      hovered: {
-        //background: background(layer, "active"),
-        text: text(layer, "mono", "active", { size: "sm" }),
-      },
 
-    });
+    let entry = toggleable(interactive({
+        base: {
+            ...baseEntry,
+            text: text(layer, "mono", "variant", { size: "sm" }),
+            status,
+        }, state:
+        {
+            hovered: {
+                background: background(layer, "variant", "hovered"),
+            }
+        }
+    }),
+        {
+            default: {
+                /*background: colorScheme.isLight
+                  ? withOpacity(background(layer, "active"), 0.5)
+                  : background(layer, "active") ,*/ // todo posiewic
+                text: text(layer, "mono", "active", { size: "sm" }),
+            },
+            hovered: {
+                //background: background(layer, "active"),
+                text: text(layer, "mono", "active", { size: "sm" }),
+            },
+
+        });
 
-  return {
-    openProjectButton: interactive({
-      base: {
+    return {
+        openProjectButton: interactive({
+            base: {
+                background: background(layer),
+                border: border(layer, "active"),
+                cornerRadius: 4,
+                margin: {
+                    top: 16,
+                    left: 16,
+                    right: 16,
+                },
+                padding: {
+                    top: 3,
+                    bottom: 3,
+                    left: 7,
+                    right: 7,
+                },
+                ...text(layer, "sans", "default", { size: "sm" })
+            }, state: {
+                hovered: {
+                    ...text(layer, "sans", "default", { size: "sm" }),
+                    background: background(layer, "hovered"),
+                    border: border(layer, "active"),
+                },
+            }
+        }),
         background: background(layer),
-        border: border(layer, "active"),
-        cornerRadius: 4,
-        margin: {
-          top: 16,
-          left: 16,
-          right: 16,
+        padding: { left: 6, right: 6, top: 0, bottom: 6 },
+        indentWidth: 12,
+        entry,
+        draggedEntry: {
+            ...baseEntry,
+            text: text(layer, "mono", "on", { size: "sm" }),
+            background: withOpacity(background(layer, "on"), 0.9),
+            border: border(layer),
+            status,
         },
-        padding: {
-          top: 3,
-          bottom: 3,
-          left: 7,
-          right: 7,
+        ignoredEntry: {
+            ...entry,
+            iconColor: foreground(layer, "disabled"),
+            text: text(layer, "mono", "disabled"),
+            active: {
+                ...entry.active,
+                iconColor: foreground(layer, "variant"),
+            },
         },
-        ...text(layer, "sans", "default", { size: "sm" })
-      }, state: {
-        hovered: {
-          ...text(layer, "sans", "default", { size: "sm" }),
-          background: background(layer, "hovered"),
-          border: border(layer, "active"),
+        cutEntry: {
+            ...entry,
+            text: text(layer, "mono", "disabled"),
+            active: {
+                ...entry.active,
+                default: {
+                    ...entry.active.default,
+                    background: background(layer, "active"),
+                    text: text(layer, "mono", "disabled", { size: "sm" }),
+                },
+
+            },
         },
-      }
-    }),
-    background: background(layer),
-    padding: { left: 6, right: 6, top: 0, bottom: 6 },
-    indentWidth: 12,
-    entry,
-    draggedEntry: {
-      ...baseEntry,
-      text: text(layer, "mono", "on", { size: "sm" }),
-      background: withOpacity(background(layer, "on"), 0.9),
-      border: border(layer),
-      status,
-    },
-    ignoredEntry: {
-      ...entry,
-      iconColor: foreground(layer, "disabled"),
-      text: text(layer, "mono", "disabled"),
-      active: {
-        ...entry.active,
-        iconColor: foreground(layer, "variant"),
-      },
-    },
-    cutEntry: {
-      ...entry,
-      text: text(layer, "mono", "disabled"),
-      active: {
-        ...entry.active,
-        default: {
-          ...entry.active.default,
-          background: background(layer, "active"),
-          text: text(layer, "mono", "disabled", { size: "sm" }),
+        filenameEditor: {
+            background: background(layer, "on"),
+            text: text(layer, "mono", "on", { size: "sm" }),
+            selection: colorScheme.players[0],
         },
-
-      },
-    },
-    filenameEditor: {
-      background: background(layer, "on"),
-      text: text(layer, "mono", "on", { size: "sm" }),
-      selection: colorScheme.players[0],
-    },
-  }
+    }
 }

styles/src/styleTree/search.ts 🔗

@@ -1,123 +1,123 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { background, border, foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 
 export default function search(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest
+    let layer = colorScheme.highest
 
-  // Search input
-  const editor = {
-    background: background(layer),
-    cornerRadius: 8,
-    minWidth: 200,
-    maxWidth: 500,
-    placeholderText: text(layer, "mono", "disabled"),
-    selection: colorScheme.players[0],
-    text: text(layer, "mono", "default"),
-    border: border(layer),
-    margin: {
-      right: 12,
-    },
-    padding: {
-      top: 3,
-      bottom: 3,
-      left: 12,
-      right: 8,
-    },
-  }
-
-  const includeExcludeEditor = {
-    ...editor,
-    minWidth: 100,
-    maxWidth: 250,
-  }
-
-  return {
-    // TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
-    matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
-    optionButton: toggleable(interactive({
-      base: {
-        ...text(layer, "mono", "on"),
-        background: background(layer, "on"),
-        cornerRadius: 6,
-        border: border(layer, "on"),
+    // Search input
+    const editor = {
+        background: background(layer),
+        cornerRadius: 8,
+        minWidth: 200,
+        maxWidth: 500,
+        placeholderText: text(layer, "mono", "disabled"),
+        selection: colorScheme.players[0],
+        text: text(layer, "mono", "default"),
+        border: border(layer),
         margin: {
-          right: 4,
+            right: 12,
         },
         padding: {
-          bottom: 2,
-          left: 10,
-          right: 10,
-          top: 2,
+            top: 3,
+            bottom: 3,
+            left: 12,
+            right: 8,
+        },
+    }
+
+    const includeExcludeEditor = {
+        ...editor,
+        minWidth: 100,
+        maxWidth: 250,
+    }
+
+    return {
+        // TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
+        matchBackground: withOpacity(foreground(layer, "accent"), 0.4),
+        optionButton: toggleable(interactive({
+            base: {
+                ...text(layer, "mono", "on"),
+                background: background(layer, "on"),
+                cornerRadius: 6,
+                border: border(layer, "on"),
+                margin: {
+                    right: 4,
+                },
+                padding: {
+                    bottom: 2,
+                    left: 10,
+                    right: 10,
+                    top: 2,
+                },
+            }, state: {
+                clicked: {
+                    ...text(layer, "mono", "on", "pressed"),
+                    background: background(layer, "on", "pressed"),
+                    border: border(layer, "on", "pressed"),
+                },
+                hovered: {
+                    ...text(layer, "mono", "on", "hovered"),
+                    background: background(layer, "on", "hovered"),
+                    border: border(layer, "on", "hovered"),
+                },
+            }
+        }), {
+            default: {
+                ...text(layer, "mono", "on", "inverted"),
+                background: background(layer, "on", "inverted"),
+                border: border(layer, "on", "inverted"),
+            },
+
+        }),
+        editor,
+        invalidEditor: {
+            ...editor,
+            border: border(layer, "negative"),
         },
-      }, state: {
-        clicked: {
-          ...text(layer, "mono", "on", "pressed"),
-          background: background(layer, "on", "pressed"),
-          border: border(layer, "on", "pressed"),
+        includeExcludeEditor,
+        invalidIncludeExcludeEditor: {
+            ...includeExcludeEditor,
+            border: border(layer, "negative"),
         },
-        hovered: {
-          ...text(layer, "mono", "on", "hovered"),
-          background: background(layer, "on", "hovered"),
-          border: border(layer, "on", "hovered"),
+        matchIndex: {
+            ...text(layer, "mono", "variant"),
+            padding: {
+                left: 6,
+            },
         },
-      }
-    }), {
-      default: {
-        ...text(layer, "mono", "on", "inverted"),
-        background: background(layer, "on", "inverted"),
-        border: border(layer, "on", "inverted"),
-      },
-
-    }),
-    editor,
-    invalidEditor: {
-      ...editor,
-      border: border(layer, "negative"),
-    },
-    includeExcludeEditor,
-    invalidIncludeExcludeEditor: {
-      ...includeExcludeEditor,
-      border: border(layer, "negative"),
-    },
-    matchIndex: {
-      ...text(layer, "mono", "variant"),
-      padding: {
-        left: 6,
-      },
-    },
-    optionButtonGroup: {
-      padding: {
-        left: 12,
-        right: 12,
-      },
-    },
-    includeExcludeInputs: {
-      ...text(layer, "mono", "variant"),
-      padding: {
-        right: 6,
-      },
-    },
-    resultsStatus: {
-      ...text(layer, "mono", "on"),
-      size: 18,
-    },
-    dismissButton: interactive({
-      base: {
-        color: foreground(layer, "variant"),
-        iconWidth: 12,
-        buttonWidth: 14,
-        padding: {
-          left: 10,
-          right: 10,
+        optionButtonGroup: {
+            padding: {
+                left: 12,
+                right: 12,
+            },
+        },
+        includeExcludeInputs: {
+            ...text(layer, "mono", "variant"),
+            padding: {
+                right: 6,
+            },
+        },
+        resultsStatus: {
+            ...text(layer, "mono", "on"),
+            size: 18,
         },
-      }, state: {
-        hovered: {
-          color: foreground(layer, "hovered"),
-        }
-      }
-    }),
-  }
+        dismissButton: interactive({
+            base: {
+                color: foreground(layer, "variant"),
+                iconWidth: 12,
+                buttonWidth: 14,
+                padding: {
+                    left: 10,
+                    right: 10,
+                },
+            }, state: {
+                hovered: {
+                    color: foreground(layer, "hovered"),
+                }
+            }
+        }),
+    }
 }

styles/src/styleTree/simpleMessageNotification.ts 🔗

@@ -1,51 +1,51 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 const headerPadding = 8
 
 export default function simpleMessageNotification(
-  colorScheme: ColorScheme
+    colorScheme: ColorScheme
 ): Object {
-  let layer = colorScheme.middle
-  return {
-    message: {
-      ...text(layer, "sans", { size: "xs" }),
-      margin: { left: headerPadding, right: headerPadding },
-    },
-    actionMessage: interactive({
-      base: {
-        ...text(layer, "sans", { size: "xs" }),
-        border: border(layer, "active"),
-        cornerRadius: 4,
-        padding: {
-          top: 3,
-          bottom: 3,
-          left: 7,
-          right: 7,
+    let layer = colorScheme.middle
+    return {
+        message: {
+            ...text(layer, "sans", { size: "xs" }),
+            margin: { left: headerPadding, right: headerPadding },
         },
+        actionMessage: interactive({
+            base: {
+                ...text(layer, "sans", { size: "xs" }),
+                border: border(layer, "active"),
+                cornerRadius: 4,
+                padding: {
+                    top: 3,
+                    bottom: 3,
+                    left: 7,
+                    right: 7,
+                },
 
-        margin: { left: headerPadding, top: 6, bottom: 6 },
-      }, state: {
-        hovered: {
-          ...text(layer, "sans", "default", { size: "xs" }),
-          background: background(layer, "hovered"),
-          border: border(layer, "active"),
-        },
-      }
-    }),
-    dismissButton: interactive({
-      base: {
-        color: foreground(layer),
-        iconWidth: 8,
-        iconHeight: 8,
-        buttonWidth: 8,
-        buttonHeight: 8,
-      }, state: {
-        hovered: {
-          color: foreground(layer, "hovered"),
-        },
-      }
-    })
-  }
+                margin: { left: headerPadding, top: 6, bottom: 6 },
+            }, state: {
+                hovered: {
+                    ...text(layer, "sans", "default", { size: "xs" }),
+                    background: background(layer, "hovered"),
+                    border: border(layer, "active"),
+                },
+            }
+        }),
+        dismissButton: interactive({
+            base: {
+                color: foreground(layer),
+                iconWidth: 8,
+                iconHeight: 8,
+                buttonWidth: 8,
+                buttonHeight: 8,
+            }, state: {
+                hovered: {
+                    color: foreground(layer, "hovered"),
+                },
+            }
+        })
+    }
 }

styles/src/styleTree/statusBar.ts 🔗

@@ -1,145 +1,145 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 export default function statusBar(colorScheme: ColorScheme) {
-  let layer = colorScheme.lowest
+    let layer = colorScheme.lowest
 
-  const statusContainer = {
-    cornerRadius: 6,
-    padding: { top: 3, bottom: 3, left: 6, right: 6 },
-  }
+    const statusContainer = {
+        cornerRadius: 6,
+        padding: { top: 3, bottom: 3, left: 6, right: 6 },
+    }
 
-  const diagnosticStatusContainer = {
-    cornerRadius: 6,
-    padding: { top: 1, bottom: 1, left: 6, right: 6 },
-  }
+    const diagnosticStatusContainer = {
+        cornerRadius: 6,
+        padding: { top: 1, bottom: 1, left: 6, right: 6 },
+    }
 
-  return {
-    height: 30,
-    itemSpacing: 8,
-    padding: {
-      top: 1,
-      bottom: 1,
-      left: 6,
-      right: 6,
-    },
-    border: border(layer, { top: true, overlay: true }),
-    cursorPosition: text(layer, "sans", "variant"),
-    activeLanguage: interactive({
-      base: {
-        padding: { left: 6, right: 6 },
-        ...text(layer, "sans", "variant")
-      },
-      state: {
-        hovered: {
-          ...text(layer, "sans", "on"),
-        }
-      }
-    },
-    ),
-    autoUpdateProgressMessage: text(layer, "sans", "variant"),
-    autoUpdateDoneMessage: text(layer, "sans", "variant"),
-    lspStatus: interactive({
-      base: {
-        ...diagnosticStatusContainer,
-        iconSpacing: 4,
-        iconWidth: 14,
-        height: 18,
-        message: text(layer, "sans"),
-        iconColor: foreground(layer)
-      },
-      state: {
-        hovered: {
-          message: text(layer, "sans"),
-          iconColor: foreground(layer),
-          background: background(layer, "hovered"),
-        }
-      }
-    }),
-    diagnosticMessage: interactive({
-      base: {
-        ...text(layer, "sans")
-      },
-      state: { hovered: text(layer, "sans", "hovered") }
-    },
-    ),
-    diagnosticSummary:
-      interactive({
-        base: {
-          height: 20,
-          iconWidth: 16,
-          iconSpacing: 2,
-          summarySpacing: 6,
-          text: text(layer, "sans", { size: "sm" }),
-          iconColorOk: foreground(layer, "variant"),
-          iconColorWarning: foreground(layer, "warning"),
-          iconColorError: foreground(layer, "negative"),
-          containerOk: {
-            cornerRadius: 6,
-            padding: { top: 3, bottom: 3, left: 7, right: 7 },
-          },
-          containerWarning: {
-            ...diagnosticStatusContainer,
-            background: background(layer, "warning"),
-            border: border(layer, "warning"),
-          },
-          containerError: {
-            ...diagnosticStatusContainer,
-            background: background(layer, "negative"),
-            border: border(layer, "negative"),
-          }
-        }, state: {
-          hovered: {
-            iconColorOk: foreground(layer, "on"),
-            containerOk: {
-              background: background(layer, "on", "hovered"),
+    return {
+        height: 30,
+        itemSpacing: 8,
+        padding: {
+            top: 1,
+            bottom: 1,
+            left: 6,
+            right: 6,
+        },
+        border: border(layer, { top: true, overlay: true }),
+        cursorPosition: text(layer, "sans", "variant"),
+        activeLanguage: interactive({
+            base: {
+                padding: { left: 6, right: 6 },
+                ...text(layer, "sans", "variant")
             },
-            containerWarning: {
-              background: background(layer, "warning", "hovered"),
-              border: border(layer, "warning", "hovered"),
+            state: {
+                hovered: {
+                    ...text(layer, "sans", "on"),
+                }
+            }
+        },
+        ),
+        autoUpdateProgressMessage: text(layer, "sans", "variant"),
+        autoUpdateDoneMessage: text(layer, "sans", "variant"),
+        lspStatus: interactive({
+            base: {
+                ...diagnosticStatusContainer,
+                iconSpacing: 4,
+                iconWidth: 14,
+                height: 18,
+                message: text(layer, "sans"),
+                iconColor: foreground(layer)
             },
-            containerError: {
-              background: background(layer, "negative", "hovered"),
-              border: border(layer, "negative", "hovered"),
+            state: {
+                hovered: {
+                    message: text(layer, "sans"),
+                    iconColor: foreground(layer),
+                    background: background(layer, "hovered"),
+                }
             }
-          }
-        }
-      }
-      ),
-    panelButtons: {
-      groupLeft: {},
-      groupBottom: {},
-      groupRight: {},
-      button: toggleable(interactive({
-        base: {
-          ...statusContainer,
-          iconSize: 16,
-          iconColor: foreground(layer, "variant"),
-          label: {
-            margin: { left: 6 },
-            ...text(layer, "sans", { size: "sm" }),
-          },
-        }, state: {
-          hovered: {
-            iconColor: foreground(layer, "hovered"),
-            background: background(layer, "variant"),
-          }
-        }
-      }),
-        {
-          default: {
-            iconColor: foreground(layer, "active"),
-            background: background(layer, "active"),
-          }
         }),
-      badge: {
-        cornerRadius: 3,
-        padding: 2,
-        margin: { bottom: -1, right: -1 },
-        border: border(layer),
-        background: background(layer, "accent"),
-      },
-    },
-  }
+        diagnosticMessage: interactive({
+            base: {
+                ...text(layer, "sans")
+            },
+            state: { hovered: text(layer, "sans", "hovered") }
+        },
+        ),
+        diagnosticSummary:
+            interactive({
+                base: {
+                    height: 20,
+                    iconWidth: 16,
+                    iconSpacing: 2,
+                    summarySpacing: 6,
+                    text: text(layer, "sans", { size: "sm" }),
+                    iconColorOk: foreground(layer, "variant"),
+                    iconColorWarning: foreground(layer, "warning"),
+                    iconColorError: foreground(layer, "negative"),
+                    containerOk: {
+                        cornerRadius: 6,
+                        padding: { top: 3, bottom: 3, left: 7, right: 7 },
+                    },
+                    containerWarning: {
+                        ...diagnosticStatusContainer,
+                        background: background(layer, "warning"),
+                        border: border(layer, "warning"),
+                    },
+                    containerError: {
+                        ...diagnosticStatusContainer,
+                        background: background(layer, "negative"),
+                        border: border(layer, "negative"),
+                    }
+                }, state: {
+                    hovered: {
+                        iconColorOk: foreground(layer, "on"),
+                        containerOk: {
+                            background: background(layer, "on", "hovered"),
+                        },
+                        containerWarning: {
+                            background: background(layer, "warning", "hovered"),
+                            border: border(layer, "warning", "hovered"),
+                        },
+                        containerError: {
+                            background: background(layer, "negative", "hovered"),
+                            border: border(layer, "negative", "hovered"),
+                        }
+                    }
+                }
+            }
+            ),
+        panelButtons: {
+            groupLeft: {},
+            groupBottom: {},
+            groupRight: {},
+            button: toggleable(interactive({
+                base: {
+                    ...statusContainer,
+                    iconSize: 16,
+                    iconColor: foreground(layer, "variant"),
+                    label: {
+                        margin: { left: 6 },
+                        ...text(layer, "sans", { size: "sm" }),
+                    },
+                }, state: {
+                    hovered: {
+                        iconColor: foreground(layer, "hovered"),
+                        background: background(layer, "variant"),
+                    }
+                }
+            }),
+                {
+                    default: {
+                        iconColor: foreground(layer, "active"),
+                        background: background(layer, "active"),
+                    }
+                }),
+            badge: {
+                cornerRadius: 3,
+                padding: 2,
+                margin: { bottom: -1, right: -1 },
+                border: border(layer),
+                background: background(layer, "accent"),
+            },
+        },
+    }
 }

styles/src/styleTree/tabBar.ts 🔗

@@ -2,117 +2,117 @@ import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { text, border, background, foreground } from "./components"
 import { toggleable } from "./toggle"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function tabBar(colorScheme: ColorScheme) {
-  const height = 32
+    const height = 32
 
-  let activeLayer = colorScheme.highest
-  let layer = colorScheme.middle
+    let activeLayer = colorScheme.highest
+    let layer = colorScheme.middle
 
-  const tab = {
-    height,
-    text: text(layer, "sans", "variant", { size: "sm" }),
-    background: background(layer),
-    border: border(layer, {
-      right: true,
-      bottom: true,
-      overlay: true,
-    }),
-    padding: {
-      left: 8,
-      right: 12,
-    },
-    spacing: 8,
+    const tab = {
+        height,
+        text: text(layer, "sans", "variant", { size: "sm" }),
+        background: background(layer),
+        border: border(layer, {
+            right: true,
+            bottom: true,
+            overlay: true,
+        }),
+        padding: {
+            left: 8,
+            right: 12,
+        },
+        spacing: 8,
 
-    // Tab type icons (e.g. Project Search)
-    typeIconWidth: 14,
+        // Tab type icons (e.g. Project Search)
+        typeIconWidth: 14,
 
-    // Close icons
-    closeIconWidth: 8,
-    iconClose: foreground(layer, "variant"),
-    iconCloseActive: foreground(layer, "hovered"),
+        // Close icons
+        closeIconWidth: 8,
+        iconClose: foreground(layer, "variant"),
+        iconCloseActive: foreground(layer, "hovered"),
 
-    // Indicators
-    iconConflict: foreground(layer, "warning"),
-    iconDirty: foreground(layer, "accent"),
+        // Indicators
+        iconConflict: foreground(layer, "warning"),
+        iconDirty: foreground(layer, "accent"),
 
-    // When two tabs of the same name are open, a label appears next to them
-    description: {
-      margin: { left: 8 },
-      ...text(layer, "sans", "disabled", { size: "2xs" }),
-    },
-  }
+        // When two tabs of the same name are open, a label appears next to them
+        description: {
+            margin: { left: 8 },
+            ...text(layer, "sans", "disabled", { size: "2xs" }),
+        },
+    }
 
-  const activePaneActiveTab = {
-    ...tab,
-    background: background(activeLayer),
-    text: text(activeLayer, "sans", "active", { size: "sm" }),
-    border: {
-      ...tab.border,
-      bottom: false,
-    },
-  }
+    const activePaneActiveTab = {
+        ...tab,
+        background: background(activeLayer),
+        text: text(activeLayer, "sans", "active", { size: "sm" }),
+        border: {
+            ...tab.border,
+            bottom: false,
+        },
+    }
 
-  const inactivePaneInactiveTab = {
-    ...tab,
-    background: background(layer),
-    text: text(layer, "sans", "variant", { size: "sm" }),
-  }
+    const inactivePaneInactiveTab = {
+        ...tab,
+        background: background(layer),
+        text: text(layer, "sans", "variant", { size: "sm" }),
+    }
 
-  const inactivePaneActiveTab = {
-    ...tab,
-    background: background(activeLayer),
-    text: text(layer, "sans", "variant", { size: "sm" }),
-    border: {
-      ...tab.border,
-      bottom: false,
-    },
-  }
+    const inactivePaneActiveTab = {
+        ...tab,
+        background: background(activeLayer),
+        text: text(layer, "sans", "variant", { size: "sm" }),
+        border: {
+            ...tab.border,
+            bottom: false,
+        },
+    }
 
-  const draggedTab = {
-    ...activePaneActiveTab,
-    background: withOpacity(tab.background, 0.9),
-    border: undefined as any,
-    shadow: colorScheme.popoverShadow,
-  }
+    const draggedTab = {
+        ...activePaneActiveTab,
+        background: withOpacity(tab.background, 0.9),
+        border: undefined as any,
+        shadow: colorScheme.popoverShadow,
+    }
 
-  return {
-    height,
-    background: background(layer),
-    activePane: {
-      activeTab: activePaneActiveTab,
-      inactiveTab: tab,
-    },
-    inactivePane: {
-      activeTab: inactivePaneActiveTab,
-      inactiveTab: inactivePaneInactiveTab,
-    },
-    draggedTab,
-    paneButton: toggleable(interactive({
-      base: {
-        color: foreground(layer, "variant"),
-        iconWidth: 12,
-        buttonWidth: activePaneActiveTab.height,
-      },
-      state: {
-        hovered: {
-          color: foreground(layer, "hovered"),
-        }
-      }
-    }),
-      {
-        default: {
-          color: foreground(layer, "accent"),
-        }
-      },
-    ),
-    paneButtonContainer: {
-      background: tab.background,
-      border: {
-        ...tab.border,
-        right: false,
-      },
-    },
-  }
+    return {
+        height,
+        background: background(layer),
+        activePane: {
+            activeTab: activePaneActiveTab,
+            inactiveTab: tab,
+        },
+        inactivePane: {
+            activeTab: inactivePaneActiveTab,
+            inactiveTab: inactivePaneInactiveTab,
+        },
+        draggedTab,
+        paneButton: toggleable(interactive({
+            base: {
+                color: foreground(layer, "variant"),
+                iconWidth: 12,
+                buttonWidth: activePaneActiveTab.height,
+            },
+            state: {
+                hovered: {
+                    color: foreground(layer, "hovered"),
+                }
+            }
+        }),
+            {
+                default: {
+                    color: foreground(layer, "accent"),
+                }
+            },
+        ),
+        paneButtonContainer: {
+            background: tab.background,
+            border: {
+                ...tab.border,
+                right: false,
+            },
+        },
+    }
 }

styles/src/styleTree/toolbarDropdownMenu.ts 🔗

@@ -1,56 +1,56 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { background, border, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import { toggleable } from "./toggle"
 export default function dropdownMenu(colorScheme: ColorScheme) {
-  let layer = colorScheme.middle
+    let layer = colorScheme.middle
 
-  return {
-    rowHeight: 30,
-    background: background(layer),
-    border: border(layer),
-    shadow: colorScheme.popoverShadow,
-    header: interactive({
-      base: {
-        ...text(layer, "sans", { size: "sm" }),
-        secondaryText: text(layer, "sans", { size: "sm", color: "#aaaaaa" }),
-        secondaryTextSpacing: 10,
-        padding: { left: 8, right: 8, top: 2, bottom: 2 },
-        cornerRadius: 6,
-        background: background(layer, "on"),
-        border: border(layer, "on", { overlay: true })
-      },
-      state: {
-        hovered: {
-          background: background(layer, "hovered"),
-          ...text(layer, "sans", "hovered", { size: "sm" }),
-        }
-      }
-    })
-    ,
-    sectionHeader: {
-      ...text(layer, "sans", { size: "sm" }),
-      padding: { left: 8, right: 8, top: 8, bottom: 8 },
-    },
-    item: toggleable(interactive({
-      base: {
-        ...text(layer, "sans", { size: "sm" }),
-        secondaryTextSpacing: 10,
-        secondaryText: text(layer, "sans", { size: "sm" }),
-        padding: { left: 18, right: 18, top: 2, bottom: 2 }
-      }, state: {
-        hovered: {
-          background: background(layer, "hovered"),
-          ...text(layer, "sans", "hovered", { size: "sm" }),
-        }
-      }
-    }), {
-      default: {
-        background: background(layer, "active"),
-      },
-      hovered: {
-        background: background(layer, "active"),
-      },
-    })
-  }
+    return {
+        rowHeight: 30,
+        background: background(layer),
+        border: border(layer),
+        shadow: colorScheme.popoverShadow,
+        header: interactive({
+            base: {
+                ...text(layer, "sans", { size: "sm" }),
+                secondaryText: text(layer, "sans", { size: "sm", color: "#aaaaaa" }),
+                secondaryTextSpacing: 10,
+                padding: { left: 8, right: 8, top: 2, bottom: 2 },
+                cornerRadius: 6,
+                background: background(layer, "on"),
+                border: border(layer, "on", { overlay: true })
+            },
+            state: {
+                hovered: {
+                    background: background(layer, "hovered"),
+                    ...text(layer, "sans", "hovered", { size: "sm" }),
+                }
+            }
+        })
+        ,
+        sectionHeader: {
+            ...text(layer, "sans", { size: "sm" }),
+            padding: { left: 8, right: 8, top: 8, bottom: 8 },
+        },
+        item: toggleable(interactive({
+            base: {
+                ...text(layer, "sans", { size: "sm" }),
+                secondaryTextSpacing: 10,
+                secondaryText: text(layer, "sans", { size: "sm" }),
+                padding: { left: 18, right: 18, top: 2, bottom: 2 }
+            }, state: {
+                hovered: {
+                    background: background(layer, "hovered"),
+                    ...text(layer, "sans", "hovered", { size: "sm" }),
+                }
+            }
+        }), {
+            default: {
+                background: background(layer, "active"),
+            },
+            hovered: {
+                background: background(layer, "active"),
+            },
+        })
+    }
 }

styles/src/styleTree/updateNotification.ts 🔗

@@ -1,39 +1,39 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { foreground, text } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 const headerPadding = 8
 
 export default function updateNotification(colorScheme: ColorScheme): Object {
-  let layer = colorScheme.middle
-  return {
-    message: {
-      ...text(layer, "sans", { size: "xs" }),
-      margin: { left: headerPadding, right: headerPadding },
-    },
-    actionMessage: interactive({
-      base: {
-        ...text(layer, "sans", { size: "xs" }),
-        margin: { left: headerPadding, top: 6, bottom: 6 }
-      }, state: {
-        hovered: {
-          color: foreground(layer, "hovered"),
-        }
-      }
-    }),
-    dismissButton: interactive({
-      base: {
-        color: foreground(layer),
-        iconWidth: 8,
-        iconHeight: 8,
-        buttonWidth: 8,
-        buttonHeight: 8
-      }, state: {
-        hovered: {
-          color: foreground(layer, "hovered"),
+    let layer = colorScheme.middle
+    return {
+        message: {
+            ...text(layer, "sans", { size: "xs" }),
+            margin: { left: headerPadding, right: headerPadding },
         },
-      },
-    })
+        actionMessage: interactive({
+            base: {
+                ...text(layer, "sans", { size: "xs" }),
+                margin: { left: headerPadding, top: 6, bottom: 6 }
+            }, state: {
+                hovered: {
+                    color: foreground(layer, "hovered"),
+                }
+            }
+        }),
+        dismissButton: interactive({
+            base: {
+                color: foreground(layer),
+                iconWidth: 8,
+                iconHeight: 8,
+                buttonWidth: 8,
+                buttonHeight: 8
+            }, state: {
+                hovered: {
+                    color: foreground(layer, "hovered"),
+                },
+            },
+        })
 
-  }
+    }
 }

styles/src/styleTree/welcome.ts 🔗

@@ -1,133 +1,133 @@
 import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import {
-  border,
-  background,
-  foreground,
-  text,
-  TextProperties,
-  svg,
+    border,
+    background,
+    foreground,
+    text,
+    TextProperties,
+    svg,
 } from "./components"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 
 export default function welcome(colorScheme: ColorScheme) {
-  let layer = colorScheme.highest
+    let layer = colorScheme.highest
 
-  let checkboxBase = {
-    cornerRadius: 4,
-    padding: {
-      left: 3,
-      right: 3,
-      top: 3,
-      bottom: 3,
-    },
-    // shadow: colorScheme.popoverShadow,
-    border: border(layer),
-    margin: {
-      right: 8,
-      top: 5,
-      bottom: 5,
-    },
-  }
-
-  let interactive_text_size: TextProperties = { size: "sm" }
-
-  return {
-    pageWidth: 320,
-    logo: svg(foreground(layer, "default"), "icons/logo_96.svg", 64, 64),
-    logoSubheading: {
-      ...text(layer, "sans", "variant", { size: "md" }),
-      margin: {
-        top: 10,
-        bottom: 7,
-      },
-    },
-    buttonGroup: {
-      margin: {
-        top: 8,
-        bottom: 16,
-      },
-    },
-    headingGroup: {
-      margin: {
-        top: 8,
-        bottom: 12,
-      },
-    },
-    checkboxGroup: {
-      border: border(layer, "variant"),
-      background: withOpacity(background(layer, "hovered"), 0.25),
-      cornerRadius: 4,
-      padding: {
-        left: 12,
-        top: 2,
-        bottom: 2,
-      },
-    },
-    button: interactive({
-      base: {
-        background: background(layer),
-        border: border(layer, "active"),
+    let checkboxBase = {
         cornerRadius: 4,
+        padding: {
+            left: 3,
+            right: 3,
+            top: 3,
+            bottom: 3,
+        },
+        // shadow: colorScheme.popoverShadow,
+        border: border(layer),
         margin: {
-          top: 4,
-          bottom: 4,
+            right: 8,
+            top: 5,
+            bottom: 5,
         },
-        padding: {
-          top: 3,
-          bottom: 3,
-          left: 7,
-          right: 7,
+    }
+
+    let interactive_text_size: TextProperties = { size: "sm" }
+
+    return {
+        pageWidth: 320,
+        logo: svg(foreground(layer, "default"), "icons/logo_96.svg", 64, 64),
+        logoSubheading: {
+            ...text(layer, "sans", "variant", { size: "md" }),
+            margin: {
+                top: 10,
+                bottom: 7,
+            },
         },
-        ...text(layer, "sans", "default", interactive_text_size)
-      }, state: {
-        hovered: {
-          ...text(layer, "sans", "default", interactive_text_size),
-          background: background(layer, "hovered"),
-        }
-      }
-    }),
+        buttonGroup: {
+            margin: {
+                top: 8,
+                bottom: 16,
+            },
+        },
+        headingGroup: {
+            margin: {
+                top: 8,
+                bottom: 12,
+            },
+        },
+        checkboxGroup: {
+            border: border(layer, "variant"),
+            background: withOpacity(background(layer, "hovered"), 0.25),
+            cornerRadius: 4,
+            padding: {
+                left: 12,
+                top: 2,
+                bottom: 2,
+            },
+        },
+        button: interactive({
+            base: {
+                background: background(layer),
+                border: border(layer, "active"),
+                cornerRadius: 4,
+                margin: {
+                    top: 4,
+                    bottom: 4,
+                },
+                padding: {
+                    top: 3,
+                    bottom: 3,
+                    left: 7,
+                    right: 7,
+                },
+                ...text(layer, "sans", "default", interactive_text_size)
+            }, state: {
+                hovered: {
+                    ...text(layer, "sans", "default", interactive_text_size),
+                    background: background(layer, "hovered"),
+                }
+            }
+        }),
 
-    usageNote: {
-      ...text(layer, "sans", "variant", { size: "2xs" }),
-      padding: {
-        top: -4,
-      },
-    },
-    checkboxContainer: {
-      margin: {
-        top: 4,
-      },
-      padding: {
-        bottom: 8,
-      },
-    },
-    checkbox: {
-      label: {
-        ...text(layer, "sans", interactive_text_size),
-        // Also supports margin, container, border, etc.
-      },
-      icon: svg(foreground(layer, "on"), "icons/check_12.svg", 12, 12),
-      default: {
-        ...checkboxBase,
-        background: background(layer, "default"),
-        border: border(layer, "active"),
-      },
-      checked: {
-        ...checkboxBase,
-        background: background(layer, "hovered"),
-        border: border(layer, "active"),
-      },
-      hovered: {
-        ...checkboxBase,
-        background: background(layer, "hovered"),
-        border: border(layer, "active"),
-      },
-      hoveredAndChecked: {
-        ...checkboxBase,
-        background: background(layer, "hovered"),
-        border: border(layer, "active"),
-      },
-    },
-  }
+        usageNote: {
+            ...text(layer, "sans", "variant", { size: "2xs" }),
+            padding: {
+                top: -4,
+            },
+        },
+        checkboxContainer: {
+            margin: {
+                top: 4,
+            },
+            padding: {
+                bottom: 8,
+            },
+        },
+        checkbox: {
+            label: {
+                ...text(layer, "sans", interactive_text_size),
+                // Also supports margin, container, border, etc.
+            },
+            icon: svg(foreground(layer, "on"), "icons/check_12.svg", 12, 12),
+            default: {
+                ...checkboxBase,
+                background: background(layer, "default"),
+                border: border(layer, "active"),
+            },
+            checked: {
+                ...checkboxBase,
+                background: background(layer, "hovered"),
+                border: border(layer, "active"),
+            },
+            hovered: {
+                ...checkboxBase,
+                background: background(layer, "hovered"),
+                border: border(layer, "active"),
+            },
+            hoveredAndChecked: {
+                ...checkboxBase,
+                background: background(layer, "hovered"),
+                border: border(layer, "active"),
+            },
+        },
+    }
 }

styles/src/styleTree/workspace.ts 🔗

@@ -2,383 +2,383 @@ import { ColorScheme } from "../theme/colorScheme"
 import { withOpacity } from "../theme/color"
 import { toggleable } from "./toggle"
 import {
-  background,
-  border,
-  borderColor,
-  foreground,
-  svg,
-  text,
+    background,
+    border,
+    borderColor,
+    foreground,
+    svg,
+    text,
 } from "./components"
 import statusBar from "./statusBar"
 import tabBar from "./tabBar"
-import { interactive } from "./interactive"
+import { interactive } from "../element/interactive"
 import merge from 'ts-deepmerge';
 export default function workspace(colorScheme: ColorScheme) {
-  const layer = colorScheme.lowest
-  const isLight = colorScheme.isLight
-  const itemSpacing = 8
-  const titlebarButton = toggleable(interactive({
-    base: {
-      cornerRadius: 6,
-      padding: {
-        top: 1,
-        bottom: 1,
-        left: 8,
-        right: 8,
-      },
-      ...text(layer, "sans", "variant", { size: "xs" }),
-      background: background(layer, "variant"),
-      border: border(layer),
-    }, state: {
-      hovered: {
-        ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
-        background: background(layer, "variant", "hovered"),
-        border: border(layer, "variant", "hovered"),
-      },
-      clicked: {
-        ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
-        background: background(layer, "variant", "pressed"),
-        border: border(layer, "variant", "pressed"),
-      }
-    }
-  }),
-    {
-      default: {
-        ...text(layer, "sans", "variant", "active", { size: "xs" }),
-        background: background(layer, "variant", "active"),
-        border: border(layer, "variant", "active"),
-      }
-    },
-  );
-  const avatarWidth = 18
-  const avatarOuterWidth = avatarWidth + 4
-  const followerAvatarWidth = 14
-  const followerAvatarOuterWidth = followerAvatarWidth + 4
-
-  return {
-    background: background(colorScheme.lowest),
-    blankPane: {
-      logoContainer: {
-        width: 256,
-        height: 256,
-      },
-      logo: svg(
-        withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
-        "icons/logo_96.svg",
-        256,
-        256
-      ),
-
-      logoShadow: svg(
-        withOpacity(
-          colorScheme.isLight
-            ? "#FFFFFF"
-            : colorScheme.lowest.base.default.background,
-          colorScheme.isLight ? 1 : 0.6
-        ),
-        "icons/logo_96.svg",
-        256,
-        256
-      ),
-      keyboardHints: {
-        margin: {
-          top: 96,
-        },
-        cornerRadius: 4,
-      },
-      keyboardHint:
-        interactive({
-          base: {
-            ...text(layer, "sans", "variant", { size: "sm" }),
+    const layer = colorScheme.lowest
+    const isLight = colorScheme.isLight
+    const itemSpacing = 8
+    const titlebarButton = toggleable(interactive({
+        base: {
+            cornerRadius: 6,
             padding: {
-              top: 3,
-              left: 8,
-              right: 8,
-              bottom: 3,
+                top: 1,
+                bottom: 1,
+                left: 8,
+                right: 8,
             },
-            cornerRadius: 8
-          }, state: {
+            ...text(layer, "sans", "variant", { size: "xs" }),
+            background: background(layer, "variant"),
+            border: border(layer),
+        }, state: {
             hovered: {
-              ...text(layer, "sans", "active", { size: "sm" }),
+                ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
+                background: background(layer, "variant", "hovered"),
+                border: border(layer, "variant", "hovered"),
+            },
+            clicked: {
+                ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
+                background: background(layer, "variant", "pressed"),
+                border: border(layer, "variant", "pressed"),
+            }
+        }
+    }),
+        {
+            default: {
+                ...text(layer, "sans", "variant", "active", { size: "xs" }),
+                background: background(layer, "variant", "active"),
+                border: border(layer, "variant", "active"),
             }
-          }
-        }),
-
-      keyboardHintWidth: 320,
-    },
-    joiningProjectAvatar: {
-      cornerRadius: 40,
-      width: 80,
-    },
-    joiningProjectMessage: {
-      padding: 12,
-      ...text(layer, "sans", { size: "lg" }),
-    },
-    externalLocationMessage: {
-      background: background(colorScheme.middle, "accent"),
-      border: border(colorScheme.middle, "accent"),
-      cornerRadius: 6,
-      padding: 12,
-      margin: { bottom: 8, right: 8 },
-      ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
-    },
-    leaderBorderOpacity: 0.7,
-    leaderBorderWidth: 2.0,
-    tabBar: tabBar(colorScheme),
-    modal: {
-      margin: {
-        bottom: 52,
-        top: 52,
-      },
-      cursor: "Arrow",
-    },
-    zoomedBackground: {
-      cursor: "Arrow",
-      background: isLight
-        ? withOpacity(background(colorScheme.lowest), 0.8)
-        : withOpacity(background(colorScheme.highest), 0.6),
-    },
-    zoomedPaneForeground: {
-      margin: 16,
-      shadow: colorScheme.modalShadow,
-      border: border(colorScheme.lowest, { overlay: true }),
-    },
-    zoomedPanelForeground: {
-      margin: 16,
-      border: border(colorScheme.lowest, { overlay: true }),
-    },
-    dock: {
-      left: {
-        border: border(layer, { right: true }),
-      },
-      bottom: {
-        border: border(layer, { top: true }),
-      },
-      right: {
-        border: border(layer, { left: true }),
-      },
-    },
-    paneDivider: {
-      color: borderColor(layer),
-      width: 1,
-    },
-    statusBar: statusBar(colorScheme),
-    titlebar: {
-      itemSpacing,
-      facePileSpacing: 2,
-      height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
-      background: background(layer),
-      border: border(layer, { bottom: true }),
-      padding: {
-        left: 80,
-        right: itemSpacing,
-      },
-
-      // Project
-      title: text(layer, "sans", "variant"),
-      highlight_color: text(layer, "sans", "active").color,
-
-      // Collaborators
-      leaderAvatar: {
-        width: avatarWidth,
-        outerWidth: avatarOuterWidth,
-        cornerRadius: avatarWidth / 2,
-        outerCornerRadius: avatarOuterWidth / 2,
-      },
-      followerAvatar: {
-        width: followerAvatarWidth,
-        outerWidth: followerAvatarOuterWidth,
-        cornerRadius: followerAvatarWidth / 2,
-        outerCornerRadius: followerAvatarOuterWidth / 2,
-      },
-      inactiveAvatarGrayscale: true,
-      followerAvatarOverlap: 8,
-      leaderSelection: {
-        margin: {
-          top: 4,
-          bottom: 4,
-        },
-        padding: {
-          left: 2,
-          right: 2,
-          top: 2,
-          bottom: 2,
         },
-        cornerRadius: 6,
-      },
-      avatarRibbon: {
-        height: 3,
-        width: 12,
-        // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
-      },
+    );
+    const avatarWidth = 18
+    const avatarOuterWidth = avatarWidth + 4
+    const followerAvatarWidth = 14
+    const followerAvatarOuterWidth = followerAvatarWidth + 4
 
-      // Sign in buttom
-      // FlatButton, Variant
-      signInPrompt:
-        merge(titlebarButton,
-          {
-            inactive: {
-              default: {
+    return {
+        background: background(colorScheme.lowest),
+        blankPane: {
+            logoContainer: {
+                width: 256,
+                height: 256,
+            },
+            logo: svg(
+                withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
+                "icons/logo_96.svg",
+                256,
+                256
+            ),
+
+            logoShadow: svg(
+                withOpacity(
+                    colorScheme.isLight
+                        ? "#FFFFFF"
+                        : colorScheme.lowest.base.default.background,
+                    colorScheme.isLight ? 1 : 0.6
+                ),
+                "icons/logo_96.svg",
+                256,
+                256
+            ),
+            keyboardHints: {
                 margin: {
-                  left: itemSpacing,
+                    top: 96,
                 },
-              }
-            }
-          }),
-
+                cornerRadius: 4,
+            },
+            keyboardHint:
+                interactive({
+                    base: {
+                        ...text(layer, "sans", "variant", { size: "sm" }),
+                        padding: {
+                            top: 3,
+                            left: 8,
+                            right: 8,
+                            bottom: 3,
+                        },
+                        cornerRadius: 8
+                    }, state: {
+                        hovered: {
+                            ...text(layer, "sans", "active", { size: "sm" }),
+                        }
+                    }
+                }),
 
-      // Offline Indicator
-      offlineIcon: {
-        color: foreground(layer, "variant"),
-        width: 16,
-        margin: {
-          left: itemSpacing,
+            keyboardHintWidth: 320,
         },
-        padding: {
-          right: 4,
+        joiningProjectAvatar: {
+            cornerRadius: 40,
+            width: 80,
         },
-      },
-
-      // Notice that the collaboration server is out of date
-      outdatedWarning: {
-        ...text(layer, "sans", "warning", { size: "xs" }),
-        background: withOpacity(background(layer, "warning"), 0.3),
-        border: border(layer, "warning"),
-        margin: {
-          left: itemSpacing,
+        joiningProjectMessage: {
+            padding: 12,
+            ...text(layer, "sans", { size: "lg" }),
         },
-        padding: {
-          left: 8,
-          right: 8,
+        externalLocationMessage: {
+            background: background(colorScheme.middle, "accent"),
+            border: border(colorScheme.middle, "accent"),
+            cornerRadius: 6,
+            padding: 12,
+            margin: { bottom: 8, right: 8 },
+            ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
         },
-        cornerRadius: 6,
-      },
-      callControl: interactive({
-        base: {
-          cornerRadius: 6,
-          color: foreground(layer, "variant"),
-          iconWidth: 12,
-          buttonWidth: 20,
-        }, state: {
-          hovered: {
-            background: background(layer, "variant", "hovered"),
-            color: foreground(layer, "variant", "hovered"),
-          },
-        }
-      }),
-      toggleContactsButton: toggleable(interactive({
-        base: {
-          margin: { left: itemSpacing },
-          cornerRadius: 6,
-          color: foreground(layer, "variant"),
-          iconWidth: 14,
-          buttonWidth: 20,
+        leaderBorderOpacity: 0.7,
+        leaderBorderWidth: 2.0,
+        tabBar: tabBar(colorScheme),
+        modal: {
+            margin: {
+                bottom: 52,
+                top: 52,
+            },
+            cursor: "Arrow",
         },
-        state: {
-          clicked: {
-            background: background(layer, "variant", "pressed"),
-            color: foreground(layer, "variant", "pressed"),
-          },
-          hovered: {
-            background: background(layer, "variant", "hovered"),
-            color: foreground(layer, "variant", "hovered"),
-          }
-        }
-      }),
-        {
-          default: {
-            background: background(layer, "variant", "active"),
-            color: foreground(layer, "variant", "active")
-          }
+        zoomedBackground: {
+            cursor: "Arrow",
+            background: isLight
+                ? withOpacity(background(colorScheme.lowest), 0.8)
+                : withOpacity(background(colorScheme.highest), 0.6),
         },
-      ),
-      userMenuButton: merge(titlebarButton, {
-        inactive: {
-          default: {
-            buttonWidth: 20,
-            iconWidth: 12
-          }
-        }, active: { // posiewic: these properties are not currently set on main
-          default: {
-            iconWidth: 12,
-            button_width: 20,
-          }
-        }
-      }),
+        zoomedPaneForeground: {
+            margin: 16,
+            shadow: colorScheme.modalShadow,
+            border: border(colorScheme.lowest, { overlay: true }),
+        },
+        zoomedPanelForeground: {
+            margin: 16,
+            border: border(colorScheme.lowest, { overlay: true }),
+        },
+        dock: {
+            left: {
+                border: border(layer, { right: true }),
+            },
+            bottom: {
+                border: border(layer, { top: true }),
+            },
+            right: {
+                border: border(layer, { left: true }),
+            },
+        },
+        paneDivider: {
+            color: borderColor(layer),
+            width: 1,
+        },
+        statusBar: statusBar(colorScheme),
+        titlebar: {
+            itemSpacing,
+            facePileSpacing: 2,
+            height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
+            background: background(layer),
+            border: border(layer, { bottom: true }),
+            padding: {
+                left: 80,
+                right: itemSpacing,
+            },
 
+            // Project
+            title: text(layer, "sans", "variant"),
+            highlight_color: text(layer, "sans", "active").color,
 
-      toggleContactsBadge: {
-        cornerRadius: 3,
-        padding: 2,
-        margin: { top: 3, left: 3 },
-        border: border(layer),
-        background: foreground(layer, "accent"),
-      },
-      shareButton: {
-        ...titlebarButton,
-      },
-    },
+            // Collaborators
+            leaderAvatar: {
+                width: avatarWidth,
+                outerWidth: avatarOuterWidth,
+                cornerRadius: avatarWidth / 2,
+                outerCornerRadius: avatarOuterWidth / 2,
+            },
+            followerAvatar: {
+                width: followerAvatarWidth,
+                outerWidth: followerAvatarOuterWidth,
+                cornerRadius: followerAvatarWidth / 2,
+                outerCornerRadius: followerAvatarOuterWidth / 2,
+            },
+            inactiveAvatarGrayscale: true,
+            followerAvatarOverlap: 8,
+            leaderSelection: {
+                margin: {
+                    top: 4,
+                    bottom: 4,
+                },
+                padding: {
+                    left: 2,
+                    right: 2,
+                    top: 2,
+                    bottom: 2,
+                },
+                cornerRadius: 6,
+            },
+            avatarRibbon: {
+                height: 3,
+                width: 12,
+                // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
+            },
 
-    toolbar: {
-      height: 34,
-      background: background(colorScheme.highest),
-      border: border(colorScheme.highest, { bottom: true }),
-      itemSpacing: 8,
-      navButton: interactive(
-        {
-          base: {
-            color: foreground(colorScheme.highest, "on"),
-            iconWidth: 12,
-            buttonWidth: 24,
-            cornerRadius: 6,
-          }, state: {
-            hovered: {
-              color: foreground(colorScheme.highest, "on", "hovered"),
-              background: background(
-                colorScheme.highest,
-                "on",
-                "hovered"
-              ),
+            // Sign in buttom
+            // FlatButton, Variant
+            signInPrompt:
+                merge(titlebarButton,
+                    {
+                        inactive: {
+                            default: {
+                                margin: {
+                                    left: itemSpacing,
+                                },
+                            }
+                        }
+                    }),
+
+
+            // Offline Indicator
+            offlineIcon: {
+                color: foreground(layer, "variant"),
+                width: 16,
+                margin: {
+                    left: itemSpacing,
+                },
+                padding: {
+                    right: 4,
+                },
+            },
+
+            // Notice that the collaboration server is out of date
+            outdatedWarning: {
+                ...text(layer, "sans", "warning", { size: "xs" }),
+                background: withOpacity(background(layer, "warning"), 0.3),
+                border: border(layer, "warning"),
+                margin: {
+                    left: itemSpacing,
+                },
+                padding: {
+                    left: 8,
+                    right: 8,
+                },
+                cornerRadius: 6,
+            },
+            callControl: interactive({
+                base: {
+                    cornerRadius: 6,
+                    color: foreground(layer, "variant"),
+                    iconWidth: 12,
+                    buttonWidth: 20,
+                }, state: {
+                    hovered: {
+                        background: background(layer, "variant", "hovered"),
+                        color: foreground(layer, "variant", "hovered"),
+                    },
+                }
+            }),
+            toggleContactsButton: toggleable(interactive({
+                base: {
+                    margin: { left: itemSpacing },
+                    cornerRadius: 6,
+                    color: foreground(layer, "variant"),
+                    iconWidth: 14,
+                    buttonWidth: 20,
+                },
+                state: {
+                    clicked: {
+                        background: background(layer, "variant", "pressed"),
+                        color: foreground(layer, "variant", "pressed"),
+                    },
+                    hovered: {
+                        background: background(layer, "variant", "hovered"),
+                        color: foreground(layer, "variant", "hovered"),
+                    }
+                }
+            }),
+                {
+                    default: {
+                        background: background(layer, "variant", "active"),
+                        color: foreground(layer, "variant", "active")
+                    }
+                },
+            ),
+            userMenuButton: merge(titlebarButton, {
+                inactive: {
+                    default: {
+                        buttonWidth: 20,
+                        iconWidth: 12
+                    }
+                }, active: { // posiewic: these properties are not currently set on main
+                    default: {
+                        iconWidth: 12,
+                        button_width: 20,
+                    }
+                }
+            }),
+
+
+            toggleContactsBadge: {
+                cornerRadius: 3,
+                padding: 2,
+                margin: { top: 3, left: 3 },
+                border: border(layer),
+                background: foreground(layer, "accent"),
             },
-            disabled: {
-              color: foreground(colorScheme.highest, "on", "disabled"),
+            shareButton: {
+                ...titlebarButton,
             },
-          }
+        },
+
+        toolbar: {
+            height: 34,
+            background: background(colorScheme.highest),
+            border: border(colorScheme.highest, { bottom: true }),
+            itemSpacing: 8,
+            navButton: interactive(
+                {
+                    base: {
+                        color: foreground(colorScheme.highest, "on"),
+                        iconWidth: 12,
+                        buttonWidth: 24,
+                        cornerRadius: 6,
+                    }, state: {
+                        hovered: {
+                            color: foreground(colorScheme.highest, "on", "hovered"),
+                            background: background(
+                                colorScheme.highest,
+                                "on",
+                                "hovered"
+                            ),
+                        },
+                        disabled: {
+                            color: foreground(colorScheme.highest, "on", "disabled"),
+                        },
+                    }
+                }),
+            padding: { left: 8, right: 8, top: 4, bottom: 4 },
+        },
+        breadcrumbHeight: 24,
+        breadcrumbs: interactive({
+            base: {
+                ...text(colorScheme.highest, "sans", "variant"),
+                cornerRadius: 6,
+                padding: {
+                    left: 6,
+                    right: 6,
+                }
+            }, state: {
+                hovered: {
+                    color: foreground(colorScheme.highest, "on", "hovered"),
+                    background: background(colorScheme.highest, "on", "hovered"),
+                },
+            }
         }),
-      padding: { left: 8, right: 8, top: 4, bottom: 4 },
-    },
-    breadcrumbHeight: 24,
-    breadcrumbs: interactive({
-      base: {
-        ...text(colorScheme.highest, "sans", "variant"),
-        cornerRadius: 6,
-        padding: {
-          left: 6,
-          right: 6,
-        }
-      }, state: {
-        hovered: {
-          color: foreground(colorScheme.highest, "on", "hovered"),
-          background: background(colorScheme.highest, "on", "hovered"),
+        disconnectedOverlay: {
+            ...text(layer, "sans"),
+            background: withOpacity(background(layer), 0.8),
         },
-      }
-    }),
-    disconnectedOverlay: {
-      ...text(layer, "sans"),
-      background: withOpacity(background(layer), 0.8),
-    },
-    notification: {
-      margin: { top: 10 },
-      background: background(colorScheme.middle),
-      cornerRadius: 6,
-      padding: 12,
-      border: border(colorScheme.middle),
-      shadow: colorScheme.popoverShadow,
-    },
-    notifications: {
-      width: 400,
-      margin: { right: 10, bottom: 10 },
-    },
-    dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
-  }
+        notification: {
+            margin: { top: 10 },
+            background: background(colorScheme.middle),
+            cornerRadius: 6,
+            padding: 12,
+            border: border(colorScheme.middle),
+            shadow: colorScheme.popoverShadow,
+        },
+        notifications: {
+            width: 400,
+            margin: { right: 10, bottom: 10 },
+        },
+        dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
+    }
 }

styles/vitest.config.ts 🔗

@@ -0,0 +1,8 @@
+import { configDefaults, defineConfig } from 'vitest/config'
+
+export default defineConfig({
+    test: {
+        exclude: [...configDefaults.exclude, 'target/*'],
+        include: ['src/**/*.{spec,test}.ts'],
+    },
+})