diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 914a8836a..db7f431ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -526,18 +526,48 @@ importers: '@mdx-js/react': specifier: ^3.0.0 version: 3.1.0(@types/react@18.3.12)(react@18.3.1) + ajv: + specifier: 8.17.1 + version: 8.17.1 + antd: + specifier: 5.21.5 + version: 5.21.5(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: + specifier: ^2.0.0 + version: 2.5.1 clsx: specifier: ^2.0.0 version: 2.1.1 + lodash: + specifier: ^4.0.0 + version: 4.17.21 + lz-string: + specifier: 1.5.0 + version: 1.5.0 + message-box: + specifier: 0.2.7 + version: 0.2.7 prism-react-renderer: specifier: ^2.3.0 version: 2.4.0(react@18.3.1) + raw-loader: + specifier: 4.0.2 + version: 4.0.2(webpack@5.95.0) react: specifier: ^18.0.0 version: 18.3.1 react-dom: specifier: ^18.0.0 version: 18.3.1(react@18.3.1) + react-feather: + specifier: 2.0.10 + version: 2.0.10(react@18.3.1) + react-frame-component: + specifier: 5.2.7 + version: 5.2.7(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + zod: + specifier: 3.23.8 + version: 3.23.8 devDependencies: '@docusaurus/module-type-aliases': specifier: 3.5.2 @@ -551,9 +581,18 @@ importers: '@docusaurus/types': specifier: 3.5.2 version: 3.5.2(acorn@8.13.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/simpl-schema': + specifier: 1.12.8 + version: 1.12.8(@aws-sdk/client-sso-oidc@3.679.0(@aws-sdk/client-sts@3.679.0)) + simpl-schema: + specifier: 1.13.1 + version: 1.13.1 typescript: specifier: ~5.5.2 version: 5.5.4 + uniforms: + specifier: workspace:* + version: link:../packages/uniforms packages: @@ -6946,6 +6985,12 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-loader@4.0.2: + resolution: {integrity: sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + rc-cascader@3.28.2: resolution: {integrity: sha512-8f+JgM83iLTvjgdkgU7GfI4qY8icXOBP0cGZjOdx2iJAkEe8ucobxDQAVE69UD/c3ehCxZlcgEHeD5hFmypbUw==} peerDependencies: @@ -7205,6 +7250,18 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + react-feather@2.0.10: + resolution: {integrity: sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==} + peerDependencies: + react: '>=16.8.6' + + react-frame-component@5.2.7: + resolution: {integrity: sha512-ROjHtSLoSVYUBfTieazj/nL8jIX9rZFmHC0yXEU+dx6Y82OcBEGgU9o7VyHMrBFUN9FuQ849MtIPNNLsb4krbg==} + peerDependencies: + prop-types: ^15.5.9 + react: '>= 16.3' + react-dom: '>= 16.3' + react-helmet-async@1.3.0: resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} peerDependencies: @@ -11278,73 +11335,69 @@ snapshots: '@open-draft/deferred-promise@2.2.0': {} - '@parcel/bundler-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/bundler-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 '@parcel/graph': 3.2.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/cache@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/cache@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/logger': 2.12.0 '@parcel/utils': 2.12.0 lmdb: 2.8.5 - transitivePeerDependencies: - - '@swc/helpers' '@parcel/codeframe@2.12.0': dependencies: chalk: 4.1.2 - '@parcel/compressor-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/compressor-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/config-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(relateurl@0.2.7)(terser@5.36.0)(typescript@5.5.4)': dependencies: - '@parcel/bundler-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/compressor-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/bundler-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/compressor-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/core': 2.12.0(@swc/helpers@0.5.13) - '@parcel/namer-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-htmlnano': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(relateurl@0.2.7)(terser@5.36.0)(typescript@5.5.4) - '@parcel/optimizer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/optimizer-svgo': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/namer-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-htmlnano': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(postcss@8.4.47)(relateurl@0.2.7)(terser@5.36.0)(typescript@5.5.4) + '@parcel/optimizer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/optimizer-svgo': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/optimizer-swc': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/packager-wasm': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/resolver-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-browser-hmr': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-react-refresh': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/runtime-service-worker': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-babel': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/packager-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/packager-wasm': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/resolver-default': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-browser-hmr': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-react-refresh': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/runtime-service-worker': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-babel': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-css': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-html': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-image': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/transformer-js': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/transformer-json': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-postcss': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-posthtml': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-react-refresh-wrap': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/transformer-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/transformer-json': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-postcss': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-posthtml': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-raw': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-react-refresh-wrap': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/transformer-svg': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@swc/helpers' - cssnano @@ -11359,20 +11412,20 @@ snapshots: '@parcel/core@2.12.0(@swc/helpers@0.5.13)': dependencies: '@mischnic/json-sourcemap': 0.1.1 - '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/diagnostic': 2.12.0 '@parcel/events': 2.12.0 '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/graph': 3.2.0 '@parcel/logger': 2.12.0 '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/profiler': 2.12.0 '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) abortcontroller-polyfill: 1.7.5 base-x: 3.0.10 browserslist: 4.24.2 @@ -11400,7 +11453,7 @@ snapshots: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 '@parcel/watcher': 2.4.1 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@swc/helpers' @@ -11417,14 +11470,13 @@ snapshots: dependencies: chalk: 4.1.2 - '@parcel/namer-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/namer-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/node-resolver-core@3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: @@ -11438,10 +11490,10 @@ snapshots: transitivePeerDependencies: - '@parcel/core' - '@parcel/optimizer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -11449,18 +11501,16 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/optimizer-htmlnano@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)(postcss@8.4.47)(relateurl@0.2.7)(terser@5.36.0)(typescript@5.5.4)': + '@parcel/optimizer-htmlnano@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(postcss@8.4.47)(relateurl@0.2.7)(terser@5.36.0)(typescript@5.5.4)': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) htmlnano: 2.1.1(postcss@8.4.47)(relateurl@0.2.7)(svgo@2.8.0)(terser@5.36.0)(typescript@5.5.4) nullthrows: 1.1.1 posthtml: 0.16.6 svgo: 2.8.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - cssnano - postcss - purgecss @@ -11470,31 +11520,28 @@ snapshots: - typescript - uncss - '@parcel/optimizer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - transitivePeerDependencies: - - '@swc/helpers' + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/optimizer-svgo@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/optimizer-svgo@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 svgo: 2.8.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/optimizer-swc@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 '@swc/core': 1.7.40(@swc/helpers@0.5.13) @@ -11512,39 +11559,37 @@ snapshots: '@parcel/node-resolver-core': 3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@swc/core': 1.7.40(@swc/helpers@0.5.13) semver: 7.6.3 transitivePeerDependencies: - '@swc/helpers' - '@parcel/packager-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 lightningcss: 1.27.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) @@ -11553,38 +11598,33 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 posthtml: 0.16.6 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/packager-wasm@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/packager-wasm@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/plugin@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/plugin@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/profiler@2.12.0': dependencies: @@ -11592,79 +11632,71 @@ snapshots: '@parcel/events': 2.12.0 chrome-trace-event: 1.0.4 - '@parcel/reporter-cli@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-cli@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 chalk: 4.1.2 term-size: 2.2.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/reporter-dev-server@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-dev-server@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/reporter-tracer@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/reporter-tracer@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 chrome-trace-event: 1.0.4 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/resolver-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/resolver-default@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/node-resolver-core': 3.3.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-browser-hmr@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-browser-hmr@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-react-refresh@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-react-refresh@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 react-error-overlay: 6.0.9 react-refresh: 0.9.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/runtime-service-worker@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/runtime-service-worker@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/rust@2.12.0': {} @@ -11672,10 +11704,10 @@ snapshots: dependencies: detect-libc: 1.0.3 - '@parcel/transformer-babel@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-babel@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -11684,12 +11716,11 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-css@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 browserslist: 4.24.2 @@ -11697,12 +11728,11 @@ snapshots: nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-html@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -11712,45 +11742,41 @@ snapshots: srcset: 4.0.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-image@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) nullthrows: 1.1.1 - transitivePeerDependencies: - - '@swc/helpers' '@parcel/transformer-js@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/source-map': 2.1.1 '@parcel/utils': 2.12.0 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@swc/helpers': 0.5.13 browserslist: 4.24.2 nullthrows: 1.1.1 regenerator-runtime: 0.13.11 semver: 7.6.3 - '@parcel/transformer-json@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-json@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) json5: 2.2.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-postcss@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-postcss@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 '@parcel/utils': 2.12.0 clone: 2.1.2 @@ -11759,11 +11785,10 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-posthtml@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-posthtml@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -11772,28 +11797,25 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-raw@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-react-refresh-wrap@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-react-refresh-wrap@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 react-refresh: 0.9.0 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' - '@parcel/transformer-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/transformer-svg@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/diagnostic': 2.12.0 - '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/plugin': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/rust': 2.12.0 nullthrows: 1.1.1 posthtml: 0.16.6 @@ -11802,16 +11824,15 @@ snapshots: semver: 7.6.3 transitivePeerDependencies: - '@parcel/core' - - '@swc/helpers' '@parcel/types@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': dependencies: - '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/cache': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/diagnostic': 2.12.0 '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/source-map': 2.1.1 - '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/workers': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) utility-types: 3.11.0 transitivePeerDependencies: - '@parcel/core' @@ -11884,7 +11905,7 @@ snapshots: '@parcel/watcher-win32-ia32': 2.4.1 '@parcel/watcher-win32-x64': 2.4.1 - '@parcel/workers@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13)': + '@parcel/workers@2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))': dependencies: '@parcel/core': 2.12.0(@swc/helpers@0.5.13) '@parcel/diagnostic': 2.12.0 @@ -11893,8 +11914,6 @@ snapshots: '@parcel/types': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/utils': 2.12.0 nullthrows: 1.1.1 - transitivePeerDependencies: - - '@swc/helpers' '@pkgr/core@0.1.1': {} @@ -17169,9 +17188,9 @@ snapshots: '@parcel/fs': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) '@parcel/logger': 2.12.0 '@parcel/package-manager': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-cli': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) - '@parcel/reporter-tracer': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13))(@swc/helpers@0.5.13) + '@parcel/reporter-cli': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-dev-server': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) + '@parcel/reporter-tracer': 2.12.0(@parcel/core@2.12.0(@swc/helpers@0.5.13)) '@parcel/utils': 2.12.0 chalk: 4.1.2 commander: 7.2.0 @@ -17613,6 +17632,12 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-loader@4.0.2(webpack@5.95.0): + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.95.0 + rc-cascader@3.28.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.25.9 @@ -17991,6 +18016,17 @@ snapshots: react-fast-compare@3.2.2: {} + react-feather@2.0.10(react@18.3.1): + dependencies: + prop-types: 15.8.1 + react: 18.3.1 + + react-frame-component@5.2.7(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.25.9 diff --git a/website/README.md b/website/README.md index 0c6c2c27b..0a1b48113 100644 --- a/website/README.md +++ b/website/README.md @@ -4,22 +4,28 @@ This website is built using [Docusaurus](https://docusaurus.io/), a modern stati ### Installation +In the root directory of the project, run: + ``` -$ yarn +$ pnpm install ``` ### Local Development +In the root directory of the project, run: + ``` -$ yarn start +$ pnpm -filter=website run start ``` This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. ### Build +In the root directory of the project, run: + ``` -$ yarn build +$ pnpm -filter=website run build ``` This command generates static content into the `build` directory and can be served using any static contents hosting service. diff --git a/website/docs/compare-matrix-landing.md b/website/docs/compare-matrix-landing.md new file mode 100644 index 000000000..81cf036ec --- /dev/null +++ b/website/docs/compare-matrix-landing.md @@ -0,0 +1,8 @@ +| Feature | [uniforms](https://github.com/vazco/uniforms) | [Formik](https://github.com/jaredpalmer/formik) | [redux-form](https://github.com/erikras/redux-form) | [React Final Form](https://github.com/final-form/react-final-form) | [react-hook-form](https://github.com/react-hook-form/react-hook-form) | +| :----------------------------------------------------------------------------- | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | ----------------------------------------------------------------------------------- | +| Automatic form layout | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | +| Manual state management | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | +| Manually trigger validation | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | +| AntD, Bootstrap 3, Bootstrap 4, Bootstrap 5, Material, MUI, Semantic UI themes | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | +| JSON, GraphQL, SimpleSchema, Zod and custom schema support | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | +| Field level validation | ![unsupported](https://github.githubassets.com/images/icons/emoji/unicode/2716.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | ![supported](https://github.githubassets.com/images/icons/emoji/unicode/2714.png) | diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 8acacd11c..a5eeb659a 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -36,7 +36,49 @@ const config: Config = { ], ], + customFields: { + email: 'hello@uniforms.tools', + companies: [ + { url: 'https://www.deskpro.com/', image: 'deskpro.png', alt: 'Deskpro' }, + { url: 'https://www.nokia.com/', image: 'nokia.png', alt: 'Nokia' }, + { + url: 'https://github.com/react-page/react-page/tree/master/packages/plugins/createPluginMaterialUi', + image: 'react-page.png', + alt: 'React Page', + }, + { + url: 'https://graphback.dev', + image: 'graphback.png', + alt: 'Graphback', + }, + { + url: 'https://www.onyx-one.com/', + image: 'onyx-one.png', + alt: 'Onyx one', + }, + { url: 'https://aerogear.org', image: 'aerogear.png', alt: 'Aerogear' }, + { + url: 'https://cleverbeagle.com/together', + image: 'cleverbeagle.png', + alt: 'Clever Beagle', + }, + { url: 'http://www.orionjs.org', image: 'orionjs.png', alt: 'Orion.js' }, + { + url: 'https://boulder.care', + image: 'boulder.svg', + alt: 'Boulder Care', + }, + ], + }, + themeConfig: { + algolia: { + apiKey: '9bab87682792c2bd77ec707a56669e29', + appId: 'WWWW16GKXU', + contextualSearch: false, + indexName: 'uniforms', + searchPagePath: false, + }, navbar: { logo: { alt: 'uniforms logo', src: 'img/uniforms.svg' }, items: [ @@ -46,11 +88,27 @@ const config: Config = { position: 'left', label: 'Docs', }, + { + label: 'Tutorial', + to: '/docs/tutorials-basic-uniforms-usage', + position: 'left', + }, + { label: 'Playground', to: '/playground', position: 'left' }, { href: 'https://github.com/vazco/uniforms', label: 'GitHub', position: 'left', }, + { + label: 'Enterprise', + href: 'https://forminer.com/?utm_source=uniforms&utm_medium=Menu_CTA&utm_campaign=Forminer_uniforms_menu_CTA&utm_id=Forminer_uniforms_menu', + position: 'left', + }, + { + label: 'Custom solutions', + href: 'https://www.vazco.eu/', + position: 'left', + }, ], }, prism: { diff --git a/website/package.json b/website/package.json index 24ff34ee8..8b61087ff 100644 --- a/website/package.json +++ b/website/package.json @@ -20,17 +20,30 @@ "@docusaurus/core": "3.5.2", "@docusaurus/preset-classic": "3.5.2", "@mdx-js/react": "^3.0.0", + "ajv": "8.17.1", + "antd": "5.21.5", + "classnames": "^2.0.0", "clsx": "^2.0.0", + "lodash": "^4.0.0", + "lz-string": "1.5.0", + "message-box": "0.2.7", "prism-react-renderer": "^2.3.0", + "raw-loader": "4.0.2", "react": "^18.0.0", - "react-dom": "^18.0.0" + "react-dom": "^18.0.0", + "react-feather": "2.0.10", + "react-frame-component": "5.2.7", + "zod": "3.23.8" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.5.2", "@docusaurus/theme-classic": "3.5.2", "@docusaurus/tsconfig": "3.5.2", "@docusaurus/types": "3.5.2", - "typescript": "~5.5.2" + "@types/simpl-schema": "1.12.8", + "simpl-schema": "1.13.1", + "typescript": "~5.5.2", + "uniforms": "workspace:*" }, "browserslist": { "production": [ diff --git a/website/src/components/Badge.tsx b/website/src/components/Badge.tsx new file mode 100644 index 000000000..368033401 --- /dev/null +++ b/website/src/components/Badge.tsx @@ -0,0 +1,45 @@ +import Link from '@docusaurus/Link'; +import classNames from 'classnames'; +import React, { ComponentType } from 'react'; + +import styles from '../css/index.module.css'; +import { Oval } from './Oval'; + +export type BadgeProps = { + border: number; + color: string; + icon: ComponentType<{ color?: string }>; + number?: string; + text: string; + to: string; +}; + +export function Badge({ + border, + color, + icon: Icon, + number, + text, + to, +}: BadgeProps) { + return ( + + + {Icon && ( + + + + )} +
+
+ {number} +
+

{text}

+
+ + ); +} diff --git a/website/src/components/Button.tsx b/website/src/components/Button.tsx new file mode 100644 index 000000000..7c811a784 --- /dev/null +++ b/website/src/components/Button.tsx @@ -0,0 +1,24 @@ +import Link from '@docusaurus/Link'; +import classNames from 'classnames'; +import React from 'react'; + +import styles from '../css/index.module.css'; + +export type ButtonProps = JSX.IntrinsicElements['button'] & { to: string }; + +export function Button({ children, className, to, ...props }: ButtonProps) { + return ( + + + + ); +} diff --git a/website/src/components/CodeSection.tsx b/website/src/components/CodeSection.tsx new file mode 100644 index 000000000..531b8d0dd --- /dev/null +++ b/website/src/components/CodeSection.tsx @@ -0,0 +1,66 @@ +import components from '@theme/MDXComponents'; +import React from 'react'; + +export type CodeSectionProps = { + language: string; + replace?: Record; + section?: string; + source: string | { default: string }; +}; + +export function CodeSection({ + language, + replace, + section, + source, +}: CodeSectionProps) { + // Unwrap ES module. + if (typeof source === 'object' && 'default' in source) { + source = source.default; + } + + // Cut out only desired section. + if (section) { + const pattern = new RegExp( + `// <${section}>\\s([\\s\\S]*?)\\s// \\s`, + 'g', + ); + + source = source + .split(pattern) + .reduce( + (source, part, index) => + index % 2 === 0 ? source : `${source}\n\n${part}`, + '', + ); + } + + // Remove remaining section tags. + source = source.replace(/\/\/ <.*?\n/g, ''); + + // Replace all mapped things. + if (replace) { + for (const [pattern, value] of Object.entries(replace)) { + source = source.replace(new RegExp(pattern, 'gs'), value); + } + } + + // At least one newline is required for non-inline view. + source = source.trim(); + if (!source.includes('\n')) { + source += '\n'; + } + + return ( + + + + ); +} diff --git a/website/src/components/ExampleCustomizer.tsx b/website/src/components/ExampleCustomizer.tsx new file mode 100644 index 000000000..1401e5381 --- /dev/null +++ b/website/src/components/ExampleCustomizer.tsx @@ -0,0 +1,63 @@ +import React, { ComponentType } from 'react'; +import { Box, Code, Database } from 'react-feather'; + +import { themeContext } from '../lib/universal'; +import { CodeSection } from './CodeSection'; +import { FormWrapper } from './FormWrapper'; +import { TogglerTabs } from './TogglerTabs'; + +const tabs = [ + { name: 'Semantic', value: 'semantic' as const }, + { name: 'MUI', value: 'mui' as const }, + { name: 'Bootstrap4', value: 'bootstrap4' as const }, + { name: 'Bootstrap5', value: 'bootstrap5' as const }, + { name: 'AntD', value: 'antd' as const }, + { name: 'Unstyled', value: 'unstyled' as const }, +]; + +const toggles = [ + { icon: , name: 'Example', tooltipText: 'Show example' }, + { icon: , name: 'Code', tooltipText: 'Show source code' }, + { icon: , name: 'Schema', tooltipText: 'Show schema' }, +]; + +export type ExampleCustomizerProps = { + code: { default: string }; + example: ComponentType; + schema: { default: string }; +}; + +export function ExampleCustomizer({ + code: { default: code }, + example: Example, + schema: { default: schema }, +}: ExampleCustomizerProps) { + return ( + + {({ tab: { value: theme }, toggle: { name } }) => { + switch (name) { + case 'Code': + return ( + + ); + case 'Example': + return ( + + + + + + ); + case 'Schema': + return ; + default: + return null; + } + }} + + ); +} diff --git a/website/src/components/FormWrapper.tsx b/website/src/components/FormWrapper.tsx new file mode 100644 index 000000000..6ab731094 --- /dev/null +++ b/website/src/components/FormWrapper.tsx @@ -0,0 +1,21 @@ +import React, { ReactNode, useContext } from 'react'; + +import styles from '../css/index.module.css'; +import { useFrameAutoResize } from '../lib/autoresize'; +import { themeContext } from '../lib/universal'; +import { PlaygroundWrap } from './Playground'; + +export type FormWrapperProps = { + children: ReactNode; +}; + +export function FormWrapper(props: FormWrapperProps) { + const theme = useContext(themeContext); + const frameProps = useFrameAutoResize([props.children]); + + return ( +
+ +
+ ); +} diff --git a/website/src/components/Heading.tsx b/website/src/components/Heading.tsx new file mode 100644 index 000000000..ab8b254f5 --- /dev/null +++ b/website/src/components/Heading.tsx @@ -0,0 +1,14 @@ +import classNames from 'classnames'; +import React from 'react'; + +import styles from '../css/index.module.css'; + +export type HeadingProps = JSX.IntrinsicElements['h1']; + +export function Heading({ children, className, ...props }: HeadingProps) { + return ( +

+ {children} +

+ ); +} diff --git a/website/src/components/IconLink.tsx b/website/src/components/IconLink.tsx new file mode 100644 index 000000000..79b98c05a --- /dev/null +++ b/website/src/components/IconLink.tsx @@ -0,0 +1,28 @@ +import Link from '@docusaurus/Link'; +import classNames from 'classnames'; +import React, { ComponentType } from 'react'; + +import styles from '../css/index.module.css'; + +export type IconLinkProps = JSX.IntrinsicElements['div'] & { + icon: ComponentType; + to: string; +}; + +export function IconLink({ + className, + icon: Icon, + to, + ...props +}: IconLinkProps) { + return ( + +
+ +
+ + ); +} diff --git a/website/src/components/Oval.tsx b/website/src/components/Oval.tsx new file mode 100644 index 000000000..b7553478c --- /dev/null +++ b/website/src/components/Oval.tsx @@ -0,0 +1,14 @@ +import classNames from 'classnames'; +import React from 'react'; + +import styles from '../css/index.module.css'; + +export type OvalProps = JSX.IntrinsicElements['span']; + +export function Oval({ children, className, ...props }: OvalProps) { + return ( + + {children} + + ); +} diff --git a/website/src/components/Playground.tsx b/website/src/components/Playground.tsx new file mode 100644 index 000000000..8ea47b679 --- /dev/null +++ b/website/src/components/Playground.tsx @@ -0,0 +1,291 @@ +import ConfigProvider from 'antd/lib/config-provider'; +import classNames from 'classnames'; +import omit from 'lodash/omit'; +import React, { Component } from 'react'; +import Frame, { FrameContextConsumer } from 'react-frame-component'; +import { ValidatedForm, connectField, context, useForm } from 'uniforms'; +import type { Option } from 'uniforms-unstyled/src/types'; + +import playgroundStyles from '../css/index.module.css'; +import presets from '../lib/presets'; +import { bridge, schema } from '../lib/schema'; +import styles from '../lib/styles'; +import { themes } from '../lib/universal'; +import { compress, parseQuery, updateQuery } from '../lib/utils'; + +export class Playground extends Component { + static getDerivedStateFromError(error: Error) { + return { error }; + } + + constructor() { + // @ts-expect-error: Types. + super(...arguments); + + const state = schema.clean(parseQuery()); + + try { + schema.validate(state); + // FIXME: Types. + } catch (error: any) { + (error.details as any[]).forEach(({ name }) => { + state[name] = schema.getDefinition(name).defaultValue; + }); + } + + this.state = state; + + this.onChange = this.onChange.bind(this); + } + + componentDidMount() { + updateQuery(this.state); + } + + componentDidUpdate() { + updateQuery(this.state); + } + + onChange(key: string, value: unknown) { + if (key === 'preset') { + // FIXME: Types. + this.setState((state: any) => ({ + props: { + ...state.props, + schema: presets[value as keyof typeof presets], + }, + })); + } + + this.setState({ error: undefined, [key]: value }); + } + + render() { + return ( + // @ts-expect-error: Types. + +
+ + + +
+ + {this.state.error ? ( +
+        ) : (
+          
+        )}
+      
+    );
+  }
+}
+
+// FIXME: ValidatedForm is not derivable.
+class PlaygroundForm extends (ValidatedForm as any) {
+  getContextState() {
+    return {
+      ...super.getContextState(),
+      theme: this.props.model.theme,
+    };
+  }
+
+  render() {
+    return (
+      
+        
+ + ); + } +} + +const PlaygroundModelDebug = () => { + const { model } = useForm(); + return ( + <> +
+
+
+        {`const model = ${JSON.stringify(model, null, 2)};`}
+      
+ + ); +}; + +class PlaygroundPreview extends Component { + constructor() { + // @ts-expect-error: Types. + super(...arguments); + + this._schema = eval(`(${this.props.value.schema})`); + } + + // eslint-disable-next-line camelcase + UNSAFE_componentWillReceiveProps(props: any) { + if (this.props.value.schema !== props.value.schema) { + this._schema = eval(`(${props.value.schema})`); + } + } + + // TODO: Types. + _schema: any; + + render() { + const { AutoFields, AutoForm, ErrorsField, SubmitField } = + themes[(this.props.theme as keyof typeof themes) || 'unstyled']; + + const { asyncOnSubmit, asyncOnValidate, schema, ...props } = + this.props.value; + + props.schema = this._schema; + if (asyncOnSubmit) { + props.onSubmit = () => + new Promise(resolve => { + setTimeout(resolve, 1000); + }); + } + if (asyncOnValidate) { + props.onValidate = (model: object, error: Error) => + new Promise(resolve => { + setTimeout(() => { + resolve(error); + }, 1000); + }); + } + + return ( + + {this.props.errorMessage ? ( + + ) : ( + + + + + + + )} + + ); + } +} + +const PlaygroundPreviewField = connectField(PlaygroundPreview); + +class PlaygroundProps extends Component { + render() { + const { onChange, schema, theme, value } = this.props; + + const isAntd = theme === 'antd'; + const isBootstrap = theme === 'bootstrap4'; + const isSemantic = theme === 'semantic'; + + // FIXME: theme is undefined during `docusaurus build`. + const { AutoForm, BoolField, ErrorsField, LongTextField, NumField } = + themes[(theme as keyof typeof themes) || 'unstyled']; + + return ( + + + + + + + + + + + + + + + + ); + } +} + +const PlaygroundPropsField = connectField(PlaygroundProps); + +class PlaygroundSelect extends Component { + render() { + // FIXME: allowedValues is undefined during `docusaurus build`. + const { options, onChange, value } = this.props; + + return ( + + ); + } +} + +const PlaygroundSelectField = connectField(PlaygroundSelect); + +export class PlaygroundWrap extends Component { + render() { + const { children, frameProps, theme } = this.props; + const content = ( + + {children} + {styles[theme as keyof typeof styles]} + + ); + + if (theme === 'mui') { + // Material-UI injects scoped CSS classes into head. + return ( +
+ ); + } + + let frameContent = content; + if (theme === 'antd') { + // Make AntD popups contained within the iframe. + frameContent = ( + + {(context: any) => ( + context.document.body}> + {content} + + )} + + ); + } + + return ( + + ); + } +} diff --git a/website/src/components/Subtitle.tsx b/website/src/components/Subtitle.tsx new file mode 100644 index 000000000..1bed4a833 --- /dev/null +++ b/website/src/components/Subtitle.tsx @@ -0,0 +1,17 @@ +import classNames from 'classnames'; +import React from 'react'; + +import styles from '../css/index.module.css'; + +export type SubtitleProps = JSX.IntrinsicElements['p']; + +export function Subtitle({ children, className, ...props }: SubtitleProps) { + return ( +

+ {children} +

+ ); +} diff --git a/website/src/components/Tabs.tsx b/website/src/components/Tabs.tsx new file mode 100644 index 000000000..06e96589c --- /dev/null +++ b/website/src/components/Tabs.tsx @@ -0,0 +1,80 @@ +import classNames from 'classnames'; +import React, { ReactNode } from 'react'; + +import styles from '../css/index.module.css'; +import { useTabs } from '../lib/tabs'; + +export type TabsItem = { + name: string; +}; + +export type TabsHeaderProps = { + activeTab: number; + items: T[]; + onTab: (tab: number) => void; +}; + +export function TabsHeader({ + activeTab, + items, + onTab, +}: TabsHeaderProps) { + return ( +
+ {items.map(({ name }, key) => ( + onTab(key)} + > + {name} + + ))} +
+ ); +} + +export type TabsHeaderItemProps = { + active: boolean; + children: ReactNode; + onClick: () => void; +}; + +export function TabsHeaderItem({ + active, + children, + onClick, +}: TabsHeaderItemProps) { + return ( + event.key === 'Enter' && onClick()} + role="button" + tabIndex={0} + > + {children} + + ); +} + +export type TabsProps = { + children: (tab: T) => ReactNode; + group: string; + tabs: T[]; +}; + +export function Tabs({ + children, + group, + tabs, +}: TabsProps) { + const { activeTab, onTab } = useTabs(group); + + return ( + <> + + {children(tabs[activeTab])} + + ); +} diff --git a/website/src/components/Toggler.tsx b/website/src/components/Toggler.tsx new file mode 100644 index 000000000..9daf9e797 --- /dev/null +++ b/website/src/components/Toggler.tsx @@ -0,0 +1,86 @@ +import classNames from 'classnames'; +import React, { ReactNode, useState } from 'react'; + +import styles from '../css/index.module.css'; + +export type TogglerItem = { + component?: ReactNode; + icon: ReactNode; + tooltipText: string; +}; + +export type TogglerHeaderItemProps = JSX.IntrinsicElements['span'] & + TogglerItem & { active: boolean }; + +export function TogglerHeaderItem({ + active, + icon, + tooltipText, + ...rest +}: TogglerHeaderItemProps) { + return ( + + {tooltipText && ( + {tooltipText} + )} + {icon} + + ); +} + +export type TogglerHeaderProps = { + activeToggle: number; + items: T[]; + onClick: (tab: number) => () => void; +}; + +export function TogglerHeader({ + activeToggle, + items, + onClick, +}: TogglerHeaderProps) { + return ( +
+ {items.map((item, key) => { + return ( + + ); + })} +
+ ); +} + +export type TogglerProps = { + items: T[]; +}; + +export function Toggler({ items }: TogglerProps) { + const [activeToggle, setState] = useState(0); + + const toggleClick = (toggle: number) => () => { + setState(toggle); + }; + + return ( + <> + +
{items[activeToggle].component}
+ + ); +} diff --git a/website/src/components/TogglerTabs.tsx b/website/src/components/TogglerTabs.tsx new file mode 100644 index 000000000..e33375497 --- /dev/null +++ b/website/src/components/TogglerTabs.tsx @@ -0,0 +1,44 @@ +import React, { ReactNode, useState } from 'react'; + +import styles from '../css/index.module.css'; +import { useTabs } from '../lib/tabs'; +import { TabsHeader, TabsItem } from './Tabs'; +import { TogglerHeader, TogglerItem } from './Toggler'; + +export type TogglerTabsProps = { + children: (args: { tab: T; toggle: U }) => ReactNode; + group: string; + tabsItems: T[]; + togglerItems: U[]; +}; + +export function TogglerTabs({ + children, + group, + tabsItems, + togglerItems, +}: TogglerTabsProps) { + const { activeTab, onTab } = useTabs(group); + const [activeToggle, setStateToggler] = useState(0); + + const handleTogglerClick = (toggle: number) => () => { + setStateToggler(toggle); + }; + + return ( +
+
+ + +
+ {children({ + tab: tabsItems[activeTab], + toggle: togglerItems[activeToggle], + })} +
+ ); +} diff --git a/website/src/css/index.module.css b/website/src/css/index.module.css new file mode 100644 index 000000000..99f6ab1ad --- /dev/null +++ b/website/src/css/index.module.css @@ -0,0 +1,949 @@ +@import url('https://fonts.googleapis.com/css?family=Poppins:400,700&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Muli:400,600&display=swap'); + +@media (max-width: 996px) { + .center-if-sm { + text-align: center; + } +} + +@media (prefers-reduced-motion: no-preference) { + html { + scroll-behavior: smooth; + } +} + +:root { + --black: #000; + --bright-cyan-50: rgba(63, 196, 254, 0.2); + --bright-cyan: #3fc4fe; + --dark-blue-grey: #211b50; + --dark-slate-blue: #2d2665; + --dodger-blue-10: rgba(63, 187, 254, 0.1); + --dodger-blue: #3fbbfe; + --dusk-blue: #412a94; + --greenblue-10: rgba(31, 216, 152, 0.1); + --greenblue: #1fd898; + --grey: #eee; + --greyish-brown: #474747; + --pale-grey: #e8e6f5; + --periwinkle-50: rgba(136, 89, 255, 0.2); + --periwinkle: #8759ff; + --sea-green-50: rgba(66, 255, 172, 0.2); + --sea-green: #42ffac; + --white: #fff; + + --uni-background-color: var(--white); + --uni-heading-color: var(--dusk-blue); + --uni-heading-helper-color: var(--dusk-blue); + --uni-hero-bgcolor: var(--dark-blue-grey); + --uni-oval-background-color: var(--white); + --uni-oval-shadow-color: var(--pale-grey); + --uni-testimonial-text-color: var(--greyish-brown); + --uni-toolbar-bgcolor: var(--grey); + + --ifm-button-color: var(--white); +} + +:root[data-theme='dark'] { + --uni-background-color: var(--ifm-background-color); + --uni-heading-color: var(--ifm-font-color-base); + --uni-heading-helper-color: var(--ifm-font-color-base); + --uni-oval-shadow-color: var(--black); + --uni-testimonial-text-color: var(--ifm-font-color-base); + --uni-toolbar-bgcolor: var(--ifm-background-color); +} + +.padding { + padding-top: 2em; +} + +.landing table thead { + color: var(--black); + background-attachment: fixed; + background-image: linear-gradient( + to right, + var(--periwinkle), + var(--bright-cyan), + var(--sea-green) + ); +} + +.landing table thead tr th { + width: 15%; +} + +.landing table thead tr th a { + color: inherit; +} + +.landing table thead tr th:first-child { + width: 30%; +} + +.landing table tr td { + background-color: var(--dark-slate-blue); + color: var(--white); +} + +.landing table tr td:first-child, +.landing table tr th:first-child { + padding-left: 4em; +} + +.landing table tr td > img { + width: 1em; +} + +.landing tr:nth-child(odd) td { + background-color: var(--dark-blue-grey); +} + +.landing ul { + padding: 0; + opacity: 0.7; + font-family: Muli; + font-size: 1em; + font-weight: 600; + line-height: 1.33; +} + +.landing ul li { + list-style: none; + position: relative; + padding-left: 1em; + margin-bottom: 1em; +} + +.landing ul li::before { + content: ''; + position: absolute; + top: 0.5em; + left: 0; + width: 4px; + height: 4px; + background-color: var(--ifm-font-color-base); +} + +.landing :global .hero.hero--primary { + --ifm-hero-background-color: var(--dark-blue-grey); +} + +.overflow-hidden { + overflow: hidden; +} + +.landing .section-content :global .row { + position: relative; +} + +@media (min-width: 997px) { + .landing :global .section { + margin-top: 4em; + } + .landing :global .container { + scroll-margin-top: 200px; + } +} + +.landing :global .hero .container { + margin-top: 0em; + margin-bottom: 0em; +} + +.landing :global .container { + margin-top: 4em; + margin-bottom: 4em; +} + +@media (max-width: 996px) { + .landing :global .col { + margin-bottom: 2em; + } + .landing :global .col:last-of-type { + margin-bottom: 0; + } +} + +.discussions { + margin-top: 0 !important; +} + +.floating-example { + position: relative; +} + +@media (max-width: 996px) { + .floating-example > *:first-child { + margin-bottom: 4em; + } + .floating-example .system-window { + margin-left: auto; + margin-right: auto; + } +} + +@media (min-width: 997px) { + .floating-example > div:last-child { + position: absolute; + top: 12.5%; + left: 40%; + } +} + +.system-window { + --ifm-leading: 0; + width: 95%; + padding: 0; + border-radius: 1em; + overflow: hidden; + background: rgb(33, 27, 80); +} + +.system-window iframe { + border-radius: unset; +} + +.system-top-bar { + background-image: linear-gradient( + to right, + var(--periwinkle-50), + var(--bright-cyan-50) 90%, + var(--sea-green-50) + ); + padding: 0.25em 1em; +} + +.system-top-bar-circle { + display: inline-block; + width: 0.5em; + height: 0.5em; + margin-left: 0.3em; + border-radius: 50%; + filter: brightness(100%); +} + +.showcase-card { + padding: 1.5em; + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1em; +} + +@media (min-width: 997px) { + .showcase-card { + flex-direction: column; + } +} + +.showcase-card img { + height: 4em; + margin: 1em; +} + +.showcase-card p { + display: block; + margin-left: 1em; +} + +.footer li { + color: var(--white); +} + +.footer .bullets { + color: var(--white); +} + +.footer .bullets li::before { + background-color: var(--dodger-blue); +} + +.footer .offset-column { + margin-left: 2em !important; +} + +.simple-yet-powerful-text { + margin-left: -5em; + margin-top: -8em; +} + +.fully-customizable-text { + margin-right: -5em; + margin-top: -8em; +} + +.reverse-wrap { + flex-wrap: wrap-reverse; +} + +.example + .example { + margin-bottom: 4em; +} + +@media (min-width: 997px) { + .example { + margin: 16em 0 !important; + } + .example + .example { + margin-bottom: 0 !important; + } +} + +.preview-border { + box-shadow: 0 6px 58px 0 var(--uni-box-shadow-color); + border: solid 1px var(--uni-border-color); +} + +.preview { + position: relative; + background-color: var(--uni-background-color); + padding: 2em; +} + +.no-padding { + padding: 0; +} + +@media (max-width: 500px) { + .preview { + padding: 1em; + } +} + +.solid-border-box { + border: solid 6px var(--uni-border-color); + padding: 4em; +} + +@media (max-width: 996px) { + .solid-border-box { + margin: 4em 0; + } +} + +@media (max-width: 400px) { + .solid-border-box { + padding: 4em 1em; + } +} + +.green-accent { + --uni-border-color: var(--greenblue); + --uni-box-shadow-color: var(--greenblue-10); + --ifm-menu-color-active: var(--uni-border-color); +} + +.blue-accent { + --uni-border-color: var(--dodger-blue); + --uni-box-shadow-color: var(--dodger-blue-10); + --ifm-menu-color-active: var(--uni-border-color); +} + +.grid3x3 { + position: relative; + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + text-align: center; + height: 100%; + padding: 4em 0; +} + +.item3x3 { + width: 33%; + align-self: center; + padding: 1.5em 1em; +} + +.company { + width: 100%; + transition: 0.2s filter; +} + +.company:hover { + filter: none; +} + +.border-dashed { + border: 2px dashed var(--pale-grey); +} + +.border-gradient { + border-style: solid; + border-width: 6px; + border-image-source: linear-gradient( + var(--uni-border-gradient-degrees), + var(--periwinkle), + var(--bright-cyan) 51%, + var(--sea-green) + ); + border-image-slice: 1; +} + +.border-disable-top-right { + --uni-border-gradient-degrees: 41deg; + border-top: 0; + border-right: 0; +} + +.border-disable-bottom-left { + --uni-border-gradient-degrees: 221deg; + border-bottom: 0; + border-left: 0; +} + +.arrow-button { + background-color: transparent; + border: none; + cursor: pointer; + transition: all 0.2s linear; +} + +.left-arrow-button:hover { + transform: translateX(-5px); +} + +.right-arrow-button:hover { + transform: translateX(5px); +} + +.arrow { + height: 35px; + width: 35px; +} + +.carousel-container { + overflow: hidden; + max-width: 968px; +} + +.carousel { + transition: transform 0.3s; + display: flex; +} + +.testimonials { + display: flex; + justify-content: center; + align-items: center; +} + +.testimonials-pair-active { + display: flex; + justify-content: center; + height: auto; +} + +@media (max-width: 768px) { + .testimonials-pair-active { + flex-direction: column; + } +} + +.testimonials-pair-inactive { + display: none; +} + +@media (max-width: 768px) { + .testimonials-pair-inactive { + flex-direction: column; + } +} + +.testimonial { + margin: 2em; + background: var(--ifm-background-surface-color); +} + +.testimonial-content { + width: 420px; + height: 100%; + padding: 4em 2em; + display: flex; + flex-direction: column; + align-items: center; +} + +.testimonial-links-wrapper { + width: 140px; + max-width: 140px; + display: flex; + justify-content: space-between; + margin-bottom: 30px; + color: var(--dusk-blue); +} + +.testimonial-links-wrapper a { + color: var(--dusk-blue); +} + +.testimonial-description::before { + content: '„'; +} + +.testimonial-description::after { + content: '”'; +} + +.testimonial-avatar { + width: 100px; + border-radius: 50%; + margin: 15px 0 10px; +} + +.section-heading { + margin: 1.5em 0; +} + +.section-bgwhite { + color: var(--ifm-font-color-base); +} + +.section-bgwhite-block { + position: absolute; + width: 200%; + height: 100%; + top: 0; + left: 0; +} + +.section-bgwhite-block-left { + background: var(--white); + margin-left: -100%; +} + +.section-bgwhite-block-right { + background: var(--uni-background-color); + margin-right: -100%; +} + +@media (min-width: 997px) { + .section-bgwhite-block-left, + .section-bgwhite-block-right { + height: 200%; + } +} + +.section-content { + position: relative; + padding: 0 4em !important; +} + +.section-content.logos { + padding-left: unset !important; +} + +@media (max-width: 996px) { + .section-content, + .section-content.logos { + margin-top: 0; + padding: 4em !important; + } +} + +@media (max-width: 400px) { + .section-content { + margin-top: 0; + padding: 0 1em !important; + } +} + +.fluid { + padding: 8em 0; +} + +.whyus { + --ifm-hero-background-color: var(--dusk-blue) !important; + color: black; +} + +.oval { + display: inline-block; + width: 64px; + height: 64px; + padding: 20px; + border-radius: 50%; + box-shadow: 0 8px 23px 0 var(--uni-oval-shadow-color); + background-color: var(--uni-oval-background-color); +} + +.link-icon-container { + display: flex; + justify-content: center; + align-items: center; + width: 37px; + height: 37px; + border-radius: 50%; + box-shadow: 0 8px 23px 0 var(--uni-oval-shadow-color); + background-color: var(--uni-oval-background-color); +} + +.link-icon-container svg:hover { + transition: filter 0.15s ease-in; + filter: brightness(1.6); +} + +.oval.white { + background-color: var(--white); + width: 100px; + height: 100px; +} + +.top-right-corner { + position: absolute; + right: 0; + transform: translate(45%, -45%); +} + +.badges { + display: flex; + justify-content: center; + flex-wrap: wrap; +} + +.badge-number { + font-size: 3em; + font-weight: bold; +} + +.badge { + position: relative; + height: 170px; + width: 260px; + margin: 2em; +} + +.badge-image { + position: absolute; + display: block; +} + +.badge-centered { + position: absolute; + top: 55%; + left: 50%; + transform: translate(-50%, -50%); +} + +.call-to-action { + --ifm-button-background-color: var(--periwinkle) !important; + --ifm-button-border-color: var(--periwinkle) !important; + --ifm-color-primary-darker: var(--bright-cyan) !important; + margin-top: 4em; + border-radius: 2em; + min-width: 240px; +} + +.theme-icon { + width: 40px; + height: 40px; + margin-right: 25px; + display: inline-block; +} + +.theme-icon:last-child { + margin-right: 0; +} + +.section { + margin-bottom: 8em; +} + +.flex-center { + display: flex; + justify-content: center; +} + +.top-margin { + margin-top: 70px; +} + +.long-button { + max-width: 100%; + white-space: pre-line; +} + +.text { + font-family: Poppins, sans-serif; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + line-height: normal; + color: var(--ifm-font-color-base); +} + +.text-big { + font-size: 1.5em; + font-weight: bold; +} + +.text-huge { + font-size: 2.5em; + font-weight: bold; + line-height: 1.25; +} + +.text.heading-helper { + color: var(--uni-heading-helper-color); + font-family: Muli; + font-size: 1em; + font-weight: 600; + letter-spacing: 1px; + opacity: 0.6; +} + +.heading { + color: var(--uni-heading-color); + font-family: Poppins; + font-size: 2em; + font-weight: bold; + line-height: 1.31; + margin-bottom: 2em; +} + +.heading-white { + --uni-heading-color: var(--white); +} + +.text.emphasis { + color: var(--dodger-blue); + font-family: Poppins; + font-size: 24px; + font-weight: 600; + line-height: 1.42; +} + +.text.paragraph { + color: var(--white); + font-family: Muli; + font-size: 1em; + line-height: 1.75; + margin-bottom: 0.8em; + opacity: 0.8; +} + +.text.section-subtitle { + color: var(--white); + font-family: Muli; + font-size: 1em; + font-weight: 600; + letter-spacing: 1px; + opacity: 0.6; +} + +.text.footer-heading { + color: var(--dodger-blue); + font-family: Muli; + font-size: 18px; + font-weight: 600; +} + +.supported { + color: var(--white); + font-family: Muli; + font-size: 0.85em; + font-weight: 600; + line-height: 2; + margin-top: 3em; + opacity: 0.6; +} + +.title { + color: var(--white); + display: block; +} + +.description { + color: var(--bright-cyan); + display: block; + margin: 24px 0; +} + +@supports (background-clip: text) { + .description { + background-image: linear-gradient( + 81deg, + var(--periwinkle), + var(--bright-cyan), + var(--sea-green) + ); + background-clip: text; + -webkit-text-fill-color: transparent; + } +} + +.text.testimonial-description { + color: var(--uni-testimonial-text-color); + font-family: Muli; + font-size: 1.2em; + line-height: 1.75; + opacity: 0.8; + text-align: center; +} + +.bullets { + color: var(--white) !important; +} + +.bullets li { + margin-bottom: 0; +} + +.bullets li::before { + background-color: var(--periwinkle) !important; +} + +.commercial-bullets > li { + font-weight: normal; +} + +.commercial-box { + align-items: center; + display: flex; + justify-content: center; + padding: 0; +} + +.vazco { + height: 2em; + margin-top: 2em; +} + +.form-wrapper { + border-radius: 5px; + border: 1px solid var(--ifm-color-emphasis-alpha-30); +} + +.playground { + height: calc(100vh - var(--ifm-navbar-height)); +} + +.playground-wrap { + background-color: #fff; + color: #0e0e0e; + display: block; + flex: 1; + overflow-y: auto; + + border-radius: 5px; + border: none; + margin: 0; + padding: 0; + width: 100%; +} + +.playground .playground-wrap { + border-radius: unset; +} + +.playground, +.playground-column, +.playground-toolbar { + display: flex; +} + +.playground iframe, +.playground-toolbar select { + border: 0; +} + +.playground-column { + flex-direction: column; +} + +.playground iframe, +.playground-column, +.playground-toolbar select { + flex: 1; +} + +.playground-toolbar { + background-color: var(--uni-toolbar-bgcolor); +} + +.playground-toolbar select { + background-color: var(--uni-toolbar-bgcolor); + font-size: 1rem; + margin: 0.25em; + padding: 0.5em; +} + +.tabs { + display: flex; + margin: 0 0 0.25em -0.2em; + font-weight: 700; + flex-wrap: wrap; +} + +.tabs .item { + text-align: center; + font-size: 0.8em; + border: 1px solid var(--ifm-menu-color-active); + padding: 0.8em; + margin: 0.25em; + border-radius: 3px; + cursor: pointer; + flex: 1; +} + +.tabs .item.active { + background-color: var(--ifm-menu-color-active); + color: white; +} + +.toggler.header { + display: flex; + justify-content: flex-end; +} + +.toggler.header .item { + margin: 0.5em 0 0.5em 1em; + cursor: pointer; +} + +.toggler.header .item.active { + color: var(--ifm-menu-color-active); +} + +.toggler .tooltip { + position: relative; + display: inline-block; +} + +.toggler .tooltip .tooltip-text { + font-size: 0.7em; + visibility: hidden; + width: 120px; + background-color: black; + color: #fff; + text-align: center; + border-radius: 6px; + padding: 5px 0; + position: absolute; + z-index: 1; + bottom: 150%; + left: 50%; + margin-left: -60px; +} + +.toggler .tooltip .tooltip-text::after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: black transparent transparent transparent; +} + +.toggler .tooltip:hover .tooltip-text { + visibility: visible; +} + +.toggler-tabs .header { + display: flex; + justify-content: space-between; + align-items: center; +} diff --git a/website/src/lib/autoresize.ts b/website/src/lib/autoresize.ts new file mode 100644 index 000000000..5769a50e5 --- /dev/null +++ b/website/src/lib/autoresize.ts @@ -0,0 +1,30 @@ +import get from 'lodash/get'; +import { RefObject, useCallback, useEffect, useRef, useState } from 'react'; + +function handleResize( + ref: RefObject, + setHeight: (height: number) => void, +) { + const scrollHeight = get(ref.current, 'contentDocument.body.scrollHeight', 0); + + if (scrollHeight !== 0) { + setHeight(scrollHeight); + } +} + +export function useFrameAutoResize(watch: unknown[]) { + const [height, setHeight] = useState(300); + const ref = useRef(); + const onLoad = useCallback( + () => handleResize(ref, setHeight), + [ref, setHeight], + ); + + useEffect(() => { + const id = setInterval(onLoad, 1000); + return () => clearInterval(id); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [onLoad, ...watch]); + + return { onLoad, ref, style: { height } }; +} diff --git a/website/src/lib/presets.ts b/website/src/lib/presets.ts new file mode 100644 index 000000000..642591fad --- /dev/null +++ b/website/src/lib/presets.ts @@ -0,0 +1,145 @@ +const preset = (strings: TemplateStringsArray) => + strings[0].slice(5, -3).replace(/([\r\n]+) {4}/g, '$1'); + +const presets = { + 'Welcome!': preset` + new SimpleSchema2Bridge({ + schema: new SimpleSchema({ + date: { type: Date, defaultValue: new Date() }, + adult: Boolean, + size: { + type: String, + defaultValue: 'm', + allowedValues: ['xs', 's', 'm', 'l', 'xl'], + }, + rating: { + type: Number, + allowedValues: [1, 2, 3, 4, 5], + uniforms: { checkboxes: true }, + }, + friends: { type: Array, minCount: 1 }, + 'friends.$': Object, + 'friends.$.name': { type: String, min: 3 }, + 'friends.$.age': { type: Number, min: 0, max: 150 }, + }) + }) + `, + + 'Address (JSONSchema)': preset` + (() => { + const ajv = new Ajv({ allErrors: true, useDefaults: true, keywords: ["uniforms"] }); + const schema = { + title: 'Address', + type: 'object', + properties: { + city: { type: 'string' }, + state: { type: 'string' }, + street: { type: 'string' }, + zip: { type: 'string', pattern: '[0-9]{5}' }, + }, + required: ['street', 'zip', 'state'], + }; + + function createValidator(schema) { + const validator = ajv.compile(schema); + + return (model) => { + validator(model); + + if (validator.errors && validator.errors.length) { + return { details: validator.errors }; + } + }; + } + + const validator = createValidator(schema); + + return new JSONSchemaBridge({ schema, validator }); + })() + `, + + 'Address (SimpleSchema)': preset` + new SimpleSchema2Bridge({ + schema: new SimpleSchema({ + city: { + type: String, + optional: true, + max: 50, + }, + state: String, + street: { type: String, max: 100 }, + zip: { + type: String, + regEx: /^[0-9]{5}$/, + }, + }) + }) + `, + + 'Address (Zod)': preset` + new ZodBridge({ + schema: z.object({ + city: z.string().max(50).optional(), + state: z.string(), + street: z.string().max(100), + zip: z.string().regex(/^[0-9]{5}$/), + }) + }) + `, + + 'All Fields (SimpleSchema)': preset` + new SimpleSchema2Bridge({ + schema: new SimpleSchema({ + text: { type: String }, + num: { type: Number }, + bool: { type: Boolean }, + nested: { type: Object }, + 'nested.text': { type: String }, + date: { type: Date }, + list: { type: Array }, + 'list.$': { + type: String, + uniforms: { label: 'List Text', placeholder: 'List Text Placeholder' }, + }, + select: { + type: String, + uniforms: { + options: [ + { label: 'Option A', value: 'a' }, + { label: 'Option B', value: 'b' }, + ], + }, + }, + radio: { + type: String, + uniforms: { + checkboxes: true, + options: [ + { label: 'Option A', value: 'a' }, + { label: 'Option B', value: 'b' }, + ], + }, + }, + }) + }) + `, + + 'All Fields (Zod)': preset` + new ZodBridge({ + schema: z.object({ + text: z.string(), + num: z.number(), + bool: z.boolean(), + nested: z.object({ text: z.string() }), + date: z.date(), + // TODO: Custom label and placeholder. + list: z.array(z.string()), + select: z.enum(['a', 'b']), + // TODO: Enums with custom props. + radio: z.enum(['a', 'b']), + }) + }) + `, +}; + +export default presets; diff --git a/website/src/lib/schema.ts b/website/src/lib/schema.ts new file mode 100644 index 000000000..8f0b292da --- /dev/null +++ b/website/src/lib/schema.ts @@ -0,0 +1,110 @@ +import Ajv from 'ajv'; +import MessageBox from 'message-box'; +import SimpleSchema from 'simpl-schema'; +import { filterDOMProps } from 'uniforms'; +import { JSONSchemaBridge } from 'uniforms-bridge-json-schema'; +import { SimpleSchema2Bridge } from 'uniforms-bridge-simple-schema-2'; +import { ZodBridge } from 'uniforms-bridge-zod'; +import { z } from 'zod'; + +import presets from './presets'; +import { themes } from './universal'; + +// Hide custom props. +declare module 'uniforms' { + interface FilterDOMProps { + const: never; + } +} + +filterDOMProps.register('const'); + +// FIXME: Make it extensible for globals. +const scope: any = typeof window === 'undefined' ? global : window; + +// FIXME: This file is loading a different version of simpl-schema than the one +// that uniforms-bridge-simple-schema-2 package. +SimpleSchema.extendOptions(['uniforms']); + +// This is required for the eval. +scope.Ajv = Ajv; +scope.JSONSchemaBridge = JSONSchemaBridge; +scope.SimpleSchema = SimpleSchema; +scope.SimpleSchema2Bridge = SimpleSchema2Bridge; +scope.ZodBridge = ZodBridge; +scope.z = z; + +// Dynamic field error. +MessageBox.defaults({ messages: { en: { syntax: '' } } }); + +const propsSchema = new SimpleSchema({ + autosave: { optional: true, type: Boolean }, + autosaveDelay: { optional: true, type: SimpleSchema.Integer }, + disabled: { optional: true, type: Boolean }, + label: { optional: true, type: Boolean }, + placeholder: { optional: true, type: Boolean }, + readOnly: { optional: true, type: Boolean }, + showInlineError: { optional: true, type: Boolean }, + asyncOnSubmit: { + optional: true, + type: Boolean, + label: 'Async onSubmit (1 sec)', + }, + asyncOnValidate: { + optional: true, + type: Boolean, + label: 'Async onValidate (1 sec)', + }, + + schema: { + optional: true, + type: String, + custom() { + try { + eval(`(${this.value ?? ''})`); + return undefined; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + MessageBox.defaults({ messages: { en: { syntax: message } } }); + return 'syntax'; + } + }, + }, +}); + +const propsBridge = new SimpleSchema2Bridge({ schema: propsSchema }); + +export const schema = new SimpleSchema({ + preset: { + type: String, + defaultValue: Object.keys(presets)[0], + allowedValues: Object.keys(presets), + }, + + props: { + type: Object, + blackbox: true, + defaultValue: { + autosave: false, + autosaveDelay: 100, + disabled: false, + label: true, + placeholder: false, + readOnly: false, + schema: presets[Object.keys(presets)[0] as keyof typeof presets], + showInlineError: false, + asyncOnSubmit: false, + asyncOnValidate: false, + }, + uniforms: { schema: propsBridge }, + }, + + theme: { + type: String, + uniforms: { transform: (theme: string) => `uniforms-${theme}` }, + defaultValue: Object.keys(themes)[0], + allowedValues: Object.keys(themes), + }, +}); + +export const bridge = new SimpleSchema2Bridge({ schema }); diff --git a/website/src/lib/stats.ts b/website/src/lib/stats.ts new file mode 100644 index 000000000..a26ba7e50 --- /dev/null +++ b/website/src/lib/stats.ts @@ -0,0 +1,144 @@ +import { useEffect, useState } from 'react'; + +function cacheKey(key: string) { + return `__cached-fetch-${key}`; +} + +function cacheGet(key: string) { + try { + const stored = localStorage.getItem(cacheKey(key)); + const { expires, data } = JSON.parse(stored ?? ''); + return { expired: !expires || expires < Date.now(), data }; + } catch (error) { + return { expired: true, data: null }; + } +} + +function cacheSet(key: string, data: unknown, expires: number) { + try { + localStorage.setItem(cacheKey(key), JSON.stringify({ data, expires })); + } catch (error) { + // Nothing. + } +} + +function cached(key: string, fallback: () => Promise, expires = 0) { + const { expired, data } = cacheGet(key); + + if (expired) { + return fallback() + .then(data => { + cacheSet(key, data, expires); + return data; + }) + .catch(() => data || 0); + } + + return Promise.resolve(data); +} + +function formatDate(date: Date) { + return date.toISOString().slice(0, 10); +} + +function formatNumber(number: number) { + return number.toLocaleString('en-US'); +} + +function getLastDayOfYear(date: Date) { + const newDate = new Date(date); + newDate.setFullYear(newDate.getFullYear() + 1); + newDate.setDate(newDate.getDate() - 1); + return newDate; +} + +function getYearRange(date: Date) { + const lastDayOfMonth = getLastDayOfYear(date); + return `${formatDate(date)}:${formatDate(lastDayOfMonth)}`; +} + +function dateRanges(from: Date, to: Date) { + const dates = []; + while (from < to) { + dates.push(getYearRange(from)); + from.setFullYear(from.getFullYear() + 1); + } + return dates; +} + +/** + * Queries are limited to at most 18 months of data. The earliest date for which data will be returned is January 10, 2015. + * {@link https://github.com/npm/registry/blob/master/docs/download-counts.md#limits See limits} + */ +async function fetchNPMDownloadsInRange(range: string) { + type NPMResponse = { + downloads: number; + start: string; + end: string; + package: string; + }; + + const response = await fetch( + `https://api.npmjs.org/downloads/point/${range}/uniforms`, + ); + const { downloads }: NPMResponse = await response.json(); + return downloads || 0; +} + +function getNPMDownloadsInRange(range: string, expires?: number) { + return cached(`npm-${range}`, () => fetchNPMDownloadsInRange(range), expires); +} + +function getNPMDownloads(from: Date, to: Date) { + const dates = dateRanges(from, to); + const lastRange = dates.pop()!; + + const oneYear = 12 * 31 * 24 * 60 * 60 * 1000; + const oneDay = 1 * 24 * 60 * 60 * 1000; + + return Promise.all( + dates + .map(range => getNPMDownloadsInRange(range, Date.now() + oneYear)) + .concat(getNPMDownloadsInRange(lastRange, Date.now() + oneDay)), + ).then(sums => sums.reduce((a, b) => a + b, 0)); +} + +function getGitHubStats() { + const twoMinutes = 2 * 60 * 1000; + return cached( + 'github', + () => + fetch('https://api.github.com/repos/vazco/uniforms') + .then(response => response.json()) + .then(({ forks_count: forks, stargazers_count: stars }) => ({ + forks, + stars, + })), + Date.now() + twoMinutes, + ); +} + +export function useStats() { + const [stars, setStars] = useState(); + const [forks, setForks] = useState(); + const [downloads, setDownloads] = useState(); + + useEffect(() => { + getGitHubStats().then(({ forks, stars }) => { + forks && setForks(formatNumber(forks)); + stars && setStars(formatNumber(stars)); + }); + }, [stars, forks]); + + useEffect(() => { + const DATE_RANGE_START = '2015-01-01'; + const start = new Date(DATE_RANGE_START); + const today = new Date(); + + getNPMDownloads(start, today).then(downloads => + setDownloads(formatNumber(downloads)), + ); + }, [downloads]); + + return { downloads, forks, stars }; +} diff --git a/website/src/lib/styles.tsx b/website/src/lib/styles.tsx new file mode 100644 index 000000000..b275db1a9 --- /dev/null +++ b/website/src/lib/styles.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +const commonStyles = ` + body { + margin: 0; + } + + textarea[name="schema"] { + font-family: monospace !important; + min-height: 20em !important; + } + + .frame-root { + padding: 1rem !important; + } +`; + +const common = \ No newline at end of file diff --git a/website/static/assets/companies/cleverbeagle.png b/website/static/assets/companies/cleverbeagle.png new file mode 100644 index 000000000..7f19166c9 Binary files /dev/null and b/website/static/assets/companies/cleverbeagle.png differ diff --git a/website/static/assets/companies/deskpro.png b/website/static/assets/companies/deskpro.png new file mode 100644 index 000000000..2715612d0 Binary files /dev/null and b/website/static/assets/companies/deskpro.png differ diff --git a/website/static/assets/companies/graphback.png b/website/static/assets/companies/graphback.png new file mode 100644 index 000000000..193cc473b Binary files /dev/null and b/website/static/assets/companies/graphback.png differ diff --git a/website/static/assets/companies/nokia.png b/website/static/assets/companies/nokia.png new file mode 100644 index 000000000..1b9de7821 Binary files /dev/null and b/website/static/assets/companies/nokia.png differ diff --git a/website/static/assets/companies/onyx-one.png b/website/static/assets/companies/onyx-one.png new file mode 100644 index 000000000..355234dfb Binary files /dev/null and b/website/static/assets/companies/onyx-one.png differ diff --git a/website/static/assets/companies/orionjs.png b/website/static/assets/companies/orionjs.png new file mode 100644 index 000000000..d3380d637 Binary files /dev/null and b/website/static/assets/companies/orionjs.png differ diff --git a/website/static/assets/companies/react-page.png b/website/static/assets/companies/react-page.png new file mode 100644 index 000000000..366520465 Binary files /dev/null and b/website/static/assets/companies/react-page.png differ diff --git a/website/static/assets/themes/antd.png b/website/static/assets/themes/antd.png new file mode 100644 index 000000000..004cb9940 Binary files /dev/null and b/website/static/assets/themes/antd.png differ diff --git a/website/static/assets/themes/bootstrap.svg b/website/static/assets/themes/bootstrap.svg new file mode 100644 index 000000000..91ded9e3e --- /dev/null +++ b/website/static/assets/themes/bootstrap.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/website/static/assets/themes/mui.png b/website/static/assets/themes/mui.png new file mode 100644 index 000000000..56526f097 Binary files /dev/null and b/website/static/assets/themes/mui.png differ diff --git a/website/static/assets/themes/semantic.svg b/website/static/assets/themes/semantic.svg new file mode 100644 index 000000000..de73ced34 --- /dev/null +++ b/website/static/assets/themes/semantic.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/website/static/avatar/florian-bienefelt.jpg b/website/static/avatar/florian-bienefelt.jpg new file mode 100644 index 000000000..14ec01748 Binary files /dev/null and b/website/static/avatar/florian-bienefelt.jpg differ diff --git a/website/static/avatar/kheang-hok-chin.jpg b/website/static/avatar/kheang-hok-chin.jpg new file mode 100644 index 000000000..4d4e2f1b4 Binary files /dev/null and b/website/static/avatar/kheang-hok-chin.jpg differ diff --git a/website/static/avatar/lorant-vajda.jpg b/website/static/avatar/lorant-vajda.jpg new file mode 100644 index 000000000..db41f8160 Binary files /dev/null and b/website/static/avatar/lorant-vajda.jpg differ diff --git a/website/static/avatar/serkan-durusoy.jpg b/website/static/avatar/serkan-durusoy.jpg new file mode 100644 index 000000000..32677002e Binary files /dev/null and b/website/static/avatar/serkan-durusoy.jpg differ diff --git a/website/static/avatar/viktor-bezdek.jpg b/website/static/avatar/viktor-bezdek.jpg new file mode 100644 index 000000000..5036eb4e0 Binary files /dev/null and b/website/static/avatar/viktor-bezdek.jpg differ diff --git a/website/static/avatar/wojciech-trocki.jpg b/website/static/avatar/wojciech-trocki.jpg new file mode 100644 index 000000000..6fec622e1 Binary files /dev/null and b/website/static/avatar/wojciech-trocki.jpg differ diff --git a/website/static/img/arrow-left.svg b/website/static/img/arrow-left.svg new file mode 100644 index 000000000..d7b68f076 --- /dev/null +++ b/website/static/img/arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/static/img/arrow-right.svg b/website/static/img/arrow-right.svg new file mode 100644 index 000000000..ff4db8b18 --- /dev/null +++ b/website/static/img/arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/static/img/border-01.svg b/website/static/img/border-01.svg new file mode 100644 index 000000000..6cfc42e3b --- /dev/null +++ b/website/static/img/border-01.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/website/static/img/border-02.svg b/website/static/img/border-02.svg new file mode 100644 index 000000000..b38bc6145 --- /dev/null +++ b/website/static/img/border-02.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/website/static/img/border-03.svg b/website/static/img/border-03.svg new file mode 100644 index 000000000..cd9f5527a --- /dev/null +++ b/website/static/img/border-03.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/website/static/img/forminer-screenshot.png b/website/static/img/forminer-screenshot.png new file mode 100644 index 000000000..1f687ca2a Binary files /dev/null and b/website/static/img/forminer-screenshot.png differ diff --git a/website/static/img/icon-01.svg b/website/static/img/icon-01.svg new file mode 100644 index 000000000..845ec0525 --- /dev/null +++ b/website/static/img/icon-01.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/website/static/img/icon-02.svg b/website/static/img/icon-02.svg new file mode 100644 index 000000000..d302f683d --- /dev/null +++ b/website/static/img/icon-02.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/website/static/img/vazco.svg b/website/static/img/vazco.svg new file mode 100644 index 000000000..aa5d98223 --- /dev/null +++ b/website/static/img/vazco.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/types/docusaurus.d.ts b/website/types/docusaurus.d.ts new file mode 100644 index 000000000..00b1685b2 --- /dev/null +++ b/website/types/docusaurus.d.ts @@ -0,0 +1,20 @@ +declare module '@docusaurus/*' { + const something: any; + export = something; +} + +declare module '@theme/*' { + const something: any; + export = something; +} + +declare module '*.md' { + import { ComponentType } from 'react'; + const Component: ComponentType>; + export = Component; +} + +declare module '*.module.css' { + const classes: Record; + export = classes; +} diff --git a/website/types/message-box.d.ts b/website/types/message-box.d.ts new file mode 100644 index 000000000..aafc635ec --- /dev/null +++ b/website/types/message-box.d.ts @@ -0,0 +1,3 @@ +declare module 'message-box' { + export function defaults(messages: unknown): void; +} diff --git a/website/types/simpl-schema.d.ts b/website/types/simpl-schema.d.ts new file mode 100644 index 000000000..790c7ce20 --- /dev/null +++ b/website/types/simpl-schema.d.ts @@ -0,0 +1,8 @@ +import { ComponentType } from 'react'; +import { GuaranteedProps, UnknownObject } from 'uniforms'; + +declare module 'simpl-schema' { + export interface SchemaDefinition { + uniforms?: ComponentType> | UnknownObject | string; + } +}