diff --git a/docs/.gitignore b/docs/.gitignore
index b2d6de30..b4a1a87d 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -3,6 +3,7 @@
# Production
/build
+/static/animations/
# Generated files
.docusaurus
diff --git a/docs/docs/behaviors/hold-tap.md b/docs/docs/behaviors/hold-tap.md
index f0096606..9a34663f 100644
--- a/docs/docs/behaviors/hold-tap.md
+++ b/docs/docs/behaviors/hold-tap.md
@@ -5,6 +5,7 @@ sidebar_label: Hold-Tap
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+import AnimationPlayer from '@site/src/components/AnimationPlayer';
## Summary
@@ -12,28 +13,75 @@ Hold-tap is the basis for other behaviors such as layer-tap and mod-tap.
Simply put, the hold-tap key will output the 'hold' behavior if it's held for a while, and output the 'tap' behavior when it's tapped quickly.
-### Hold-Tap
+### Flavors
-The graph below shows how the hold-tap decides between a 'tap' and a 'hold'.
+The 'flavor' of a hold-tap determines its behavior when it is tapped, held, and when another key is pressed while the hold-tap is undecided. For example, the [mod-tap](mod-tap.md) is a 'hold-preferred' hold-tap, while the [layer-tap](layers.md/#layer-tap) is of the 'tap-preferred' variety.
-
+
+
+
+
+The simplest flavor, 'hold-preferred', triggers the hold behavior when the [`tapping-term-ms`](#tapping-term-ms) has expired or another key is pressed.
+When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
+
+
By default, the hold-tap is configured to also select the 'hold' functionality if another key is tapped while it's active:
-
+
-We call this the 'hold-preferred' flavor of hold-taps. While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are two more flavors to choose from: 'tap-preferred' and 'balanced'.
+While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are more flavors to choose from: 'balanced', 'tap-preferred' and 'tap-unless-interrupted'.
-#### Flavors
+
-- The 'hold-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired or another key is pressed.
-- The 'balanced' flavor will trigger the hold behavior when the `tapping-term-ms` has expired or another key is pressed and released.
-- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. Pressing another key within `tapping-term-ms` does not affect the decision.
-- The 'tap-unless-interrupted' flavor triggers a hold behavior only when another key is pressed before `tapping-term-ms` has expired. It triggers the tap behavior in all other situations.
+
-When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
+The 'balanced' flavor triggers the hold behavior when the [`tapping-term-ms`](#tapping-term-ms) has expired.
-
+
+
+Alternatively, if another key is pressed while the 'balanced' hold-tap pressed, releasing the _hold-tap_ before the interrupting keypress will invoke the tap behavior.
+
+
+
+On the other hand, if the _interrupting key_ is released before the hold-tap, the hold behavior will be invoked.
+
+
+
+
+
+
+
+The 'tap-preferred' flavor triggers the hold behavior when the [`tapping-term-ms`](#tapping-term-ms) has expired.
+
+
+
+As shown below, pressing another key within [`tapping-term-ms`](#tapping-term-ms) does not affect the hold-tap decision; only the press duration will decide if the 'tap-preferred' hold-tap is a 'hold' or a 'tap'.
+
+
+
+
+
+
+
+The press duration of the 'tap-unless-interrupted' flavor of hold-tap does not have an effect on the output: the 'tap' behavior will always be invoked.
+
+
+
+Only another key being pressed can invoke the 'hold' behavior.
+
+
+
+
+
+
### Basic usage
@@ -43,7 +91,7 @@ For basic usage, please see the [mod-tap](mod-tap.md) and [layer-tap](layers.md#
#### `tapping-term-ms`
-Defines how long a key must be pressed to trigger Hold behavior.
+Defines how long a key must be pressed to trigger the 'hold' behavior.
#### `quick-tap-ms`
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 2c8a7fba..bb954242 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -14,6 +14,11 @@
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.18",
"@mdx-js/react": "^1.6.22",
+ "@motion-canvas/2d": "^2.2.0",
+ "@motion-canvas/core": "^2.2.0",
+ "@motion-canvas/player": "^2.2.0",
+ "@motion-canvas/ui": "^2.2.0",
+ "@motion-canvas/vite-plugin": "^2.2.0",
"classnames": "^2.2.6",
"js-yaml": "^4.1.0",
"react": "^17.0.2",
@@ -2583,6 +2588,38 @@
"node": ">=16.14"
}
},
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@eslint/eslintrc": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -2979,6 +3016,70 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/@motion-canvas/2d": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-2.2.0.tgz",
+ "integrity": "sha512-IE/svVCBsD1EAqBoMtkuFovO8IrDG55BOqo1CgfwDLvhoKC1PnGgseBDNXT4CfCPlCsJ+M/xWWCFiYK3YIOi3Q==",
+ "dependencies": {
+ "@motion-canvas/core": "^2.2.0",
+ "code-fns": "^0.7.0"
+ }
+ },
+ "node_modules/@motion-canvas/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-iGVKp6Sl7rvmZHCM0LObnpG9KqK7ch7UBItx03l2BQFcqf/ltBANDzJulF2MZBdEXVj7vgwuRZidfAJxTyBQEA==",
+ "dependencies": {
+ "@types/chroma-js": "^2.1.4",
+ "chroma-js": "^2.4.2"
+ },
+ "peerDependencies": {
+ "vite": "^3.0.5"
+ }
+ },
+ "node_modules/@motion-canvas/player": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/player/-/player-2.2.0.tgz",
+ "integrity": "sha512-E4M8EqXSY1DXnhqPwlCDYxZrqGGt2C1AEEwnm6/fU8hAZ3xfi2mIUAL+/jE5r2OBn/sbb/j5757OB4yzqvQkJQ=="
+ },
+ "node_modules/@motion-canvas/ui": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-2.2.0.tgz",
+ "integrity": "sha512-97r6Zee6PVUcBCtK+RtKi/f9Z+vKVtWR/FzrAVJUq3t0icduiDKRmxIEBwNyaWcHaSXAlBf9widZ1NkXrjASLA==",
+ "dependencies": {
+ "@motion-canvas/core": "^2.2.0"
+ }
+ },
+ "node_modules/@motion-canvas/vite-plugin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-2.2.0.tgz",
+ "integrity": "sha512-D9K/pl5NmSiCcAqBiGVkd1v6uuBD94jOH1yV2Dxur5ziCf6AjIV0DACKsWH8JE7KEDWuWfeJlbCoFkH+p9JbJA==",
+ "dependencies": {
+ "mime-types": "^2.1.35"
+ },
+ "peerDependencies": {
+ "vite": "3.x"
+ }
+ },
+ "node_modules/@motion-canvas/vite-plugin/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@motion-canvas/vite-plugin/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -3374,6 +3475,11 @@
"@types/node": "*"
}
},
+ "node_modules/@types/chroma-js": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.5.tgz",
+ "integrity": "sha512-LnJmElng1zoH7GOYqIo/EuL7L0/vEh5rc+fKaF4rsylJyjwOkX0pXeBemH25FQAWHifKJWqaRwR0EhC+yDod9A=="
+ },
"node_modules/@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
@@ -3836,6 +3942,21 @@
"@xtuc/long": "4.2.2"
}
},
+ "node_modules/@wooorm/starry-night": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@wooorm/starry-night/-/starry-night-1.5.0.tgz",
+ "integrity": "sha512-YEkNgM8IxKwzRQgTp1nyiraB5rc4LiLpnMTrJvX5+SVs7zgVqkTx6QAZgZFqrZrqq/UCWVYBzE9+zZfxpLPTYQ==",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "import-meta-resolve": "^2.0.0",
+ "vscode-oniguruma": "^1.0.0",
+ "vscode-textmate": "^7.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -4753,6 +4874,11 @@
"fsevents": "~2.3.2"
}
},
+ "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/chrome-trace-event": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
@@ -4881,6 +5007,14 @@
"node": ">=6"
}
},
+ "node_modules/code-fns": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/code-fns/-/code-fns-0.7.1.tgz",
+ "integrity": "sha512-5OXF24qyo2bcW52h2mJesu2N+5hu6jk8P32SyFjjQUO2YQRgbpv3sRrF9mSmaJwvAf7B69nQBkHPTzcH35Hlmg==",
+ "dependencies": {
+ "@wooorm/starry-night": "^1.2.0"
+ }
+ },
"node_modules/collapse-white-space": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
@@ -6138,6 +6272,363 @@
"es6-symbol": "^3.1.1"
}
},
+ "node_modules/esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "hasInstallScript": true,
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -8441,6 +8932,15 @@
"node": ">=4"
}
},
+ "node_modules/import-meta-resolve": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.1.tgz",
+ "integrity": "sha512-C6lLL7EJPY44kBvA80gq4uMsVFw5x3oSKfuMl1cuZ2RkI5+UJqQXgn+6hlUew0y4ig7Ypt4CObAAIzU53Nfpuw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -13331,6 +13831,21 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "peer": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
"node_modules/rtl-detect": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz",
@@ -15302,6 +15817,65 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/vite": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
+ "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.15.9",
+ "postcss": "^8.4.18",
+ "resolve": "^1.22.1",
+ "rollup": "^2.79.1"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vscode-oniguruma": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
+ "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
+ },
+ "node_modules/vscode-textmate": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-7.0.4.tgz",
+ "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A=="
+ },
"node_modules/wait-on": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz",
@@ -17793,6 +18367,20 @@
"tslib": "^2.4.0"
}
},
+ "@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "optional": true,
+ "peer": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "optional": true,
+ "peer": true
+ },
"@eslint/eslintrc": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz",
@@ -18091,6 +18679,60 @@
"resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz",
"integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA=="
},
+ "@motion-canvas/2d": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-2.2.0.tgz",
+ "integrity": "sha512-IE/svVCBsD1EAqBoMtkuFovO8IrDG55BOqo1CgfwDLvhoKC1PnGgseBDNXT4CfCPlCsJ+M/xWWCFiYK3YIOi3Q==",
+ "requires": {
+ "@motion-canvas/core": "^2.2.0",
+ "code-fns": "^0.7.0"
+ }
+ },
+ "@motion-canvas/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-iGVKp6Sl7rvmZHCM0LObnpG9KqK7ch7UBItx03l2BQFcqf/ltBANDzJulF2MZBdEXVj7vgwuRZidfAJxTyBQEA==",
+ "requires": {
+ "@types/chroma-js": "^2.1.4",
+ "chroma-js": "^2.4.2"
+ }
+ },
+ "@motion-canvas/player": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/player/-/player-2.2.0.tgz",
+ "integrity": "sha512-E4M8EqXSY1DXnhqPwlCDYxZrqGGt2C1AEEwnm6/fU8hAZ3xfi2mIUAL+/jE5r2OBn/sbb/j5757OB4yzqvQkJQ=="
+ },
+ "@motion-canvas/ui": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-2.2.0.tgz",
+ "integrity": "sha512-97r6Zee6PVUcBCtK+RtKi/f9Z+vKVtWR/FzrAVJUq3t0icduiDKRmxIEBwNyaWcHaSXAlBf9widZ1NkXrjASLA==",
+ "requires": {
+ "@motion-canvas/core": "^2.2.0"
+ }
+ },
+ "@motion-canvas/vite-plugin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-2.2.0.tgz",
+ "integrity": "sha512-D9K/pl5NmSiCcAqBiGVkd1v6uuBD94jOH1yV2Dxur5ziCf6AjIV0DACKsWH8JE7KEDWuWfeJlbCoFkH+p9JbJA==",
+ "requires": {
+ "mime-types": "^2.1.35"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ }
+ }
+ },
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -18336,6 +18978,11 @@
"@types/node": "*"
}
},
+ "@types/chroma-js": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.5.tgz",
+ "integrity": "sha512-LnJmElng1zoH7GOYqIo/EuL7L0/vEh5rc+fKaF4rsylJyjwOkX0pXeBemH25FQAWHifKJWqaRwR0EhC+yDod9A=="
+ },
"@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
@@ -18798,6 +19445,17 @@
"@xtuc/long": "4.2.2"
}
},
+ "@wooorm/starry-night": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@wooorm/starry-night/-/starry-night-1.5.0.tgz",
+ "integrity": "sha512-YEkNgM8IxKwzRQgTp1nyiraB5rc4LiLpnMTrJvX5+SVs7zgVqkTx6QAZgZFqrZrqq/UCWVYBzE9+zZfxpLPTYQ==",
+ "requires": {
+ "@types/hast": "^2.0.0",
+ "import-meta-resolve": "^2.0.0",
+ "vscode-oniguruma": "^1.0.0",
+ "vscode-textmate": "^7.0.0"
+ }
+ },
"@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -19463,6 +20121,11 @@
"readdirp": "~3.6.0"
}
},
+ "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=="
+ },
"chrome-trace-event": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
@@ -19558,6 +20221,14 @@
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
},
+ "code-fns": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/code-fns/-/code-fns-0.7.1.tgz",
+ "integrity": "sha512-5OXF24qyo2bcW52h2mJesu2N+5hu6jk8P32SyFjjQUO2YQRgbpv3sRrF9mSmaJwvAf7B69nQBkHPTzcH35Hlmg==",
+ "requires": {
+ "@wooorm/starry-night": "^1.2.0"
+ }
+ },
"collapse-white-space": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
@@ -20474,6 +21145,176 @@
"es6-symbol": "^3.1.1"
}
},
+ "esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "peer": true,
+ "requires": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "optional": true,
+ "peer": true
+ },
+ "esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "optional": true,
+ "peer": true
+ },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -22156,6 +22997,11 @@
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
"integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A=="
},
+ "import-meta-resolve": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.1.tgz",
+ "integrity": "sha512-C6lLL7EJPY44kBvA80gq4uMsVFw5x3oSKfuMl1cuZ2RkI5+UJqQXgn+6hlUew0y4ig7Ypt4CObAAIzU53Nfpuw=="
+ },
"imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -25530,6 +26376,15 @@
"glob": "^7.1.3"
}
},
+ "rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "peer": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
"rtl-detect": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.0.4.tgz",
@@ -26951,6 +27806,29 @@
}
}
},
+ "vite": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
+ "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
+ "peer": true,
+ "requires": {
+ "esbuild": "^0.15.9",
+ "fsevents": "~2.3.2",
+ "postcss": "^8.4.18",
+ "resolve": "^1.22.1",
+ "rollup": "^2.79.1"
+ }
+ },
+ "vscode-oniguruma": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
+ "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
+ },
+ "vscode-textmate": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-7.0.4.tgz",
+ "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A=="
+ },
"wait-on": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz",
diff --git a/docs/package.json b/docs/package.json
index 70105b54..0c3d7681 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"start": "docusaurus start --host 0.0.0.0",
- "build": "docusaurus build",
+ "build": "npm run build_animations && docusaurus build",
"serve": "docusaurus serve",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
@@ -12,7 +12,8 @@
"lint": "eslint . --ext js,jsx,md,mdx",
"prettier:check": "prettier --check .",
"prettier:format": "prettier --write .",
- "typecheck": "tsc"
+ "typecheck": "tsc",
+ "build_animations": "cd src/animationhelpers && npm run build"
},
"dependencies": {
"@docusaurus/core": "^2.1.0",
@@ -21,6 +22,11 @@
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.18",
"@mdx-js/react": "^1.6.22",
+ "@motion-canvas/2d": "^2.2.0",
+ "@motion-canvas/core": "^2.2.0",
+ "@motion-canvas/player": "^2.2.0",
+ "@motion-canvas/ui": "^2.2.0",
+ "@motion-canvas/vite-plugin": "^2.2.0",
"classnames": "^2.2.6",
"js-yaml": "^4.1.0",
"react": "^17.0.2",
diff --git a/docs/src/animationhelpers/.gitignore b/docs/src/animationhelpers/.gitignore
new file mode 100644
index 00000000..829b1c7e
--- /dev/null
+++ b/docs/src/animationhelpers/.gitignore
@@ -0,0 +1,15 @@
+# Generated files
+node_modules
+output
+dist
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/docs/src/animationhelpers/package-lock.json b/docs/src/animationhelpers/package-lock.json
new file mode 100644
index 00000000..055f5988
--- /dev/null
+++ b/docs/src/animationhelpers/package-lock.json
@@ -0,0 +1,710 @@
+{
+ "name": "animationhelpers",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "animationhelpers",
+ "version": "0.0.0",
+ "dependencies": {
+ "@motion-canvas/2d": "^2.2.0",
+ "@motion-canvas/core": "^2.2.0"
+ },
+ "devDependencies": {
+ "@motion-canvas/ui": "^2.2.0",
+ "@motion-canvas/vite-plugin": "^2.2.0",
+ "typescript": "^4.9.5",
+ "vite": "^3.0.5"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+ "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+ "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@motion-canvas/2d": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/2d/-/2d-2.2.0.tgz",
+ "integrity": "sha512-IE/svVCBsD1EAqBoMtkuFovO8IrDG55BOqo1CgfwDLvhoKC1PnGgseBDNXT4CfCPlCsJ+M/xWWCFiYK3YIOi3Q==",
+ "dependencies": {
+ "@motion-canvas/core": "^2.2.0",
+ "code-fns": "^0.7.0"
+ }
+ },
+ "node_modules/@motion-canvas/core": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/core/-/core-2.2.0.tgz",
+ "integrity": "sha512-iGVKp6Sl7rvmZHCM0LObnpG9KqK7ch7UBItx03l2BQFcqf/ltBANDzJulF2MZBdEXVj7vgwuRZidfAJxTyBQEA==",
+ "dependencies": {
+ "@types/chroma-js": "^2.1.4",
+ "chroma-js": "^2.4.2"
+ },
+ "peerDependencies": {
+ "vite": "^3.0.5"
+ }
+ },
+ "node_modules/@motion-canvas/ui": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/ui/-/ui-2.2.0.tgz",
+ "integrity": "sha512-97r6Zee6PVUcBCtK+RtKi/f9Z+vKVtWR/FzrAVJUq3t0icduiDKRmxIEBwNyaWcHaSXAlBf9widZ1NkXrjASLA==",
+ "dev": true,
+ "dependencies": {
+ "@motion-canvas/core": "^2.2.0"
+ }
+ },
+ "node_modules/@motion-canvas/vite-plugin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@motion-canvas/vite-plugin/-/vite-plugin-2.2.0.tgz",
+ "integrity": "sha512-D9K/pl5NmSiCcAqBiGVkd1v6uuBD94jOH1yV2Dxur5ziCf6AjIV0DACKsWH8JE7KEDWuWfeJlbCoFkH+p9JbJA==",
+ "dev": true,
+ "dependencies": {
+ "mime-types": "^2.1.35"
+ },
+ "peerDependencies": {
+ "vite": "3.x"
+ }
+ },
+ "node_modules/@types/chroma-js": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.5.tgz",
+ "integrity": "sha512-LnJmElng1zoH7GOYqIo/EuL7L0/vEh5rc+fKaF4rsylJyjwOkX0pXeBemH25FQAWHifKJWqaRwR0EhC+yDod9A=="
+ },
+ "node_modules/@types/hast": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz",
+ "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
+ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
+ },
+ "node_modules/@wooorm/starry-night": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@wooorm/starry-night/-/starry-night-1.5.0.tgz",
+ "integrity": "sha512-YEkNgM8IxKwzRQgTp1nyiraB5rc4LiLpnMTrJvX5+SVs7zgVqkTx6QAZgZFqrZrqq/UCWVYBzE9+zZfxpLPTYQ==",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "import-meta-resolve": "^2.0.0",
+ "vscode-oniguruma": "^1.0.0",
+ "vscode-textmate": "^7.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "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/code-fns": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/code-fns/-/code-fns-0.7.1.tgz",
+ "integrity": "sha512-5OXF24qyo2bcW52h2mJesu2N+5hu6jk8P32SyFjjQUO2YQRgbpv3sRrF9mSmaJwvAf7B69nQBkHPTzcH35Hlmg==",
+ "dependencies": {
+ "@wooorm/starry-night": "^1.2.0"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+ "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.15.18",
+ "@esbuild/linux-loong64": "0.15.18",
+ "esbuild-android-64": "0.15.18",
+ "esbuild-android-arm64": "0.15.18",
+ "esbuild-darwin-64": "0.15.18",
+ "esbuild-darwin-arm64": "0.15.18",
+ "esbuild-freebsd-64": "0.15.18",
+ "esbuild-freebsd-arm64": "0.15.18",
+ "esbuild-linux-32": "0.15.18",
+ "esbuild-linux-64": "0.15.18",
+ "esbuild-linux-arm": "0.15.18",
+ "esbuild-linux-arm64": "0.15.18",
+ "esbuild-linux-mips64le": "0.15.18",
+ "esbuild-linux-ppc64le": "0.15.18",
+ "esbuild-linux-riscv64": "0.15.18",
+ "esbuild-linux-s390x": "0.15.18",
+ "esbuild-netbsd-64": "0.15.18",
+ "esbuild-openbsd-64": "0.15.18",
+ "esbuild-sunos-64": "0.15.18",
+ "esbuild-windows-32": "0.15.18",
+ "esbuild-windows-64": "0.15.18",
+ "esbuild-windows-arm64": "0.15.18"
+ }
+ },
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+ "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+ "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+ "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+ "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+ "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+ "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+ "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+ "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+ "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+ "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+ "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+ "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+ "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+ "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+ "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+ "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+ "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+ "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+ "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.18",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+ "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/import-meta-resolve": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.1.tgz",
+ "integrity": "sha512-C6lLL7EJPY44kBvA80gq4uMsVFw5x3oSKfuMl1cuZ2RkI5+UJqQXgn+6hlUew0y4ig7Ypt4CObAAIzU53Nfpuw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "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/postcss": {
+ "version": "8.4.21",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
+ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "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/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz",
+ "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==",
+ "dependencies": {
+ "esbuild": "^0.15.9",
+ "postcss": "^8.4.18",
+ "resolve": "^1.22.1",
+ "rollup": "^2.79.1"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ },
+ "peerDependencies": {
+ "@types/node": ">= 14",
+ "less": "*",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vscode-oniguruma": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
+ "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
+ },
+ "node_modules/vscode-textmate": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-7.0.4.tgz",
+ "integrity": "sha512-9hJp0xL7HW1Q5OgGe03NACo7yiCTMEk3WU/rtKXUbncLtdg6rVVNJnHwD88UhbIYU2KoxY0Dih0x+kIsmUKn2A=="
+ }
+ }
+}
diff --git a/docs/src/animationhelpers/package.json b/docs/src/animationhelpers/package.json
new file mode 100644
index 00000000..fc00d3a0
--- /dev/null
+++ b/docs/src/animationhelpers/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "animationhelpers",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "serve": "vite",
+ "build": "tsc && vite build"
+ },
+ "dependencies": {
+ "@motion-canvas/core": "^2.2.0",
+ "@motion-canvas/2d": "^2.2.0"
+ },
+ "devDependencies": {
+ "@motion-canvas/ui": "^2.2.0",
+ "@motion-canvas/vite-plugin": "^2.2.0",
+ "typescript": "^4.9.5",
+ "vite": "^3.0.5"
+ }
+}
diff --git a/docs/src/animationhelpers/src/components/Key.tsx b/docs/src/animationhelpers/src/components/Key.tsx
new file mode 100644
index 00000000..5563dd7d
--- /dev/null
+++ b/docs/src/animationhelpers/src/components/Key.tsx
@@ -0,0 +1,82 @@
+import { Rect, Text, Node } from "@motion-canvas/2d/lib/components";
+import { SignalValue } from "@motion-canvas/core/lib/signals";
+import { makeRef } from "@motion-canvas/core/lib/utils";
+
+const KeySize = 200;
+const KeyRadius = 10;
+export const KeyBorderThickness = 10;
+export const KeyTravel = 40;
+
+export default function Key({
+ refs,
+ binding,
+ params,
+}: {
+ refs: {
+ group: Node;
+ body: Node;
+ fill: Rect;
+ duration: Rect;
+ shadow: Rect;
+ binding: Text;
+ params: Text;
+ };
+ binding: SignalValue;
+ params: SignalValue;
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/src/animationhelpers/src/components/Output.tsx b/docs/src/animationhelpers/src/components/Output.tsx
new file mode 100644
index 00000000..1fbb36a2
--- /dev/null
+++ b/docs/src/animationhelpers/src/components/Output.tsx
@@ -0,0 +1,126 @@
+import { Rect, Text } from "@motion-canvas/2d/lib/components";
+import { makeRef } from "@motion-canvas/core/lib/utils";
+import { KeyBorderThickness } from "./Key";
+
+const OutputThickness = KeyBorderThickness / 2;
+const OutputFontSize = 40;
+const OutputFontWeight = 600;
+const ModifierRadius = 10;
+const ModifierFontSize = 32;
+const ModifierFontWeight = 600;
+const ModifierMargin = 20;
+
+export default function Output({
+ refs,
+}: {
+ refs: {
+ group: Rect;
+ output: Text;
+ shift: Rect;
+ alt: Rect;
+ ctrl: Rect;
+ gui: Rect;
+ };
+}) {
+ return (
+
+
+
+
+
+
+ "SHIFT"}
+ fontWeight={ModifierFontWeight}
+ fontSize={ModifierFontSize}
+ fontFamily={"sans-serif"}
+ margin={ModifierMargin}
+ />
+
+
+
+ "ALT"}
+ fontWeight={ModifierFontWeight}
+ fontSize={ModifierFontSize}
+ fontFamily={"sans-serif"}
+ margin={ModifierMargin}
+ />
+
+
+
+ "CTRL"}
+ fontWeight={ModifierFontWeight}
+ fontSize={ModifierFontSize}
+ fontFamily={"sans-serif"}
+ margin={ModifierMargin}
+ />
+
+
+
+ "GUI"}
+ fontWeight={ModifierFontWeight}
+ fontSize={ModifierFontSize}
+ fontFamily={"sans-serif"}
+ margin={ModifierMargin}
+ />
+
+
+
+ );
+}
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.meta b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.ts b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.ts
new file mode 100644
index 00000000..6c0389ef
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_comparison.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import balanced_comparison from "../../scenes/hold_tap/balanced/balanced_comparison?scene";
+
+export default makeProject({
+ scenes: [balanced_comparison],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.meta b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.ts b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.ts
new file mode 100644
index 00000000..5aebe298
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_hold_tap_up.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import balanced_hold_tap_up from "../../scenes/hold_tap/balanced/balanced_hold_tap_up?scene";
+
+export default makeProject({
+ scenes: [balanced_hold_tap_up],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.meta b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.ts b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.ts
new file mode 100644
index 00000000..6b7cc2e7
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/balanced/balanced_other_key_up.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import balanced_other_key_up from "../../scenes/hold_tap/balanced/balanced_other_key_up?scene";
+
+export default makeProject({
+ scenes: [balanced_other_key_up],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.meta b/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.ts b/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.ts
new file mode 100644
index 00000000..8dd1f7ff
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/hold_tap_comparison.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import hold_tap_comparison from "../scenes/hold_tap/hold_tap_comparison?scene";
+
+export default makeProject({
+ scenes: [hold_tap_comparison],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.meta b/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.ts b/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.ts
new file mode 100644
index 00000000..88ee3b97
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/hold_tap_interrupted.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import hold_tap_interrupted from "../scenes/hold_tap/hold_tap_interrupted?scene";
+
+export default makeProject({
+ scenes: [hold_tap_interrupted],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.meta b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.ts b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.ts
new file mode 100644
index 00000000..7656cf4d
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_comparison.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import tap_preferred_comparison from "../../scenes/hold_tap/tap_preferred/tap_preferred_comparison?scene";
+
+export default makeProject({
+ scenes: [tap_preferred_comparison],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.ts b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.ts
new file mode 100644
index 00000000..11c37d8a
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import tap_preferred_hold_tap_up from "../../scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up?scene";
+
+export default makeProject({
+ scenes: [tap_preferred_hold_tap_up],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.ts b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.ts
new file mode 100644
index 00000000..7ad122ad
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import tap_unless_interrupted from "../../scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted?scene";
+
+export default makeProject({
+ scenes: [tap_unless_interrupted],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.ts b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.ts
new file mode 100644
index 00000000..9af21b02
--- /dev/null
+++ b/docs/src/animationhelpers/src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.ts
@@ -0,0 +1,8 @@
+import { makeProject } from "@motion-canvas/core/lib";
+
+import tap_unless_interrupted_invoke_hold from "../../scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold?scene";
+
+export default makeProject({
+ scenes: [tap_unless_interrupted_invoke_hold],
+ background: "#FFFFFF",
+});
diff --git a/docs/src/animationhelpers/src/motion-canvas.d.ts b/docs/src/animationhelpers/src/motion-canvas.d.ts
new file mode 100644
index 00000000..067c6a44
--- /dev/null
+++ b/docs/src/animationhelpers/src/motion-canvas.d.ts
@@ -0,0 +1 @@
+///
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.meta b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.tsx
new file mode 100644
index 00000000..9dfa54c8
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_comparison.tsx
@@ -0,0 +1,53 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const tap = makeRefs();
+ view.add();
+ tap.group.position.x(-400);
+ tap.group.position.y(-150);
+ tap.duration.fill("#D9D9D9");
+
+ const tap_output = makeRefs();
+ view.add();
+ tap_output.group.position(tap.group.position());
+ tap_output.group.position.y(tap_output.group.position.y() + 300);
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(400);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position());
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* all(
+ tap.body.position.y(KeyTravel, 0.15),
+ hold.body.position.y(KeyTravel, 0.15)
+ );
+ yield* all(
+ tap.duration.grow(0.5, 1, linear),
+ delay(1, tap.body.position.y(0, 0.15)),
+ hold.duration.grow(1, 2, linear)
+ );
+ yield* chain(
+ all(tap.group.rotation(3, 0.03), hold.group.rotation(3, 0.03)),
+ all(tap.group.rotation(-3, 0.06), hold.group.rotation(-3, 0.06)),
+ all(tap.group.rotation(0, 0.03), hold.group.rotation(0, 0.03)),
+ all(tap_output.output.text("f", 0), hold_output.shift.fill("#969696", 0.15))
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(
+ 0.5,
+ all(tap.duration.grow(0, 0.15), hold.duration.grow(0, 0.15))
+ );
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.meta b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.tsx
new file mode 100644
index 00000000..5c094bc6
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_hold_tap_up.tsx
@@ -0,0 +1,53 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { any, all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const interrupt = makeRefs();
+ view.add();
+ interrupt.group.position.x(125);
+ interrupt.group.position.y(-150);
+ interrupt.duration.fill("#D9D9D9");
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(-125);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position().addX(125));
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* any(
+ hold.body.position.y(KeyTravel, 0.15),
+ hold.duration.grow(0.5, 1, linear)
+ );
+ yield* delay(
+ 0.35,
+ all(
+ interrupt.body.position.y(KeyTravel, 0.15),
+ hold.duration.fill("F21D00", 0.15)
+ )
+ );
+ yield* delay(
+ 0.35,
+ chain(
+ hold.body.position.y(0, 0.15),
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ hold.duration.grow(0, 0.15),
+ delay(0.05, hold_output.output.text("f", 0)),
+ delay(0.05, hold_output.output.text("fj", 0))
+ )
+ );
+ yield* waitFor(0.25);
+ yield* interrupt.body.position.y(0, 0.15);
+ yield* waitFor(1);
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.meta b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.tsx
new file mode 100644
index 00000000..7d1c0752
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/balanced/balanced_other_key_up.tsx
@@ -0,0 +1,55 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { any, all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const interrupt = makeRefs();
+ view.add();
+ interrupt.group.position.x(125);
+ interrupt.group.position.y(-150);
+ interrupt.duration.fill("#D9D9D9");
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(-125);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position().addX(125));
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* any(
+ hold.body.position.y(KeyTravel, 0.15),
+ hold.duration.grow(0.5, 1, linear)
+ );
+ yield* delay(
+ 0.35,
+ all(
+ interrupt.body.position.y(KeyTravel, 0.15),
+ hold.duration.fill("F21D00", 0.15)
+ )
+ );
+ yield* delay(
+ 0.35,
+ chain(
+ interrupt.body.position.y(0, 0.15),
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ hold.duration.grow(0, 0.15),
+ all(
+ delay(0.05, hold_output.output.text("J", 0)),
+ hold_output.shift.fill("#969696", 0.1)
+ )
+ )
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* waitFor(1);
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.meta b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.tsx
new file mode 100644
index 00000000..af360c5d
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_comparison.tsx
@@ -0,0 +1,80 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { Text } from "@motion-canvas/2d/lib/components";
+import { createRef, makeRefs } from "@motion-canvas/core/lib/utils";
+import { all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../components/Key";
+import Output from "../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const tap = makeRefs();
+ view.add();
+ tap.group.position.x(-400);
+ tap.group.position.y(-150);
+ tap.duration.fill("#D9D9D9");
+
+ const tap_output = makeRefs();
+ view.add();
+ tap_output.group.position(tap.group.position());
+ tap_output.group.position.y(tap_output.group.position.y() + 300);
+
+ const tap_label = createRef();
+ view.add(
+
+ tap
+
+ );
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(400);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position());
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ const hold_tap = createRef();
+ view.add(
+
+ hold
+
+ );
+
+ yield* waitFor(0.5);
+ yield* all(
+ tap.body.position.y(KeyTravel, 0.15),
+ hold.body.position.y(KeyTravel, 0.15)
+ );
+ yield* all(
+ tap.duration.grow(0.5, 1, linear),
+ delay(1, tap.body.position.y(0, 0.15)),
+ hold.duration.grow(1, 2, linear)
+ );
+ yield* chain(
+ all(tap.group.rotation(3, 0.03), hold.group.rotation(3, 0.03)),
+ all(tap.group.rotation(-3, 0.06), hold.group.rotation(-3, 0.06)),
+ all(tap.group.rotation(0, 0.03), hold.group.rotation(0, 0.03)),
+ all(tap_output.output.text("f", 0), hold_output.shift.fill("#969696", 0.15))
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(
+ 0.5,
+ all(tap.duration.grow(0, 0.15), hold.duration.grow(0, 0.15))
+ );
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.meta b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.tsx
new file mode 100644
index 00000000..134e312f
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/hold_tap_interrupted.tsx
@@ -0,0 +1,50 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { any, all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../components/Key";
+import Output from "../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const interrupt = makeRefs();
+ view.add();
+ interrupt.group.position.x(125);
+ interrupt.group.position.y(-150);
+ interrupt.duration.fill("#D9D9D9");
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(-125);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position().addX(125));
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* any(
+ hold.body.position.y(KeyTravel, 0.15),
+ hold.duration.grow(0.75, 1.5, linear)
+ );
+ yield* delay(
+ 1.2,
+ all(
+ interrupt.body.position.y(KeyTravel, 0.15),
+ hold.duration.fill("F21D00", 0.15)
+ )
+ );
+ yield* chain(
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ all(
+ delay(0.15, hold_output.output.text("J", 0)),
+ hold_output.shift.fill("#969696", 0.15)
+ )
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(0.5, hold.duration.grow(0, 0.15));
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.meta b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.tsx
new file mode 100644
index 00000000..6121175b
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_comparison.tsx
@@ -0,0 +1,53 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const tap = makeRefs();
+ view.add();
+ tap.group.position.x(-400);
+ tap.group.position.y(-150);
+ tap.duration.fill("#D9D9D9");
+
+ const tap_output = makeRefs();
+ view.add();
+ tap_output.group.position(tap.group.position());
+ tap_output.group.position.y(tap_output.group.position.y() + 300);
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(400);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position());
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* all(
+ tap.body.position.y(KeyTravel, 0.15),
+ hold.body.position.y(KeyTravel, 0.15)
+ );
+ yield* all(
+ tap.duration.grow(0.5, 1, linear),
+ delay(1, tap.body.position.y(0, 0.15)),
+ hold.duration.grow(1, 2, linear)
+ );
+ yield* chain(
+ all(tap.group.rotation(3, 0.03), hold.group.rotation(3, 0.03)),
+ all(tap.group.rotation(-3, 0.06), hold.group.rotation(-3, 0.06)),
+ all(tap.group.rotation(0, 0.03), hold.group.rotation(0, 0.03)),
+ all(tap_output.output.text("f", 0), hold_output.shift.fill("#969696", 0.15))
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(
+ 0.5,
+ all(tap.duration.grow(0, 0.15), hold.duration.grow(0, 0.15))
+ );
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.tsx
new file mode 100644
index 00000000..fb61a616
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_preferred/tap_preferred_hold_tap_up.tsx
@@ -0,0 +1,47 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { any, all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const interrupt = makeRefs();
+ view.add();
+ interrupt.group.position.x(125);
+ interrupt.group.position.y(-150);
+ interrupt.duration.fill("#D9D9D9");
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(-125);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position().addX(125));
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* any(
+ hold.body.position.y(KeyTravel, 0.15),
+ hold.duration.grow(0.5, 1, linear)
+ );
+ yield* delay(0.35, interrupt.body.position.y(KeyTravel, 0.15));
+ yield* delay(
+ 0.35,
+ chain(
+ hold.body.position.y(0, 0.15),
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ hold.duration.grow(0, 0.15),
+ delay(0.05, hold_output.output.text("f", 0)),
+ delay(0.05, hold_output.output.text("fj", 0))
+ )
+ );
+ yield* waitFor(0.25);
+ yield* interrupt.body.position.y(0, 0.15);
+ yield* waitFor(1);
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.tsx
new file mode 100644
index 00000000..143dc6df
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted.tsx
@@ -0,0 +1,62 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const tap = makeRefs();
+ view.add();
+ tap.group.position.x(-400);
+ tap.group.position.y(-150);
+ tap.duration.fill("#D9D9D9");
+
+ const tap_output = makeRefs();
+ view.add();
+ tap_output.group.position(tap.group.position());
+ tap_output.group.position.y(tap_output.group.position.y() + 300);
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(400);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position());
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* all(
+ tap.body.position.y(KeyTravel, 0.15),
+ hold.body.position.y(KeyTravel, 0.15)
+ );
+ yield* all(
+ tap.duration.grow(0.5, 1, linear),
+ delay(
+ 1,
+ chain(
+ tap.body.position.y(0, 0.15),
+ tap.group.rotation(3, 0.03),
+ tap.group.rotation(-3, 0.06),
+ tap.group.rotation(0, 0.03),
+ tap_output.output.text("f", 0)
+ )
+ ),
+ hold.duration.grow(1, 2, linear)
+ );
+ yield* chain(
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ hold_output.output.text("f", 0)
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(
+ 0.5,
+ all(tap.duration.grow(0, 0.15), hold.duration.grow(0, 0.15))
+ );
+});
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta
new file mode 100644
index 00000000..0e33e3fe
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.meta
@@ -0,0 +1,3 @@
+{
+ "version": 0
+}
\ No newline at end of file
diff --git a/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.tsx b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.tsx
new file mode 100644
index 00000000..93a692f2
--- /dev/null
+++ b/docs/src/animationhelpers/src/scenes/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.tsx
@@ -0,0 +1,50 @@
+import { makeScene2D } from "@motion-canvas/2d/lib/scenes";
+import { makeRefs } from "@motion-canvas/core/lib/utils";
+import { any, all, chain, delay, waitFor } from "@motion-canvas/core/lib/flow";
+import Key, { KeyTravel } from "../../../components/Key";
+import Output from "../../../components/Output";
+import { linear } from "@motion-canvas/core/lib/tweening";
+
+export default makeScene2D(function* (view) {
+ const interrupt = makeRefs();
+ view.add();
+ interrupt.group.position.x(125);
+ interrupt.group.position.y(-150);
+ interrupt.duration.fill("#D9D9D9");
+
+ const hold = makeRefs();
+ view.add();
+ hold.group.position.x(-125);
+ hold.group.position.y(-150);
+ hold.duration.fill("#D9D9D9");
+
+ const hold_output = makeRefs();
+ view.add();
+ hold_output.group.position(hold.group.position().addX(125));
+ hold_output.group.position.y(hold_output.group.position.y() + 300);
+
+ yield* waitFor(0.5);
+ yield* any(
+ hold.body.position.y(KeyTravel, 0.15),
+ hold.duration.grow(0.75, 1.5, linear)
+ );
+ yield* delay(
+ 1.2,
+ all(
+ interrupt.body.position.y(KeyTravel, 0.15),
+ hold.duration.fill("F21D00", 0.15)
+ )
+ );
+ yield* chain(
+ hold.group.rotation(3, 0.03),
+ hold.group.rotation(-3, 0.06),
+ hold.group.rotation(0, 0.03),
+ all(
+ delay(0.15, hold_output.output.text("J", 0)),
+ hold_output.shift.fill("#969696", 0.15)
+ )
+ );
+ yield* waitFor(0.25);
+ yield* hold.body.position.y(0, 0.15);
+ yield* delay(0.5, hold.duration.grow(0, 0.15));
+});
diff --git a/docs/src/animationhelpers/tsconfig.json b/docs/src/animationhelpers/tsconfig.json
new file mode 100644
index 00000000..789b7d1b
--- /dev/null
+++ b/docs/src/animationhelpers/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "@motion-canvas/2d/tsconfig.project.json",
+ "compilerOptions": {
+ "baseUrl": "src"
+ },
+ "include": ["src"]
+}
diff --git a/docs/src/animationhelpers/vite.config.ts b/docs/src/animationhelpers/vite.config.ts
new file mode 100644
index 00000000..4e9fd189
--- /dev/null
+++ b/docs/src/animationhelpers/vite.config.ts
@@ -0,0 +1,28 @@
+import { defineConfig } from "vite";
+import motionCanvas from "@motion-canvas/vite-plugin";
+
+export default defineConfig({
+ plugins: [
+ motionCanvas({
+ project: [
+ "./src/hold_tap/hold_tap_comparison.ts",
+ "./src/hold_tap/hold_tap_interrupted.ts",
+ "./src/hold_tap/balanced/balanced_comparison.ts",
+ "./src/hold_tap/balanced/balanced_other_key_up.ts",
+ "./src/hold_tap/balanced/balanced_hold_tap_up.ts",
+ "./src/hold_tap/tap_preferred/tap_preferred_comparison.ts",
+ "./src/hold_tap/tap_preferred/tap_preferred_hold_tap_up.ts",
+ "./src/hold_tap/tap_unless_interrupted/tap_unless_interrupted.ts",
+ "./src/hold_tap/tap_unless_interrupted/tap_unless_interrupted_invoke_hold.ts",
+ ],
+ }),
+ ],
+ build: {
+ rollupOptions: {
+ output: {
+ dir: "../../static/animations",
+ entryFileNames: "[name].js",
+ },
+ },
+ },
+});
diff --git a/docs/src/components/AnimationPlayer/index.tsx b/docs/src/components/AnimationPlayer/index.tsx
new file mode 100644
index 00000000..8855512a
--- /dev/null
+++ b/docs/src/components/AnimationPlayer/index.tsx
@@ -0,0 +1,39 @@
+import type { MotionCanvasPlayerProps } from "@motion-canvas/player";
+import React, { ComponentProps } from "react";
+import styles from "./styles.module.css";
+import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
+import clsx from "clsx";
+
+if (ExecutionEnvironment.canUseDOM) {
+ import("@motion-canvas/player");
+}
+
+declare global {
+ namespace JSX {
+ interface IntrinsicElements {
+ "motion-canvas-player": MotionCanvasPlayerProps & ComponentProps<"div">;
+ }
+ }
+}
+
+export interface AnimationPlayerProps {
+ small?: boolean;
+ auto?: boolean;
+ name: string;
+}
+
+export default function AnimationPlayer({
+ name,
+ auto,
+ small,
+}: AnimationPlayerProps) {
+ return (
+
+
+
+ );
+}
diff --git a/docs/src/components/AnimationPlayer/styles.module.css b/docs/src/components/AnimationPlayer/styles.module.css
new file mode 100644
index 00000000..f148f432
--- /dev/null
+++ b/docs/src/components/AnimationPlayer/styles.module.css
@@ -0,0 +1,21 @@
+.container {
+ width: 100%;
+ overflow: hidden;
+ border-radius: var(--ifm-global-radius);
+ background-color: var(--ifm-background-surface-color);
+ position: relative;
+ aspect-ratio: 16 / 9;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+.container.small {
+ max-width: 720px;
+ aspect-ratio: 16/9;
+ margin: 0 auto var(--ifm-leading);
+}
+
+.player {
+ aspect-ratio: 16 / 9;
+}