diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 359c1f131c..afc1b85cb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -367,6 +367,12 @@ importers: '@headlessui/react': specifier: ^1.7.13 version: 1.7.13(react-dom@18.2.0)(react@18.2.0) + '@liveblocks/client': + specifier: ^1.5.0 + version: 1.5.0 + '@liveblocks/react': + specifier: ^1.5.0 + version: 1.5.0(react@18.2.0) '@loglib/tracker': specifier: ^0.5.0 version: 0.5.0(react@18.2.0) @@ -398,14 +404,14 @@ importers: specifier: workspace:* version: link:.. next: - specifier: ^13.4.19 - version: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) + specifier: ^13.5.6 + version: 13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) nextra: - specifier: ^2.12.3 - version: 2.12.3(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) + specifier: ^2.13.2 + version: 2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) nextra-theme-docs: - specifier: ^2.12.3 - version: 2.12.3(next@13.4.19)(nextra@2.12.3)(react-dom@18.2.0)(react@18.2.0) + specifier: ^2.13.2 + version: 2.13.2(next@13.5.6)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0) postcss: specifier: ^8.4.21 version: 8.4.21 @@ -2552,6 +2558,28 @@ packages: '@lezer/common': 1.0.4 dev: false + /@liveblocks/client@1.5.0: + resolution: {integrity: sha512-q1FbVAb6MmuECH58/KwmWtxL2uZ0jLdA4GQM1HPsuCL9iWxk0C1xJprhgOvQ0zBJkWAgr3MCa5oVnfoHXtXRWQ==} + dependencies: + '@liveblocks/core': 1.5.0 + dev: false + + /@liveblocks/core@1.5.0: + resolution: {integrity: sha512-ejFp07eb91wShTt82AQ107ToxB4jTp3ZAehBsOByfK8v8qerx6dnkQFtneX2s0ggc3EO3PSnoIc+GS9CAfzkqg==} + dev: false + + /@liveblocks/react@1.5.0(react@18.2.0): + resolution: {integrity: sha512-OHozoxOLo/aed4Ro+HLPz2dp9AUO/xwrUubII0RPrBnD3HWypzCk4MlYbTifD8BrJDvdcKhzl0gELa4/u194LQ==} + peerDependencies: + react: ^16.14.0 || ^17 || ^18 + dependencies: + '@liveblocks/client': 1.5.0 + '@liveblocks/core': 1.5.0 + nanoid: 3.3.6 + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + /@loglib/tracker@0.5.0(react@18.2.0): resolution: {integrity: sha512-WhSAtGfm0Dv746gLAtQrvHO7QUBUh4Kem7RvGwL0kh2dGY/oDvMxNaenJppR2lxZkfw5cIKACqiwbL0p1tE7EA==} peerDependencies: @@ -2830,8 +2858,8 @@ packages: '@napi-rs/simple-git-win32-x64-msvc': 0.1.9 dev: false - /@next/env@13.4.19: - resolution: {integrity: sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ==} + /@next/env@13.5.6: + resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} dev: false /@next/eslint-plugin-next@12.1.2: @@ -2840,8 +2868,8 @@ packages: glob: 7.1.7 dev: true - /@next/swc-darwin-arm64@13.4.19: - resolution: {integrity: sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==} + /@next/swc-darwin-arm64@13.5.6: + resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -2849,8 +2877,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.4.19: - resolution: {integrity: sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==} + /@next/swc-darwin-x64@13.5.6: + resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -2858,8 +2886,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.4.19: - resolution: {integrity: sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==} + /@next/swc-linux-arm64-gnu@13.5.6: + resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2867,8 +2895,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.4.19: - resolution: {integrity: sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==} + /@next/swc-linux-arm64-musl@13.5.6: + resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -2876,8 +2904,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.4.19: - resolution: {integrity: sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==} + /@next/swc-linux-x64-gnu@13.5.6: + resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2885,8 +2913,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.4.19: - resolution: {integrity: sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==} + /@next/swc-linux-x64-musl@13.5.6: + resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -2894,8 +2922,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.4.19: - resolution: {integrity: sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==} + /@next/swc-win32-arm64-msvc@13.5.6: + resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -2903,8 +2931,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.4.19: - resolution: {integrity: sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==} + /@next/swc-win32-ia32-msvc@13.5.6: + resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -2912,8 +2940,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.4.19: - resolution: {integrity: sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==} + /@next/swc-win32-x64-msvc@13.5.6: + resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -3207,6 +3235,12 @@ packages: tslib: 2.6.2 dev: false + /@swc/helpers@0.5.2: + resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} + dependencies: + tslib: 2.6.2 + dev: false + /@tailwindcss/line-clamp@0.4.4(tailwindcss@3.2.7): resolution: {integrity: sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g==} peerDependencies: @@ -3250,8 +3284,8 @@ packages: resolution: {integrity: sha512-jtkwqdP2rY2iCCDVAFuaNBH3fiEi29aTn2RhtIoky8DTTiCdc48plpHHreLwmv1PICJ4AJUUESaq3xa8fZH8+g==} dev: false - /@theguild/remark-mermaid@0.0.4(react@18.2.0): - resolution: {integrity: sha512-C1gssw07eURtCwzXqZZdvyV/eawQ/cXfARaXIgBU9orffox+/YQ+exxmNu9v16NSGzAVsGF4qEVHvCOcCR/FpQ==} + /@theguild/remark-mermaid@0.0.5(react@18.2.0): + resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} peerDependencies: react: ^18.2.0 dependencies: @@ -3262,10 +3296,10 @@ packages: - supports-color dev: false - /@theguild/remark-npm2yarn@0.1.1: - resolution: {integrity: sha512-ZKwd/bjQ9V+pESLnu8+q8jqn15alXzJOuVckraebsXwqVBTw53Gmupiw9zCdLNHU829KTYNycJYea6m9HRLuOg==} + /@theguild/remark-npm2yarn@0.2.1: + resolution: {integrity: sha512-jUTFWwDxtLEFtGZh/TW/w30ySaDJ8atKWH8dq2/IiQF61dPrGfETpl0WxD0VdBfuLOeU14/kop466oBSRO/5CA==} dependencies: - npm-to-yarn: 2.0.0 + npm-to-yarn: 2.1.0 unist-util-visit: 5.0.0 dev: false @@ -3432,10 +3466,6 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true - /@types/katex@0.14.0: - resolution: {integrity: sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==} - dev: false - /@types/katex@0.16.2: resolution: {integrity: sha512-dHsSjSlU/EWEEbeNADr3FtZZOAXPkFPUO457QCnoNqcZQXNqNEu/svQd0Nritvd3wNff4vvC/f4e6xgX3Llt8A==} dev: false @@ -3902,7 +3932,7 @@ packages: eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.25.4) eslint-import-resolver-typescript: 2.7.0(eslint-plugin-import@2.25.4)(eslint@8.34.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.34.0) - eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0) + eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.53.0)(eslint@8.34.0) eslint-plugin-jest: 26.1.3(@typescript-eslint/eslint-plugin@5.17.0)(eslint@8.34.0)(typescript@5.1.6) eslint-plugin-jsx-a11y: 6.5.1(eslint@8.34.0) eslint-plugin-react: 7.29.4(eslint@8.34.0) @@ -5801,7 +5831,7 @@ packages: peerDependencies: eslint-plugin-import: '>=1.4.0' dependencies: - eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0) + eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.53.0)(eslint@8.34.0) dev: true /eslint-import-resolver-node@0.3.9: @@ -5823,7 +5853,7 @@ packages: dependencies: debug: 4.3.4 eslint: 8.34.0 - eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0) + eslint-plugin-import: 2.25.4(@typescript-eslint/parser@5.53.0)(eslint@8.34.0) glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.4 @@ -5832,7 +5862,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.53.0)(eslint-import-resolver-node@0.3.9)(eslint@8.34.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -5853,11 +5883,10 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.17.0(eslint@8.34.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.53.0(eslint@8.34.0)(typescript@5.1.6) debug: 3.2.7 eslint: 8.34.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.0(eslint-plugin-import@2.25.4)(eslint@8.34.0) transitivePeerDependencies: - supports-color dev: true @@ -5873,7 +5902,7 @@ packages: ignore: 5.2.4 dev: true - /eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0): + /eslint-plugin-import@2.25.4(@typescript-eslint/parser@5.53.0)(eslint@8.34.0): resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==} engines: {node: '>=4'} peerDependencies: @@ -5883,14 +5912,14 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.17.0(eslint@8.34.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.53.0(eslint@8.34.0)(typescript@5.1.6) array-includes: 3.1.6 array.prototype.flat: 1.3.1 debug: 2.6.9 doctrine: 2.1.0 eslint: 8.34.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.17.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.0)(eslint@8.34.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.53.0)(eslint-import-resolver-node@0.3.9)(eslint@8.34.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -6706,42 +6735,32 @@ packages: type-fest: 1.4.0 dev: false - /hast-util-from-dom@4.2.0: - resolution: {integrity: sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==} + /hast-util-from-dom@5.0.0: + resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} dependencies: - hastscript: 7.2.0 + '@types/hast': 3.0.0 + hastscript: 8.0.0 web-namespaces: 2.0.1 dev: false - /hast-util-from-html-isomorphic@1.0.0: - resolution: {integrity: sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==} + /hast-util-from-html-isomorphic@2.0.0: + resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} dependencies: - '@types/hast': 2.3.5 - hast-util-from-dom: 4.2.0 - hast-util-from-html: 1.0.2 - unist-util-remove-position: 4.0.2 + '@types/hast': 3.0.0 + hast-util-from-dom: 5.0.0 + hast-util-from-html: 2.0.1 + unist-util-remove-position: 5.0.0 dev: false - /hast-util-from-html@1.0.2: - resolution: {integrity: sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==} + /hast-util-from-html@2.0.1: + resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} dependencies: - '@types/hast': 2.3.5 - hast-util-from-parse5: 7.1.2 + '@types/hast': 3.0.0 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 parse5: 7.1.2 - vfile: 5.3.7 - vfile-message: 3.1.4 - dev: false - - /hast-util-from-parse5@7.1.2: - resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} - dependencies: - '@types/hast': 2.3.5 - '@types/unist': 2.0.7 - hastscript: 7.2.0 - property-information: 6.2.0 - vfile: 5.3.7 - vfile-location: 4.1.0 - web-namespaces: 2.0.1 + vfile: 6.0.1 + vfile-message: 4.0.2 dev: false /hast-util-from-parse5@8.0.1: @@ -6757,17 +6776,10 @@ packages: web-namespaces: 2.0.1 dev: false - /hast-util-is-element@2.1.3: - resolution: {integrity: sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==} - dependencies: - '@types/hast': 2.3.5 - '@types/unist': 2.0.7 - dev: false - - /hast-util-parse-selector@3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} + /hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} dependencies: - '@types/hast': 2.3.5 + '@types/hast': 3.0.0 dev: false /hast-util-parse-selector@4.0.0: @@ -6828,29 +6840,19 @@ packages: zwitch: 2.0.4 dev: false - /hast-util-to-text@3.1.2: - resolution: {integrity: sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==} + /hast-util-to-text@4.0.0: + resolution: {integrity: sha512-EWiE1FSArNBPUo1cKWtzqgnuRQwEeQbQtnFJRYV1hb1BWDgrAlBU0ExptvZMM/KSA82cDpm2sFGf3Dmc5Mza3w==} dependencies: - '@types/hast': 2.3.5 - '@types/unist': 2.0.7 - hast-util-is-element: 2.1.3 - unist-util-find-after: 4.0.1 + '@types/hast': 3.0.0 + '@types/unist': 3.0.0 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 dev: false /hast-util-whitespace@2.0.1: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} dev: false - /hastscript@7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} - dependencies: - '@types/hast': 2.3.5 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - dev: false - /hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} dependencies: @@ -7535,8 +7537,8 @@ packages: object.values: 1.1.6 dev: true - /katex@0.16.8: - resolution: {integrity: sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==} + /katex@0.16.9: + resolution: {integrity: sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==} hasBin: true dependencies: commander: 8.3.0 @@ -8111,7 +8113,7 @@ packages: resolution: {integrity: sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==} dependencies: '@types/katex': 0.16.2 - katex: 0.16.8 + katex: 0.16.9 micromark-factory-space: 1.1.0 micromark-util-character: 1.2.0 micromark-util-symbol: 1.1.0 @@ -8542,26 +8544,26 @@ packages: - supports-color dev: false - /next-seo@6.1.0(next@13.4.19)(react-dom@18.2.0)(react@18.2.0): + /next-seo@6.1.0(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA==} peerDependencies: next: ^8.1.1-canary.54 || >=9.0.0 react: '>=16.0.0' react-dom: '>=16.0.0' dependencies: - next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /next-themes@0.2.1(next@13.4.19)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -8570,9 +8572,9 @@ packages: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false - /next@13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==} - engines: {node: '>=16.8.0'} + /next@13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} + engines: {node: '>=16.14.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -8585,36 +8587,35 @@ packages: sass: optional: true dependencies: - '@next/env': 13.4.19 - '@swc/helpers': 0.5.1 + '@next/env': 13.5.6 + '@swc/helpers': 0.5.2 busboy: 1.6.0 caniuse-lite: 1.0.30001522 - postcss: 8.4.14 + postcss: 8.4.31 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.22.10)(react@18.2.0) watchpack: 2.4.0 - zod: 3.21.4 optionalDependencies: - '@next/swc-darwin-arm64': 13.4.19 - '@next/swc-darwin-x64': 13.4.19 - '@next/swc-linux-arm64-gnu': 13.4.19 - '@next/swc-linux-arm64-musl': 13.4.19 - '@next/swc-linux-x64-gnu': 13.4.19 - '@next/swc-linux-x64-musl': 13.4.19 - '@next/swc-win32-arm64-msvc': 13.4.19 - '@next/swc-win32-ia32-msvc': 13.4.19 - '@next/swc-win32-x64-msvc': 13.4.19 + '@next/swc-darwin-arm64': 13.5.6 + '@next/swc-darwin-x64': 13.5.6 + '@next/swc-linux-arm64-gnu': 13.5.6 + '@next/swc-linux-arm64-musl': 13.5.6 + '@next/swc-linux-x64-gnu': 13.5.6 + '@next/swc-linux-x64-musl': 13.5.6 + '@next/swc-win32-arm64-msvc': 13.5.6 + '@next/swc-win32-ia32-msvc': 13.5.6 + '@next/swc-win32-x64-msvc': 13.5.6 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros dev: false - /nextra-theme-docs@2.12.3(next@13.4.19)(nextra@2.12.3)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-aZywZwokk/h5HrUTh/bsU981Sd2prZks7ci+HNG9wuMnm+drp3PBmRKIuQxBCiJurePVBJ2Qk2/wTV3VECGKnA==} + /nextra-theme-docs@2.13.2(next@13.5.6)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yE4umXaImp1/kf/sFciPj2+EFrNSwd9Db26hi98sIIiujzGf3+9eUgAz45vF9CwBw50FSXxm1QGRcY+slQ4xQQ==} peerDependencies: next: '>=9.5.3' - nextra: 2.12.3 + nextra: 2.13.2 react: '>=16.13.1' react-dom: '>=16.13.1' dependencies: @@ -8627,18 +8628,18 @@ packages: git-url-parse: 13.1.0 intersection-observer: 0.12.2 match-sorter: 6.3.1 - next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) - next-seo: 6.1.0(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) - next-themes: 0.2.1(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) - nextra: 2.12.3(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) + next-seo: 6.1.0(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) + next-themes: 0.2.1(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) + nextra: 2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) scroll-into-view-if-needed: 3.0.10 - zod: 3.22.2 + zod: 3.22.4 dev: false - /nextra@2.12.3(next@13.4.19)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-0d8wXpGAccFpMFZuxnlnN56MIZj+AWGYXW3Xk6ByXyr0Mb+B/C/0aGZV5YrBex0V1wEqMGQl4LLAJI+AfCbSXg==} + /nextra@2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-pIgOSXNUqTz1laxV4ChFZOU7lzJAoDHHaBPj8L09PuxrLKqU1BU/iZtXAG6bQeKCx8EPdBsoXxEuENnL9QGnGA==} engines: {node: '>=16'} peerDependencies: next: '>=9.5.3' @@ -8649,20 +8650,20 @@ packages: '@mdx-js/mdx': 2.3.0 '@mdx-js/react': 2.3.0(react@18.2.0) '@napi-rs/simple-git': 0.1.9 - '@theguild/remark-mermaid': 0.0.4(react@18.2.0) - '@theguild/remark-npm2yarn': 0.1.1 + '@theguild/remark-mermaid': 0.0.5(react@18.2.0) + '@theguild/remark-npm2yarn': 0.2.1 clsx: 2.0.0 github-slugger: 2.0.0 graceful-fs: 4.2.11 gray-matter: 4.0.3 - katex: 0.16.8 + katex: 0.16.9 lodash.get: 4.4.2 - next: 13.4.19(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) + next: 13.5.6(@babel/core@7.22.10)(react-dom@18.2.0)(react@18.2.0) next-mdx-remote: 4.4.1(react-dom@18.2.0)(react@18.2.0) p-limit: 3.1.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - rehype-katex: 6.0.3 + rehype-katex: 7.0.0 rehype-pretty-code: 0.9.11(shiki@0.14.3) rehype-raw: 7.0.0 remark-gfm: 3.0.1 @@ -8673,7 +8674,7 @@ packages: title: 3.5.3 unist-util-remove: 4.0.0 unist-util-visit: 5.0.0 - zod: 3.22.2 + zod: 3.22.4 transitivePeerDependencies: - supports-color dev: false @@ -8752,9 +8753,9 @@ packages: path-key: 4.0.0 dev: true - /npm-to-yarn@2.0.0: - resolution: {integrity: sha512-/IbjiJ7vqbxfxJxAZ+QI9CCRjnIbvGxn5KQcSY9xHh0lMKc/Sgqmm7yp7KPmd6TiTZX5/KiSBKlkGHo59ucZbg==} - engines: {node: '>=6.0.0'} + /npm-to-yarn@2.1.0: + resolution: {integrity: sha512-2C1IgJLdJngq1bSER7K7CGFszRr9s2rijEwvENPEgI0eK9xlD3tNwDc0UJnRj7FIT2aydWm72jB88uVswAhXHA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false /nwsapi@2.2.7: @@ -9125,8 +9126,8 @@ packages: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: false - /postcss@8.4.14: - resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} + /postcss@8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 @@ -9134,22 +9135,22 @@ packages: source-map-js: 1.0.2 dev: false - /postcss@8.4.21: - resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + /postcss@8.4.28: + resolution: {integrity: sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: false - /postcss@8.4.28: - resolution: {integrity: sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==} + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: false /preact@10.15.0: resolution: {integrity: sha512-nZSa8M2R2m1n7nJSBlzDpxRJaIsejrTO1vlFbdpFvyC8qM1iU+On2y0otfoUm6SRB5o0lF0CKDFxg6grEFU0iQ==} @@ -9678,15 +9679,16 @@ packages: jsesc: 0.5.0 dev: false - /rehype-katex@6.0.3: - resolution: {integrity: sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==} + /rehype-katex@7.0.0: + resolution: {integrity: sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q==} dependencies: - '@types/hast': 2.3.5 - '@types/katex': 0.14.0 - hast-util-from-html-isomorphic: 1.0.0 - hast-util-to-text: 3.1.2 - katex: 0.16.8 - unist-util-visit: 4.1.2 + '@types/hast': 3.0.0 + '@types/katex': 0.16.2 + hast-util-from-html-isomorphic: 2.0.0 + hast-util-to-text: 4.0.0 + katex: 0.16.9 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.1 dev: false /rehype-pretty-code@0.9.11(shiki@0.14.3): @@ -10772,11 +10774,11 @@ packages: vfile: 5.3.7 dev: false - /unist-util-find-after@4.0.1: - resolution: {integrity: sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==} + /unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} dependencies: - '@types/unist': 2.0.7 - unist-util-is: 5.2.1 + '@types/unist': 3.0.0 + unist-util-is: 6.0.0 dev: false /unist-util-generated@2.0.1: @@ -10820,6 +10822,13 @@ packages: unist-util-visit: 4.1.2 dev: false + /unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + dependencies: + '@types/unist': 3.0.0 + unist-util-visit: 5.0.0 + dev: false + /unist-util-remove@4.0.0: resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==} dependencies: @@ -11030,13 +11039,6 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - /vfile-location@4.1.0: - resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} - dependencies: - '@types/unist': 2.0.7 - vfile: 5.3.7 - dev: false - /vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} dependencies: @@ -11483,12 +11485,8 @@ packages: - supports-color dev: false - /zod@3.21.4: - resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} - dev: false - - /zod@3.22.2: - resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==} + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false /zustand@4.4.1(@types/react@18.2.20)(react@18.2.0): diff --git a/website/.gitignore b/website/.gitignore index f74c78183c..2442b5bf9b 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -1,2 +1,3 @@ .next node_modules +.env \ No newline at end of file diff --git a/website/components/cursor.tsx b/website/components/cursor.tsx new file mode 100644 index 0000000000..7aa59f4283 --- /dev/null +++ b/website/components/cursor.tsx @@ -0,0 +1,31 @@ +export function Cursor({ + color, + x, + y, +}: { + color: string; + x: number; + y: number; +}) { + return ( + + + + ); +} diff --git a/website/components/extra-content.tsx b/website/components/extra-content.tsx index d2ce39e8f2..e234f4fce8 100644 --- a/website/components/extra-content.tsx +++ b/website/components/extra-content.tsx @@ -1,18 +1,39 @@ import dynamic from 'next/dynamic'; import { startTransition, useEffect, useRef, useState } from 'react'; import { CarbonAds } from './ad'; +import { getCount } from './live'; const LagRadar = dynamic(() => import('react-lag-radar'), { ssr: false }); export function ExtraContent() { return ( <> - + ); } +export function Status() { + const [, forceUpdate] = useState({}); + const count = getCount(); + // useEffect(() => { + // const interval = setInterval(() => { + // forceUpdate({}); + // }, 1000); + // return () => clearInterval(interval); + // }, []); + return ( +
+
+
+
+
+ {count} users connected. +
+ ); +} + // million-ignore export function Showdown({ initStart = false, amount = 1000 }) { const [start, setStart] = useState(false); diff --git a/website/components/live.tsx b/website/components/live.tsx new file mode 100644 index 0000000000..a7d603e1f3 --- /dev/null +++ b/website/components/live.tsx @@ -0,0 +1,136 @@ +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; +import { + RoomProvider, + useOthers, + useUpdateMyPresence, +} from '../liveblocks.config'; +import { Cursor } from './cursor'; + +const COLORS = [ + '#E57373', + '#9575CD', + '#4FC3F7', + '#81C784', + '#FFF176', + '#FF8A65', + '#F06292', + '#7986CB', +]; + +function useLiveCursors() { + const updateMyPresence = useUpdateMyPresence(); + + useEffect(() => { + const scroll = { + x: window.scrollX, + y: window.scrollY, + }; + + let lastPosition: { x: number; y: number } | null = null; + + function transformPosition(cursor: { x: number; y: number }) { + return { + x: cursor.x / window.innerWidth, + y: cursor.y, + }; + } + + function onPointerMove(event: PointerEvent) { + event.preventDefault(); + const position = { + x: event.pageX, + y: event.pageY, + }; + lastPosition = position; + updateMyPresence({ + cursor: transformPosition(position), + }); + } + + function onPointerLeave() { + lastPosition = null; + updateMyPresence({ cursor: null }); + } + + function onDocumentScroll() { + if (lastPosition) { + const offsetX = window.scrollX - scroll.x; + const offsetY = window.scrollY - scroll.y; + const position = { + x: lastPosition.x + offsetX, + y: lastPosition.y + offsetY, + }; + lastPosition = position; + updateMyPresence({ + cursor: transformPosition(position), + }); + } + scroll.x = window.scrollX; + scroll.y = window.scrollY; + } + + document.addEventListener('scroll', onDocumentScroll); + document.addEventListener('pointermove', onPointerMove); + document.addEventListener('pointerleave', onPointerLeave); + + return () => { + document.removeEventListener('scroll', onDocumentScroll); + document.removeEventListener('pointermove', onPointerMove); + document.removeEventListener('pointerleave', onPointerLeave); + }; + }, [updateMyPresence]); + + const others = useOthers(); + + const cursors: { + x: number; + y: number; + connectionId: number; + }[] = []; + + for (const { connectionId, presence } of others) { + if (presence.cursor) { + cursors.push({ + x: presence.cursor.x * window.innerWidth, + y: presence.cursor.y, + connectionId, + }); + } + } + + return cursors; +} + +export function Cursors() { + const cursors = useLiveCursors(); + + return cursors.map(({ x, y, connectionId }) => ( + + )); +} + +export function getCount() { + const others = useOthers(); + return others.length; +} + +export function LiveProvider({ children }) { + const { pathname } = useRouter(); + return ( + + {children} + + + ); +} diff --git a/website/liveblocks.config.ts b/website/liveblocks.config.ts new file mode 100644 index 0000000000..a8072cd2c0 --- /dev/null +++ b/website/liveblocks.config.ts @@ -0,0 +1,14 @@ +import { createClient } from '@liveblocks/client'; +import { createRoomContext } from '@liveblocks/react'; +import type { JsonObject} from '@liveblocks/client'; + +const client = createClient({ + throttle: 16, + publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY!, +}); +interface Presence extends JsonObject { + cursor: { x: number; y: number } | null; +} + +export const { RoomProvider, useOthers, useMyPresence, useUpdateMyPresence } = + createRoomContext(client); diff --git a/website/package.json b/website/package.json index 29c82bf5c1..72da1b7d75 100644 --- a/website/package.json +++ b/website/package.json @@ -13,6 +13,8 @@ "@babel/traverse": "^7.21.5", "@codesandbox/sandpack-react": "^2.6.7", "@headlessui/react": "^1.7.13", + "@liveblocks/client": "^1.5.0", + "@liveblocks/react": "^1.5.0", "@loglib/tracker": "^0.5.0", "@tailwindcss/line-clamp": "^0.4.4", "@vercel/analytics": "^1.0.0", @@ -23,9 +25,9 @@ "dedent": "^0.7.0", "framer-motion": "^10.12.4", "million": "workspace:*", - "next": "^13.4.19", - "nextra": "^2.12.3", - "nextra-theme-docs": "^2.12.3", + "next": "^13.5.6", + "nextra": "^2.13.2", + "nextra-theme-docs": "^2.13.2", "postcss": "^8.4.21", "react": "^18.2.0", "react-card-flip": "^1.2.0", diff --git a/website/pages/_app.mdx b/website/pages/_app.mdx index bc9c227869..0a00f26868 100644 --- a/website/pages/_app.mdx +++ b/website/pages/_app.mdx @@ -1,14 +1,17 @@ import '../styles/global.css'; import { Analytics } from '@vercel/analytics/react'; import { Inter } from 'next/font/google'; +import { LiveProvider } from '../components/live'; export const inter = Inter({ subsets: ['latin'] }); export default function App({ Component, pageProps }) { return ( -
- - -
+ +
+ + +
+
); } diff --git a/website/pages/blog/_meta.json b/website/pages/blog/_meta.json index 0df42c10bb..7a4d6baeb4 100644 --- a/website/pages/blog/_meta.json +++ b/website/pages/blog/_meta.json @@ -8,6 +8,7 @@ "typesetting": "article" } }, + "wyze": "Case Study: Wyze", "million-hacktoberfest-celebration": "Million.js Hacktoberfest: Join the Celebration!", "million-beyond-speed": "Million Beyond 'Speed'", "million-v2.5.3": "Million.js v2.5.3", diff --git a/website/pages/blog/wyze.mdx b/website/pages/blog/wyze.mdx new file mode 100644 index 0000000000..8a03093bd2 --- /dev/null +++ b/website/pages/blog/wyze.mdx @@ -0,0 +1,58 @@ +--- +title: 'Case Study: Wyze' +date: OCT 19, 2023 +description: How Million.js helped Wyze speed up the Web View product by 8x in less than a week. +--- + +import Image from 'next/image'; + + + +
+ +# Case Study: Wyze + +

+ How Million.js helped Wyze speed up the Web View product by 8x in less than a + week. +

+ + [AIDEN BAI](https://aidenybai.com) OCT 19 2023 +
+ +Introduction +Wyze.com, a platform renowned for its smart home products, has always been on the lookout for cutting-edge technologies to enhance user interaction and engagement on its web view product. In its quest for a robust, performant, and user-friendly web view, Wyze.com collaborated with Million.js, a lightweight virtual DOM library. + +Challenges +Wyze's web view product was facing challenges with rendering speed and efficiency which was impacting the user experience. The existing technology stack was not adept at handling high-frequency updates and rendering large lists of dynamic content. + +The primary challenge was to find a solution that could significantly enhance rendering performance without compromising on the usability and the existing features of the web view product. Moreover, the solution needed to be lightweight and easy to integrate with the existing technology stack. + +Requirements + +Boost rendering performance significantly. +Ensure a lightweight solution to not burden the existing infrastructure. +Easy integration with the existing technology stack. +Maintain or enhance the current level of usability and features. +Solution and Implementation +Million.js emerged as a promising solution to Wyze.com's challenges. It's a lightweight virtual DOM library that provides high-performance rendering, making it a perfect match for the requirements. + +The implementation process kicked off with a thorough analysis and benchmarking to understand the performance gaps and set clear performance goals. The Wyze.com’s development team, along with the Million.js community, worked in tandem to devise a robust implementation plan. + +The integration of Million.js was smooth, and it was customized to align with the Wyze.com's web view product's architecture. The Million.js library was adept at handling high-frequency updates and rendering large lists of dynamic content efficiently. + +During the implementation, several performance optimization techniques were also employed to further boost the rendering speed. This included optimizing the existing codebase to take full advantage of Million.js's virtual DOM diffing and patching capabilities. + +Results +The integration of Million.js significantly improved the rendering performance of Wyze.com’s web view product. The rendering times were reduced drastically which contributed to a smoother and more responsive user experience. + +Furthermore, the lightweight nature of Million.js ensured that the web view remained highly performant even under heavy loads, showcasing its capability to handle high-frequency updates efficiently. + +The collaboration with Million.js not only addressed the performance challenges but also laid a strong foundation for future enhancements. The success of this integration has spurred Wyze.com to explore further optimizations and additional features to continue enhancing the user experience. + +Conclusion +The case study exemplifies how a focused and collaborative effort between Wyze.com and Million.js led to significant performance improvements. The integration of Million.js proved to be a decisive step towards achieving a superior, user-friendly, and performant web view product on Wyze.com. This collaboration underscores the potential of lightweight virtual DOM libraries like Million.js in addressing performance challenges and enhancing the user experience in web-based applications. diff --git a/website/public/wyze-banner.png b/website/public/wyze-banner.png new file mode 100644 index 0000000000..f09e34c3a8 Binary files /dev/null and b/website/public/wyze-banner.png differ diff --git a/website/styles/global.css b/website/styles/global.css index 7deea0e6d1..0cf2fb42de 100644 --- a/website/styles/global.css +++ b/website/styles/global.css @@ -1,6 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + @layer utilities { .pause { animation-play-state: paused; @@ -73,6 +74,23 @@ html[class~='dark'] .gradient-text { animation-iteration-count: 1; } +.animate-ping { + -webkit-animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; + animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; +} + +@keyframes ping { + 0% { + transform: scale(1); + opacity: 1; + } + 75%, + 100% { + transform: scale(2); + opacity: 0; + } +} + .svg { width: 100%; height: 100%;