mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-26 04:07:07 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c38d403f77 | |||
| c3bde7d989 | |||
| 8a08b0f366 | |||
| ed17c11715 | |||
| 6ce3f4b17a | |||
| fb9c8f4d2c | |||
| fbf6951c71 | |||
| 5e975ab95b | |||
| a3ec264764 | |||
| 5d504ffa4c | |||
| 04999662db | |||
| f7a34706c7 | |||
| f328a41982 | |||
| 20ebecb114 | |||
| d8cfb10974 | |||
| 3cdba0ae8e | |||
| 83e02b621a | |||
| cb2cc52c26 | |||
| 0e15229c52 | |||
| 8547867c6d | |||
| 5a69692f54 | |||
| 42ca7e1580 | |||
| c4ebb3fecd | |||
| 2a805cc082 | |||
| 89a5816ee4 | |||
| c3f6b8c003 | |||
| 0e201d5899 | |||
| ae5f1abc58 | |||
| 580101d04e | |||
| 81b4a4db53 | |||
| 8339e91e2b | |||
| 3119066728 | |||
| 326e28e9b0 | |||
| 90f0127ada | |||
| 0353a8186c | |||
| dd043df00f | |||
| 97b7c79bc6 | |||
| 634e0b4302 | |||
| 2a23f1f003 | |||
| 88ffdcc303 | |||
| b6b09d42af | |||
| ebc39e9db9 | |||
| 0df3849ea2 | |||
| 8ed1bda2f2 | |||
| d67699a1f1 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": minor
|
||||
---
|
||||
|
||||
Fix images in reusable content across spaces.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'gitbook': patch
|
||||
---
|
||||
|
||||
Fix openapi-select hover in responses
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Show sections tabs only if there is at least two sections
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@gitbook/colors": patch
|
||||
---
|
||||
|
||||
Update chroma ratio per step
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@gitbook/react-openapi": patch
|
||||
---
|
||||
|
||||
Fix Python code example for JSON payload
|
||||
@@ -3,4 +3,4 @@
|
||||
'gitbook': patch
|
||||
---
|
||||
|
||||
Improve OpenAPIResponses examples and schemas
|
||||
Fix openapi CR preview
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": minor
|
||||
---
|
||||
|
||||
Adds AI sidebar with recommendations based on browsing behaviour
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@gitbook/react-openapi": minor
|
||||
"gitbook": minor
|
||||
---
|
||||
|
||||
Design tweaks to code blocks and OpenAPI pages
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@gitbook/react-openapi": patch
|
||||
"gitbook-v2": patch
|
||||
"gitbook": patch
|
||||
"@gitbook/colors": patch
|
||||
---
|
||||
|
||||
Fix code highlighting for HTTP
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Fix resolution of links in reusable contents
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"gitbook-v2": minor
|
||||
"gitbook": minor
|
||||
---
|
||||
|
||||
Add support for reusable content across spaces.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@gitbook/react-openapi": patch
|
||||
---
|
||||
|
||||
Bump scalar packages
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Fix invalid sitemap.xml generated with relative URLs instead of absolute ones
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Change OpenAPI schema-optional from `info` to `tint` color
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@gitbook/colors": patch
|
||||
---
|
||||
|
||||
Change lightness check for color step 9 to allow input colors with a higher-than-needed contrast
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@gitbook/react-openapi': patch
|
||||
'gitbook': patch
|
||||
---
|
||||
|
||||
Fix schemas disclosure label causing client error
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@gitbook/react-openapi': patch
|
||||
---
|
||||
|
||||
Missing top-level required OpenAPI alternatives
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook-v2": patch
|
||||
---
|
||||
|
||||
Improve error messages around undefined site sections.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"gitbook-v2": patch
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Increase logging around caching behaviour causing page crashes.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Change `Dropdown`s to use Radix's `DropdownMenu`
|
||||
@@ -2,4 +2,4 @@
|
||||
"@gitbook/react-openapi": patch
|
||||
---
|
||||
|
||||
Merge simple alternatives
|
||||
Fix Python code sample "null vs None"
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Add border to filled sidebar on gradient theme
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
"gitbook-v2": patch
|
||||
---
|
||||
|
||||
Revert investigation work around URL caches.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Fix OpenAPI disclosure label ("Show properties") misalignment on mobile
|
||||
Vendored
+1
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"tailwindCSS.classAttributes": ["class", "className", "style", ".*Style"],
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports.biome": "explicit",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"name": "@gitbook/cache-tags",
|
||||
"version": "0.3.1",
|
||||
"dependencies": {
|
||||
"@gitbook/api": "^0.109.0",
|
||||
"@gitbook/api": "^0.111.0",
|
||||
"assert-never": "^1.2.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -49,7 +49,7 @@
|
||||
},
|
||||
"packages/gitbook": {
|
||||
"name": "gitbook",
|
||||
"version": "0.10.1",
|
||||
"version": "0.11.1",
|
||||
"dependencies": {
|
||||
"@gitbook/api": "*",
|
||||
"@gitbook/cache-do": "workspace:*",
|
||||
@@ -62,6 +62,7 @@
|
||||
"@gitbook/react-math": "workspace:*",
|
||||
"@gitbook/react-openapi": "workspace:*",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.12",
|
||||
"@radix-ui/react-navigation-menu": "^1.2.3",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
@@ -89,8 +90,8 @@
|
||||
"p-map": "^7.0.0",
|
||||
"parse-cache-control": "^1.0.1",
|
||||
"partial-json": "^0.1.7",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hotkeys-hook": "^4.4.1",
|
||||
"rehype-sanitize": "^6.0.0",
|
||||
"rehype-stringify": "^10.0.1",
|
||||
@@ -111,7 +112,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@argos-ci/playwright": "^5.0.3",
|
||||
"@cloudflare/next-on-pages": "1.13.7",
|
||||
"@cloudflare/next-on-pages": "1.13.12",
|
||||
"@cloudflare/workers-types": "^4.20241230.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
@@ -231,7 +232,7 @@
|
||||
},
|
||||
"packages/react-openapi": {
|
||||
"name": "@gitbook/react-openapi",
|
||||
"version": "1.1.10",
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"@gitbook/openapi-parser": "workspace:*",
|
||||
"@scalar/api-client-react": "^1.2.19",
|
||||
@@ -259,9 +260,9 @@
|
||||
},
|
||||
"overrides": {
|
||||
"@codemirror/state": "6.4.1",
|
||||
"@gitbook/api": "0.109.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"@gitbook/api": "0.113.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@1.1.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-0M+qjp+clUD0R1E5eWQFhxEvWLNaOtGQRUaBn8CUABnSKredagq92hUS9VjOzGsTm37xLfpaxl97AVtbeOsHew=="],
|
||||
@@ -472,7 +473,7 @@
|
||||
|
||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="],
|
||||
|
||||
"@cloudflare/next-on-pages": ["@cloudflare/next-on-pages@1.13.7", "", { "dependencies": { "acorn": "^8.8.0", "ast-types": "^0.14.2", "chalk": "^5.2.0", "chokidar": "^3.5.3", "commander": "^11.1.0", "cookie": "^0.5.0", "esbuild": "^0.15.3", "js-yaml": "^4.1.0", "miniflare": "^3.20231218.1", "package-manager-manager": "^0.2.0", "pcre-to-regexp": "^1.1.0", "semver": "^7.5.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240208.0", "vercel": ">=30.0.0", "wrangler": "^3.28.2" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "next-on-pages": "bin/index.js" } }, "sha512-TSMVy+1fmxzeyykOC9guMEj7G2FgENw1T8V1sIFnah6piaJNBmybdyikPdQSdikP5w6v9eQhBt/TrXDPMDw0dw=="],
|
||||
"@cloudflare/next-on-pages": ["@cloudflare/next-on-pages@1.13.12", "", { "dependencies": { "acorn": "^8.8.0", "ast-types": "^0.14.2", "chalk": "^5.2.0", "chokidar": "^3.5.3", "commander": "^11.1.0", "cookie": "^0.5.0", "esbuild": "^0.15.3", "js-yaml": "^4.1.0", "miniflare": "^3.20231218.1", "package-manager-manager": "^0.2.0", "pcre-to-regexp": "^1.1.0", "semver": "^7.5.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240208.0", "vercel": ">=30.0.0", "wrangler": "^3.28.2 || ^4.0.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "next-on-pages": "bin/index.js" } }, "sha512-rPy7x9c2+0RDDdJ5o0TeRUwXJ1b7N1epnqF6qKSp5Wz1r9KHOyvaZh1ACoOC6Vu5k9su5WZOgy+8fPLIyrldMQ=="],
|
||||
|
||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.3.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.15", "workerd": "^1.20250320.0" }, "optionalPeers": ["workerd"] }, "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg=="],
|
||||
|
||||
@@ -546,10 +547,6 @@
|
||||
|
||||
"@emotion/memoize": ["@emotion/memoize@0.7.4", "", {}, "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw=="],
|
||||
|
||||
"@esbuild-plugins/node-globals-polyfill": ["@esbuild-plugins/node-globals-polyfill@0.2.3", "", { "peerDependencies": { "esbuild": "*" } }, "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw=="],
|
||||
|
||||
"@esbuild-plugins/node-modules-polyfill": ["@esbuild-plugins/node-modules-polyfill@0.2.2", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "rollup-plugin-node-polyfills": "^0.2.1" }, "peerDependencies": { "esbuild": "*" } }, "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="],
|
||||
@@ -628,7 +625,7 @@
|
||||
|
||||
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="],
|
||||
|
||||
"@gitbook/api": ["@gitbook/api@0.109.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-nzhxmiNR2MMHh+HoU7fFdOJ+u4BFyXjtsVquQf3VhZMjeI71yeLx5JEbjkOcijVd/GMAtvpYlYR2qcPqzq27gw=="],
|
||||
"@gitbook/api": ["@gitbook/api@0.113.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-PWMeAkdm4bHSl3b5OmtcmskZ6qRkkDhauCPybo8sGnjS03O14YAUtubAQiNCKX/uwbs+yiQ8KRPyeIwn+g42yw=="],
|
||||
|
||||
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
|
||||
|
||||
@@ -822,11 +819,15 @@
|
||||
|
||||
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.12", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VJoMs+BWWE7YhzEQyVwvF9n22Eiyr83HotCVrMQzla/OwRovXCgah7AcaEr4hMNj4gJxSdtIbcHGvmJXOoJVHA=="],
|
||||
|
||||
"@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="],
|
||||
|
||||
"@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.0", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA=="],
|
||||
|
||||
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="],
|
||||
"@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
|
||||
|
||||
"@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.4", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.7", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.4", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.4", "@radix-ui/react-portal": "1.1.6", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-roving-focus": "1.1.7", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+qYq6LfbiGo97Zz9fioX83HCiIYYFNs8zAsVCMQrIakoNYylIzWuoD/anAD3UzvvR6cnswmfRFJFq/zYYq/k7Q=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-dismissable-layer": "1.1.4", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.1", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-previous": "1.1.0", "@radix-ui/react-visually-hidden": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wUi01RrTDTOoGtjEPHsxlzPtVzVc3R/AZ5wfh0dyqMAqolhHAHvG5iQjBCTi2AjQqa77FWWbA3kE3RkD+bDMgQ=="],
|
||||
|
||||
@@ -840,6 +841,8 @@
|
||||
|
||||
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.0", "", { "dependencies": { "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw=="],
|
||||
|
||||
"@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collection": "1.1.4", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q=="],
|
||||
|
||||
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw=="],
|
||||
|
||||
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.1.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-popper": "1.2.2", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-visually-hidden": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA=="],
|
||||
@@ -848,6 +851,8 @@
|
||||
|
||||
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="],
|
||||
|
||||
"@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
|
||||
|
||||
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="],
|
||||
|
||||
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="],
|
||||
@@ -1094,7 +1099,7 @@
|
||||
|
||||
"@scalar/object-utils": ["@scalar/object-utils@1.1.13", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1" } }, "sha512-311eTykIXgOtjCs4VTELj9UMT97jHTWc5qkGNoIzZ5nxjCcvOVe7kDQobIkE8dGT+ybOgHz5qly02Eu7nVHeZQ=="],
|
||||
|
||||
"@scalar/openapi-parser": ["@scalar/openapi-parser@0.10.10", "", { "dependencies": { "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-formats": "^3.0.1", "jsonpointer": "^5.0.1", "leven": "^4.0.0", "yaml": "^2.4.5" } }, "sha512-6MSgvpNKu/anZy96dn8tXQZo1PuDCoeB4m2ZLLDS4vC2zaTnuNBvvQHx+gjwXNKWhTbIVy8bQpYBzlMAYnFNcQ=="],
|
||||
"@scalar/openapi-parser": ["@scalar/openapi-parser@0.10.14", "", { "dependencies": { "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-formats": "^3.0.1", "jsonpointer": "^5.0.1", "leven": "^4.0.0", "yaml": "^2.4.5" } }, "sha512-VXr979NMx6wZ+kpFKor2eyCJZOjyMwcBRc6c4Gc92ZMOC7ZNYqjwbw+Ubh2ELJyP5cWAjOFSrNwtylema0pw5w=="],
|
||||
|
||||
"@scalar/openapi-types": ["@scalar/openapi-types@0.1.9", "", {}, "sha512-HQQudOSQBU7ewzfnBW9LhDmBE2XOJgSfwrh5PlUB7zJup/kaRkBGNgV2wMjNz9Af/uztiU/xNrO179FysmUT+g=="],
|
||||
|
||||
@@ -1390,7 +1395,7 @@
|
||||
|
||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||
|
||||
"acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="],
|
||||
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="],
|
||||
|
||||
@@ -1510,8 +1515,6 @@
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001668", "", {}, "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw=="],
|
||||
|
||||
"capnp-ts": ["capnp-ts@0.7.0", "", { "dependencies": { "debug": "^4.3.1", "tslib": "^2.2.0" } }, "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g=="],
|
||||
|
||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
||||
|
||||
"chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
|
||||
@@ -1564,8 +1567,6 @@
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
|
||||
|
||||
"configstore": ["configstore@5.0.1", "", { "dependencies": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", "make-dir": "^3.0.0", "unique-string": "^2.0.0", "write-file-atomic": "^3.0.0", "xdg-basedir": "^4.0.0" } }, "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA=="],
|
||||
|
||||
"consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="],
|
||||
@@ -1756,7 +1757,7 @@
|
||||
|
||||
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
||||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
"escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"esniff": ["esniff@2.0.1", "", { "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.62", "event-emitter": "^0.3.5", "type": "^2.7.2" } }, "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg=="],
|
||||
|
||||
@@ -2308,8 +2309,6 @@
|
||||
|
||||
"mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="],
|
||||
|
||||
"mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="],
|
||||
|
||||
"mnemonist": ["mnemonist@0.38.3", "", { "dependencies": { "obliterator": "^1.6.1" } }, "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw=="],
|
||||
|
||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
||||
@@ -2454,8 +2453,6 @@
|
||||
|
||||
"pirates": ["pirates@4.0.6", "", {}, "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg=="],
|
||||
|
||||
"pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||
|
||||
"playwright": ["playwright@1.51.1", "", { "dependencies": { "playwright-core": "1.51.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw=="],
|
||||
|
||||
"playwright-core": ["playwright-core@1.51.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw=="],
|
||||
@@ -2518,13 +2515,13 @@
|
||||
|
||||
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
||||
|
||||
"react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
|
||||
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||
|
||||
"react-aria": ["react-aria@3.37.0", "", { "dependencies": { "@internationalized/string": "^3.2.5", "@react-aria/breadcrumbs": "^3.5.20", "@react-aria/button": "^3.11.1", "@react-aria/calendar": "^3.7.0", "@react-aria/checkbox": "^3.15.1", "@react-aria/color": "^3.0.3", "@react-aria/combobox": "^3.11.1", "@react-aria/datepicker": "^3.13.0", "@react-aria/dialog": "^3.5.21", "@react-aria/disclosure": "^3.0.1", "@react-aria/dnd": "^3.8.1", "@react-aria/focus": "^3.19.1", "@react-aria/gridlist": "^3.10.1", "@react-aria/i18n": "^3.12.5", "@react-aria/interactions": "^3.23.0", "@react-aria/label": "^3.7.14", "@react-aria/link": "^3.7.8", "@react-aria/listbox": "^3.14.0", "@react-aria/menu": "^3.17.0", "@react-aria/meter": "^3.4.19", "@react-aria/numberfield": "^3.11.10", "@react-aria/overlays": "^3.25.0", "@react-aria/progress": "^3.4.19", "@react-aria/radio": "^3.10.11", "@react-aria/searchfield": "^3.8.0", "@react-aria/select": "^3.15.1", "@react-aria/selection": "^3.22.0", "@react-aria/separator": "^3.4.5", "@react-aria/slider": "^3.7.15", "@react-aria/ssr": "^3.9.7", "@react-aria/switch": "^3.6.11", "@react-aria/table": "^3.16.1", "@react-aria/tabs": "^3.9.9", "@react-aria/tag": "^3.4.9", "@react-aria/textfield": "^3.16.0", "@react-aria/tooltip": "^3.7.11", "@react-aria/utils": "^3.27.0", "@react-aria/visually-hidden": "^3.8.19", "@react-types/shared": "^3.27.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-u3WUEMTcbQFaoHauHO3KhPaBYzEv1o42EdPcLAs05GBw9Q6Axlqwo73UFgMrsc2ElwLAZ4EKpSdWHLo1R5gfiw=="],
|
||||
|
||||
"react-aria-components": ["react-aria-components@1.6.0", "", { "dependencies": { "@internationalized/date": "^3.7.0", "@internationalized/string": "^3.2.5", "@react-aria/autocomplete": "3.0.0-alpha.37", "@react-aria/collections": "3.0.0-alpha.7", "@react-aria/color": "^3.0.3", "@react-aria/disclosure": "^3.0.1", "@react-aria/dnd": "^3.8.1", "@react-aria/focus": "^3.19.1", "@react-aria/interactions": "^3.23.0", "@react-aria/live-announcer": "^3.4.1", "@react-aria/menu": "^3.17.0", "@react-aria/toolbar": "3.0.0-beta.12", "@react-aria/tree": "3.0.0-beta.3", "@react-aria/utils": "^3.27.0", "@react-aria/virtualizer": "^4.1.1", "@react-stately/autocomplete": "3.0.0-alpha.0", "@react-stately/color": "^3.8.2", "@react-stately/disclosure": "^3.0.1", "@react-stately/layout": "^4.1.1", "@react-stately/menu": "^3.9.1", "@react-stately/selection": "^3.19.0", "@react-stately/table": "^3.13.1", "@react-stately/utils": "^3.10.5", "@react-stately/virtualizer": "^4.2.1", "@react-types/color": "^3.0.2", "@react-types/form": "^3.7.9", "@react-types/grid": "^3.2.11", "@react-types/shared": "^3.27.0", "@react-types/table": "^3.10.4", "@swc/helpers": "^0.5.0", "client-only": "^0.0.1", "react-aria": "^3.37.0", "react-stately": "^3.35.0", "use-sync-external-store": "^1.2.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-YfG9PUE7XrXtDDAqT4pLTGyYQaiHHTBFdAK/wNgGsypVnQSdzmyYlV3Ty8aHlZJI6hP9RWkbywvosXkU7KcPHg=="],
|
||||
|
||||
"react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
|
||||
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||
|
||||
"react-hotkeys-hook": ["react-hotkeys-hook@4.5.1", "", { "peerDependencies": { "react": ">=16.8.1", "react-dom": ">=16.8.1" } }, "sha512-scAEJOh3Irm0g95NIn6+tQVf/OICCjsQsC9NBHfQws/Vxw4sfq1tDQut5fhTEvPraXhu/sHxRd9lOtxzyYuNAg=="],
|
||||
|
||||
@@ -2598,12 +2595,6 @@
|
||||
|
||||
"rollup": ["rollup@3.29.5", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w=="],
|
||||
|
||||
"rollup-plugin-inject": ["rollup-plugin-inject@3.0.2", "", { "dependencies": { "estree-walker": "^0.6.1", "magic-string": "^0.25.3", "rollup-pluginutils": "^2.8.1" } }, "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w=="],
|
||||
|
||||
"rollup-plugin-node-polyfills": ["rollup-plugin-node-polyfills@0.2.1", "", { "dependencies": { "rollup-plugin-inject": "^3.0.0" } }, "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA=="],
|
||||
|
||||
"rollup-pluginutils": ["rollup-pluginutils@2.8.2", "", { "dependencies": { "estree-walker": "^0.6.1" } }, "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ=="],
|
||||
|
||||
"router": ["router@2.0.0", "", { "dependencies": { "array-flatten": "3.0.0", "is-promise": "4.0.0", "methods": "~1.1.2", "parseurl": "~1.3.3", "path-to-regexp": "^8.0.0", "setprototypeof": "1.2.0", "utils-merge": "1.0.1" } }, "sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
@@ -2612,7 +2603,7 @@
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
|
||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||
|
||||
"secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="],
|
||||
|
||||
@@ -2660,8 +2651,6 @@
|
||||
|
||||
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||
|
||||
"sourcemap-codec": ["sourcemap-codec@1.4.8", "", {}, "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="],
|
||||
|
||||
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
||||
|
||||
"spawndamnit": ["spawndamnit@3.0.1", "", { "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" } }, "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg=="],
|
||||
@@ -3558,15 +3547,13 @@
|
||||
|
||||
"@changesets/parse/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||
|
||||
"@cloudflare/next-on-pages/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
|
||||
|
||||
"@cloudflare/next-on-pages/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/esbuild": ["esbuild@0.15.18", "", { "optionalDependencies": { "@esbuild/android-arm": "0.15.18", "@esbuild/linux-loong64": "0.15.18", "esbuild-android-64": "0.15.18", "esbuild-android-arm64": "0.15.18", "esbuild-darwin-64": "0.15.18", "esbuild-darwin-arm64": "0.15.18", "esbuild-freebsd-64": "0.15.18", "esbuild-freebsd-arm64": "0.15.18", "esbuild-linux-32": "0.15.18", "esbuild-linux-64": "0.15.18", "esbuild-linux-arm": "0.15.18", "esbuild-linux-arm64": "0.15.18", "esbuild-linux-mips64le": "0.15.18", "esbuild-linux-ppc64le": "0.15.18", "esbuild-linux-riscv64": "0.15.18", "esbuild-linux-s390x": "0.15.18", "esbuild-netbsd-64": "0.15.18", "esbuild-openbsd-64": "0.15.18", "esbuild-sunos-64": "0.15.18", "esbuild-windows-32": "0.15.18", "esbuild-windows-64": "0.15.18", "esbuild-windows-arm64": "0.15.18" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare": ["miniflare@3.20241018.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "^8.8.0", "acorn-walk": "^8.2.0", "capnp-ts": "^0.7.0", "exit-hook": "^2.2.1", "glob-to-regexp": "^0.4.1", "stoppable": "^1.1.0", "undici": "^5.28.4", "workerd": "1.20241018.1", "ws": "^8.17.1", "youch": "^3.2.2", "zod": "^3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-g7i5oGAoJOk8+hJp77A5/wAdu7PEvi5hQc+0wzwzjhUNM2I5DHd2Cc29ACPhAe1kIXvCCVkxs3+REF52qnX0aw=="],
|
||||
"@cloudflare/next-on-pages/miniflare": ["miniflare@3.20250214.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250214.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-t+lT4p2lbOcKv4PS3sx1F/wcDAlbEYZCO2VooLp4H7JErWWYIi9yjD3UillC3CGOpiBahVg5nrPCoFltZf6UlA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler": ["wrangler@3.112.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.3.4", "@esbuild-plugins/node-globals-polyfill": "0.2.3", "@esbuild-plugins/node-modules-polyfill": "0.2.2", "blake3-wasm": "2.1.5", "esbuild": "0.17.19", "miniflare": "3.20250214.2", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.1", "workerd": "1.20250214.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250214.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-PNQWGze3ODlWwG33LPr8kNhbht3eB3L9fogv+fapk2fjaqj0kNweRapkwmvtz46ojcqWzsxmTe4nOC0hIVUfPA=="],
|
||||
"@cloudflare/next-on-pages/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"@codemirror/lang-html/@codemirror/autocomplete": ["@codemirror/autocomplete@6.18.1", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-iWHdj/B1ethnHRTwZj+C1obmmuCzquH29EbcKr0qIjA9NfDeBDJ7vs+WOHsFeLeflE4o+dHfYndJloMKHUkWUA=="],
|
||||
|
||||
@@ -3676,24 +3663,88 @@
|
||||
|
||||
"@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.0", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
|
||||
|
||||
"@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-r2annK27lIW5w9Ho5NyQgqs0MmgZSTIKXWpVCJaLC1q2kZrZkcqnmHkCHMEmv8XLvsLlurKMPT+kbKkRkm/xVA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.4", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.4", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.6", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.0", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll": ["react-remove-scroll@2.6.3", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="],
|
||||
|
||||
"@radix-ui/react-popover/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.1", "", { "dependencies": { "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ=="],
|
||||
|
||||
"@radix-ui/react-popover/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="],
|
||||
|
||||
"@radix-ui/react-popper/@radix-ui/react-context": ["@radix-ui/react-context@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.0", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.2", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="],
|
||||
@@ -3706,6 +3757,8 @@
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q=="],
|
||||
|
||||
"@radix-ui/react-use-effect-event/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="],
|
||||
|
||||
"@react-aria/focus/clsx": ["clsx@2.0.0", "", {}, "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="],
|
||||
@@ -3714,14 +3767,10 @@
|
||||
|
||||
"@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"@scalar/api-client/@scalar/openapi-parser": ["@scalar/openapi-parser@0.10.14", "", { "dependencies": { "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-formats": "^3.0.1", "jsonpointer": "^5.0.1", "leven": "^4.0.0", "yaml": "^2.4.5" } }, "sha512-VXr979NMx6wZ+kpFKor2eyCJZOjyMwcBRc6c4Gc92ZMOC7ZNYqjwbw+Ubh2ELJyP5cWAjOFSrNwtylema0pw5w=="],
|
||||
|
||||
"@scalar/api-client/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
|
||||
|
||||
"@scalar/api-client/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="],
|
||||
|
||||
"@scalar/import/@scalar/openapi-parser": ["@scalar/openapi-parser@0.10.14", "", { "dependencies": { "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-formats": "^3.0.1", "jsonpointer": "^5.0.1", "leven": "^4.0.0", "yaml": "^2.4.5" } }, "sha512-VXr979NMx6wZ+kpFKor2eyCJZOjyMwcBRc6c4Gc92ZMOC7ZNYqjwbw+Ubh2ELJyP5cWAjOFSrNwtylema0pw5w=="],
|
||||
|
||||
"@scalar/oas-utils/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
|
||||
|
||||
"@scalar/object-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
|
||||
@@ -3922,8 +3971,6 @@
|
||||
|
||||
"@vercel/gatsby-plugin-vercel-builder/fs-extra": ["fs-extra@11.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw=="],
|
||||
|
||||
"@vercel/nft/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"@vercel/nft/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"@vercel/nft/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
@@ -3980,8 +4027,6 @@
|
||||
|
||||
"cacheable-request/lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],
|
||||
|
||||
"capnp-ts/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||
|
||||
"codemirror/@codemirror/autocomplete": ["@codemirror/autocomplete@6.18.1", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-iWHdj/B1ethnHRTwZj+C1obmmuCzquH29EbcKr0qIjA9NfDeBDJ7vs+WOHsFeLeflE4o+dHfYndJloMKHUkWUA=="],
|
||||
|
||||
"codemirror/@codemirror/commands": ["@codemirror/commands@6.7.0", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-+cduIZ2KbesDhbykV02K25A5xIVrquSPz4UxxYBemRlAT2aW8dhwUgLDwej7q/RJUHKk4nALYcR1puecDvbdqw=="],
|
||||
@@ -4032,7 +4077,7 @@
|
||||
|
||||
"gaxios/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
|
||||
"gitbook-v2/next": ["next@15.3.1-canary.7", "", { "dependencies": { "@next/env": "15.3.1-canary.7", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.3.1-canary.7", "@next/swc-darwin-x64": "15.3.1-canary.7", "@next/swc-linux-arm64-gnu": "15.3.1-canary.7", "@next/swc-linux-arm64-musl": "15.3.1-canary.7", "@next/swc-linux-x64-gnu": "15.3.1-canary.7", "@next/swc-linux-x64-musl": "15.3.1-canary.7", "@next/swc-win32-arm64-msvc": "15.3.1-canary.7", "@next/swc-win32-x64-msvc": "15.3.1-canary.7", "sharp": "^0.34.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-RblvC7A7k8cKpSa6JSCbaatb6JAncv2niUSH7TqXt6xHUoItnxa3Fu7xkducFJQdcW2Hv2h0+NBu6kaKf0S4zw=="],
|
||||
"gitbook-v2/next": ["next@15.4.0-canary.7", "", { "dependencies": { "@next/env": "15.4.0-canary.7", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.0-canary.7", "@next/swc-darwin-x64": "15.4.0-canary.7", "@next/swc-linux-arm64-gnu": "15.4.0-canary.7", "@next/swc-linux-arm64-musl": "15.4.0-canary.7", "@next/swc-linux-x64-gnu": "15.4.0-canary.7", "@next/swc-linux-x64-musl": "15.4.0-canary.7", "@next/swc-win32-arm64-msvc": "15.4.0-canary.7", "@next/swc-win32-x64-msvc": "15.4.0-canary.7", "sharp": "^0.34.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-ZYjT0iu+4osz8XIlr31MuoXaNQKRU75UcwEgNBt93gftoh6tzV2Mebz6sOGeVReYuYUvYlLJJksMBTNcFcPbSA=="],
|
||||
|
||||
"global-dirs/ini": ["ini@1.3.7", "", {}, "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="],
|
||||
|
||||
@@ -4070,8 +4115,6 @@
|
||||
|
||||
"make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"mdast-util-gfm/mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="],
|
||||
|
||||
"mdast-util-gfm-footnote/mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="],
|
||||
@@ -4090,8 +4133,6 @@
|
||||
|
||||
"micromark/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||
|
||||
"miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"miniflare/undici": ["undici@5.28.5", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA=="],
|
||||
|
||||
"miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="],
|
||||
@@ -4102,8 +4143,6 @@
|
||||
|
||||
"minizlib/minipass": ["minipass@2.9.0", "", { "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg=="],
|
||||
|
||||
"mlly/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"next/@swc/helpers": ["@swc/helpers@0.5.5", "", { "dependencies": { "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A=="],
|
||||
|
||||
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||
@@ -4156,12 +4195,6 @@
|
||||
|
||||
"rimraf/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
|
||||
|
||||
"rollup-plugin-inject/estree-walker": ["estree-walker@0.6.1", "", {}, "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="],
|
||||
|
||||
"rollup-plugin-inject/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="],
|
||||
|
||||
"rollup-pluginutils/estree-walker": ["estree-walker@0.6.1", "", {}, "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="],
|
||||
|
||||
"router/is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
||||
|
||||
"router/path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="],
|
||||
@@ -4200,10 +4233,10 @@
|
||||
|
||||
"terminal-link/supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="],
|
||||
|
||||
"terser/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"ts-node/acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="],
|
||||
|
||||
"ts-node/acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
||||
|
||||
"ts-node/arg": ["arg@4.1.0", "", {}, "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="],
|
||||
@@ -4650,21 +4683,13 @@
|
||||
|
||||
"@cloudflare/next-on-pages/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.15.18", "", { "os": "linux", "cpu": "none" }, "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
||||
"@cloudflare/next-on-pages/miniflare/undici": ["undici@5.28.5", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd": ["workerd@1.20241018.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20241018.1", "@cloudflare/workerd-darwin-arm64": "1.20241018.1", "@cloudflare/workerd-linux-64": "1.20241018.1", "@cloudflare/workerd-linux-arm64": "1.20241018.1", "@cloudflare/workerd-windows-64": "1.20241018.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-JPW2oAbYOnJj1c5boyDOdjl/Yvur45jhVE8lf+I9oxR6myyAvuH2tdXO62kye68jRluJOMUeyssLes+JRwLmaA=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd": ["workerd@1.20250214.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250214.0", "@cloudflare/workerd-darwin-arm64": "1.20250214.0", "@cloudflare/workerd-linux-64": "1.20250214.0", "@cloudflare/workerd-linux-arm64": "1.20250214.0", "@cloudflare/workerd-windows-64": "1.20250214.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-QWcqXZLiMpV12wiaVnb3nLmfs/g4ZsFQq2mX85z546r3AX4CTIkXl0VP50W3CwqLADej3PGYiRDOTelDOwVG1g=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||
"@cloudflare/next-on-pages/miniflare/youch": ["youch@3.2.3", "", { "dependencies": { "cookie": "^0.5.0", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.3.4", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild": ["esbuild@0.17.19", "", { "optionalDependencies": { "@esbuild/android-arm": "0.17.19", "@esbuild/android-arm64": "0.17.19", "@esbuild/android-x64": "0.17.19", "@esbuild/darwin-arm64": "0.17.19", "@esbuild/darwin-x64": "0.17.19", "@esbuild/freebsd-arm64": "0.17.19", "@esbuild/freebsd-x64": "0.17.19", "@esbuild/linux-arm": "0.17.19", "@esbuild/linux-arm64": "0.17.19", "@esbuild/linux-ia32": "0.17.19", "@esbuild/linux-loong64": "0.17.19", "@esbuild/linux-mips64el": "0.17.19", "@esbuild/linux-ppc64": "0.17.19", "@esbuild/linux-riscv64": "0.17.19", "@esbuild/linux-s390x": "0.17.19", "@esbuild/linux-x64": "0.17.19", "@esbuild/netbsd-x64": "0.17.19", "@esbuild/openbsd-x64": "0.17.19", "@esbuild/sunos-x64": "0.17.19", "@esbuild/win32-arm64": "0.17.19", "@esbuild/win32-ia32": "0.17.19", "@esbuild/win32-x64": "0.17.19" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/miniflare": ["miniflare@3.20250214.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250214.0", "ws": "8.18.0", "youch": "3.2.3", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-t+lT4p2lbOcKv4PS3sx1F/wcDAlbEYZCO2VooLp4H7JErWWYIi9yjD3UillC3CGOpiBahVg5nrPCoFltZf6UlA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/unenv": ["unenv@2.0.0-rc.1", "", { "dependencies": { "defu": "^6.1.4", "mlly": "^1.7.4", "ohash": "^1.1.4", "pathe": "^1.1.2", "ufo": "^1.5.4" } }, "sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd": ["workerd@1.20250214.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250214.0", "@cloudflare/workerd-darwin-arm64": "1.20250214.0", "@cloudflare/workerd-linux-64": "1.20250214.0", "@cloudflare/workerd-linux-arm64": "1.20250214.0", "@cloudflare/workerd-windows-64": "1.20250214.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-QWcqXZLiMpV12wiaVnb3nLmfs/g4ZsFQq2mX85z546r3AX4CTIkXl0VP50W3CwqLADej3PGYiRDOTelDOwVG1g=="],
|
||||
"@cloudflare/next-on-pages/miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="],
|
||||
|
||||
"@codemirror/lang-json/@codemirror/language/@codemirror/view": ["@codemirror/view@6.34.1", "", { "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ=="],
|
||||
|
||||
@@ -4742,8 +4767,44 @@
|
||||
|
||||
"@radix-ui/react-dismissable-layer/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="],
|
||||
|
||||
"@radix-ui/react-dropdown-menu/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper/@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper/@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper/@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-popper/@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-menu/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll/react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll/react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll/use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
|
||||
|
||||
"@radix-ui/react-menu/react-remove-scroll/use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
|
||||
|
||||
"@radix-ui/react-navigation-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="],
|
||||
|
||||
"@radix-ui/react-roving-focus/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-tooltip/@radix-ui/react-popper/@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg=="],
|
||||
|
||||
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
||||
@@ -4908,23 +4969,23 @@
|
||||
|
||||
"gaxios/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||
|
||||
"gitbook-v2/next/@next/env": ["@next/env@15.3.1-canary.7", "", {}, "sha512-QSzAlzxaGrQYj3Nzgxd35WM6pmxmNk9lOCn0nsNLPidvc3H6wj/fV3Pl8/tVCYQP61luGuA0Ib0VwZc8ja119w=="],
|
||||
"gitbook-v2/next/@next/env": ["@next/env@15.4.0-canary.7", "", {}, "sha512-q8S7f2lQti3Y3gcAPzE8Pj8y0EwiWHVyyilMzoLbDPXGVfxlQhXLRiFdy2cDkKN4DyjGZWDeehEtw4huvJAa3Q=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.1-canary.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fs7JYU0MKtpgsDBIvbT/wn1MwKP8C+bqcb6IjWnDtVcciFKzYDs/tPCBW6CtYg1wpHqm9horZDA1ytb/sAghxA=="],
|
||||
"gitbook-v2/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.0-canary.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+TMxUu5CAWNe+UFRc47BZAXQxCRqZfVbGyCldddiog4MorvL7kBxSd1qlmrwI73fRRKtXkHIH1TaeItyxzC9rQ=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.1-canary.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-Efl6es/IEXJf5groF78fc1PrTEwK9bOyi6fRjp1bsa/AWOHp8rTc3l0T6EeY5T0SWeYilisZZa9rax7nTgw4bw=="],
|
||||
"gitbook-v2/next/@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.4.0-canary.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-veXp8lg/X/7O+pG9BDQ3OizFz3B40v29jsvEWj+ULY/W8Z6+dCSd5XPP2M8fG/gKKKA0D6L0CnnM2Mj0RRSUJw=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.3.1-canary.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-IS71I8z2wlecRZRHXqWTtxVozZt1h9IH/2MX1P/WkCjQH98acFmCkw0jo/y70mrZ4lw6tRGTNkSBMun+5P5P+w=="],
|
||||
"gitbook-v2/next/@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.0-canary.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-KxNGfW7BO0Z5B9rJyl9p7YVjNrxAhu06mH6h1PSdouZG7YMYpdRCconVXeuBI0PEu6g3ywNrOVxZUk1V6G5u0Q=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.3.1-canary.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-uJ4env9fZxIFM+aRBCjNeG91HHZ2cRXiF25xJqGmCC1Y5jT5oYAB/tIBCFRSj6NRzdt4pZAamCMRS41WzzVVUQ=="],
|
||||
"gitbook-v2/next/@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.0-canary.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-THgXgmP/cC4DsNwvC6uqB90CebB7Ep1KyZajQL3fYKT5V4SWr46yngKLyoyJVeAYWJH908MrWddf7Ya/Zq7cyg=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.1-canary.7", "", { "os": "linux", "cpu": "x64" }, "sha512-/+efTL2TxoSAYCxdf+g6WvDKIJDoaETvF3I+lxpixhctfrIwpr2qnG0e6u2M55k1iYiiyFIOA63fpIsGnIMJZA=="],
|
||||
"gitbook-v2/next/@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.0-canary.7", "", { "os": "linux", "cpu": "x64" }, "sha512-kpLB3Jj7fProynQYj2ahFyZlJs0xwm71VzCVrNRu6u7qJGXn6dK5h7+hro8y/y1iqjXWgCLSdxWSHahhWK8XdQ=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.1-canary.7", "", { "os": "linux", "cpu": "x64" }, "sha512-Hb+agfULOjEhJAmq/r9OTVAo8KxFlnuCT7BEUbSuVP/Gxn883al6juSG7ZZfk7P4a+ZU6iVYyHKIFAKCarZmUA=="],
|
||||
"gitbook-v2/next/@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.0-canary.7", "", { "os": "linux", "cpu": "x64" }, "sha512-rnGAKvl4cWPVV9D+SybWOGijm0VmKXyqQ+IN0A6WDgdlYZAZP0ZnJv/rq7DSvuOh19AXS8UpQc88SelXV/3j3Q=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.3.1-canary.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-gNd5Vq7k9xIEQj85JoavHGRsyvu1zKOjVoPUYtsZRxXw6kcBg84x2g8NeT/3SmwH1PiFU/sjQXtRzr2Kuc2j3A=="],
|
||||
"gitbook-v2/next/@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.0-canary.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-/PRbn//EuR3UGiquk050gqvjxLliEgGBy1Cx9KkpAT7szaHOBj1mDDQmxMTEhRex4i3YfKGJXWn5mLMCveya6Q=="],
|
||||
|
||||
"gitbook-v2/next/@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.1-canary.7", "", { "os": "win32", "cpu": "x64" }, "sha512-D5i+KinvNNmspXfgIvEZ1RFOKVhOgdtoSC7/xEUm55hEkcWFVHOtVVPvgV7WUeo1elNxbgxytzmyKbLaifP03g=="],
|
||||
"gitbook-v2/next/@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.0-canary.7", "", { "os": "win32", "cpu": "x64" }, "sha512-7a92XL+DlrbWyycCpQjjQMHOrsA0p+VvS7iA2dyi89Xsq0qtOPzFH0Gb56fsjh6M6BQGFhboOSzjmpjlkMTilQ=="],
|
||||
|
||||
"gitbook-v2/next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||
|
||||
@@ -5114,81 +5175,15 @@
|
||||
|
||||
"@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20241018.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-CRySEzjNRoR8frP5AbtJXd1tgVJa5v7bZon9Dh6nljYlhG+piDv8jvOVEUqF3cXXS+M5aXwr4NlozdMvl5g5mg=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250214.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cDvvedWDc5zrgDnuXe2qYcz/TwBvzmweO55C7XpPuAWJ9Oqxv81PkdekYxD8mH989aQ/GI5YD0Fe6fDYlM+T3Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20241018.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y63yWJNTgETDFkY3Ony71/k/G1HRDFIhEzwbT+OWmg1Qbsqa4TquHPVFkgv+OJhpmD3HV9gTBcn/M2QJ/+pGmg=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250214.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-NytCvRveVzu0mRKo+tvZo3d/gCUway3B2ZVqSi/TS6NXDGBYIJo7g6s3BnTLS74kgyzeDOjhu9j/RBJBS809qw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20241018.1", "", { "os": "linux", "cpu": "x64" }, "sha512-a2AbSAXNMMiREvN+PwjHdJ5zOzI4+qf8+rb6H/y4HcVbPZN5C2fanxv5Bx7NUHLiMD/W0FrGug1aU+RPUVZC9Q=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250214.0", "", { "os": "linux", "cpu": "x64" }, "sha512-pQ7+aHNHj8SiYEs4d/6cNoimE5xGeCMfgU1yfDFtA9YGN9Aj2BITZgOWPec+HW7ZkOy9oWlNrO6EvVjGgB4tbQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20241018.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-iCJ7bjD/+zhlp3IWnkiry180DwdNvak/sVoS98pIAS41aR3gJVzE5BCz/2yTWFdCoUVZ5yKJrv1HhSKgQRBIEw=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250214.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Vhlfah6Yd9ny1npNQjNgElLIjR6OFdEbuR3LCfbLDCwzWEBFhIf7yC+Tpp/a0Hq7kLz3sLdktaP7xl3PJhyOjA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20241018.1", "", { "os": "win32", "cpu": "x64" }, "sha512-qwDVh/KrwEPY82h6tZ1O4BXBAKeGy30BeTr9wvTUVeY9eX/KT73GuEG+ttwiashRfqjOa0Gcqjsfpd913ITFyg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.17.19", "", { "os": "android", "cpu": "arm" }, "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.17.19", "", { "os": "android", "cpu": "arm64" }, "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.17.19", "", { "os": "android", "cpu": "x64" }, "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.17.19", "", { "os": "darwin", "cpu": "arm64" }, "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.17.19", "", { "os": "darwin", "cpu": "x64" }, "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.17.19", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.17.19", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.17.19", "", { "os": "linux", "cpu": "arm" }, "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.17.19", "", { "os": "linux", "cpu": "arm64" }, "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.17.19", "", { "os": "linux", "cpu": "ia32" }, "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.17.19", "", { "os": "linux", "cpu": "ppc64" }, "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.17.19", "", { "os": "linux", "cpu": "none" }, "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.17.19", "", { "os": "linux", "cpu": "s390x" }, "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.17.19", "", { "os": "linux", "cpu": "x64" }, "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.17.19", "", { "os": "none", "cpu": "x64" }, "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.17.19", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.17.19", "", { "os": "sunos", "cpu": "x64" }, "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.17.19", "", { "os": "win32", "cpu": "arm64" }, "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.17.19", "", { "os": "win32", "cpu": "ia32" }, "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.17.19", "", { "os": "win32", "cpu": "x64" }, "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/miniflare/undici": ["undici@5.28.5", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/miniflare/youch": ["youch@3.2.3", "", { "dependencies": { "cookie": "^0.5.0", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/unenv/ohash": ["ohash@1.1.4", "", {}, "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/unenv/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250214.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cDvvedWDc5zrgDnuXe2qYcz/TwBvzmweO55C7XpPuAWJ9Oqxv81PkdekYxD8mH989aQ/GI5YD0Fe6fDYlM+T3Q=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250214.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-NytCvRveVzu0mRKo+tvZo3d/gCUway3B2ZVqSi/TS6NXDGBYIJo7g6s3BnTLS74kgyzeDOjhu9j/RBJBS809qw=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250214.0", "", { "os": "linux", "cpu": "x64" }, "sha512-pQ7+aHNHj8SiYEs4d/6cNoimE5xGeCMfgU1yfDFtA9YGN9Aj2BITZgOWPec+HW7ZkOy9oWlNrO6EvVjGgB4tbQ=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250214.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Vhlfah6Yd9ny1npNQjNgElLIjR6OFdEbuR3LCfbLDCwzWEBFhIf7yC+Tpp/a0Hq7kLz3sLdktaP7xl3PJhyOjA=="],
|
||||
|
||||
"@cloudflare/next-on-pages/wrangler/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250214.0", "", { "os": "win32", "cpu": "x64" }, "sha512-GMwMyFbkjBKjYJoKDhGX8nuL4Gqe3IbVnVWf2Q6086CValyIknupk5J6uQWGw2EBU3RGO3x4trDXT5WphQJZDQ=="],
|
||||
"@cloudflare/next-on-pages/miniflare/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250214.0", "", { "os": "win32", "cpu": "x64" }, "sha512-GMwMyFbkjBKjYJoKDhGX8nuL4Gqe3IbVnVWf2Q6086CValyIknupk5J6uQWGw2EBU3RGO3x4trDXT5WphQJZDQ=="],
|
||||
|
||||
"@node-minify/core/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
|
||||
+3
-3
@@ -10,9 +10,9 @@
|
||||
"packageManager": "bun@1.2.8",
|
||||
"overrides": {
|
||||
"@codemirror/state": "6.4.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"@gitbook/api": "0.109.0"
|
||||
"@gitbook/api": "0.113.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"version": "0.3.1",
|
||||
"dependencies": {
|
||||
"@gitbook/api": "^0.109.0",
|
||||
"@gitbook/api": "^0.111.0",
|
||||
"assert-never": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -214,13 +214,31 @@ export function colorScale(
|
||||
const targetL =
|
||||
foregroundColor.L * mapping[index] + backgroundColor.L * (1 - mapping[index]);
|
||||
|
||||
if (index === 8 && !mix && Math.abs(baseColor.L - targetL) < 0.2) {
|
||||
if (
|
||||
index === 8 &&
|
||||
!mix &&
|
||||
(darkMode ? targetL - baseColor.L < 0.2 : baseColor.L - targetL < 0.2)
|
||||
) {
|
||||
// Original colour is close enough to target, so let's use the original colour as step 9.
|
||||
result.push(hex);
|
||||
continue;
|
||||
}
|
||||
|
||||
const chromaRatio = index === 8 || index === 9 ? 1 : index * 0.05;
|
||||
const chromaRatio = (() => {
|
||||
switch (index) {
|
||||
// Step 9 and 10 have max chroma, meaning they are fully saturated.
|
||||
case 8:
|
||||
case 9:
|
||||
return 1;
|
||||
// Step 11 and 12 have a reduced chroma
|
||||
case 10:
|
||||
return 0.4;
|
||||
case 11:
|
||||
return 0.1;
|
||||
default:
|
||||
return index * 0.05;
|
||||
}
|
||||
})();
|
||||
|
||||
const shade = {
|
||||
L: targetL, // Blend lightness
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
getDataOrNull,
|
||||
throwIfDataError,
|
||||
} from '@v2/lib/data';
|
||||
import assertNever from 'assert-never';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { assert } from 'ts-essentials';
|
||||
import { GITBOOK_URL } from './env';
|
||||
@@ -242,19 +243,45 @@ export async function fetchSiteContextByIds(
|
||||
? parseSiteSectionsAndGroups(siteStructure, ids.siteSection)
|
||||
: null;
|
||||
|
||||
const siteSpace = (
|
||||
siteStructure.type === 'siteSpaces' && siteStructure.structure
|
||||
? siteStructure.structure
|
||||
: sections?.current.siteSpaces
|
||||
)?.find((siteSpace) => siteSpace.id === ids.siteSpace);
|
||||
if (!siteSpace) {
|
||||
throw new Error('Site space not found');
|
||||
}
|
||||
// Parse the current siteSpace and siteSpaces based on the site structure type.
|
||||
const { siteSpaces, siteSpace }: { siteSpaces: SiteSpace[]; siteSpace: SiteSpace } = (() => {
|
||||
if (siteStructure.type === 'siteSpaces') {
|
||||
const siteSpaces = siteStructure.structure;
|
||||
const siteSpace = siteSpaces.find((siteSpace) => siteSpace.id === ids.siteSpace);
|
||||
|
||||
const siteSpaces =
|
||||
siteStructure.type === 'siteSpaces'
|
||||
? siteStructure.structure
|
||||
: (sections?.current.siteSpaces ?? []);
|
||||
if (!siteSpace) {
|
||||
throw new Error(
|
||||
`Site space "${ids.siteSpace}" not found in structure type="siteSpaces"`
|
||||
);
|
||||
}
|
||||
|
||||
return { siteSpaces, siteSpace };
|
||||
}
|
||||
|
||||
if (siteStructure.type === 'sections') {
|
||||
assert(
|
||||
sections,
|
||||
`cannot find site space "${ids.siteSpace}" because parsed sections are missing siteStructure.type="sections" siteSection="${ids.siteSection}"`
|
||||
);
|
||||
|
||||
const currentSection = sections.current;
|
||||
const siteSpaces = currentSection.siteSpaces;
|
||||
const siteSpace = currentSection.siteSpaces.find(
|
||||
(siteSpace) => siteSpace.id === ids.siteSpace
|
||||
);
|
||||
|
||||
if (!siteSpace) {
|
||||
throw new Error(
|
||||
`Site space "${ids.siteSpace}" not found in structure type="sections" currentSection="${currentSection.id}"`
|
||||
);
|
||||
}
|
||||
|
||||
return { siteSpaces, siteSpace };
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
assertNever(siteStructure, `cannot handle site structure of type ${siteStructure.type}`);
|
||||
})();
|
||||
|
||||
const customization = (() => {
|
||||
if (ids.siteSpace) {
|
||||
@@ -380,7 +407,7 @@ export function checkIsRootSiteContext(context: GitBookSiteContext): boolean {
|
||||
function parseSiteSectionsAndGroups(structure: SiteStructure, siteSectionId: string) {
|
||||
const sectionsAndGroups = getSiteStructureSections(structure, { ignoreGroups: false });
|
||||
const section = parseCurrentSection(structure, siteSectionId);
|
||||
assert(section, 'A section must be defined when there are multiple sections');
|
||||
assert(section, `couldn't find section "${siteSectionId}" in site structure`);
|
||||
return { list: sectionsAndGroups, current: section } satisfies SiteSections;
|
||||
}
|
||||
|
||||
|
||||
@@ -1394,6 +1394,7 @@ async function* streamAIResponse(
|
||||
input: params.input,
|
||||
output: params.output,
|
||||
model: params.model,
|
||||
tools: params.tools,
|
||||
});
|
||||
|
||||
for await (const event of res) {
|
||||
|
||||
@@ -189,5 +189,6 @@ export interface GitBookDataFetcher {
|
||||
input: api.AIMessageInput[];
|
||||
output: api.AIOutputFormat;
|
||||
model: api.AIModel;
|
||||
tools?: api.AIToolCapabilities;
|
||||
}): AsyncGenerator<api.AIStreamResponse, void, unknown>;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
# gitbook
|
||||
|
||||
## 0.11.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ebc39e9]
|
||||
- Updated dependencies [b6b09d4]
|
||||
- @gitbook/react-openapi@1.2.1
|
||||
|
||||
## 0.11.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- d67699a: Add OpenAPI Webhook block
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4b8a621: Show sections tabs only if there is at least two sections
|
||||
- 8ed1bda: Translate OpenAPI blocks
|
||||
- 7588cfe: Improve OpenAPIResponses examples and schemas
|
||||
- Updated dependencies [eeb977f]
|
||||
- Updated dependencies [3363a18]
|
||||
- Updated dependencies [d67699a]
|
||||
- Updated dependencies [8ed1bda]
|
||||
- Updated dependencies [7588cfe]
|
||||
- Updated dependencies [ad1dc0b]
|
||||
- @gitbook/react-openapi@1.2.0
|
||||
|
||||
## 0.10.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -10,18 +10,18 @@ const testCases: TestsCase[] = [
|
||||
{ name: 'OpenAPI', url: '/snyk-api/reference/apps', run: waitForCookiesDialog },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Nexthink',
|
||||
contentBaseURL: 'https://docs.nexthink.com',
|
||||
tests: [
|
||||
{
|
||||
name: 'Home',
|
||||
url: '/',
|
||||
screenshot: { waitForTOCScrolling: false },
|
||||
run: waitForCookiesDialog,
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: 'Nexthink',
|
||||
// contentBaseURL: 'https://docs.nexthink.com',
|
||||
// tests: [
|
||||
// {
|
||||
// name: 'Home',
|
||||
// url: '/',
|
||||
// screenshot: { waitForTOCScrolling: false },
|
||||
// run: waitForCookiesDialog,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
name: 'asiksupport-stg.dto.kemkes.go.id',
|
||||
contentBaseURL: 'https://asiksupport-stg.dto.kemkes.go.id',
|
||||
@@ -157,11 +157,11 @@ const testCases: TestsCase[] = [
|
||||
contentBaseURL: 'https://wiki.redmodding.org',
|
||||
tests: [{ name: 'Home', url: '/' }],
|
||||
},
|
||||
{
|
||||
name: 'docs.cherry-ai.com',
|
||||
contentBaseURL: 'https://docs.cherry-ai.com',
|
||||
tests: [{ name: 'Home', url: '/', run: waitForCookiesDialog }],
|
||||
},
|
||||
// {
|
||||
// name: 'docs.cherry-ai.com',
|
||||
// contentBaseURL: 'https://docs.cherry-ai.com',
|
||||
// tests: [{ name: 'Home', url: '/', run: waitForCookiesDialog }],
|
||||
// },
|
||||
{
|
||||
name: 'docs.snyk.io',
|
||||
contentBaseURL: 'https://docs.snyk.io',
|
||||
|
||||
@@ -111,24 +111,24 @@ const testCases: TestsCase[] = [
|
||||
name: 'Customized variant titles are displayed',
|
||||
url: '',
|
||||
run: async (page) => {
|
||||
const spaceDrowpdown = page
|
||||
const spaceDropdown = page
|
||||
.locator('[data-testid="space-dropdown-button"]')
|
||||
.locator('visible=true');
|
||||
await spaceDrowpdown.click();
|
||||
await spaceDropdown.click();
|
||||
|
||||
const variantSelectionDropdown = page.locator(
|
||||
'css=[data-testid="space-dropdown-button"] + div'
|
||||
'css=[data-testid="dropdown-menu"]'
|
||||
);
|
||||
// the customized space title
|
||||
await expect(
|
||||
variantSelectionDropdown.getByRole('link', {
|
||||
variantSelectionDropdown.getByRole('menuitem', {
|
||||
name: 'Multi-Variants',
|
||||
})
|
||||
).toBeVisible();
|
||||
|
||||
// the NON-customized space title
|
||||
await expect(
|
||||
variantSelectionDropdown.getByRole('link', {
|
||||
variantSelectionDropdown.getByRole('menuitem', {
|
||||
name: 'RFCs',
|
||||
})
|
||||
).toBeVisible();
|
||||
@@ -145,14 +145,17 @@ const testCases: TestsCase[] = [
|
||||
url: 'api-multi-versions/reference/api-reference/pets',
|
||||
screenshot: false,
|
||||
run: async (page) => {
|
||||
const spaceDrowpdown = await page
|
||||
const spaceDropdown = await page
|
||||
.locator('[data-testid="space-dropdown-button"]')
|
||||
.locator('visible=true');
|
||||
await spaceDrowpdown.click();
|
||||
await spaceDropdown.click();
|
||||
|
||||
const variantSelectionDropdown = page.locator(
|
||||
'css=[data-testid="dropdown-menu"]'
|
||||
);
|
||||
// Click the second variant in the dropdown
|
||||
await page
|
||||
.getByRole('link', {
|
||||
await variantSelectionDropdown
|
||||
.getByRole('menuitem', {
|
||||
name: '2.0',
|
||||
})
|
||||
.click();
|
||||
@@ -168,14 +171,18 @@ const testCases: TestsCase[] = [
|
||||
url: 'api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/reference/api-reference/pets',
|
||||
screenshot: false,
|
||||
run: async (page) => {
|
||||
const spaceDrowpdown = await page
|
||||
const spaceDropdown = await page
|
||||
.locator('[data-testid="space-dropdown-button"]')
|
||||
.locator('visible=true');
|
||||
await spaceDrowpdown.click();
|
||||
await spaceDropdown.click();
|
||||
|
||||
const variantSelectionDropdown = page.locator(
|
||||
'css=[data-testid="dropdown-menu"]'
|
||||
);
|
||||
|
||||
// Click the second variant in the dropdown
|
||||
await page
|
||||
.getByRole('link', {
|
||||
await variantSelectionDropdown
|
||||
.getByRole('menuitem', {
|
||||
name: '2.0',
|
||||
})
|
||||
.click();
|
||||
@@ -205,14 +212,18 @@ const testCases: TestsCase[] = [
|
||||
return `api-multi-versions-va/reference/api-reference/pets?jwt_token=${token}`;
|
||||
},
|
||||
run: async (page) => {
|
||||
const spaceDrowpdown = await page
|
||||
const spaceDropdown = await page
|
||||
.locator('[data-testid="space-dropdown-button"]')
|
||||
.locator('visible=true');
|
||||
await spaceDrowpdown.click();
|
||||
await spaceDropdown.click();
|
||||
|
||||
const variantSelectionDropdown = page.locator(
|
||||
'css=[data-testid="dropdown-menu"]'
|
||||
);
|
||||
|
||||
// Click the second variant in the dropdown
|
||||
await page
|
||||
.getByRole('link', {
|
||||
await variantSelectionDropdown
|
||||
.getByRole('menuitem', {
|
||||
name: '2.0',
|
||||
})
|
||||
.click();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gitbook",
|
||||
"version": "0.10.1",
|
||||
"version": "0.11.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "env-cmd --silent -f ../../.env.local next dev",
|
||||
@@ -27,6 +27,7 @@
|
||||
"@gitbook/react-math": "workspace:*",
|
||||
"@gitbook/react-openapi": "workspace:*",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.12",
|
||||
"@radix-ui/react-navigation-menu": "^1.2.3",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-tooltip": "^1.1.8",
|
||||
@@ -37,6 +38,7 @@
|
||||
"assert-never": "^1.2.1",
|
||||
"bun-types": "^1.1.20",
|
||||
"classnames": "^2.5.1",
|
||||
"event-iterator": "^2.0.0",
|
||||
"framer-motion": "^10.16.14",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsontoxml": "^1.0.1",
|
||||
@@ -52,8 +54,9 @@
|
||||
"openapi-types": "^12.1.3",
|
||||
"p-map": "^7.0.0",
|
||||
"parse-cache-control": "^1.0.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"partial-json": "^0.1.7",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hotkeys-hook": "^4.4.1",
|
||||
"rehype-sanitize": "^6.0.0",
|
||||
"rehype-stringify": "^10.0.1",
|
||||
@@ -70,13 +73,11 @@
|
||||
"usehooks-ts": "^3.1.0",
|
||||
"zod": "^3.24.2",
|
||||
"zod-to-json-schema": "^3.24.5",
|
||||
"event-iterator": "^2.0.0",
|
||||
"partial-json": "^0.1.7",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@argos-ci/playwright": "^5.0.3",
|
||||
"@cloudflare/next-on-pages": "1.13.7",
|
||||
"@cloudflare/next-on-pages": "1.13.12",
|
||||
"@cloudflare/workers-types": "^4.20241230.0",
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
'use client';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useVisitedPages } from '../Insights';
|
||||
import { usePageContext } from '../PageContext';
|
||||
import { useAdaptiveContext } from './AdaptiveContext';
|
||||
import { streamPageSummary } from './server-actions/streamPageSummary';
|
||||
|
||||
export function AIPageSummary() {
|
||||
const { toggle, setLoading, setToggle } = useAdaptiveContext();
|
||||
|
||||
const currentPage = usePageContext();
|
||||
const visitedPages = useVisitedPages((state) => state.pages);
|
||||
const visitedPagesRef = useRef(visitedPages);
|
||||
|
||||
const [summary, setSummary] = useState<{
|
||||
keyFacts?: string;
|
||||
bigPicture?: string;
|
||||
}>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!summary.keyFacts) setLoading(true);
|
||||
if (!visitedPages?.length) return;
|
||||
|
||||
// Skip if the visited pages haven't changed
|
||||
if (JSON.stringify(visitedPagesRef.current) === JSON.stringify(visitedPages)) return;
|
||||
|
||||
visitedPagesRef.current = visitedPages;
|
||||
|
||||
let canceled = false;
|
||||
setLoading(true);
|
||||
|
||||
(async () => {
|
||||
const stream = await streamPageSummary({
|
||||
currentPage: {
|
||||
id: currentPage.pageId,
|
||||
title: currentPage.title,
|
||||
},
|
||||
currentSpace: {
|
||||
id: currentPage.spaceId,
|
||||
},
|
||||
visitedPages: visitedPages,
|
||||
});
|
||||
|
||||
for await (const summary of stream) {
|
||||
if (canceled) return;
|
||||
|
||||
setSummary(summary);
|
||||
}
|
||||
})().finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return () => {
|
||||
canceled = true;
|
||||
};
|
||||
}, [currentPage, visitedPages, toggle, setLoading, setToggle]);
|
||||
|
||||
const shimmerBlocks = [20, 35, 25, 10, 45, 30, 30, 35, 25, 10, 40, 30]; // Widths in percentages
|
||||
|
||||
return (
|
||||
toggle.open && (
|
||||
<div className="flex min-w-64 animate-fadeIn flex-col gap-4">
|
||||
{summary.keyFacts ? (
|
||||
<div>
|
||||
<h5 className="mb-0.5 font-semibold text-tint-subtle text-xs uppercase">
|
||||
Key facts
|
||||
</h5>
|
||||
{summary.keyFacts}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full flex-wrap gap-2">
|
||||
{shimmerBlocks.map((width, index) => (
|
||||
<div
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: No other distinguishing feature available
|
||||
key={index}
|
||||
className="h-4 animate-pulse rounded bg-tint-active"
|
||||
style={{
|
||||
width: `${width}%`,
|
||||
animationDelay: `${index * 0.1}s`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{visitedPages.length > 1 && summary?.bigPicture ? (
|
||||
<div>
|
||||
<h5 className="mb-0.5 font-semibold text-tint-subtle text-xs uppercase">
|
||||
Big Picture
|
||||
</h5>
|
||||
{summary?.bigPicture}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
type AdaptiveContextType = {
|
||||
loading: boolean;
|
||||
setLoading: (loading: boolean) => void;
|
||||
toggle: {
|
||||
open: boolean;
|
||||
manual: boolean;
|
||||
};
|
||||
setToggle: (toggle: { open: boolean; manual: boolean }) => void;
|
||||
};
|
||||
|
||||
export const AdaptiveContext = React.createContext<AdaptiveContextType | null>(null);
|
||||
|
||||
/**
|
||||
* Client side context provider to pass information about the current page.
|
||||
*/
|
||||
export function AdaptiveContextProvider({ children }: { children: React.ReactNode }) {
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
|
||||
// Start with a default state that works for SSR
|
||||
const [toggle, setToggle] = React.useState({
|
||||
open: false, // Default to open for SSR
|
||||
manual: false,
|
||||
});
|
||||
|
||||
// Update the toggle state on the client side only
|
||||
React.useEffect(() => {
|
||||
// Check for mobile only on the client
|
||||
const handleResize = () => {
|
||||
if (!toggle.manual) {
|
||||
const isMobile = window.innerWidth < 1280;
|
||||
setToggle((prev) => ({
|
||||
...prev,
|
||||
open: !isMobile,
|
||||
}));
|
||||
}
|
||||
};
|
||||
handleResize();
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [toggle.manual]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (toggle.open) {
|
||||
document.body.classList.add('adaptive-pane');
|
||||
} else {
|
||||
document.body.classList.remove('adaptive-pane');
|
||||
}
|
||||
}, [toggle.open]);
|
||||
|
||||
return (
|
||||
<AdaptiveContext.Provider value={{ loading, setLoading, toggle, setToggle }}>
|
||||
{children}
|
||||
</AdaptiveContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to use the adaptive context.
|
||||
*/
|
||||
export function useAdaptiveContext() {
|
||||
const context = React.useContext(AdaptiveContext);
|
||||
if (!context) {
|
||||
throw new Error('useAdaptiveContext must be used within a AdaptiveContextProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
'use client';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import { AIPageSummary } from './AIPageSummary';
|
||||
import { useAdaptiveContext } from './AdaptiveContext';
|
||||
import { AdaptivePaneHeader } from './AdaptivePaneHeader';
|
||||
export function AdaptivePane() {
|
||||
const { toggle } = useAdaptiveContext();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={tcls(
|
||||
'flex shrink-0 flex-col gap-4 overflow-x-hidden rounded-md straight-corners:rounded-none bg-tint-subtle ring-1 ring-tint-subtle ring-inset transition-all duration-300',
|
||||
toggle.open ? 'max-h px-4 py-4 xl:w-72' : 'px-4 py-3 xl:w-56'
|
||||
)}
|
||||
>
|
||||
<AdaptivePaneHeader />
|
||||
<AIPageSummary />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
'use client';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { Button, Loading } from '../primitives';
|
||||
import { useAdaptiveContext } from './AdaptiveContext';
|
||||
|
||||
export function AdaptivePaneHeader() {
|
||||
const { loading, toggle, setToggle } = useAdaptiveContext();
|
||||
|
||||
return (
|
||||
<div className="flex flex-row items-center gap-3 rounded-md straight-corners:rounded-none transition-all duration-500">
|
||||
<div className="flex grow flex-col">
|
||||
<h4 className="flex items-center gap-1.5 font-semibold ">
|
||||
<Loading className="size-4 text-tint-subtle" busy={loading} />
|
||||
For you
|
||||
</h4>
|
||||
<AnimatePresence initial={false} mode="wait">
|
||||
<motion.h5
|
||||
key={loading ? 'loading' : 'loaded'}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="text-tint-subtle text-xs"
|
||||
>
|
||||
{loading ? 'Basing on your context...' : 'Based on your context'}
|
||||
</motion.h5>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
<Button
|
||||
variant="blank"
|
||||
className={tcls('px-2 *:transition-transform', !toggle.open && '*:-rotate-45')}
|
||||
iconOnly
|
||||
label="Close"
|
||||
icon="close"
|
||||
onClick={() =>
|
||||
setToggle({
|
||||
open: !toggle.open,
|
||||
manual: true,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
export * from './AIPageLinkSummary';
|
||||
export * from './AIPageSummary';
|
||||
export * from './AdaptiveContext';
|
||||
export * from './AdaptivePane';
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
'use server';
|
||||
import { type AIMessageInput, AIModel, type AIStreamResponse } from '@gitbook/api';
|
||||
import {
|
||||
type AIMessageInput,
|
||||
AIModel,
|
||||
type AIStreamResponse,
|
||||
type AIToolCapabilities,
|
||||
} from '@gitbook/api';
|
||||
import type { GitBookBaseContext } from '@v2/lib/context';
|
||||
import { EventIterator } from 'event-iterator';
|
||||
import type { MaybePromise } from 'p-map';
|
||||
@@ -47,11 +52,13 @@ export async function streamGenerateObject<T>(
|
||||
schema,
|
||||
messages,
|
||||
model = AIModel.Fast,
|
||||
tools = {},
|
||||
}: {
|
||||
schema: z.ZodSchema<T>;
|
||||
messages: AIMessageInput[];
|
||||
model?: AIModel;
|
||||
previousResponseId?: string;
|
||||
tools?: AIToolCapabilities;
|
||||
}
|
||||
) {
|
||||
const rawStream = context.dataFetcher.streamAIResponse({
|
||||
@@ -62,12 +69,13 @@ export async function streamGenerateObject<T>(
|
||||
type: 'object',
|
||||
schema: zodToJsonSchema(schema),
|
||||
},
|
||||
tools,
|
||||
model,
|
||||
});
|
||||
|
||||
let json = '';
|
||||
return parseResponse<DeepPartial<T>>(rawStream, (event) => {
|
||||
if (event.type === 'response_object') {
|
||||
if (event.type === 'response_object' && event.jsonChunk) {
|
||||
json += event.jsonChunk;
|
||||
|
||||
const parsed = partialJson.parse(json, partialJson.ALL);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './streamLinkPageSummary';
|
||||
export * from './streamPageSummary';
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
'use server';
|
||||
import { getV1BaseContext } from '@/lib/v1';
|
||||
import { isV2 } from '@/lib/v2';
|
||||
import { AIMessageRole } from '@gitbook/api';
|
||||
import { getSiteURLDataFromMiddleware } from '@v2/lib/middleware';
|
||||
import { fetchServerActionSiteContext, getServerActionBaseContext } from '@v2/lib/server-actions';
|
||||
import { z } from 'zod';
|
||||
import { streamGenerateObject } from './api';
|
||||
|
||||
/**
|
||||
* Get a summary of a page, in the context of another page
|
||||
*/
|
||||
export async function* streamPageSummary({
|
||||
currentPage,
|
||||
currentSpace,
|
||||
visitedPages,
|
||||
}: {
|
||||
currentPage: {
|
||||
id: string;
|
||||
title: string;
|
||||
};
|
||||
currentSpace: {
|
||||
id: string;
|
||||
// title: string;
|
||||
};
|
||||
visitedPages: {
|
||||
pageId: string;
|
||||
spaceId: string;
|
||||
}[];
|
||||
}) {
|
||||
const baseContext = isV2() ? await getServerActionBaseContext() : await getV1BaseContext();
|
||||
const siteURLData = await getSiteURLDataFromMiddleware();
|
||||
|
||||
const [{ stream }] = await Promise.all([
|
||||
streamGenerateObject(
|
||||
baseContext,
|
||||
{
|
||||
organizationId: siteURLData.organization,
|
||||
siteId: siteURLData.site,
|
||||
},
|
||||
{
|
||||
schema: z.object({
|
||||
keyFacts: z
|
||||
.string()
|
||||
.describe(
|
||||
'A collection of key facts from the page that together form a comprehensive summary. Keep it under 30 words.'
|
||||
),
|
||||
bigPicture:
|
||||
visitedPages.length > 0
|
||||
? z
|
||||
.string()
|
||||
.describe(
|
||||
'A natural-sounding summary of how specific concepts connect with real benefits. Use a conversational tone with concrete examples. Avoid overly formal language while still being specific. Keep it under 30 words.'
|
||||
)
|
||||
: z.undefined(),
|
||||
}),
|
||||
tools: {
|
||||
// getPages: true,
|
||||
// getPageContent: true,
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `# 1. Role
|
||||
You are a fact extractor. Your job is to identify and extract the most important facts from the current page.
|
||||
|
||||
# 2. Task
|
||||
Extract multiple key facts that:
|
||||
- Cover the most important concepts, features, or capabilities on the page
|
||||
- Represent specific, actionable information rather than general descriptions
|
||||
- Provide concrete details about functionality, limitations, or specifications
|
||||
- Together form a comprehensive understanding of the page content
|
||||
- Relate to the user's learning journey through the documentation when relevant
|
||||
|
||||
# 3. Instructions
|
||||
1. Analyze the current page to identify 3-5 concrete, specific facts (not general summaries)
|
||||
2. Focus on facts that would be most useful and relevant to someone using this documentation
|
||||
3. If the user has visited other pages, identify facts that build upon their previous knowledge
|
||||
4. Present facts as clear, declarative statements about what exists or is true
|
||||
5. Separate distinct facts rather than combining them into a single summary
|
||||
6. Include specific details, numbers, limitations, or capabilities where available`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `# 4. Current page
|
||||
The content of the current page is:`,
|
||||
attachments: [
|
||||
{
|
||||
type: 'page' as const,
|
||||
spaceId: currentSpace.id,
|
||||
pageId: currentPage.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
...(visitedPages && visitedPages.length > 0
|
||||
? [
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `# 5. Previous Pages and Learning Journey
|
||||
The content across ${visitedPages.length} page(s) builds a knowledge framework. Use this to:
|
||||
- Identify specific, concrete ways concepts interact (not just "work together")
|
||||
- Show exact functional relationships between ideas (not vague "enhances")
|
||||
- Highlight tangible capabilities that emerge from combined concepts
|
||||
- Describe precise benefits that result from these connections
|
||||
- Focus on what becomes possible when these concepts are combined
|
||||
|
||||
The content of up to 5 most recent pages are included below:`,
|
||||
},
|
||||
...visitedPages.slice(0, 5).map(({ spaceId, pageId }, index) => ({
|
||||
role: AIMessageRole.Developer,
|
||||
content: `## Previous Page ${index + 1}: ${pageId}`,
|
||||
attachments: [
|
||||
{
|
||||
type: 'page' as const,
|
||||
spaceId,
|
||||
pageId,
|
||||
},
|
||||
],
|
||||
})),
|
||||
]
|
||||
: []),
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `# 6. Guidelines for Fact Extraction
|
||||
ALWAYS:
|
||||
- ALWAYS extract multiple distinct facts rather than a single summary
|
||||
- ALWAYS focus on specific, concrete details rather than general descriptions
|
||||
- ALWAYS include numbers, limitations, requirements, or specifications when available
|
||||
- ALWAYS prioritize facts that would be most useful to someone using the documentation
|
||||
- ALWAYS consider how facts on this page relate to previously visited pages
|
||||
|
||||
NEVER:
|
||||
- NEVER use instructional language like "learn", "how to", "discover", etc.
|
||||
- NEVER include vague or generic statements that lack specific details.
|
||||
- NEVER repeat the page title without adding informative value.
|
||||
- NEVER combine multiple distinct facts into a single general statement.
|
||||
- NEVER use numbered lists.`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `## Examples
|
||||
|
||||
Page content: "Content blocks in GitBook include text, images, videos, code snippets, and more. Each block can be customized with specific settings. Text blocks support Markdown formatting and can include inline code. Images can be resized and have alt text added."
|
||||
✓ "Text blocks support Markdown formatting. Images can be resized and include alt text. Available block types include text, images, videos, and code snippets."
|
||||
✗ "GitBook offers various content blocks with customization options."
|
||||
|
||||
Page content: "Change Requests allow teams to propose, review, and approve content changes before publishing. Each reviewer's approval is tracked separately. Changes are highlighted with color coding. Change Requests can be merged automatically or manually after approval."
|
||||
✓ "Reviewer approvals are tracked individually. Changes are color-coded for visibility. Merging can be automatic or manual after approval. Multiple reviewers can collaborate on a single Change Request."
|
||||
✗ "Change Requests provide a collaborative workflow for content changes."
|
||||
|
||||
Page content: "API authentication requires an API key generated in account settings. Keys expire after 90 days by default. Rate limits are set to 1000 requests per hour. Keys can have read-only or read-write permissions."
|
||||
✓ "API keys expire after 90 days by default. Rate limits are capped at 1000 requests per hour. Keys can be configured with read-only or read-write permissions."
|
||||
✗ "API keys are required for authentication and have various settings."`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `# 7. Guidelines for Big Picture
|
||||
For the big picture summary:
|
||||
|
||||
ALWAYS:
|
||||
- ALWAYS highlight practical patterns and workflows that emerge when combining these concepts.
|
||||
- ALWAYS focus on real capabilities that come from understanding multiple features together.
|
||||
- ALWAYS use specific examples that show the value of combining these ideas.
|
||||
- ALWAYS keep the language simple, direct and conversational without corporate jargon.
|
||||
- ALWAYS use short sentences with a single clause and no commas.
|
||||
|
||||
NEVER:
|
||||
- NEVER use corporate jargon like "seamless", "ensures", "integrates", etc.
|
||||
- NEVER use complex sentences with multiple clauses.
|
||||
- NEVER use passive voice.
|
||||
- NEVER state the same fact twice.
|
||||
- NEVER repeat the page title without adding informative value.`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `## Big Picture Examples
|
||||
POOR "BIG PICTURE" EXAMPLES TO AVOID:
|
||||
✗ "GitBook combines content creation, collaboration, and integrations, building on your understanding of identifiers and paginated results for seamless documentation management."
|
||||
✗ "The platform's robust features for content organization, versioning, and access control work together to create a powerful documentation ecosystem."
|
||||
✗ "By leveraging GitBook's content blocks, permissions system, and API capabilities, you can build comprehensive documentation solutions."
|
||||
|
||||
GOOD "BIG PICTURE" EXAMPLES TO FOLLOW:
|
||||
✓ "Combining Markdown tables with webhook notifications means your API docs stay up-to-date automatically. When you update a parameter, the PDF version refreshes too."
|
||||
✓ "Content blocks and version history together solve the biggest docs headache. You can experiment with different layouts while keeping a clean record of what changed and why."
|
||||
✓ "The real power comes from linking custom domains with content permissions. Your sales team gets branded docs while your developers see the technical details on the same site."
|
||||
✓ "With spaces, webhooks, and custom metadata working together, you're not just making docs. You're building a knowledge system that responds to how your team actually works."`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.Developer,
|
||||
content: `The current page is: "${currentPage.title}" (ID ${currentPage.id})`,
|
||||
},
|
||||
{
|
||||
role: AIMessageRole.User,
|
||||
content:
|
||||
'What are the key facts on this page, and what have I learned across the documentation so far?',
|
||||
},
|
||||
],
|
||||
}
|
||||
),
|
||||
fetchServerActionSiteContext(baseContext),
|
||||
]);
|
||||
|
||||
for await (const value of stream) {
|
||||
const keyFacts = value.keyFacts;
|
||||
const bigPicture = value.bigPicture;
|
||||
|
||||
if (!keyFacts) continue;
|
||||
|
||||
yield {
|
||||
keyFacts,
|
||||
bigPicture,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import { IntegrationBlock } from './Integration';
|
||||
import { List } from './List';
|
||||
import { ListItem } from './ListItem';
|
||||
import { BlockMath } from './Math';
|
||||
import { OpenAPIOperation, OpenAPISchemas } from './OpenAPI';
|
||||
import { OpenAPIOperation, OpenAPISchemas, OpenAPIWebhook } from './OpenAPI';
|
||||
import { Paragraph } from './Paragraph';
|
||||
import { Quote } from './Quote';
|
||||
import { ReusableContent } from './ReusableContent';
|
||||
@@ -85,6 +85,8 @@ export function Block<T extends DocumentBlock>(props: BlockProps<T>) {
|
||||
return <OpenAPIOperation {...props} block={block} />;
|
||||
case 'openapi-schemas':
|
||||
return <OpenAPISchemas {...props} block={block} />;
|
||||
case 'openapi-webhook':
|
||||
return <OpenAPIWebhook {...props} block={block} />;
|
||||
case 'embed':
|
||||
return <Embed {...props} block={block} />;
|
||||
case 'blockquote':
|
||||
@@ -159,6 +161,7 @@ export function BlockSkeleton(props: { block: DocumentBlock; style: ClassValue }
|
||||
case 'swagger':
|
||||
case 'openapi-operation':
|
||||
case 'openapi-schemas':
|
||||
case 'openapi-webhook':
|
||||
case 'math':
|
||||
case 'divider':
|
||||
case 'content-ref':
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
.highlight-line-number {
|
||||
@apply text-sm text-right pr-3.5 rounded-l pl-2 sticky left-[-3px] bg-gradient-to-r from-80% from-tint to-transparent;
|
||||
@apply text-sm text-right pr-3.5 rounded-l pl-2 sticky left-[-3px] bg-gradient-to-r from-80% from-tint-subtle contrast-more:from-tint-base theme-muted:from-tint-base [html.theme-bold.sidebar-filled_&]:from-tint-base to-transparent;
|
||||
@apply before:text-tint before:content-[counter(line)];
|
||||
|
||||
.highlight-line.highlighted > & {
|
||||
|
||||
@@ -39,7 +39,7 @@ export const CodeBlockRenderer = forwardRef(function CodeBlockRenderer(
|
||||
>
|
||||
<div className="flex items-center justify-start gap-2 text-sm [grid-area:1/1]">
|
||||
{title ? (
|
||||
<div className="inline-flex items-center justify-center rounded-t straight-corners:rounded-t-s bg-tint px-3 py-2 text-tint text-xs leading-none tracking-wide">
|
||||
<div className="relative top-px z-20 inline-flex items-center justify-center rounded-t straight-corners:rounded-t-s border border-tint-subtle border-b-0 bg-tint-subtle theme-muted:bg-tint-base px-3 py-2 text-tint text-xs leading-none tracking-wide contrast-more:border-tint contrast-more:bg-tint-base [html.theme-bold.sidebar-filled_&]:bg-tint-base">
|
||||
{title}
|
||||
</div>
|
||||
) : null}
|
||||
@@ -50,8 +50,8 @@ export const CodeBlockRenderer = forwardRef(function CodeBlockRenderer(
|
||||
/>
|
||||
<pre
|
||||
className={tcls(
|
||||
'hide-scroll relative overflow-auto bg-tint theme-gradient:bg-tint-12/1 ring-tint-subtle [grid-area:2/1]',
|
||||
'rounded-md straight-corners:rounded-sm',
|
||||
'hide-scroll relative overflow-auto border border-tint-subtle bg-tint-subtle theme-muted:bg-tint-base [grid-area:2/1] contrast-more:border-tint contrast-more:bg-tint-base [html.theme-bold.sidebar-filled_&]:bg-tint-base',
|
||||
'rounded-md straight-corners:rounded-sm shadow-sm',
|
||||
title && 'rounded-ss-none'
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -1,31 +1,67 @@
|
||||
:root {
|
||||
--shiki-color-text: theme("colors.tint.11");
|
||||
--shiki-token-constant: #0a6355;
|
||||
--shiki-token-string: #8b6d32;
|
||||
--shiki-token-comment: theme("colors.teal.700/.64");
|
||||
--shiki-token-keyword: theme("colors.pomegranate.600");
|
||||
--shiki-token-parameter: #0a3069;
|
||||
--shiki-token-function: #8250df;
|
||||
--shiki-token-string-expression: #6a4906;
|
||||
--shiki-token-punctuation: theme("colors.pomegranate.700/.92");
|
||||
--shiki-token-link: theme("colors.tint.12");
|
||||
--shiki-token-inserted: #22863a;
|
||||
--shiki-token-deleted: #b31d28;
|
||||
--shiki-token-changed: #8250df;
|
||||
--shiki-token-punctuation: theme("colors.tint.11");
|
||||
--shiki-token-comment: theme("colors.neutral.9/.7");
|
||||
--shiki-token-link: theme("colors.primary.10");
|
||||
|
||||
--shiki-token-constant: theme("colors.warning.10");
|
||||
--shiki-token-string: theme("colors.warning.10");
|
||||
--shiki-token-string-expression: theme("colors.success.10");
|
||||
--shiki-token-keyword: theme("colors.danger.10");
|
||||
--shiki-token-parameter: theme("colors.warning.10");
|
||||
--shiki-token-function: theme("colors.primary.10");
|
||||
|
||||
--shiki-token-inserted: theme("colors.success.10");
|
||||
--shiki-token-deleted: theme("colors.danger.10");
|
||||
--shiki-token-changed: theme("colors.tint.12");
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
:root {
|
||||
--shiki-color-text: theme("colors.tint.12");
|
||||
--shiki-token-punctuation: theme("colors.tint.12");
|
||||
--shiki-token-comment: theme("colors.neutral.11");
|
||||
--shiki-token-link: theme("colors.primary.11");
|
||||
|
||||
--shiki-token-constant: theme("colors.warning.11");
|
||||
--shiki-token-string: theme("colors.warning.11");
|
||||
--shiki-token-string-expression: theme("colors.success.11");
|
||||
--shiki-token-keyword: theme("colors.danger.11");
|
||||
--shiki-token-parameter: theme("colors.warning.11");
|
||||
--shiki-token-function: theme("colors.primary.11");
|
||||
|
||||
--shiki-token-inserted: theme("colors.success.11");
|
||||
--shiki-token-deleted: theme("colors.danger.11");
|
||||
--shiki-token-changed: theme("colors.tint.12");
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--shiki-color-text: theme("colors.tint.11");
|
||||
--shiki-token-constant: #d19a66;
|
||||
--shiki-token-string: theme("colors.pomegranate.300");
|
||||
--shiki-token-comment: theme("colors.teal.300/.64");
|
||||
--shiki-token-keyword: theme("colors.pomegranate.400");
|
||||
--shiki-token-parameter: theme("colors.yellow.500");
|
||||
--shiki-token-function: #56b6c2;
|
||||
--shiki-token-string-expression: theme("colors.tint.11");
|
||||
--shiki-token-punctuation: #acc6ee;
|
||||
--shiki-token-link: theme("colors.pomegranate.400");
|
||||
--shiki-token-inserted: #85e89d;
|
||||
--shiki-token-deleted: #fdaeb7;
|
||||
--shiki-token-changed: #56b6c2;
|
||||
/* Override select colors to have more contrast */
|
||||
--shiki-token-comment: theme("colors.neutral.9");
|
||||
|
||||
--shiki-token-constant: theme("colors.warning.11");
|
||||
--shiki-token-string: theme("colors.warning.11");
|
||||
--shiki-token-string-expression: theme("colors.success.11");
|
||||
--shiki-token-keyword: theme("colors.danger.11");
|
||||
--shiki-token-parameter: theme("colors.warning.11");
|
||||
--shiki-token-function: theme("colors.primary.11");
|
||||
}
|
||||
|
||||
.code-monochrome {
|
||||
--shiki-token-constant: theme("colors.tint.11");
|
||||
--shiki-token-string: theme("colors.tint.12");
|
||||
--shiki-token-string-expression: theme("colors.tint.12");
|
||||
--shiki-token-keyword: theme("colors.primary.10");
|
||||
--shiki-token-parameter: theme("colors.tint.9");
|
||||
--shiki-token-function: theme("colors.primary.9");
|
||||
}
|
||||
|
||||
html.dark.code-monochrome {
|
||||
--shiki-token-constant: theme("colors.tint.11");
|
||||
--shiki-token-string: theme("colors.tint.12");
|
||||
--shiki-token-string-expression: theme("colors.tint.12");
|
||||
--shiki-token-keyword: theme("colors.primary.11");
|
||||
--shiki-token-parameter: theme("colors.tint.10");
|
||||
--shiki-token-function: theme("colors.primary.10");
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ export const contentKitServerContext: ContentKitServerContext = {
|
||||
'link-external': (props) => <Icon icon="arrow-up-right-from-square" {...props} />,
|
||||
eye: (props) => <Icon icon="eye" {...props} />,
|
||||
lock: (props) => <Icon icon="lock" {...props} />,
|
||||
check: (props) => <Icon icon="check" {...props} />,
|
||||
'check-circle': (props) => <Icon icon="check-circle" {...props} />,
|
||||
},
|
||||
codeBlock: (props) => {
|
||||
return <PlainCodeBlock code={props.code} syntax={props.syntax} />;
|
||||
|
||||
@@ -51,7 +51,7 @@ async function OpenAPIOperationBody(props: BlockProps<AnyOpenAPIOperationsBlock>
|
||||
return (
|
||||
<BaseOpenAPIOperation
|
||||
data={data}
|
||||
context={getOpenAPIContext({ props, specUrl })}
|
||||
context={getOpenAPIContext({ props, specUrl, context: context.contentContext })}
|
||||
className="openapi-block"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@ async function OpenAPISchemasBody(props: BlockProps<OpenAPISchemasBlock>) {
|
||||
<BaseOpenAPISchemas
|
||||
schemas={data.schemas}
|
||||
grouped={block.data.grouped}
|
||||
context={getOpenAPIContext({ props, specUrl })}
|
||||
context={getOpenAPIContext({ props, specUrl, context: context.contentContext })}
|
||||
className="openapi-block"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { OpenAPIWebhook as BaseOpenAPIWebhook } from '@gitbook/react-openapi';
|
||||
|
||||
import { resolveOpenAPIWebhookBlock } from '@/lib/openapi/resolveOpenAPIWebhookBlock';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import type { BlockProps } from '../Block';
|
||||
|
||||
import './scalar.css';
|
||||
import './style.css';
|
||||
import type { OpenAPIWebhookBlock } from '@/lib/openapi/types';
|
||||
import { getOpenAPIContext } from './context';
|
||||
|
||||
/**
|
||||
* Render an openapi block or an openapi-webhook block.
|
||||
*/
|
||||
export async function OpenAPIWebhook(props: BlockProps<OpenAPIWebhookBlock>) {
|
||||
const { style } = props;
|
||||
return (
|
||||
<div className={tcls('flex w-full min-w-0', style, 'max-w-full')}>
|
||||
<OpenAPIWebhookBody {...props} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
async function OpenAPIWebhookBody(props: BlockProps<OpenAPIWebhookBlock>) {
|
||||
const { block, context } = props;
|
||||
|
||||
if (!context.contentContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { data, specUrl, error } = await resolveOpenAPIWebhookBlock({
|
||||
block,
|
||||
context: context.contentContext,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="hidden">
|
||||
<p>
|
||||
Error with {specUrl}: {error.message}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!data || !specUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<BaseOpenAPIWebhook
|
||||
data={data}
|
||||
context={getOpenAPIContext({ props, specUrl, context: context.contentContext })}
|
||||
className="openapi-block"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { JSONDocument } from '@gitbook/api';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import type { OpenAPIContext } from '@gitbook/react-openapi';
|
||||
import { type OpenAPIContextInput, checkIsValidLocale } from '@gitbook/react-openapi';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
@@ -11,17 +11,31 @@ import { Heading } from '../Heading';
|
||||
|
||||
import './scalar.css';
|
||||
import './style.css';
|
||||
import type { AnyOpenAPIOperationsBlock, OpenAPISchemasBlock } from '@/lib/openapi/types';
|
||||
import { DEFAULT_LOCALE, getCustomizationLocale } from '@/intl/server';
|
||||
import type {
|
||||
AnyOpenAPIOperationsBlock,
|
||||
OpenAPISchemasBlock,
|
||||
OpenAPIWebhookBlock,
|
||||
} from '@/lib/openapi/types';
|
||||
import type { GitBookAnyContext } from '@v2/lib/context';
|
||||
|
||||
/**
|
||||
* Get the OpenAPI context to render a block.
|
||||
*/
|
||||
export function getOpenAPIContext(args: {
|
||||
props: BlockProps<AnyOpenAPIOperationsBlock | OpenAPISchemasBlock>;
|
||||
props: BlockProps<AnyOpenAPIOperationsBlock | OpenAPISchemasBlock | OpenAPIWebhookBlock>;
|
||||
specUrl: string;
|
||||
}): OpenAPIContext {
|
||||
const { props, specUrl } = args;
|
||||
context: GitBookAnyContext | undefined;
|
||||
}): OpenAPIContextInput {
|
||||
const { props, specUrl, context } = args;
|
||||
const { block } = props;
|
||||
|
||||
const customization = context && 'customization' in context ? context.customization : null;
|
||||
const customizationLocale = customization
|
||||
? getCustomizationLocale(customization)
|
||||
: DEFAULT_LOCALE;
|
||||
const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE;
|
||||
|
||||
return {
|
||||
specUrl,
|
||||
icons: {
|
||||
@@ -69,5 +83,6 @@ export function getOpenAPIContext(args: {
|
||||
defaultInteractiveOpened: props.context.mode === 'print',
|
||||
id: block.meta?.id,
|
||||
blockKey: block.key,
|
||||
locale,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './OpenAPIOperation';
|
||||
export * from './OpenAPISchemas';
|
||||
export * from './OpenAPIWebhook';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Layout Components */
|
||||
.openapi-operation,
|
||||
.openapi-schemas {
|
||||
.openapi-schemas,
|
||||
.openapi-webhook {
|
||||
@apply flex-1 flex flex-col gap-8 mb-14 min-w-0;
|
||||
}
|
||||
|
||||
@@ -168,41 +169,18 @@
|
||||
@apply flex flex-col;
|
||||
}
|
||||
|
||||
.openapi-schema {
|
||||
.openapi-schema,
|
||||
.openapi-disclosure {
|
||||
@apply py-2.5 flex flex-col gap-2;
|
||||
}
|
||||
|
||||
.openapi-section-body .openapi-schema-properties {
|
||||
@apply divide-y divide-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-panel > .openapi-schema-properties > *:first-child > .openapi-schema {
|
||||
@apply pt-0;
|
||||
}
|
||||
|
||||
.openapi-responsebody > .openapi-schema-properties > .openapi-schema:last-child {
|
||||
@apply pb-0;
|
||||
}
|
||||
|
||||
.openapi-responsebody > .openapi-schema-properties > .openapi-schema:only-child {
|
||||
@apply py-0;
|
||||
}
|
||||
|
||||
.openapi-schema-properties .openapi-schema:last-child {
|
||||
@apply border-b-0;
|
||||
}
|
||||
|
||||
.openapi-schema-properties .openapi-schema-opened {
|
||||
@apply pb-3;
|
||||
}
|
||||
|
||||
.openapi-schema > .openapi-schema-properties {
|
||||
@apply mt-3;
|
||||
}
|
||||
|
||||
/* Schema Presentation */
|
||||
.openapi-schema-presentation {
|
||||
@apply flex flex-col gap-1.5 font-normal;
|
||||
@apply flex flex-col gap-1 font-normal;
|
||||
}
|
||||
|
||||
.openapi-schema-properties:last-child {
|
||||
@@ -220,7 +198,7 @@
|
||||
}
|
||||
|
||||
.openapi-schema-propertyname {
|
||||
@apply select-all font-mono font-normal text-tint-strong;
|
||||
@apply select-all font-mono font-semibold text-tint-strong;
|
||||
}
|
||||
|
||||
.openapi-schema-propertyname[data-deprecated="true"] {
|
||||
@@ -228,19 +206,23 @@
|
||||
}
|
||||
|
||||
.openapi-schema-required {
|
||||
@apply text-warning-subtle text-[0.813rem];
|
||||
@apply text-warning-subtle text-[0.813rem] lowercase;
|
||||
}
|
||||
|
||||
.openapi-schema-optional {
|
||||
@apply text-info-subtle text-[0.813rem];
|
||||
@apply text-tint-subtle text-[0.813rem] lowercase;
|
||||
}
|
||||
|
||||
.openapi-schema-readonly {
|
||||
@apply text-primary-subtle/9 text-[0.813rem];
|
||||
@apply text-primary-subtle/9 text-[0.813rem] lowercase;
|
||||
}
|
||||
|
||||
.openapi-schema-writeonly {
|
||||
@apply text-success dark:text-success-subtle/9 text-[0.813rem];
|
||||
@apply text-success dark:text-success-subtle/9 text-[0.813rem] lowercase;
|
||||
}
|
||||
|
||||
.openapi-schema-types {
|
||||
@apply flex items-baseline flex-wrap gap-1;
|
||||
}
|
||||
|
||||
.openapi-schema-type {
|
||||
@@ -320,7 +302,7 @@
|
||||
.openapi-schema-pattern code,
|
||||
.openapi-schema-enum-value code,
|
||||
.openapi-schema-default code {
|
||||
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-xs leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
||||
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint-subtle bg-tint rounded text-xs leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
||||
}
|
||||
|
||||
/* Authentication */
|
||||
@@ -372,28 +354,25 @@
|
||||
}
|
||||
|
||||
.openapi-response-tab-content {
|
||||
@apply overflow-hidden max-w-full flex items-baseline;
|
||||
@apply text-left text-pretty relative leading-[1.125rem] text-tint !font-normal truncate select-text;
|
||||
@apply flex items-baseline truncate grow shrink max-w-max basis-[60%] mr-auto;
|
||||
@apply text-left text-pretty relative leading-tight text-tint select-text;
|
||||
}
|
||||
|
||||
.openapi-response-description.openapi-markdown {
|
||||
@apply text-left prose-sm text-[0.813rem] text-pretty h-auto relative leading-[1.125rem] text-tint !font-normal truncate select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||
@apply text-left truncate prose-sm text-sm leading-tight text-tint select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||
}
|
||||
|
||||
.openapi-response-description.openapi-markdown::-webkit-scrollbar {
|
||||
display: none;
|
||||
.openapi-disclosure-group-trigger[aria-expanded="true"] .openapi-response-tab-content {
|
||||
@apply basis-full;
|
||||
}
|
||||
|
||||
.openapi-response-description p {
|
||||
@apply truncate max-w-full inline pr-1;
|
||||
}
|
||||
|
||||
.openapi-response-content-type {
|
||||
@apply text-xs text-tint-8 ml-auto shrink-0;
|
||||
.openapi-disclosure-group-trigger[aria-expanded="true"]
|
||||
.openapi-response-description.openapi-markdown {
|
||||
@apply whitespace-normal;
|
||||
}
|
||||
|
||||
.openapi-response-body {
|
||||
@apply flex flex-col gap-3;
|
||||
@apply flex flex-col;
|
||||
}
|
||||
|
||||
/* Response Body and Headers */
|
||||
@@ -410,16 +389,7 @@
|
||||
@apply px-3 py-1;
|
||||
}
|
||||
|
||||
.openapi-responsebody-header-content,
|
||||
.openapi-responseheaders-header-content {
|
||||
/* unstyled */
|
||||
}
|
||||
|
||||
/* Code Sample */
|
||||
.openapi-codesample {
|
||||
@apply border rounded-md straight-corners:rounded-none bg-tint border-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-codesample-header {
|
||||
@apply flex flex-row items-center;
|
||||
}
|
||||
@@ -428,6 +398,12 @@
|
||||
@apply flex flex-row items-center gap-2.5;
|
||||
}
|
||||
|
||||
.openapi-panel-heading,
|
||||
.openapi-codesample-header,
|
||||
.openapi-response-examples-header {
|
||||
@apply border-b border-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-response-examples-header .openapi-select > button {
|
||||
@apply max-w-full overflow-hidden shrink pl-0.5 py-0.5;
|
||||
}
|
||||
@@ -502,8 +478,16 @@
|
||||
}
|
||||
|
||||
/* Panel */
|
||||
.openapi-panel {
|
||||
@apply border rounded-md straight-corners:rounded-none bg-tint border-tint-subtle;
|
||||
.openapi-panel,
|
||||
.openapi-codesample,
|
||||
.openapi-response-examples {
|
||||
@apply border rounded-md straight-corners:rounded-none bg-tint-subtle border-tint-subtle shadow-sm;
|
||||
}
|
||||
|
||||
.openapi-panel pre,
|
||||
.openapi-codesample pre,
|
||||
.openapi-response-examples pre {
|
||||
@apply bg-transparent border-none rounded-none shadow-none;
|
||||
}
|
||||
|
||||
.openapi-panel-heading {
|
||||
@@ -512,12 +496,11 @@
|
||||
|
||||
.openapi-panel-body {
|
||||
@apply relative;
|
||||
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
|
||||
}
|
||||
|
||||
.openapi-panel-footer,
|
||||
.openapi-codesample-footer {
|
||||
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint;
|
||||
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint empty:hidden;
|
||||
}
|
||||
|
||||
.openapi-panel-footer .openapi-markdown {
|
||||
@@ -525,10 +508,6 @@
|
||||
}
|
||||
|
||||
/* Example */
|
||||
.openapi-response-examples {
|
||||
@apply border rounded-md straight-corners:rounded-none bg-tint border-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-response-examples-header {
|
||||
@apply flex flex-row items-center p-2.5;
|
||||
}
|
||||
@@ -550,7 +529,6 @@
|
||||
.openapi-response-examples-panel,
|
||||
.openapi-codesample-panel {
|
||||
@apply flex-1 text-sm relative focus-visible:outline-none;
|
||||
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
|
||||
}
|
||||
|
||||
.openapi-example-empty {
|
||||
@@ -702,29 +680,33 @@ body:has(.openapi-select-popover) {
|
||||
|
||||
/* Disclosure group */
|
||||
.openapi-disclosure-group {
|
||||
@apply border-tint-subtle border-b border-x overflow-auto last:rounded-b-md straight-corners:last:rounded-none first:rounded-t-md straight-corners:first:rounded-none first:border-t relative;
|
||||
@apply border-tint-subtle transition-all border-b border-x overflow-auto last:rounded-b-md straight-corners:last:rounded-none first:rounded-t-md straight-corners:first:rounded-none first:border-t relative;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-header {
|
||||
@apply flex flex-row items-baseline justify-between gap-3 relative;
|
||||
.openapi-disclosure-group:has(.openapi-disclosure-group-trigger:hover) {
|
||||
@apply bg-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group:has(.openapi-disclosure-group-trigger:hover):has(.openapi-select:hover) {
|
||||
@apply !bg-transparent;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger {
|
||||
@apply flex items-baseline transition-all hover:bg-tint-subtle relative flex-1 gap-2.5 p-3 truncate -outline-offset-1;
|
||||
@apply flex w-full cursor-pointer items-baseline gap-3 transition-all relative flex-1 p-3 -outline-offset-1;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger:disabled {
|
||||
.openapi-disclosure-group-label {
|
||||
@apply flex flex-wrap items-baseline gap-x-3 gap-y-1 flex-1 truncate;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger[aria-disabled="true"] {
|
||||
@apply cursor-default hover:bg-inherit;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger:disabled .openapi-disclosure-group-icon {
|
||||
.openapi-disclosure-group-trigger[aria-disabled="true"] .openapi-disclosure-group-icon {
|
||||
@apply invisible;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger[aria-expanded="true"] .openapi-response-description {
|
||||
@apply whitespace-normal;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-icon > svg {
|
||||
@apply size-3 text-tint-subtle transition-all duration-300;
|
||||
}
|
||||
@@ -734,29 +716,20 @@ body:has(.openapi-select-popover) {
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-panel {
|
||||
@apply p-3 pt-1 transition-all;
|
||||
@apply px-3 transition-all;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-trigger[aria-expanded="true"] > .openapi-disclosure-group-icon > svg {
|
||||
@apply rotate-90;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group:hover .openapi-disclosure-group-mediatype,
|
||||
.openapi-disclosure-group-mediatype:has(> .openapi-select[data-open="true"]) {
|
||||
@apply opacity-11 visible flex;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-mediatype {
|
||||
@apply opacity-0 invisible text-xs transition-opacity duration-300 shrink-0 absolute right-2.5 top-2.5;
|
||||
}
|
||||
|
||||
.openapi-disclosure-group-mediatype > span {
|
||||
@apply px-1 bg-tint-6 text-tint-12 rounded-full straight-corners:rounded-md;
|
||||
.openapi-disclosure-group-mediatype:not(:has(.openapi-select)) {
|
||||
@apply text-[0.625rem] font-mono shrink-0 grow-0 text-tint-subtle contrast-more:text-tint;
|
||||
}
|
||||
|
||||
/* Disclosure */
|
||||
.openapi-schemas-disclosure > .openapi-disclosure-trigger {
|
||||
@apply flex items-center font-mono !w-full transition-all text-tint-strong !text-sm hover:bg-tint-subtle relative flex-1 gap-2.5 p-3 truncate -outline-offset-1;
|
||||
@apply flex items-center font-mono transition-all text-tint-strong !text-sm hover:bg-tint-subtle relative flex-1 gap-2.5 p-3 truncate -outline-offset-1;
|
||||
}
|
||||
|
||||
.openapi-schemas-disclosure > .openapi-disclosure-trigger,
|
||||
@@ -764,51 +737,97 @@ body:has(.openapi-select-popover) {
|
||||
@apply straight-corners:!rounded-none;
|
||||
}
|
||||
|
||||
.openapi-disclosure-panel {
|
||||
@apply ml-1.5 pl-3 border-l border-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-schema .openapi-schema-properties .openapi-schema {
|
||||
@apply animate-fadeIn [animation-fill-mode:both];
|
||||
}
|
||||
|
||||
.openapi-schemas-disclosure > .openapi-disclosure-trigger[aria-expanded="true"] > svg {
|
||||
@apply rotate-90;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger {
|
||||
@apply transition-all truncate duration-300 max-w-full hover:text-tint-strong rounded-2xl straight-corners:rounded border border-tint-subtle px-2.5 py-1 text-[0.813rem] text-tint flex flex-row items-center gap-1.5 -outline-offset-1;
|
||||
@apply flex flex-row justify-between flex-wrap relative items-start gap-2 text-left -mx-3 px-3 -my-2.5 py-2.5 pr-10;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger span {
|
||||
@apply truncate;
|
||||
.openapi-disclosure {
|
||||
@apply -mx-3 px-3 py-2.5 transition-all flex flex-col ring-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-disclosure svg {
|
||||
@apply size-3 shrink-0 transition-transform duration-300;
|
||||
.openapi-disclosure:not(
|
||||
.openapi-disclosure-group .openapi-disclosure,
|
||||
.openapi-schema-alternatives .openapi-disclosure,
|
||||
.openapi-schemas-disclosure .openapi-schema.openapi-disclosure
|
||||
) {
|
||||
@apply rounded-xl;
|
||||
}
|
||||
|
||||
.openapi-disclosure .openapi-schemas-disclosure .openapi-schema.openapi-disclosure {
|
||||
@apply !rounded-none;
|
||||
}
|
||||
|
||||
.openapi-disclosure:has(> .openapi-disclosure-trigger:hover) {
|
||||
@apply bg-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-disclosure:has(> .openapi-disclosure-trigger:hover),
|
||||
.openapi-disclosure[data-expanded="true"] {
|
||||
@apply ring-1 shadow-sm;
|
||||
}
|
||||
|
||||
.openapi-disclosure[data-expanded="true"]:not(:first-child) {
|
||||
@apply mt-2;
|
||||
}
|
||||
.openapi-disclosure[data-expanded="true"]:not(:last-child) {
|
||||
@apply mb-2;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger-label {
|
||||
@apply absolute right-3 px-2 h-5 justify-end shrink-0 ring-tint-subtle truncate text-tint duration-300 transition-all rounded straight-corners:rounded-none flex flex-row gap-1 items-center text-xs;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger-label span {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger-label svg {
|
||||
@apply size-3 shrink-0 transition-transform duration-300 text-tint-subtle;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger:hover > .openapi-disclosure-trigger-label,
|
||||
.openapi-disclosure-trigger[aria-expanded="true"] > .openapi-disclosure-trigger-label {
|
||||
@apply shadow ring-1 bg-tint-base;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger:hover > .openapi-disclosure-trigger-label span,
|
||||
.openapi-disclosure-trigger[aria-expanded="true"] > .openapi-disclosure-trigger-label span {
|
||||
@apply block animate-fadeIn;
|
||||
}
|
||||
|
||||
@media (hover: none) {
|
||||
/* Make button label always visible on non-hover devices like phones */
|
||||
.openapi-disclosure-trigger-label {
|
||||
@apply relative ring-1 bg-tint-base right-0;
|
||||
}
|
||||
.openapi-disclosure-trigger-label span {
|
||||
@apply block;
|
||||
}
|
||||
.openapi-disclosure-trigger {
|
||||
@apply pr-3;
|
||||
}
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger[aria-expanded="true"] svg {
|
||||
@apply rotate-45;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger[aria-expanded="true"] {
|
||||
@apply w-full rounded-lg border-b rounded-b-none straight-corners:rounded-b-none;
|
||||
}
|
||||
|
||||
.openapi-disclosure-trigger[aria-expanded="false"] {
|
||||
@apply w-auto;
|
||||
}
|
||||
|
||||
.openapi-disclosure-panel[aria-hidden="false"] {
|
||||
@apply border-b border-x border-tint-subtle rounded-b-lg straight-corners:rounded-b;
|
||||
}
|
||||
|
||||
.openapi-disclosure-panel .openapi-schema {
|
||||
@apply p-2.5;
|
||||
}
|
||||
|
||||
.openapi-disclosure .openapi-schema-properties .openapi-schema:only-child,
|
||||
.openapi-disclosure .openapi-schema-properties .openapi-schema:only-child .openapi-schema-name {
|
||||
@apply !m-0;
|
||||
}
|
||||
|
||||
.openapi-disclosure .openapi-schema-properties .openapi-schema-enum {
|
||||
@apply pt-0 mt-0;
|
||||
}
|
||||
|
||||
.openapi-section-body.openapi-schema.openapi-schema-root {
|
||||
@apply space-y-2.5;
|
||||
}
|
||||
@@ -818,6 +837,16 @@ body:has(.openapi-select-popover) {
|
||||
@apply p-2.5;
|
||||
}
|
||||
|
||||
.openapi-schema-alternatives {
|
||||
@apply ml-1.5 pl-3 border-l border-tint-subtle;
|
||||
}
|
||||
.openapi-schema-alternative {
|
||||
@apply relative;
|
||||
}
|
||||
.openapi-schema-alternative-separator {
|
||||
@apply p-0.5 tracking-wide leading-none uppercase text-[0.625rem] text-tint-subtle whitespace-nowrap absolute -left-3 -bottom-2.5 -translate-x-1/2 z-10 bg-tint-base border-y border-tint-subtle -rotate-6;
|
||||
}
|
||||
|
||||
.openapi-tooltip {
|
||||
@apply flex items-center gap-1 bg-tint-base border border-tint-subtle text-tint-strong rounded-md straight-corners:rounded-none font-medium px-1.5 py-0.5 shadow-sm text-[13px];
|
||||
}
|
||||
@@ -864,11 +893,11 @@ body:has(.openapi-select-popover) {
|
||||
}
|
||||
|
||||
@keyframes popover-leave {
|
||||
0% {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
100% {
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(4px) scale(0.95);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { DocumentBlockReusableContent } from '@gitbook/api';
|
||||
|
||||
import { resolveContentRef } from '@/lib/references';
|
||||
|
||||
import type { GitBookSpaceContext } from '@v2/lib/context';
|
||||
import { getDataOrNull } from '@v2/lib/data';
|
||||
import type { BlockProps } from './Block';
|
||||
import { UnwrappedBlocks } from './Blocks';
|
||||
@@ -13,15 +14,28 @@ export async function ReusableContent(props: BlockProps<DocumentBlockReusableCon
|
||||
throw new Error('Expected a content context to render a reusable content block');
|
||||
}
|
||||
|
||||
const resolved = await resolveContentRef(block.data.ref, context.contentContext);
|
||||
if (!resolved?.reusableContent?.document) {
|
||||
const dataFetcher = block.meta?.token
|
||||
? context.contentContext.dataFetcher.withToken({ apiToken: block.meta.token })
|
||||
: context.contentContext.dataFetcher;
|
||||
|
||||
const resolved = await resolveContentRef(block.data.ref, {
|
||||
...context.contentContext,
|
||||
dataFetcher,
|
||||
});
|
||||
|
||||
if (!resolved?.reusableContent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const reusableContent = resolved.reusableContent.revisionReusableContent;
|
||||
if (!reusableContent.document) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const document = await getDataOrNull(
|
||||
context.contentContext.dataFetcher.getDocument({
|
||||
spaceId: context.contentContext.space.id,
|
||||
documentId: resolved.reusableContent.document,
|
||||
dataFetcher.getDocument({
|
||||
spaceId: resolved.reusableContent.space.id,
|
||||
documentId: reusableContent.document,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -29,12 +43,34 @@ export async function ReusableContent(props: BlockProps<DocumentBlockReusableCon
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a new context for reusable content block, including
|
||||
// the data fetcher with the token from the block meta and the correct
|
||||
// space and revision pointers.
|
||||
const reusableContentContext: GitBookSpaceContext =
|
||||
context.contentContext.space.id === resolved.reusableContent.space.id
|
||||
? context.contentContext
|
||||
: {
|
||||
...context.contentContext,
|
||||
dataFetcher,
|
||||
space: resolved.reusableContent.space,
|
||||
revisionId: resolved.reusableContent.revision,
|
||||
// When the reusable content is in a different space, we don't resolve relative links to pages
|
||||
// as this space might not be part of the current site.
|
||||
// In the future, we might expand the logic to look up the space from the list of all spaces in the site
|
||||
// and adapt the relative links to point to the correct variant.
|
||||
pages: [],
|
||||
shareKey: undefined,
|
||||
};
|
||||
|
||||
return (
|
||||
<UnwrappedBlocks
|
||||
nodes={document.nodes}
|
||||
document={document}
|
||||
ancestorBlocks={[...ancestorBlocks, block]}
|
||||
context={context}
|
||||
context={{
|
||||
...context,
|
||||
contentContext: reusableContentContext,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
|
||||
return <Tag className={tcls(['w-full', verticalAlignment])}>{''}</Tag>;
|
||||
}
|
||||
|
||||
const alignment = getColumnAlignment(definition);
|
||||
const horizontalAlignment = `[&_*]:${getColumnAlignment(definition)} ${getColumnAlignment(definition)}`;
|
||||
|
||||
return (
|
||||
<Blocks
|
||||
@@ -130,8 +130,7 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
|
||||
'lg:space-y-3',
|
||||
'leading-normal',
|
||||
verticalAlignment,
|
||||
alignment === 'right' ? 'text-right' : null,
|
||||
alignment === 'center' ? 'text-center' : null,
|
||||
horizontalAlignment,
|
||||
]}
|
||||
context={context}
|
||||
blockStyle={['w-full', 'max-w-[unset]']}
|
||||
|
||||
@@ -42,32 +42,28 @@ export function ViewGrid(props: TableViewProps<DocumentTableViewGrid>) {
|
||||
)}
|
||||
>
|
||||
<div role="row" className={tcls('flex', 'w-full')}>
|
||||
{view.columns.map((column) => {
|
||||
const alignment = getColumnAlignment(block.data.definition[column]);
|
||||
return (
|
||||
<div
|
||||
key={column}
|
||||
role="columnheader"
|
||||
className={tcls(
|
||||
styles.columnHeader,
|
||||
alignment === 'right' ? 'text-right' : null,
|
||||
alignment === 'center' ? 'text-center' : null
|
||||
)}
|
||||
style={{
|
||||
width: getColumnWidth({
|
||||
column,
|
||||
columnWidths,
|
||||
autoSizedColumns,
|
||||
fixedColumns,
|
||||
}),
|
||||
minWidth: columnWidths?.[column] || '100px',
|
||||
}}
|
||||
title={block.data.definition[column].title}
|
||||
>
|
||||
{block.data.definition[column].title}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{view.columns.map((column) => (
|
||||
<div
|
||||
key={column}
|
||||
role="columnheader"
|
||||
className={tcls(
|
||||
styles.columnHeader,
|
||||
getColumnAlignment(block.data.definition[column])
|
||||
)}
|
||||
style={{
|
||||
width: getColumnWidth({
|
||||
column,
|
||||
columnWidths,
|
||||
autoSizedColumns,
|
||||
fixedColumns,
|
||||
}),
|
||||
minWidth: columnWidths?.[column] || '100px',
|
||||
}}
|
||||
title={block.data.definition[column].title}
|
||||
>
|
||||
{block.data.definition[column].title}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
}
|
||||
|
||||
.columnHeader {
|
||||
@apply text-sm font-medium py-2 px-4 text-tint-strong;
|
||||
@apply text-sm font-medium py-2 px-3 text-tint-strong;
|
||||
}
|
||||
|
||||
.row {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ContentRef, DocumentTableDefinition, DocumentTableRecord } from '@gitbook/api';
|
||||
import assertNever from 'assert-never';
|
||||
|
||||
/**
|
||||
* Get the value for a column in a record.
|
||||
@@ -14,11 +15,24 @@ export function getRecordValue<T extends number | string | boolean | string[] |
|
||||
/**
|
||||
* Get the text alignment for a column.
|
||||
*/
|
||||
export function getColumnAlignment(column: DocumentTableDefinition): 'left' | 'right' | 'center' {
|
||||
export function getColumnAlignment(column: DocumentTableDefinition) {
|
||||
const defaultAlignment = 'text-left';
|
||||
|
||||
if (column.type === 'text') {
|
||||
return column.textAlignment ?? 'left';
|
||||
switch (column.textAlignment) {
|
||||
case undefined:
|
||||
case 'left':
|
||||
return defaultAlignment;
|
||||
case 'center':
|
||||
return 'text-center';
|
||||
case 'right':
|
||||
return 'text-right';
|
||||
default:
|
||||
assertNever(column.textAlignment);
|
||||
}
|
||||
}
|
||||
return 'left';
|
||||
|
||||
return defaultAlignment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import { type DetailedHTMLProps, type HTMLAttributes, useId } from 'react';
|
||||
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
|
||||
import { Link, type LinkInsightsProps } from '../primitives';
|
||||
|
||||
export type DropdownButtonProps<E extends HTMLElement = HTMLElement> = Omit<
|
||||
Partial<DetailedHTMLProps<HTMLAttributes<E>, E>>,
|
||||
'ref'
|
||||
>;
|
||||
|
||||
/**
|
||||
* Button with a dropdown.
|
||||
*/
|
||||
export function Dropdown<E extends HTMLElement>(props: {
|
||||
/** Content of the button */
|
||||
button: (buttonProps: DropdownButtonProps<E>) => React.ReactNode;
|
||||
/** Content of the dropdown */
|
||||
children: React.ReactNode;
|
||||
/** Custom styles */
|
||||
className?: ClassValue;
|
||||
}) {
|
||||
const { button, children, className } = props;
|
||||
const dropdownId = useId();
|
||||
|
||||
return (
|
||||
<div className={tcls('group/dropdown', 'relative flex min-w-0 shrink')}>
|
||||
{button({
|
||||
id: dropdownId,
|
||||
tabIndex: 0,
|
||||
'aria-expanded': true,
|
||||
'aria-haspopup': true,
|
||||
})}
|
||||
<div
|
||||
tabIndex={-1}
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
aria-labelledby={dropdownId}
|
||||
className={tcls(
|
||||
'w-52',
|
||||
'max-h-80',
|
||||
'flex',
|
||||
'absolute',
|
||||
'top-full',
|
||||
'left-0',
|
||||
'origin-top-left',
|
||||
'invisible',
|
||||
'transition-opacity',
|
||||
'duration-1000',
|
||||
'group-hover/dropdown:visible',
|
||||
'group-focus-within/dropdown:visible',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="fixed z-50 w-52">
|
||||
<div
|
||||
className={tcls(
|
||||
'mt-2',
|
||||
'w-full',
|
||||
'max-h-80',
|
||||
'bg-tint-base',
|
||||
'rounded-lg',
|
||||
'straight-corners:rounded-sm',
|
||||
'p-2',
|
||||
'shadow-1xs',
|
||||
'overflow-auto',
|
||||
'ring-1',
|
||||
'ring-tint-subtle',
|
||||
'focus:outline-none'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animated chevron to display in the dropdown button.
|
||||
*/
|
||||
export function DropdownChevron() {
|
||||
return (
|
||||
<Icon
|
||||
icon="chevron-down"
|
||||
className={tcls(
|
||||
'shrink-0',
|
||||
'opacity-6',
|
||||
'size-3',
|
||||
'ms-1',
|
||||
'transition-all',
|
||||
'group-hover/dropdown:opacity-11',
|
||||
'group-focus-within/dropdown:rotate-180'
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Group of menu items in a dropdown.
|
||||
*/
|
||||
export function DropdownMenu(props: { children: React.ReactNode }) {
|
||||
const { children } = props;
|
||||
|
||||
return <div className={tcls('flex', 'flex-col', 'gap-1')}>{children}</div>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu item in a dropdown.
|
||||
*/
|
||||
export function DropdownMenuItem(
|
||||
props: {
|
||||
href: string | null;
|
||||
active?: boolean;
|
||||
className?: ClassValue;
|
||||
children: React.ReactNode;
|
||||
} & LinkInsightsProps
|
||||
) {
|
||||
const { children, active = false, href, className, insights } = props;
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
insights={insights}
|
||||
className={tcls(
|
||||
'rounded straight-corners:rounded-sm px-3 py-1 text-sm',
|
||||
active ? 'bg-primary text-primary-strong' : null,
|
||||
'hover:bg-tint-hover',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={tcls('px-3 py-1 font-medium text-tint text-xs', className)}>{children}</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
'use client';
|
||||
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
|
||||
import * as RadixDropdownMenu from '@radix-ui/react-dropdown-menu';
|
||||
|
||||
import { Link, type LinkInsightsProps } from '../primitives';
|
||||
|
||||
export type DropdownButtonProps<E extends HTMLElement = HTMLElement> = Omit<
|
||||
Partial<DetailedHTMLProps<HTMLAttributes<E>, E>>,
|
||||
'ref'
|
||||
>;
|
||||
|
||||
/**
|
||||
* Button with a dropdown.
|
||||
*/
|
||||
export function DropdownMenu(props: {
|
||||
/** Content of the button */
|
||||
button: React.ReactNode;
|
||||
/** Content of the dropdown */
|
||||
children: React.ReactNode;
|
||||
/** Custom styles */
|
||||
className?: ClassValue;
|
||||
/** Open the dropdown on hover */
|
||||
openOnHover?: boolean;
|
||||
}) {
|
||||
const { button, children, className, openOnHover = false } = props;
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const [clicked, setClicked] = useState(false);
|
||||
|
||||
return (
|
||||
<RadixDropdownMenu.Root
|
||||
modal={false}
|
||||
open={openOnHover ? clicked || hovered : clicked}
|
||||
onOpenChange={setClicked}
|
||||
>
|
||||
<RadixDropdownMenu.Trigger
|
||||
asChild
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
onClick={() => (openOnHover ? setClicked(!clicked) : null)}
|
||||
className="group/dropdown"
|
||||
>
|
||||
{button}
|
||||
</RadixDropdownMenu.Trigger>
|
||||
|
||||
<RadixDropdownMenu.Portal>
|
||||
<RadixDropdownMenu.Content
|
||||
data-testid="dropdown-menu"
|
||||
hideWhenDetached
|
||||
collisionPadding={8}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
align="start"
|
||||
className="z-40 animate-present pt-2"
|
||||
>
|
||||
<div
|
||||
className={tcls(
|
||||
'flex max-h-80 min-w-40 max-w-[40vw] flex-col gap-1 overflow-auto rounded-lg straight-corners:rounded-sm bg-tint-base p-2 shadow-lg ring-1 ring-tint-subtle sm:min-w-52 sm:max-w-80',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</RadixDropdownMenu.Content>
|
||||
</RadixDropdownMenu.Portal>
|
||||
</RadixDropdownMenu.Root>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animated chevron to display in the dropdown button.
|
||||
*/
|
||||
export function DropdownChevron() {
|
||||
return (
|
||||
<Icon
|
||||
icon="chevron-down"
|
||||
className={tcls(
|
||||
'shrink-0',
|
||||
'opacity-6',
|
||||
'size-3',
|
||||
'ms-1',
|
||||
'transition-all',
|
||||
'group-hover/dropdown:opacity-11',
|
||||
'group-data-[state=open]/dropdown:opacity-11',
|
||||
'group-data-[state=open]/dropdown:rotate-180'
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Button with a chevron for use in dropdowns.
|
||||
*/
|
||||
export function DropdownButton(props: {
|
||||
children: React.ReactNode;
|
||||
className?: ClassValue;
|
||||
}) {
|
||||
const { children, className } = props;
|
||||
|
||||
return (
|
||||
<div className={tcls('group/dropdown', 'flex', 'items-center', className)}>
|
||||
{children}
|
||||
<DropdownChevron />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu item in a dropdown.
|
||||
*/
|
||||
export function DropdownMenuItem(
|
||||
props: {
|
||||
href: string | null;
|
||||
active?: boolean;
|
||||
className?: ClassValue;
|
||||
children: React.ReactNode;
|
||||
} & LinkInsightsProps
|
||||
) {
|
||||
const { children, active = false, href, className, insights } = props;
|
||||
|
||||
const itemClassName = tcls(
|
||||
'rounded straight-corners:rounded-sm px-3 py-1 text-sm',
|
||||
active
|
||||
? 'bg-primary text-primary-strong data-[highlighted]:bg-primary-hover'
|
||||
: 'data-[highlighted]:bg-tint-hover',
|
||||
'focus:outline-none',
|
||||
className
|
||||
);
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<RadixDropdownMenu.Item asChild>
|
||||
<Link href={href} insights={insights} className={itemClassName}>
|
||||
{children}
|
||||
</Link>
|
||||
</RadixDropdownMenu.Item>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<RadixDropdownMenu.Item
|
||||
className={tcls('px-3 py-1 font-medium text-tint text-xs', className)}
|
||||
>
|
||||
{children}
|
||||
</RadixDropdownMenu.Item>
|
||||
);
|
||||
}
|
||||
|
||||
export function DropdownSubMenu(props: { children: React.ReactNode; label: React.ReactNode }) {
|
||||
const { children, label } = props;
|
||||
|
||||
return (
|
||||
<RadixDropdownMenu.Sub>
|
||||
<RadixDropdownMenu.SubTrigger className="flex cursor-pointer items-center justify-between rounded straight-corners:rounded-sm px-3 py-1 text-sm focus:outline-none data-[highlighted]:bg-tint-hover">
|
||||
{label}
|
||||
<Icon icon="chevron-right" className="size-3 shrink-0 opacity-6" />
|
||||
</RadixDropdownMenu.SubTrigger>
|
||||
<RadixDropdownMenu.Portal>
|
||||
<RadixDropdownMenu.SubContent
|
||||
hideWhenDetached
|
||||
collisionPadding={8}
|
||||
className="z-40 animate-present"
|
||||
>
|
||||
<div className="flex max-h-80 min-w-40 max-w-[40vw] flex-col gap-1 overflow-auto rounded-lg straight-corners:rounded-sm bg-tint-base p-2 shadow-lg ring-1 ring-tint-subtle sm:min-w-52 sm:max-w-80">
|
||||
{children}
|
||||
</div>
|
||||
</RadixDropdownMenu.SubContent>
|
||||
</RadixDropdownMenu.Portal>
|
||||
</RadixDropdownMenu.Sub>
|
||||
);
|
||||
}
|
||||
@@ -106,12 +106,16 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
|
||||
'lg:max-w-lg',
|
||||
'lg:ml-[max(calc((100%-18rem-48rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - margin (3rem)
|
||||
'xl:ml-[max(calc((100%-18rem-48rem-14rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - outline (14rem) - margin (3rem)
|
||||
'adaptive-pane:xl:ml-[max(calc((100%-18rem-48rem-18rem-3rem)/2),1.5rem)]',
|
||||
'page-no-toc:lg:ml-[max(calc((100%-18rem-48rem-18rem-3rem)/2),0rem)]',
|
||||
'page-full-width:lg:ml-[max(calc((100%-18rem-103rem-3rem)/2),1.5rem)]',
|
||||
'page-full-width:2xl:ml-[max(calc((100%-18rem-96rem-14rem+3rem)/2),1.5rem)]',
|
||||
'[body.adaptive-pane:has(.page-full-width)_&]:2xl:ml-[max(calc((100%-18rem-96rem-18rem+3rem)/2),1.5rem)]',
|
||||
'md:mr-auto',
|
||||
'order-last',
|
||||
'md:order-[unset]',
|
||||
'transition-[margin-left]',
|
||||
'duration-300',
|
||||
]
|
||||
: ['order-last']
|
||||
)}
|
||||
|
||||
@@ -13,12 +13,11 @@ import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { Button, Link } from '../primitives';
|
||||
import {
|
||||
Dropdown,
|
||||
type DropdownButtonProps,
|
||||
DropdownChevron,
|
||||
DropdownMenu,
|
||||
DropdownMenuItem,
|
||||
} from './Dropdown';
|
||||
} from './DropdownMenu';
|
||||
|
||||
export async function HeaderLink(props: {
|
||||
context: GitBookSiteContext;
|
||||
@@ -33,21 +32,13 @@ export async function HeaderLink(props: {
|
||||
|
||||
if (link.links && link.links.length > 0) {
|
||||
return (
|
||||
<Dropdown
|
||||
<DropdownMenu
|
||||
className={`shrink ${customization.styling.search === 'prominent' ? 'right-0 left-auto' : null}`}
|
||||
button={(buttonProps) => {
|
||||
if (!target || !link.to) {
|
||||
return (
|
||||
<HeaderItemDropdown
|
||||
{...buttonProps}
|
||||
headerPreset={headerPreset}
|
||||
title={link.title}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
button={
|
||||
!target || !link.to ? (
|
||||
<HeaderItemDropdown headerPreset={headerPreset} title={link.title} />
|
||||
) : (
|
||||
<HeaderLinkNavItem
|
||||
{...buttonProps}
|
||||
linkTarget={link.to}
|
||||
linkStyle={linkStyle}
|
||||
headerPreset={headerPreset}
|
||||
@@ -55,15 +46,14 @@ export async function HeaderLink(props: {
|
||||
isDropdown
|
||||
href={target?.href}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
)
|
||||
}
|
||||
openOnHover={true}
|
||||
>
|
||||
<DropdownMenu>
|
||||
{link.links.map((subLink, index) => (
|
||||
<SubHeaderLink key={index} {...props} link={subLink} />
|
||||
))}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
{link.links.map((subLink, index) => (
|
||||
<SubHeaderLink key={index} {...props} link={subLink} />
|
||||
))}
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,10 +147,12 @@ function getHeaderLinkClassName(_props: { headerPreset: CustomizationHeaderPrese
|
||||
|
||||
'text-tint',
|
||||
'links-default:hover:text-primary',
|
||||
'links-default:data-[state=open]:text-primary',
|
||||
'links-default:tint:hover:text-tint-strong',
|
||||
|
||||
'links-default:tint:data-[state=open]:text-tint-strong',
|
||||
'underline-offset-2',
|
||||
'links-accent:hover:underline',
|
||||
'links-accent:data-[state=open]:underline',
|
||||
'links-accent:underline-offset-4',
|
||||
'links-accent:decoration-primary-subtle',
|
||||
'links-accent:decoration-[3px]',
|
||||
|
||||
@@ -10,7 +10,7 @@ import type React from 'react';
|
||||
import { resolveContentRef } from '@/lib/references';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { Dropdown, DropdownChevron, DropdownMenu, DropdownMenuItem } from './Dropdown';
|
||||
import { DropdownChevron, DropdownMenu, DropdownMenuItem, DropdownSubMenu } from './DropdownMenu';
|
||||
import styles from './headerLinks.module.css';
|
||||
|
||||
/**
|
||||
@@ -23,7 +23,7 @@ export function HeaderLinkMore(props: {
|
||||
}) {
|
||||
const { label, links, context } = props;
|
||||
|
||||
const renderButton = () => (
|
||||
const renderButton = (
|
||||
<button
|
||||
type="button"
|
||||
className={tcls(
|
||||
@@ -45,19 +45,18 @@ export function HeaderLinkMore(props: {
|
||||
|
||||
return (
|
||||
<div className={`${styles.linkEllipsis} z-20 items-center`}>
|
||||
<Dropdown
|
||||
<DropdownMenu
|
||||
button={renderButton}
|
||||
openOnHover={true}
|
||||
className={tcls(
|
||||
'max-md:right-0 max-md:left-auto',
|
||||
context.customization.styling.search === 'prominent' && 'right-0 left-auto'
|
||||
)}
|
||||
>
|
||||
<DropdownMenu>
|
||||
{links.map((link, index) => (
|
||||
<MoreMenuLink key={index} link={link} context={context} />
|
||||
))}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
{links.map((link, index) => (
|
||||
<MoreMenuLink key={index} link={link} context={context} />
|
||||
))}
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -70,32 +69,28 @@ async function MoreMenuLink(props: {
|
||||
|
||||
const target = link.to ? await resolveContentRef(link.to, context) : null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{'links' in link && link.links.length > 0 && (
|
||||
<hr className="-mx-2 my-1 border-tint border-t first:hidden" />
|
||||
)}
|
||||
<DropdownMenuItem
|
||||
href={target?.href ?? null}
|
||||
insights={
|
||||
link.to
|
||||
? {
|
||||
type: 'link_click',
|
||||
link: {
|
||||
target: link.to,
|
||||
position: SiteInsightsLinkPosition.Header,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{link.title}
|
||||
</DropdownMenuItem>
|
||||
{'links' in link
|
||||
? link.links.map((subLink, index) => (
|
||||
<MoreMenuLink key={index} {...props} link={subLink} />
|
||||
))
|
||||
: null}
|
||||
</>
|
||||
return 'links' in link && link.links.length > 0 ? (
|
||||
<DropdownSubMenu label={link.title}>
|
||||
{link.links.map((subLink, index) => {
|
||||
return <MoreMenuLink key={index} {...props} link={subLink} />;
|
||||
})}
|
||||
</DropdownSubMenu>
|
||||
) : (
|
||||
<DropdownMenuItem
|
||||
href={target?.href ?? null}
|
||||
insights={
|
||||
link.to
|
||||
? {
|
||||
type: 'link_click',
|
||||
link: {
|
||||
target: link.to,
|
||||
position: SiteInsightsLinkPosition.Header,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{link.title}
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { SiteSpace } from '@gitbook/api';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import { Dropdown, DropdownChevron, DropdownMenu } from './Dropdown';
|
||||
import { DropdownChevron, DropdownMenu } from './DropdownMenu';
|
||||
import { SpacesDropdownMenuItem } from './SpacesDropdownMenuItem';
|
||||
|
||||
export function SpacesDropdown(props: {
|
||||
@@ -16,14 +16,13 @@ export function SpacesDropdown(props: {
|
||||
const { linker } = context;
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
<DropdownMenu
|
||||
className={tcls(
|
||||
'group-hover/dropdown:invisible', // Prevent hover from opening the dropdown, as it's annoying in this context
|
||||
'group-focus-within/dropdown:group-hover/dropdown:visible' // When the dropdown is already open, it should remain visible when hovered
|
||||
)}
|
||||
button={(buttonProps) => (
|
||||
button={
|
||||
<div
|
||||
{...buttonProps}
|
||||
data-testid="space-dropdown-button"
|
||||
className={tcls(
|
||||
'flex',
|
||||
@@ -40,25 +39,24 @@ export function SpacesDropdown(props: {
|
||||
'straight-corners:rounded-none',
|
||||
|
||||
'bg-tint-base',
|
||||
'group-hover/dropdown:bg-tint-base',
|
||||
'group-focus-within/dropdown:bg-tint-base',
|
||||
|
||||
'text-sm',
|
||||
'text-tint',
|
||||
'group-hover/dropdown:text-tint-strong',
|
||||
'group-focus-within/dropdown:text-tint-strong',
|
||||
'hover:text-tint-strong',
|
||||
'data-[state=open]:text-tint-strong',
|
||||
|
||||
'ring-1',
|
||||
'ring-tint-subtle',
|
||||
'group-hover/dropdown:ring-tint-hover',
|
||||
'group-focus-within/dropdown:ring-tint-hover',
|
||||
'hover:ring-tint-hover',
|
||||
'data-[state=open]:ring-tint-hover',
|
||||
|
||||
'contrast-more:bg-tint-base',
|
||||
'contrast-more:ring-1',
|
||||
'contrast-more:group-hover/dropdown:ring-2',
|
||||
'contrast-more:hover:ring-2',
|
||||
'contrast-more:data-[state=open]:ring-2',
|
||||
'contrast-more:ring-tint',
|
||||
'contrast-more:group-hover/dropdown:ring-tint-hover',
|
||||
'contrast-more:group-focus-within/dropdown:ring-tint-hover',
|
||||
'contrast-more:hover:ring-tint-hover',
|
||||
'contrast-more:data-[state=open]:ring-tint-hover',
|
||||
|
||||
className
|
||||
)}
|
||||
@@ -66,23 +64,21 @@ export function SpacesDropdown(props: {
|
||||
<span className={tcls('line-clamp-1', 'grow')}>{siteSpace.title}</span>
|
||||
<DropdownChevron />
|
||||
</div>
|
||||
)}
|
||||
}
|
||||
>
|
||||
<DropdownMenu>
|
||||
{siteSpaces.map((otherSiteSpace, index) => (
|
||||
<SpacesDropdownMenuItem
|
||||
key={`${otherSiteSpace.id}-${index}`}
|
||||
variantSpace={{
|
||||
id: otherSiteSpace.id,
|
||||
title: otherSiteSpace.title,
|
||||
url: otherSiteSpace.urls.published
|
||||
? linker.toLinkForContent(otherSiteSpace.urls.published)
|
||||
: otherSiteSpace.space.urls.app,
|
||||
}}
|
||||
active={otherSiteSpace.id === siteSpace.id}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
{siteSpaces.map((otherSiteSpace, index) => (
|
||||
<SpacesDropdownMenuItem
|
||||
key={`${otherSiteSpace.id}-${index}`}
|
||||
variantSpace={{
|
||||
id: otherSiteSpace.id,
|
||||
title: otherSiteSpace.title,
|
||||
url: otherSiteSpace.urls.published
|
||||
? linker.toLinkForContent(otherSiteSpace.urls.published)
|
||||
: otherSiteSpace.space.urls.app,
|
||||
}}
|
||||
active={otherSiteSpace.id === siteSpace.id}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Space } from '@gitbook/api';
|
||||
|
||||
import { joinPath } from '@/lib/paths';
|
||||
import { useCurrentPagePath } from '../hooks';
|
||||
import { DropdownMenuItem } from './Dropdown';
|
||||
import { DropdownMenuItem } from './DropdownMenu';
|
||||
|
||||
function useVariantSpaceHref(variantSpaceUrl: string) {
|
||||
const currentPathname = useCurrentPagePath();
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { getSpaceLanguage, t } from '@/intl/server';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import type { RevisionPageDocument, Space } from '@gitbook/api';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import React from 'react';
|
||||
import urlJoin from 'url-join';
|
||||
import { getPDFURLSearchParams } from '../PDF';
|
||||
import { PageFeedbackForm } from '../PageFeedback';
|
||||
|
||||
export function PageActions(props: {
|
||||
page: RevisionPageDocument;
|
||||
context: GitBookSiteContext;
|
||||
withPageFeedback: boolean;
|
||||
}) {
|
||||
const { page, withPageFeedback, context } = props;
|
||||
const { customization, space } = context;
|
||||
const language = getSpaceLanguage(customization);
|
||||
|
||||
const pdfHref = context.linker.toPathInSpace(
|
||||
`~gitbook/pdf?${getPDFURLSearchParams({
|
||||
page: page.id,
|
||||
only: true,
|
||||
limit: 100,
|
||||
}).toString()}`
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-col',
|
||||
'gap-2',
|
||||
'sidebar-list-default:px-3',
|
||||
'page-api-block:xl:max-2xl:px-3',
|
||||
'empty:hidden'
|
||||
)}
|
||||
>
|
||||
{withPageFeedback ? (
|
||||
<React.Suspense fallback={null}>
|
||||
<PageFeedbackForm pageId={page.id} />
|
||||
</React.Suspense>
|
||||
) : null}
|
||||
{customization.git.showEditLink && space.gitSync?.url && page.git ? (
|
||||
<div>
|
||||
<a
|
||||
href={urlJoin(space.gitSync.url, page.git.path)}
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'text-sm',
|
||||
'hover:text-tint-strong',
|
||||
'links-accent:hover:underline',
|
||||
'links-accent:hover:underline-offset-4',
|
||||
'links-accent:hover:decoration-[3px]',
|
||||
'links-accent:hover:decoration-primary-subtle'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon={
|
||||
space.gitSync.installationProvider === 'gitlab'
|
||||
? 'gitlab'
|
||||
: 'github'
|
||||
}
|
||||
className={tcls('size-4', 'mr-1.5')}
|
||||
/>
|
||||
{t(language, 'edit_on_git', getGitSyncName(space))}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
{customization.pdf.enabled ? (
|
||||
<div>
|
||||
<a
|
||||
href={pdfHref}
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'text-sm',
|
||||
'hover:text-tint-strong',
|
||||
'links-accent:hover:underline',
|
||||
'links-accent:hover:underline-offset-4',
|
||||
'links-accent:hover:decoration-[3px]',
|
||||
'links-accent:hover:decoration-primary-subtle'
|
||||
)}
|
||||
>
|
||||
<Icon icon="file-pdf" className={tcls('size-4', 'mr-1.5')} />
|
||||
{t(language, 'pdf_download')}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getGitSyncName(space: Space): string {
|
||||
if (space.gitSync?.installationProvider === 'github') {
|
||||
return 'GitHub';
|
||||
}
|
||||
if (space.gitSync?.installationProvider === 'gitlab') {
|
||||
return 'GitLab';
|
||||
}
|
||||
|
||||
return 'Git';
|
||||
}
|
||||
@@ -3,22 +3,17 @@ import {
|
||||
type RevisionPageDocument,
|
||||
SiteAdsStatus,
|
||||
SiteInsightsAdPlacement,
|
||||
type Space,
|
||||
} from '@gitbook/api';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import React from 'react';
|
||||
import urlJoin from 'url-join';
|
||||
|
||||
import { getSpaceLanguage, t } from '@/intl/server';
|
||||
import { getDocumentSections } from '@/lib/document-sections';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { AdaptivePane } from '../Adaptive/AdaptivePane';
|
||||
import { Ad } from '../Ads';
|
||||
import { getPDFURLSearchParams } from '../PDF';
|
||||
import { PageFeedbackForm } from '../PageFeedback';
|
||||
import { ThemeToggler } from '../ThemeToggler';
|
||||
import { ScrollSectionsList } from './ScrollSectionsList';
|
||||
import { PageActions } from './PageActions';
|
||||
import { PageOutline } from './PageOutline';
|
||||
|
||||
/**
|
||||
* Aside listing the headings in the document.
|
||||
@@ -33,33 +28,34 @@ export function PageAside(props: {
|
||||
}) {
|
||||
const { page, document, withPageFeedback, context } = props;
|
||||
const { customization, site, space } = context;
|
||||
const language = getSpaceLanguage(customization);
|
||||
|
||||
const pdfHref = context.linker.toPathInSpace(
|
||||
`~gitbook/pdf?${getPDFURLSearchParams({
|
||||
page: page.id,
|
||||
only: true,
|
||||
limit: 100,
|
||||
}).toString()}`
|
||||
);
|
||||
const useAdaptivePane = customization.ai?.pageLinkSummaries.enabled;
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={tcls(
|
||||
'group/aside',
|
||||
'hidden',
|
||||
'flex',
|
||||
// 'hidden',
|
||||
'xl:flex',
|
||||
// 'page-no-toc:lg:flex',
|
||||
'flex-col',
|
||||
'basis-56',
|
||||
// 'page-no-toc:basis-40',
|
||||
// 'page-no-toc:xl:basis-56',
|
||||
'xl:basis-56',
|
||||
'grow-0',
|
||||
'shrink-0',
|
||||
'break-anywhere', // To prevent long words in headings from breaking the layout
|
||||
|
||||
'text-tint',
|
||||
'contrast-more:text-tint-strong',
|
||||
'sticky',
|
||||
'text-sm',
|
||||
'xl:sticky',
|
||||
|
||||
'lg:px-12',
|
||||
'xl:px-0',
|
||||
'mx-auto',
|
||||
'xl:mx-0',
|
||||
'w-full',
|
||||
'max-w-3xl',
|
||||
|
||||
// Without header
|
||||
'lg:top-0',
|
||||
'lg:max-h-screen',
|
||||
@@ -91,144 +87,22 @@ export function PageAside(props: {
|
||||
'page-api-block:p-2'
|
||||
)}
|
||||
>
|
||||
{page.layout.outline ? (
|
||||
<>
|
||||
<div
|
||||
className={tcls(
|
||||
'hidden',
|
||||
'page-api-block:xl:max-2xl:flex',
|
||||
'text-xs',
|
||||
'tracking-wide',
|
||||
'font-semibold',
|
||||
'uppercase',
|
||||
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'gap-2'
|
||||
)}
|
||||
>
|
||||
<Icon icon="block-quote" className={tcls('size-3')} />
|
||||
{t(language, 'on_this_page')}
|
||||
<Icon
|
||||
icon="chevron-down"
|
||||
className={tcls(
|
||||
'size-3',
|
||||
'opacity-6',
|
||||
'ml-auto',
|
||||
'page-api-block:xl:max-2xl:group-hover/aside:hidden'
|
||||
)}
|
||||
<div className="lg:top:0 sticky flex grow flex-col gap-6 overflow-y-auto overflow-x-visible border-none pt-8 *:border-tint-subtle site-header-sections:lg:top-[6.75rem] site-header:lg:top-16 xl:pb-8 [&>*:not(:first-child)]:border-t [&>*:not(:first-child)]:pt-6">
|
||||
{useAdaptivePane ? <AdaptivePane /> : null}
|
||||
{page.layout.outline ? (
|
||||
<div className="hidden flex-col gap-6 xl:flex">
|
||||
<PageOutline document={document} context={context} />
|
||||
<PageActions
|
||||
page={page}
|
||||
context={context}
|
||||
withPageFeedback={withPageFeedback}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={tcls(
|
||||
'overflow-y-auto',
|
||||
'overflow-x-visible',
|
||||
|
||||
'flex',
|
||||
'flex-col',
|
||||
'shrink',
|
||||
'pb-12',
|
||||
|
||||
'sticky',
|
||||
'lg:top:0',
|
||||
'site-header:lg:top-16',
|
||||
'site-header-sections:lg:top-[6.75rem]',
|
||||
|
||||
'gap-6',
|
||||
'pt-8',
|
||||
|
||||
'page-api-block:xl:max-2xl:py-0',
|
||||
// Hide it for api page, until hovered
|
||||
'page-api-block:xl:max-2xl:hidden',
|
||||
'page-api-block:xl:max-2xl:group-hover/aside:flex'
|
||||
)}
|
||||
>
|
||||
{document ? (
|
||||
<React.Suspense fallback={null}>
|
||||
<PageAsideSections document={document} context={context} />
|
||||
</React.Suspense>
|
||||
) : null}
|
||||
<div
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-col',
|
||||
'gap-3',
|
||||
'sidebar-list-default:px-3',
|
||||
'border-t',
|
||||
'first:border-none',
|
||||
'border-tint-subtle',
|
||||
'py-4',
|
||||
'first:pt-0',
|
||||
'page-api-block:xl:max-2xl:px-3',
|
||||
'empty:hidden'
|
||||
)}
|
||||
>
|
||||
{withPageFeedback ? (
|
||||
<React.Suspense fallback={null}>
|
||||
<PageFeedbackForm pageId={page.id} className={tcls('mt-2')} />
|
||||
</React.Suspense>
|
||||
) : null}
|
||||
{customization.git.showEditLink && space.gitSync?.url && page.git ? (
|
||||
<div>
|
||||
<a
|
||||
href={urlJoin(space.gitSync.url, page.git.path)}
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'text-sm',
|
||||
'hover:text-tint-strong',
|
||||
'links-accent:hover:underline',
|
||||
'links-accent:hover:underline-offset-4',
|
||||
'links-accent:hover:decoration-[3px]',
|
||||
'links-accent:hover:decoration-primary-subtle',
|
||||
'py-2'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon={
|
||||
space.gitSync.installationProvider === 'gitlab'
|
||||
? 'gitlab'
|
||||
: 'github'
|
||||
}
|
||||
className={tcls('size-4', 'mr-1.5')}
|
||||
/>
|
||||
{t(language, 'edit_on_git', getGitSyncName(space))}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
{customization.pdf.enabled ? (
|
||||
<div>
|
||||
<a
|
||||
href={pdfHref}
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-row',
|
||||
'items-center',
|
||||
'text-sm',
|
||||
'hover:text-tint-strong',
|
||||
'links-accent:hover:underline',
|
||||
'links-accent:hover:underline-offset-4',
|
||||
'links-accent:hover:decoration-[3px]',
|
||||
'links-accent:hover:decoration-primary-subtle',
|
||||
'py-2'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon="file-pdf"
|
||||
className={tcls('size-4', 'mr-1.5')}
|
||||
/>
|
||||
{t(language, 'pdf_download')}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
) : null}
|
||||
</div>
|
||||
<div
|
||||
className={tcls(
|
||||
'sticky bottom-0 z-10 mt-auto flex flex-col bg-tint-base theme-gradient-tint:bg-gradient-tint theme-gradient:bg-gradient-primary theme-muted:bg-tint-subtle pb-4 page-api-block:xl:max-2xl:hidden page-api-block:xl:max-2xl:pb-0 page-api-block:xl:max-2xl:group-hover/aside:flex [html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||
'sticky bottom-0 z-10 mt-auto hidden flex-col bg-tint-base theme-gradient-tint:bg-gradient-tint theme-gradient:bg-gradient-primary theme-muted:bg-tint-subtle pb-4 xl:flex page-api-block:xl:max-2xl:hidden page-api-block:xl:max-2xl:pb-0 page-api-block:xl:max-2xl:group-hover/aside:flex [html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||
'page-api-block:xl:max-2xl:bg-transparent'
|
||||
)}
|
||||
>
|
||||
@@ -254,22 +128,3 @@ export function PageAside(props: {
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
async function PageAsideSections(props: { document: JSONDocument; context: GitBookSiteContext }) {
|
||||
const { document, context } = props;
|
||||
|
||||
const sections = await getDocumentSections(context, document);
|
||||
|
||||
return sections.length > 1 ? <ScrollSectionsList sections={sections} /> : null;
|
||||
}
|
||||
|
||||
function getGitSyncName(space: Space): string {
|
||||
if (space.gitSync?.installationProvider === 'github') {
|
||||
return 'GitHub';
|
||||
}
|
||||
if (space.gitSync?.installationProvider === 'gitlab') {
|
||||
return 'GitLab';
|
||||
}
|
||||
|
||||
return 'Git';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { getSpaceLanguage, t } from '@/intl/server';
|
||||
import { getDocumentSections } from '@/lib/document-sections';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
import type { JSONDocument } from '@gitbook/api';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
import React from 'react';
|
||||
import { ScrollSectionsList } from './ScrollSectionsList';
|
||||
|
||||
export async function PageOutline(props: {
|
||||
document: JSONDocument | null;
|
||||
context: GitBookSiteContext;
|
||||
}) {
|
||||
const { document, context } = props;
|
||||
const { customization } = context;
|
||||
const language = getSpaceLanguage(customization);
|
||||
|
||||
if (!document) return;
|
||||
|
||||
const sections = await getDocumentSections(context, document);
|
||||
|
||||
return document && sections.length > 1 ? (
|
||||
<div>
|
||||
<div className="mb-1 flex flex-row items-center gap-2 font-semibold text-xs uppercase tracking-wide">
|
||||
<Icon icon="block-quote" className={tcls('size-3')} />
|
||||
{t(language, 'on_this_page')}
|
||||
</div>
|
||||
<div
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-col'
|
||||
|
||||
// 'page-api-block:xl:max-2xl:py-0',
|
||||
// // Hide it for api page, until hovered
|
||||
// 'page-api-block:xl:max-2xl:hidden',
|
||||
// 'page-api-block:xl:max-2xl:group-hover/aside:flex'
|
||||
)}
|
||||
>
|
||||
<React.Suspense fallback={null}>
|
||||
<ScrollSectionsList sections={sections} />
|
||||
</React.Suspense>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import { ClientContexts } from './ClientContexts';
|
||||
import '@gitbook/icons/style.css';
|
||||
import './globals.css';
|
||||
import { GITBOOK_FONTS_URL, GITBOOK_ICONS_TOKEN, GITBOOK_ICONS_URL } from '@v2/lib/env';
|
||||
import { AdaptiveContextProvider } from '../Adaptive/AdaptiveContext';
|
||||
import { AnnouncementDismissedScript } from '../Announcement';
|
||||
|
||||
/**
|
||||
@@ -175,7 +176,9 @@ export async function CustomizationRootLayout(props: {
|
||||
: null) || IconStyle.Regular
|
||||
}
|
||||
>
|
||||
<ClientContexts language={language}>{children}</ClientContexts>
|
||||
<ClientContexts language={language}>
|
||||
<AdaptiveContextProvider>{children}</AdaptiveContextProvider>
|
||||
</ClientContexts>
|
||||
</IconsProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -70,7 +70,7 @@ export async function SitePage(props: SitePageProps) {
|
||||
<PageCover as="full" page={page} cover={page.cover} context={context} />
|
||||
) : null}
|
||||
{/* We use a flex row reverse to render the aside first because the page is streamed. */}
|
||||
<div className="flex grow flex-row-reverse justify-end">
|
||||
<div className="flex grow flex-col xl:flex-row-reverse xl:justify-end">
|
||||
<PageAside
|
||||
page={page}
|
||||
document={document}
|
||||
|
||||
@@ -75,13 +75,13 @@ export function SiteSectionListItem(props: {
|
||||
const isMounted = useIsMounted();
|
||||
React.useEffect(() => {}, [isMounted]); // This updates the useScrollToActiveTOCItem hook once we're mounted, so we can actually scroll to the this item
|
||||
|
||||
const linkRef = React.createRef<HTMLAnchorElement>();
|
||||
useScrollToActiveTOCItem({ linkRef, isActive });
|
||||
const anchorRef = React.createRef<HTMLAnchorElement>();
|
||||
useScrollToActiveTOCItem({ anchorRef, isActive });
|
||||
|
||||
return (
|
||||
<Link
|
||||
ref={anchorRef}
|
||||
href={section.url}
|
||||
ref={linkRef}
|
||||
aria-current={isActive && 'page'}
|
||||
className={tcls(
|
||||
'group/section-link flex flex-row items-center gap-3 rounded-md straight-corners:rounded-none px-3 py-2 transition-all hover:bg-tint-hover hover:text-tint-strong contrast-more:hover:ring-1 contrast-more:hover:ring-tint',
|
||||
@@ -121,18 +121,15 @@ export function SiteSectionGroupItem(props: {
|
||||
|
||||
const hasDescendants = group.sections.length > 0;
|
||||
const isActiveGroup = group.sections.some((section) => section.id === currentSection.id);
|
||||
const [isVisible, setIsVisible] = React.useState(isActiveGroup);
|
||||
const shouldOpen = hasDescendants && isActiveGroup;
|
||||
const [isOpen, setIsOpen] = React.useState(shouldOpen);
|
||||
|
||||
// Update the visibility of the children, if we are navigating to a descendant.
|
||||
// Update the visibility of the children if the group becomes active.
|
||||
React.useEffect(() => {
|
||||
if (!hasDescendants) {
|
||||
return;
|
||||
if (shouldOpen) {
|
||||
setIsOpen(shouldOpen);
|
||||
}
|
||||
|
||||
setIsVisible((prev) => prev || isActiveGroup);
|
||||
}, [isActiveGroup, hasDescendants]);
|
||||
|
||||
const { show, hide, scope } = useToggleAnimation({ hasDescendants, isVisible });
|
||||
}, [shouldOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -141,7 +138,7 @@ export function SiteSectionGroupItem(props: {
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setIsVisible((prev) => !prev);
|
||||
setIsOpen((prev) => !prev);
|
||||
}}
|
||||
className={`group/section-link flex w-full flex-row items-center gap-3 rounded-md straight-corners:rounded-none px-3 py-2 text-left transition-all hover:bg-tint-hover hover:text-tint-strong contrast-more:hover:ring-1 contrast-more:hover:ring-tint ${
|
||||
isActiveGroup
|
||||
@@ -184,7 +181,7 @@ export function SiteSectionGroupItem(props: {
|
||||
'after:h-7',
|
||||
'hover:bg-tint-active',
|
||||
'hover:text-current',
|
||||
isActiveGroup ? ['hover:bg-tint-hover'] : []
|
||||
isActiveGroup && 'hover:bg-tint-hover'
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
@@ -201,17 +198,13 @@ export function SiteSectionGroupItem(props: {
|
||||
'group-hover:opacity-11',
|
||||
'contrast-more:opacity-11',
|
||||
|
||||
isVisible ? ['rotate-90'] : ['rotate-0']
|
||||
isOpen ? 'rotate-90' : 'rotate-0'
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
{hasDescendants ? (
|
||||
<motion.div
|
||||
ref={scope}
|
||||
className={tcls(isVisible ? null : '[&_ul>li]:opacity-1')}
|
||||
initial={isVisible ? show : hide}
|
||||
>
|
||||
<Descendants isVisible={isOpen}>
|
||||
{group.sections.map((section) => (
|
||||
<SiteSectionListItem
|
||||
section={section}
|
||||
@@ -220,8 +213,25 @@ export function SiteSectionGroupItem(props: {
|
||||
className="pl-5"
|
||||
/>
|
||||
))}
|
||||
</motion.div>
|
||||
</Descendants>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Descendants(props: {
|
||||
isVisible: boolean;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const { isVisible, children } = props;
|
||||
const { show, hide, scope } = useToggleAnimation(isVisible);
|
||||
return (
|
||||
<motion.div
|
||||
ref={scope}
|
||||
className={isVisible ? undefined : '[&_ul>li]:opacity-1'}
|
||||
initial={isVisible ? show : hide}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function PageDocumentItem(props: {
|
||||
const href = context.linker.toPathForPage({ pages: rootPages, page });
|
||||
|
||||
return (
|
||||
<li className={tcls('flex', 'flex-col')}>
|
||||
<li className="flex flex-col">
|
||||
<ToggleableLinkItem
|
||||
href={href}
|
||||
pathname={getPagePath(rootPages, page)}
|
||||
@@ -52,7 +52,7 @@ export async function PageDocumentItem(props: {
|
||||
}
|
||||
>
|
||||
{page.emoji || page.icon ? (
|
||||
<span className={tcls('flex', 'gap-3', 'items-center')}>
|
||||
<span className="flex items-center gap-3">
|
||||
<TOCPageIcon page={page} />
|
||||
{page.title}
|
||||
</span>
|
||||
|
||||
@@ -15,27 +15,13 @@ export function PageGroupItem(props: {
|
||||
const { rootPages, page, context } = props;
|
||||
|
||||
return (
|
||||
<li className={tcls('flex', 'flex-col', 'group/page-group-item')}>
|
||||
<li className="group/page-group-item flex flex-col">
|
||||
<div
|
||||
className={tcls(
|
||||
'flex',
|
||||
'items-center',
|
||||
|
||||
'gap-3',
|
||||
'px-3',
|
||||
'z-[1]',
|
||||
'sticky',
|
||||
'-top-5',
|
||||
'pt-6',
|
||||
'group-first/page-group-item:-mt-5',
|
||||
'-top-5 group-first/page-group-item:-mt-5 sticky z-[1] flex items-center gap-3 px-3 pt-6',
|
||||
'font-semibold text-xs uppercase tracking-wide',
|
||||
'pb-3', // Add extra padding to make the header fade a bit nicer
|
||||
'-mb-1.5', // Then pull the page items a bit closer, effective bottom padding is 1.5 units / 6px.
|
||||
|
||||
'text-xs',
|
||||
'tracking-wide',
|
||||
'font-semibold',
|
||||
'uppercase',
|
||||
|
||||
'[mask-image:linear-gradient(rgba(0,0,0,1)_70%,rgba(0,0,0,0))]', // Fade out effect of fixed page items. We want the fade to start past the header, this is a good approximation.
|
||||
'bg-tint-base',
|
||||
'sidebar-filled:bg-tint-subtle',
|
||||
|
||||
@@ -55,9 +55,9 @@ export async function PageLinkItem(props: { page: RevisionPageLink; context: Git
|
||||
'shrink-0',
|
||||
'text-current',
|
||||
'transition-colors',
|
||||
'[&>path]:transition-[opacity]',
|
||||
'[&>path]:[opacity:0.40]',
|
||||
'group-hover:[&>path]:[opacity:1]'
|
||||
'[&>path]:transition-opacity',
|
||||
'[&>path]:opacity-[0.4]',
|
||||
'group-hover:[&>path]:opacity-11'
|
||||
)}
|
||||
/>
|
||||
</Link>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { type RevisionPage, RevisionPageType } from '@gitbook/api';
|
||||
import type { RevisionPage } from '@gitbook/api';
|
||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
|
||||
import assertNever from 'assert-never';
|
||||
import { PageDocumentItem } from './PageDocumentItem';
|
||||
import { PageGroupItem } from './PageGroupItem';
|
||||
import { PageLinkItem } from './PageLinkItem';
|
||||
@@ -16,41 +17,45 @@ export function PagesList(props: {
|
||||
const { rootPages, pages, context, style } = props;
|
||||
|
||||
return (
|
||||
<ul className={tcls('flex', 'flex-col', 'gap-y-0.5', style)}>
|
||||
<ul className={tcls('flex flex-col gap-y-0.5', style)}>
|
||||
{pages.map((page) => {
|
||||
if (page.type === RevisionPageType.Computed) {
|
||||
if (page.type === 'computed') {
|
||||
throw new Error(
|
||||
'Unexpected computed page, it should have been computed in the API'
|
||||
);
|
||||
}
|
||||
|
||||
if (page.type === RevisionPageType.Link) {
|
||||
return <PageLinkItem key={page.id} page={page} context={context} />;
|
||||
}
|
||||
|
||||
if (page.hidden) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (page.type === RevisionPageType.Group) {
|
||||
return (
|
||||
<PageGroupItem
|
||||
key={page.id}
|
||||
rootPages={rootPages}
|
||||
page={page}
|
||||
context={context}
|
||||
/>
|
||||
);
|
||||
}
|
||||
switch (page.type) {
|
||||
case 'document':
|
||||
return (
|
||||
<PageDocumentItem
|
||||
key={page.id}
|
||||
rootPages={rootPages}
|
||||
page={page}
|
||||
context={context}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageDocumentItem
|
||||
key={page.id}
|
||||
rootPages={rootPages}
|
||||
page={page}
|
||||
context={context}
|
||||
/>
|
||||
);
|
||||
case 'link':
|
||||
return <PageLinkItem key={page.id} page={page} context={context} />;
|
||||
|
||||
case 'group':
|
||||
return (
|
||||
<PageGroupItem
|
||||
key={page.id}
|
||||
rootPages={rootPages}
|
||||
page={page}
|
||||
context={context}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
assertNever(page);
|
||||
}
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
|
||||
@@ -1,40 +1,64 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
type ComponentPropsWithoutRef,
|
||||
} from 'react';
|
||||
import { assert } from 'ts-essentials';
|
||||
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
interface TOCScrollContainerContextType {
|
||||
onContainerMount: (listener: (element: HTMLDivElement) => void) => () => void;
|
||||
}
|
||||
|
||||
const TOCScrollContainerRefContext = React.createContext<React.RefObject<HTMLDivElement> | null>(
|
||||
null
|
||||
);
|
||||
const TOCScrollContainerContext = React.createContext<TOCScrollContainerContextType | null>(null);
|
||||
|
||||
function useTOCScrollContainerRefContext() {
|
||||
const ctx = React.useContext(TOCScrollContainerRefContext);
|
||||
if (!ctx) {
|
||||
throw new Error('Context `TOCScrollContainerRefContext` must be used within Provider');
|
||||
}
|
||||
function useTOCScrollContainerContext() {
|
||||
const ctx = React.useContext(TOCScrollContainerContext);
|
||||
assert(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function TOCScrollContainer(props: {
|
||||
children: React.ReactNode;
|
||||
className?: ClassValue;
|
||||
style?: React.CSSProperties;
|
||||
}) {
|
||||
const { children, className, style } = props;
|
||||
const scrollContainerRef = React.createRef<HTMLDivElement>();
|
||||
/**
|
||||
* Table of contents scroll container.
|
||||
*/
|
||||
export function TOCScrollContainer(props: ComponentPropsWithoutRef<'div'>) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const listeners = useRef<((element: HTMLDivElement) => void)[]>([]);
|
||||
const onContainerMount: TOCScrollContainerContextType['onContainerMount'] = useCallback(
|
||||
(listener) => {
|
||||
if (ref.current) {
|
||||
listener(ref.current);
|
||||
return () => {};
|
||||
}
|
||||
listeners.current.push(listener);
|
||||
return () => {
|
||||
listeners.current = listeners.current.filter((l) => l !== listener);
|
||||
};
|
||||
},
|
||||
[]
|
||||
);
|
||||
const value: TOCScrollContainerContextType = useMemo(
|
||||
() => ({ onContainerMount }),
|
||||
[onContainerMount]
|
||||
);
|
||||
useEffect(() => {
|
||||
const element = ref.current;
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
listeners.current.forEach((listener) => listener(element));
|
||||
return () => {
|
||||
listeners.current = [];
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<TOCScrollContainerRefContext.Provider value={scrollContainerRef}>
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
data-testid="toc-scroll-container"
|
||||
className={tcls(className)}
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</TOCScrollContainerRefContext.Provider>
|
||||
<TOCScrollContainerContext.Provider value={value}>
|
||||
<div ref={ref} data-testid="toc-scroll-container" {...props} />
|
||||
</TOCScrollContainerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,39 +66,31 @@ export function TOCScrollContainer(props: {
|
||||
const TOC_ITEM_OFFSET = 100;
|
||||
|
||||
/**
|
||||
* Scrolls the table of contents container to the page item when it becomes active
|
||||
* Scrolls the table of contents container to the page item when it's initially active.
|
||||
*/
|
||||
export function useScrollToActiveTOCItem(props: {
|
||||
anchorRef: React.RefObject<HTMLAnchorElement>;
|
||||
isActive: boolean;
|
||||
linkRef: React.RefObject<HTMLAnchorElement>;
|
||||
}) {
|
||||
const { isActive, linkRef } = props;
|
||||
const scrollContainerRef = useTOCScrollContainerRefContext();
|
||||
const isScrolled = React.useRef(false);
|
||||
React.useLayoutEffect(() => {
|
||||
if (!isActive) {
|
||||
isScrolled.current = false;
|
||||
return;
|
||||
const { isActive, anchorRef } = props;
|
||||
const isInitialActiveRef = useRef(isActive);
|
||||
const { onContainerMount } = useTOCScrollContainerContext();
|
||||
useEffect(() => {
|
||||
const anchor = anchorRef.current;
|
||||
if (isInitialActiveRef.current && anchor) {
|
||||
return onContainerMount((container) => {
|
||||
if (isOutOfView(anchor, container)) {
|
||||
container.scrollTo({ top: anchor.offsetTop - TOC_ITEM_OFFSET });
|
||||
}
|
||||
});
|
||||
}
|
||||
if (isScrolled.current) {
|
||||
return;
|
||||
}
|
||||
const tocItem = linkRef.current;
|
||||
const tocContainer = scrollContainerRef.current;
|
||||
if (!tocItem || !tocContainer || !isOutOfView(tocItem, tocContainer)) {
|
||||
return;
|
||||
}
|
||||
tocContainer?.scrollTo({
|
||||
top: tocItem.offsetTop - TOC_ITEM_OFFSET,
|
||||
});
|
||||
isScrolled.current = true;
|
||||
}, [isActive, linkRef, scrollContainerRef]);
|
||||
}, [onContainerMount, anchorRef]);
|
||||
}
|
||||
|
||||
function isOutOfView(tocItem: HTMLElement, tocContainer: HTMLElement) {
|
||||
const tocItemTop = tocItem.offsetTop;
|
||||
const containerTop = tocContainer.scrollTop;
|
||||
const containerBottom = containerTop + tocContainer.clientHeight;
|
||||
function isOutOfView(element: HTMLElement, container: HTMLElement) {
|
||||
const tocItemTop = element.offsetTop;
|
||||
const containerTop = container.scrollTop;
|
||||
const containerBottom = containerTop + container.clientHeight;
|
||||
return (
|
||||
tocItemTop < containerTop + TOC_ITEM_OFFSET ||
|
||||
tocItemTop > containerBottom - TOC_ITEM_OFFSET
|
||||
|
||||
@@ -66,36 +66,26 @@ export function TableOfContents(props: {
|
||||
<div // The actual sidebar, either shown with a filled bg or transparent.
|
||||
className={tcls(
|
||||
'lg:-ms-5',
|
||||
'overflow-hidden',
|
||||
'relative',
|
||||
|
||||
'flex',
|
||||
'flex-col',
|
||||
'flex-grow',
|
||||
'relative flex flex-grow flex-col overflow-hidden border-tint-subtle',
|
||||
|
||||
'sidebar-filled:bg-tint-subtle',
|
||||
'theme-muted:bg-tint-subtle',
|
||||
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
|
||||
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
|
||||
'[html.sidebar-filled.theme-gradient_&]:border',
|
||||
'page-no-toc:!bg-transparent',
|
||||
|
||||
'sidebar-filled:rounded-xl',
|
||||
'straight-corners:rounded-none'
|
||||
)}
|
||||
>
|
||||
{innerHeader && <div className={tcls('px-5 *:my-4')}>{innerHeader}</div>}
|
||||
{innerHeader && <div className="px-5 *:my-4">{innerHeader}</div>}
|
||||
<TOCScrollContainer // The scrollview inside the sidebar
|
||||
className={tcls(
|
||||
'flex',
|
||||
'flex-grow',
|
||||
'flex-col',
|
||||
|
||||
'p-2',
|
||||
'flex flex-grow flex-col p-2',
|
||||
customization.trademark.enabled && 'lg:pb-20',
|
||||
|
||||
'overflow-y-auto',
|
||||
'lg:gutter-stable',
|
||||
'lg:gutter-stable overflow-y-auto',
|
||||
'[&::-webkit-scrollbar]:bg-transparent',
|
||||
'[&::-webkit-scrollbar-thumb]:bg-transparent',
|
||||
'group-hover:[&::-webkit-scrollbar]:bg-tint-subtle',
|
||||
@@ -107,11 +97,7 @@ export function TableOfContents(props: {
|
||||
rootPages={pages}
|
||||
pages={pages}
|
||||
context={context}
|
||||
style={tcls(
|
||||
'page-no-toc:hidden',
|
||||
'sidebar-list-line:border-l',
|
||||
'border-tint-subtle'
|
||||
)}
|
||||
style="page-no-toc:hidden border-tint-subtle sidebar-list-line:border-l"
|
||||
/>
|
||||
{customization.trademark.enabled ? (
|
||||
<Trademark
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import { motion } from 'framer-motion';
|
||||
import React from 'react';
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { useCurrentPagePath, useToggleAnimation } from '../hooks';
|
||||
import { Link, type LinkInsightsProps } from '../primitives';
|
||||
import { useCurrentPagePath } from '../hooks';
|
||||
import { Link, type LinkInsightsProps, type LinkProps } from '../primitives';
|
||||
import { useScrollToActiveTOCItem } from './TOCScroller';
|
||||
|
||||
/**
|
||||
@@ -24,128 +24,190 @@ export function ToggleableLinkItem(
|
||||
const { href, children, descendants, pathname, insights } = props;
|
||||
|
||||
const currentPagePath = useCurrentPagePath();
|
||||
|
||||
const isActive = currentPagePath === pathname;
|
||||
const hasDescendants = !!descendants;
|
||||
const hasActiveDescendant =
|
||||
hasDescendants && (isActive || currentPagePath.startsWith(`${pathname}/`));
|
||||
|
||||
const [isVisible, setIsVisible] = React.useState(hasActiveDescendant);
|
||||
|
||||
// Update the visibility of the children, if we are navigating to a descendant.
|
||||
React.useEffect(() => {
|
||||
if (!hasDescendants) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsVisible((prev) => prev || hasActiveDescendant);
|
||||
}, [hasActiveDescendant, hasDescendants]);
|
||||
|
||||
const { show, hide, scope } = useToggleAnimation({ hasDescendants, isVisible });
|
||||
|
||||
const linkRef = React.createRef<HTMLAnchorElement>();
|
||||
useScrollToActiveTOCItem({ linkRef, isActive });
|
||||
if (!descendants) {
|
||||
return (
|
||||
<LinkItem href={href} insights={insights} isActive={isActive}>
|
||||
{children}
|
||||
</LinkItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Link
|
||||
ref={linkRef}
|
||||
href={href}
|
||||
insights={insights}
|
||||
{...(isActive ? { 'aria-current': 'page' } : {})}
|
||||
className={tcls(
|
||||
'group/toclink relative transition-colors',
|
||||
'flex flex-row justify-between',
|
||||
'rounded-md straight-corners:rounded-none p-1.5 pl-3',
|
||||
'text-balance font-normal text-sm text-tint-strong/7 hover:bg-tint-hover hover:text-tint-strong contrast-more:text-tint-strong',
|
||||
'hover:contrast-more:text-tint-strong hover:contrast-more:ring-1 hover:contrast-more:ring-tint-12',
|
||||
'before:contents[] before:-left-px before:absolute before:inset-y-0',
|
||||
'sidebar-list-line:rounded-l-none sidebar-list-line:before:w-px sidebar-list-default:[&+div_a]:rounded-l-none [&+div_a]:pl-5 sidebar-list-default:[&+div_a]:before:w-px',
|
||||
|
||||
isActive && [
|
||||
'font-semibold',
|
||||
'sidebar-list-line:before:w-0.5',
|
||||
|
||||
'before:bg-primary-solid',
|
||||
'text-primary-subtle',
|
||||
'contrast-more:text-primary',
|
||||
|
||||
'sidebar-list-pill:bg-primary',
|
||||
'[html.sidebar-list-pill.theme-muted_&]:bg-primary-hover',
|
||||
'[html.sidebar-list-pill.theme-bold.tint_&]:bg-primary-hover',
|
||||
'[html.sidebar-filled.sidebar-list-pill.theme-muted_&]:bg-primary',
|
||||
'[html.sidebar-filled.sidebar-list-pill.theme-bold.tint_&]:bg-primary',
|
||||
|
||||
'hover:bg-primary-hover',
|
||||
'hover:text-primary',
|
||||
'hover:before:bg-primary-solid-hover',
|
||||
'sidebar-list-pill:hover:bg-primary-hover',
|
||||
|
||||
'contrast-more:text-primary',
|
||||
'contrast-more:hover:text-primary-strong',
|
||||
'contrast-more:bg-primary',
|
||||
'contrast-more:ring-1',
|
||||
'contrast-more:ring-primary',
|
||||
'contrast-more:hover:ring-primary-hover',
|
||||
]
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
{hasDescendants ? (
|
||||
<span
|
||||
className={tcls(
|
||||
'group',
|
||||
'relative',
|
||||
'rounded-full',
|
||||
'straight-corners:rounded-sm',
|
||||
'w-5',
|
||||
'h-5',
|
||||
'after:grid-area-1-1',
|
||||
'after:absolute',
|
||||
'after:-top-1',
|
||||
'after:grid',
|
||||
'after:-left-1',
|
||||
'after:w-7',
|
||||
'after:h-7',
|
||||
'hover:bg-tint-active',
|
||||
'hover:text-current',
|
||||
isActive ? ['hover:bg-tint-hover'] : []
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setIsVisible((prev) => !prev);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
icon="chevron-right"
|
||||
className={tcls(
|
||||
'grid',
|
||||
'flex-shrink-0',
|
||||
'size-3',
|
||||
'm-1',
|
||||
'transition-[opacity]',
|
||||
'text-current',
|
||||
'transition-transform',
|
||||
'opacity-6',
|
||||
'group-hover:opacity-11',
|
||||
'contrast-more:opacity-11',
|
||||
|
||||
isVisible ? ['rotate-90'] : ['rotate-0']
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
) : null}
|
||||
</Link>
|
||||
{hasDescendants ? (
|
||||
<motion.div
|
||||
ref={scope}
|
||||
className={tcls(isVisible ? null : '[&_ul>li]:opacity-1')}
|
||||
initial={isVisible ? show : hide}
|
||||
>
|
||||
<DescendantsRenderer
|
||||
descendants={descendants}
|
||||
defaultIsOpen={isActive || currentPagePath.startsWith(`${pathname}/`)}
|
||||
>
|
||||
{({ descendants, toggler }) => (
|
||||
<>
|
||||
<LinkItem href={href} insights={insights} isActive={isActive}>
|
||||
{children}
|
||||
{toggler}
|
||||
</LinkItem>
|
||||
{descendants}
|
||||
</motion.div>
|
||||
) : null}
|
||||
</>
|
||||
</>
|
||||
)}
|
||||
</DescendantsRenderer>
|
||||
);
|
||||
}
|
||||
|
||||
function LinkItem(
|
||||
props: Pick<LinkProps, 'href' | 'insights' | 'children'> & {
|
||||
isActive: boolean;
|
||||
}
|
||||
) {
|
||||
const { isActive, href, insights, children } = props;
|
||||
const anchorRef = useRef<HTMLAnchorElement>(null);
|
||||
useScrollToActiveTOCItem({ anchorRef, isActive });
|
||||
return (
|
||||
<Link
|
||||
ref={anchorRef}
|
||||
href={href}
|
||||
insights={insights}
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
className={tcls(
|
||||
'group/toclink relative transition-colors',
|
||||
'flex flex-row justify-between',
|
||||
'rounded-md straight-corners:rounded-none p-1.5 pl-3',
|
||||
'text-balance font-normal text-sm text-tint-strong/7 hover:bg-tint-hover hover:text-tint-strong contrast-more:text-tint-strong',
|
||||
'hover:contrast-more:text-tint-strong hover:contrast-more:ring-1 hover:contrast-more:ring-tint-12',
|
||||
'before:contents[] before:-left-px before:absolute before:inset-y-0',
|
||||
'sidebar-list-line:rounded-l-none sidebar-list-line:before:w-px sidebar-list-default:[&+div_a]:rounded-l-none [&+div_a]:pl-5 sidebar-list-default:[&+div_a]:before:w-px',
|
||||
|
||||
isActive && [
|
||||
'font-semibold',
|
||||
'sidebar-list-line:before:w-0.5',
|
||||
|
||||
'before:bg-primary-solid',
|
||||
'text-primary-subtle',
|
||||
'contrast-more:text-primary',
|
||||
|
||||
'sidebar-list-pill:bg-primary',
|
||||
'[html.sidebar-list-pill.theme-muted_&]:bg-primary-hover',
|
||||
'[html.sidebar-list-pill.theme-bold.tint_&]:bg-primary-hover',
|
||||
'[html.sidebar-filled.sidebar-list-pill.theme-muted_&]:bg-primary',
|
||||
'[html.sidebar-filled.sidebar-list-pill.theme-bold.tint_&]:bg-primary',
|
||||
|
||||
'hover:bg-primary-hover',
|
||||
'hover:text-primary',
|
||||
'hover:before:bg-primary-solid-hover',
|
||||
'sidebar-list-pill:hover:bg-primary-hover',
|
||||
|
||||
'contrast-more:text-primary',
|
||||
'contrast-more:hover:text-primary-strong',
|
||||
'contrast-more:bg-primary',
|
||||
'contrast-more:ring-1',
|
||||
'contrast-more:ring-primary',
|
||||
'contrast-more:hover:ring-primary-hover',
|
||||
]
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function DescendantsRenderer(props: {
|
||||
defaultIsOpen: boolean;
|
||||
descendants: React.ReactNode;
|
||||
children: (renderProps: {
|
||||
descendants: React.ReactNode;
|
||||
toggler: React.ReactNode;
|
||||
}) => React.ReactNode;
|
||||
}) {
|
||||
const { defaultIsOpen, children, descendants } = props;
|
||||
const [isOpen, setIsOpen] = React.useState(defaultIsOpen);
|
||||
|
||||
// Update the visibility of the children if one of the descendants becomes active.
|
||||
React.useEffect(() => {
|
||||
if (defaultIsOpen) {
|
||||
setIsOpen(defaultIsOpen);
|
||||
}
|
||||
}, [defaultIsOpen]);
|
||||
|
||||
return children({
|
||||
toggler: (
|
||||
<Toggler
|
||||
isLinkActive={isOpen}
|
||||
isOpen={isOpen}
|
||||
onToggle={() => {
|
||||
setIsOpen((prev) => !prev);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
descendants: <Descendants isVisible={isOpen}>{descendants}</Descendants>,
|
||||
});
|
||||
}
|
||||
|
||||
function Toggler(props: {
|
||||
isLinkActive: boolean;
|
||||
isOpen: boolean;
|
||||
onToggle: () => void;
|
||||
}) {
|
||||
const { isLinkActive, isOpen, onToggle } = props;
|
||||
return (
|
||||
<span
|
||||
className={tcls(
|
||||
'group',
|
||||
'relative',
|
||||
'rounded-full',
|
||||
'straight-corners:rounded-sm',
|
||||
'w-5',
|
||||
'h-5',
|
||||
'after:grid-area-1-1',
|
||||
'after:absolute',
|
||||
'after:-top-1',
|
||||
'after:grid',
|
||||
'after:-left-1',
|
||||
'after:w-7',
|
||||
'after:h-7',
|
||||
'hover:bg-tint-active',
|
||||
'hover:text-current',
|
||||
isLinkActive && 'hover:bg-tint-hover'
|
||||
)}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onToggle();
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
icon="chevron-right"
|
||||
className={tcls(
|
||||
'm-1 grid size-3 flex-shrink-0 text-current opacity-6 transition',
|
||||
'group-hover:opacity-11 contrast-more:opacity-11',
|
||||
isOpen ? 'rotate-90' : 'rotate-0'
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const show = {
|
||||
opacity: 1,
|
||||
height: 'auto',
|
||||
};
|
||||
const hide = {
|
||||
opacity: 0,
|
||||
height: 0,
|
||||
transitionEnd: {
|
||||
display: 'none',
|
||||
},
|
||||
};
|
||||
|
||||
function Descendants(props: {
|
||||
isVisible: boolean;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const { isVisible, children } = props;
|
||||
return (
|
||||
<motion.div
|
||||
className="overflow-hidden"
|
||||
animate={isVisible ? show : hide}
|
||||
initial={isVisible ? show : hide}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useParams, useSelectedLayoutSegment } from 'next/navigation';
|
||||
|
||||
import { removeLeadingSlash } from '@/lib/paths';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
/**
|
||||
* Return the page of the current page being rendered.
|
||||
@@ -14,9 +15,11 @@ export function useCurrentPagePath() {
|
||||
// For V1, we use the selected layout segment.
|
||||
const rawActiveSegment = useSelectedLayoutSegment() ?? '';
|
||||
|
||||
if (typeof params.pagePath === 'string') {
|
||||
return removeLeadingSlash(decodeURIComponent(params.pagePath));
|
||||
}
|
||||
return useMemo(() => {
|
||||
if (typeof params.pagePath === 'string') {
|
||||
return removeLeadingSlash(decodeURIComponent(params.pagePath));
|
||||
}
|
||||
|
||||
return decodeURIComponent(rawActiveSegment);
|
||||
return decodeURIComponent(rawActiveSegment);
|
||||
}, [params.pagePath, rawActiveSegment]);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { stagger, useAnimate } from 'framer-motion';
|
||||
import React from 'react';
|
||||
'use client';
|
||||
|
||||
import { useIsMounted } from '.';
|
||||
import { stagger, useAnimate } from 'framer-motion';
|
||||
import React, { useLayoutEffect } from 'react';
|
||||
|
||||
const show = {
|
||||
opacity: 1,
|
||||
@@ -19,44 +19,35 @@ const hide = {
|
||||
|
||||
const staggerMenuItems = stagger(0.02, { ease: (p) => p ** 2 });
|
||||
|
||||
export function useToggleAnimation({
|
||||
hasDescendants,
|
||||
isVisible,
|
||||
}: {
|
||||
hasDescendants: boolean;
|
||||
isVisible: boolean;
|
||||
}) {
|
||||
const isMounted = useIsMounted();
|
||||
export function useToggleAnimation(isVisible: boolean) {
|
||||
const [scope, animate] = useAnimate();
|
||||
const previousIsVisibleRef = React.useRef<boolean | undefined>(undefined);
|
||||
useLayoutEffect(() => {
|
||||
previousIsVisibleRef.current = isVisible;
|
||||
});
|
||||
const previousIsVisible = previousIsVisibleRef.current;
|
||||
|
||||
// Animate the visibility of the children
|
||||
// only after the initial state.
|
||||
React.useEffect(() => {
|
||||
if (!isMounted || !hasDescendants) {
|
||||
if (previousIsVisible === undefined || previousIsVisible === isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
animate(scope.current, isVisible ? show : hide, {
|
||||
duration: 0.1,
|
||||
});
|
||||
animate(scope.current, isVisible ? show : hide, { duration: 0.1 });
|
||||
|
||||
const selector = '& > ul > li';
|
||||
if (isVisible)
|
||||
animate(
|
||||
selector,
|
||||
{ opacity: 1 },
|
||||
{
|
||||
delay: staggerMenuItems,
|
||||
}
|
||||
);
|
||||
else {
|
||||
if (isVisible) {
|
||||
animate(selector, { opacity: 1 }, { delay: staggerMenuItems });
|
||||
} else {
|
||||
animate(selector, { opacity: 0 });
|
||||
}
|
||||
} catch (error) {
|
||||
// The selector can crash in some browsers, we ignore it as the animation is not critical.
|
||||
console.error(error);
|
||||
}
|
||||
}, [isVisible, isMounted, hasDescendants, animate, scope]);
|
||||
}, [previousIsVisible, isVisible, animate, scope]);
|
||||
|
||||
return { show, hide, scope };
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ export function Button({
|
||||
'contrast-more:hover:ring-2',
|
||||
'contrast-more:hover:ring-tint-12',
|
||||
|
||||
'hover:scale-105',
|
||||
'hover:scale-104',
|
||||
'active:scale-100',
|
||||
'transition-all',
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { SVGProps } from 'react';
|
||||
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
export const Loading = ({
|
||||
busy = true,
|
||||
...props
|
||||
@@ -13,29 +11,26 @@ export const Loading = ({
|
||||
preserveAspectRatio="xMaxYMid meet"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-busy
|
||||
aria-busy={busy}
|
||||
{...props}
|
||||
>
|
||||
<title>{busy ? 'Loading' : 'Loaded'}</title>
|
||||
<path
|
||||
className={tcls(
|
||||
busy
|
||||
? 'animate-[pathLoading_2s_ease_infinite_forwards]'
|
||||
: 'animate-[pathLoading_2s_ease_forwards]'
|
||||
)}
|
||||
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
||||
stroke="currentColor"
|
||||
pathLength="100"
|
||||
strokeOpacity={busy ? 0.24 : 1}
|
||||
className="transition-[stroke-opacity] duration-500"
|
||||
fill="none"
|
||||
strokeWidth="11"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
className="animate-[pathLoading_2s_ease_infinite_forwards] transition-opacity delay-500 duration-500"
|
||||
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
||||
stroke="currentColor"
|
||||
pathLength="100"
|
||||
strokeOpacity={busy ? 0.24 : 1}
|
||||
className="transition-opacity duration-1000"
|
||||
fill="none"
|
||||
strokeWidth="11"
|
||||
strokeLinecap="round"
|
||||
|
||||
@@ -28,6 +28,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
multiWeight: {
|
||||
@@ -81,6 +84,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
multiSource: {
|
||||
@@ -99,6 +105,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
missingFormat: {
|
||||
@@ -117,6 +126,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
empty: {
|
||||
@@ -124,6 +136,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
custom: true,
|
||||
fontFamily: 'Empty Font',
|
||||
fontFaces: [],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
specialChars: {
|
||||
@@ -136,6 +151,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
sources: [{ url: 'https://example.com/fonts/special.woff2', format: 'woff2' }],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
complex: {
|
||||
@@ -158,6 +176,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
|
||||
variousURLs: {
|
||||
@@ -174,6 +195,9 @@ const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = {
|
||||
],
|
||||
},
|
||||
],
|
||||
permissions: {
|
||||
edit: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { CustomizationFontDefinition } from '@gitbook/api';
|
||||
import type { CustomizationFontDefinitionInput } from '@gitbook/api';
|
||||
|
||||
/**
|
||||
* Define the custom font faces and set the --font-custom to the custom font name
|
||||
*/
|
||||
export function generateFontFacesCSS(customFont: CustomizationFontDefinition): string {
|
||||
export function generateFontFacesCSS(customFont: CustomizationFontDefinitionInput): string {
|
||||
const { fontFaces } = customFont;
|
||||
|
||||
// Generate font face declarations for all weights
|
||||
@@ -45,7 +45,7 @@ export function generateFontFacesCSS(customFont: CustomizationFontDefinition): s
|
||||
/**
|
||||
* Get a list of font sources to preload (only 400 and 700 weights)
|
||||
*/
|
||||
export function getFontSourcesToPreload(customFont: CustomizationFontDefinition) {
|
||||
export function getFontSourcesToPreload(customFont: CustomizationFontDefinitionInput) {
|
||||
return customFont.fontFaces.filter(
|
||||
(face): face is typeof face & { weight: 400 | 700 } =>
|
||||
face.weight === 400 || face.weight === 700
|
||||
|
||||
@@ -4,17 +4,26 @@ import { type TranslationLanguage, languages } from './translations';
|
||||
|
||||
export * from './translate';
|
||||
|
||||
export const DEFAULT_LOCALE = 'en';
|
||||
|
||||
/**
|
||||
* Get the locale of the customization.
|
||||
*/
|
||||
export function getCustomizationLocale(customization: SiteCustomizationSettings): string {
|
||||
return customization.internationalization.locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the translation context for a space to use in the server components.
|
||||
*/
|
||||
export function getSpaceLanguage(customization: SiteCustomizationSettings): TranslationLanguage {
|
||||
const fallback = languages.en;
|
||||
const fallback = languages[DEFAULT_LOCALE];
|
||||
|
||||
const { locale } = customization.internationalization;
|
||||
const locale = getCustomizationLocale(customization);
|
||||
|
||||
let language = fallback;
|
||||
// @ts-ignore
|
||||
if (locale !== 'en' && languages[locale]) {
|
||||
if (locale !== DEFAULT_LOCALE && languages[locale]) {
|
||||
// @ts-ignore
|
||||
language = languages[locale];
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
type CacheFunctionOptions,
|
||||
cache,
|
||||
cacheResponse,
|
||||
getResponseCacheTags,
|
||||
noCacheFetchOptions,
|
||||
parseCacheResponse,
|
||||
} from './cache';
|
||||
@@ -268,6 +267,7 @@ export const getPublishedContentByUrl = cache({
|
||||
|
||||
const parsed = parseCacheResponse(response);
|
||||
|
||||
// biome-ignore lint/suspicious/noConsole: log the ttl of the token
|
||||
console.log(
|
||||
`Parsed ttl: ${parsed.ttl} at ${Date.now()}, for ${'apiToken' in response.data ? response.data.apiToken : '<no-token>'}`
|
||||
);
|
||||
@@ -371,17 +371,6 @@ interface GetRevisionOptions {
|
||||
* These options don't impact the cache key and it means revisions can be shared between different fetches with different metadata options.
|
||||
*/
|
||||
metadata: boolean;
|
||||
|
||||
/**
|
||||
* Whether to fetch the revision as a computed revision.
|
||||
* @default true
|
||||
*/
|
||||
computed?: boolean;
|
||||
|
||||
/**
|
||||
* Additional tags to add to the cache entry.
|
||||
*/
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
const getAPIContextId = async () => {
|
||||
@@ -394,14 +383,8 @@ const getAPIContextId = async () => {
|
||||
*/
|
||||
export const getRevision = cache({
|
||||
name: 'api.getRevision.v2',
|
||||
tag: (spaceId, revisionId, fetchOptions) =>
|
||||
// Temporary hack to make it work with OpenAPI on v1
|
||||
fetchOptions.tags?.[0] ??
|
||||
getCacheTag({
|
||||
tag: 'revision',
|
||||
space: spaceId,
|
||||
revision: revisionId,
|
||||
}),
|
||||
tag: (spaceId, revisionId) =>
|
||||
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||
tagImmutable: true,
|
||||
getKeySuffix: getAPIContextId,
|
||||
get: async (
|
||||
@@ -423,20 +406,9 @@ export const getRevision = cache({
|
||||
}
|
||||
);
|
||||
|
||||
return cacheResponse(response, {
|
||||
...(fetchOptions.metadata ? cacheTtl_7days : cacheTtl_1day),
|
||||
data: {
|
||||
...response.data,
|
||||
tags: getResponseCacheTags(response),
|
||||
},
|
||||
});
|
||||
},
|
||||
getKeyArgs: ([spaceId, revisionId, fetchOptions]) => {
|
||||
if (fetchOptions.computed === true) {
|
||||
return [spaceId, revisionId, { computed: true }];
|
||||
}
|
||||
return [spaceId, revisionId];
|
||||
return cacheResponse(response, fetchOptions.metadata ? cacheTtl_7days : cacheTtl_1day);
|
||||
},
|
||||
getKeyArgs: (args) => [args[0], args[1]],
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -444,14 +416,8 @@ export const getRevision = cache({
|
||||
*/
|
||||
export const getRevisionPages = cache({
|
||||
name: 'api.getRevisionPages.v4',
|
||||
tag: (spaceId, revisionId, fetchOptions) =>
|
||||
// Temporary hack to make it work with OpenAPI on v1
|
||||
fetchOptions.tags?.[0] ??
|
||||
getCacheTag({
|
||||
tag: 'revision',
|
||||
space: spaceId,
|
||||
revision: revisionId,
|
||||
}),
|
||||
tag: (spaceId, revisionId) =>
|
||||
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||
tagImmutable: true,
|
||||
getKeySuffix: getAPIContextId,
|
||||
get: async (
|
||||
@@ -475,15 +441,10 @@ export const getRevisionPages = cache({
|
||||
|
||||
return cacheResponse(response, {
|
||||
...(fetchOptions.metadata ? cacheTtl_7days : cacheTtl_1day),
|
||||
data: { ...response.data, tags: getResponseCacheTags(response) },
|
||||
data: response.data.pages,
|
||||
});
|
||||
},
|
||||
getKeyArgs: ([spaceId, revisionId, fetchOptions]) => {
|
||||
if (fetchOptions.computed === true) {
|
||||
return [spaceId, revisionId, { computed: true }];
|
||||
}
|
||||
return [spaceId, revisionId];
|
||||
},
|
||||
getKeyArgs: (args) => [args[0], args[1]],
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
+3
-10
@@ -13,14 +13,6 @@ export const noCacheFetchOptions: Partial<RequestInit> = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the cache tags from the response.
|
||||
*/
|
||||
export function getResponseCacheTags(response: Response): string[] {
|
||||
const cacheTagHeader = response.headers.get('x-gitbook-cache-tag');
|
||||
return !cacheTagHeader ? [] : cacheTagHeader.split(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an HTTP response into a cache entry.
|
||||
*/
|
||||
@@ -34,7 +26,8 @@ export function parseCacheResponse(response: Response): {
|
||||
const cacheControlHeader = response.headers.get('cache-control');
|
||||
const cacheControl = cacheControlHeader ? parseCacheControl(cacheControlHeader) : null;
|
||||
|
||||
const tags = getResponseCacheTags(response);
|
||||
const cacheTagHeader = response.headers.get('x-gitbook-cache-tag');
|
||||
const tags = !cacheTagHeader ? [] : cacheTagHeader.split(',');
|
||||
|
||||
const entry = {
|
||||
ttl: 60 * 60 * 24,
|
||||
@@ -54,7 +47,7 @@ export function parseCacheResponse(response: Response): {
|
||||
export function cacheResponse<Result, DefaultData = Result>(
|
||||
response: Response & { data: Result },
|
||||
defaultEntry: Partial<CacheResult<DefaultData>> = {}
|
||||
): CacheResult<DefaultData extends undefined ? Result : DefaultData> {
|
||||
): CacheResult<DefaultData extends Result ? Result : DefaultData> {
|
||||
const parsed = parseCacheResponse(response);
|
||||
|
||||
return {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { type CacheFunctionOptions, cache, noCacheFetchOptions } from '@/lib/cac
|
||||
import type {
|
||||
AnyOpenAPIOperationsBlock,
|
||||
OpenAPISchemasBlock,
|
||||
OpenAPIWebhookBlock,
|
||||
ResolveOpenAPIBlockArgs,
|
||||
} from '@/lib/openapi/types';
|
||||
import { getCloudflareRequestGlobal } from '@v2/lib/data/cloudflare';
|
||||
@@ -16,7 +17,7 @@ import { isV2 } from '../v2';
|
||||
import { enrichFilesystem } from './enrich';
|
||||
import type { FetchOpenAPIFilesystemResult } from './types';
|
||||
|
||||
type AnyOpenAPIBlock = AnyOpenAPIOperationsBlock | OpenAPISchemasBlock;
|
||||
type AnyOpenAPIBlock = AnyOpenAPIOperationsBlock | OpenAPISchemasBlock | OpenAPIWebhookBlock;
|
||||
|
||||
/**
|
||||
* Fetch OpenAPI block.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { fetchOpenAPIFilesystem } from '@/lib/openapi/fetch';
|
||||
import { OpenAPIParseError } from '@gitbook/openapi-parser';
|
||||
import { type OpenAPIWebhookData, resolveOpenAPIWebhook } from '@gitbook/react-openapi';
|
||||
import type {
|
||||
OpenAPIWebhookBlock,
|
||||
ResolveOpenAPIBlockArgs,
|
||||
ResolveOpenAPIBlockResult,
|
||||
} from './types';
|
||||
|
||||
type ResolveOpenAPIWebhookBlockResult = ResolveOpenAPIBlockResult<OpenAPIWebhookData>;
|
||||
|
||||
const weakmap = new WeakMap<OpenAPIWebhookBlock, Promise<ResolveOpenAPIWebhookBlockResult>>();
|
||||
|
||||
/**
|
||||
* Cache the result of resolving an OpenAPI block.
|
||||
* It is important because the resolve is called in sections and in the block itself.
|
||||
*/
|
||||
export function resolveOpenAPIWebhookBlock(
|
||||
args: ResolveOpenAPIBlockArgs<OpenAPIWebhookBlock>
|
||||
): Promise<ResolveOpenAPIWebhookBlockResult> {
|
||||
if (weakmap.has(args.block)) {
|
||||
return weakmap.get(args.block)!;
|
||||
}
|
||||
|
||||
const result = baseResolveOpenAPIWebhookBlock(args);
|
||||
weakmap.set(args.block, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve OpenAPI webhook block.
|
||||
*/
|
||||
async function baseResolveOpenAPIWebhookBlock(
|
||||
args: ResolveOpenAPIBlockArgs<OpenAPIWebhookBlock>
|
||||
): Promise<ResolveOpenAPIWebhookBlockResult> {
|
||||
const { context, block } = args;
|
||||
if (!block.data.name || !block.data.method) {
|
||||
return { data: null, specUrl: null };
|
||||
}
|
||||
|
||||
try {
|
||||
const { filesystem, specUrl } = await fetchOpenAPIFilesystem({ block, context });
|
||||
|
||||
if (!filesystem) {
|
||||
return { data: null, specUrl: null };
|
||||
}
|
||||
|
||||
const data = await resolveOpenAPIWebhook(filesystem, {
|
||||
name: block.data.name,
|
||||
method: block.data.method,
|
||||
});
|
||||
|
||||
return { data, specUrl };
|
||||
} catch (error) {
|
||||
if (error instanceof OpenAPIParseError) {
|
||||
return { error };
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import type {
|
||||
DocumentBlockOpenAPI,
|
||||
DocumentBlockOpenAPIOperation,
|
||||
DocumentBlockOpenAPISchemas,
|
||||
DocumentBlockOpenAPIWebhook,
|
||||
} from '@gitbook/api';
|
||||
import type { Filesystem, OpenAPIParseError, OpenAPIV3xDocument } from '@gitbook/openapi-parser';
|
||||
import type { GitBookAnyContext } from '@v2/lib/context';
|
||||
@@ -16,6 +17,11 @@ export type AnyOpenAPIOperationsBlock = DocumentBlockOpenAPI | DocumentBlockOpen
|
||||
*/
|
||||
export type OpenAPISchemasBlock = DocumentBlockOpenAPISchemas;
|
||||
|
||||
/**
|
||||
* Type for OpenAPI Webhook block
|
||||
*/
|
||||
export type OpenAPIWebhookBlock = DocumentBlockOpenAPIWebhook;
|
||||
|
||||
/**
|
||||
* Arguments for resolving OpenAPI block.
|
||||
*/
|
||||
|
||||
@@ -41,8 +41,12 @@ export interface ResolvedContentRef {
|
||||
file?: RevisionFile;
|
||||
/** Page document resolved from the content ref */
|
||||
page?: RevisionPageDocument;
|
||||
/** Resolved reusable content, if the ref points to reusable content on a revision. */
|
||||
reusableContent?: RevisionReusableContent;
|
||||
/** Resolved reusable content, if the ref points to reusable content on a revision. Also contains the space and revision used for resolution. */
|
||||
reusableContent?: {
|
||||
revisionReusableContent: RevisionReusableContent;
|
||||
space: Space;
|
||||
revision: string;
|
||||
};
|
||||
/** Resolve OpenAPI spec filesystem. */
|
||||
openAPIFilesystem?: Filesystem;
|
||||
}
|
||||
@@ -231,21 +235,52 @@ export async function resolveContentRef(
|
||||
}
|
||||
|
||||
case 'reusable-content': {
|
||||
// Figure out which space and revision the reusable content is in.
|
||||
const container: { space: Space; revision: string } | null = await (async () => {
|
||||
// without a space on the content ref, or if the space is the same as the current one, we can use the current revision.
|
||||
if (!contentRef.space || contentRef.space === context.space.id) {
|
||||
return { space: context.space, revision: revisionId };
|
||||
}
|
||||
|
||||
const space = await getDataOrNull(
|
||||
dataFetcher.getSpace({
|
||||
spaceId: contentRef.space,
|
||||
shareKey: undefined,
|
||||
})
|
||||
);
|
||||
|
||||
if (!space) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { space, revision: space.revision };
|
||||
})();
|
||||
|
||||
if (!container) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const reusableContent = await getDataOrNull(
|
||||
dataFetcher.getReusableContent({
|
||||
spaceId: space.id,
|
||||
revisionId,
|
||||
spaceId: container.space.id,
|
||||
revisionId: container.revision,
|
||||
reusableContentId: contentRef.reusableContent,
|
||||
})
|
||||
);
|
||||
|
||||
if (!reusableContent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
href: getGitBookAppHref(`/s/${space.id}`),
|
||||
href: getGitBookAppHref(`/s/${container.space}/~/reusable/${reusableContent.id}`),
|
||||
text: reusableContent.title,
|
||||
active: false,
|
||||
reusableContent,
|
||||
reusableContent: {
|
||||
revisionReusableContent: reusableContent,
|
||||
space: container.space,
|
||||
revision: container.revision,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+191
-156
@@ -8,7 +8,7 @@ import type { GitBookDataFetcher } from '@v2/lib/data/types';
|
||||
import { createImageResizer } from '@v2/lib/images';
|
||||
import { createLinker } from '@v2/lib/links';
|
||||
|
||||
import { RevisionPageType } from '@gitbook/api';
|
||||
import { GitBookAPI } from '@gitbook/api';
|
||||
import { DataFetcherError, wrapDataFetcherError } from '@v2/lib/data';
|
||||
import { headers } from 'next/headers';
|
||||
import {
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
getUserById,
|
||||
renderIntegrationUi,
|
||||
searchSiteContent,
|
||||
withAPI as withAPIV1,
|
||||
} from './api';
|
||||
import { getDynamicCustomizationSettings } from './customization';
|
||||
import { withLeadingSlash, withTrailingSlash } from './paths';
|
||||
@@ -59,7 +60,7 @@ export async function getV1BaseContext(): Promise<GitBookBaseContext> {
|
||||
return url;
|
||||
};
|
||||
|
||||
const dataFetcher = await getDataFetcherV1();
|
||||
const dataFetcher = getDataFetcherV1();
|
||||
|
||||
const imageResizer = createImageResizer({
|
||||
imagesContextId: host,
|
||||
@@ -83,97 +84,121 @@ export async function getV1BaseContext(): Promise<GitBookBaseContext> {
|
||||
* Try not to use this as much as possible, and instead take the data fetcher from the props.
|
||||
* This data fetcher should only be used at the top of the tree.
|
||||
*/
|
||||
async function getDataFetcherV1(): Promise<GitBookDataFetcher> {
|
||||
function getDataFetcherV1(apiTokenOverride?: string): GitBookDataFetcher {
|
||||
let apiClient: GitBookAPI | undefined;
|
||||
|
||||
/**
|
||||
* Run a function with the correct API client. If an API token is provided, we
|
||||
* create a new API client with the token. Otherwise, we use the default API client.
|
||||
*/
|
||||
async function withAPI<T>(fn: () => Promise<T>): Promise<T> {
|
||||
// No token override - we can use the default API client.
|
||||
if (!apiTokenOverride) {
|
||||
return fn();
|
||||
}
|
||||
|
||||
const client = await api();
|
||||
|
||||
if (!apiClient) {
|
||||
// New client uses same endpoint and user agent as the default client.
|
||||
apiClient = new GitBookAPI({
|
||||
endpoint: client.client.endpoint,
|
||||
authToken: apiTokenOverride,
|
||||
userAgent: client.client.userAgent,
|
||||
});
|
||||
}
|
||||
|
||||
return withAPIV1(
|
||||
{
|
||||
client: apiClient,
|
||||
contextId: client.contextId,
|
||||
},
|
||||
fn
|
||||
);
|
||||
}
|
||||
|
||||
const dataFetcher: GitBookDataFetcher = {
|
||||
async api() {
|
||||
const result = await api();
|
||||
return result.client;
|
||||
return withAPI(async () => {
|
||||
const result = await api();
|
||||
return result.client;
|
||||
});
|
||||
},
|
||||
|
||||
withToken() {
|
||||
// In v1, the token is global and controlled by the middleware.
|
||||
// We don't need to do anything special here.
|
||||
return dataFetcher;
|
||||
withToken({ apiToken }) {
|
||||
return getDataFetcherV1(apiToken);
|
||||
},
|
||||
|
||||
getUserById(userId) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const user = await getUserById(userId);
|
||||
if (!user) {
|
||||
throw new DataFetcherError('User not found', 404);
|
||||
}
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const user = await getUserById(userId);
|
||||
if (!user) {
|
||||
throw new DataFetcherError('User not found', 404);
|
||||
}
|
||||
|
||||
return user;
|
||||
});
|
||||
return user;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getPublishedContentSite(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
return getPublishedContentSite(params);
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
return getPublishedContentSite(params);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getSpace(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
return getSpace(params.spaceId, params.shareKey);
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
return getSpace(params.spaceId, params.shareKey);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getChangeRequest(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const changeRequest = await getChangeRequest(
|
||||
params.spaceId,
|
||||
params.changeRequestId
|
||||
);
|
||||
if (!changeRequest) {
|
||||
throw new DataFetcherError('Change request not found', 404);
|
||||
}
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const changeRequest = await getChangeRequest(
|
||||
params.spaceId,
|
||||
params.changeRequestId
|
||||
);
|
||||
if (!changeRequest) {
|
||||
throw new DataFetcherError('Change request not found', 404);
|
||||
}
|
||||
|
||||
return changeRequest;
|
||||
});
|
||||
return changeRequest;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getRevision(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const { tags, ...revision } = await getRevision(params.spaceId, params.revisionId, {
|
||||
metadata: params.metadata,
|
||||
computed: false,
|
||||
});
|
||||
|
||||
if (
|
||||
Object.values(revision.pages).some(
|
||||
(page) => page.type === RevisionPageType.Computed
|
||||
)
|
||||
) {
|
||||
const { tags: _tags, ...revision } = await getRevision(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
{
|
||||
metadata: params.metadata,
|
||||
computed: true,
|
||||
tags,
|
||||
}
|
||||
);
|
||||
return revision;
|
||||
}
|
||||
|
||||
return revision;
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
return getRevision(params.spaceId, params.revisionId, {
|
||||
metadata: params.metadata,
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getRevisionFile(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const revisionFile = await getRevisionFile(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.fileId
|
||||
);
|
||||
if (!revisionFile) {
|
||||
throw new DataFetcherError('Revision file not found', 404);
|
||||
}
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const revisionFile = await getRevisionFile(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.fileId
|
||||
);
|
||||
if (!revisionFile) {
|
||||
throw new DataFetcherError('Revision file not found', 404);
|
||||
}
|
||||
|
||||
return revisionFile;
|
||||
});
|
||||
return revisionFile;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getRevisionPageMarkdown() {
|
||||
@@ -181,130 +206,140 @@ async function getDataFetcherV1(): Promise<GitBookDataFetcher> {
|
||||
},
|
||||
|
||||
getDocument(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const document = await getDocument(params.spaceId, params.documentId);
|
||||
if (!document) {
|
||||
throw new DataFetcherError('Document not found', 404);
|
||||
}
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const document = await getDocument(params.spaceId, params.documentId);
|
||||
if (!document) {
|
||||
throw new DataFetcherError('Document not found', 404);
|
||||
}
|
||||
|
||||
return document;
|
||||
});
|
||||
return document;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getComputedDocument(params) {
|
||||
return wrapDataFetcherError(() => {
|
||||
return getComputedDocument(
|
||||
params.organizationId,
|
||||
params.spaceId,
|
||||
params.source,
|
||||
params.seed
|
||||
);
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(() => {
|
||||
return getComputedDocument(
|
||||
params.organizationId,
|
||||
params.spaceId,
|
||||
params.source,
|
||||
params.seed
|
||||
);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getRevisionPages(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const { pages, tags } = await getRevisionPages(params.spaceId, params.revisionId, {
|
||||
metadata: params.metadata,
|
||||
computed: false,
|
||||
});
|
||||
|
||||
if (pages.some((page) => page.type === RevisionPageType.Computed)) {
|
||||
const { pages } = await getRevisionPages(params.spaceId, params.revisionId, {
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
return getRevisionPages(params.spaceId, params.revisionId, {
|
||||
metadata: params.metadata,
|
||||
computed: true,
|
||||
tags,
|
||||
});
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
return pages;
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getRevisionPageByPath(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const revisionPage = await getRevisionPageByPath(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.path
|
||||
);
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const revisionPage = await getRevisionPageByPath(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.path
|
||||
);
|
||||
|
||||
if (!revisionPage) {
|
||||
throw new DataFetcherError('Revision page not found', 404);
|
||||
}
|
||||
if (!revisionPage) {
|
||||
throw new DataFetcherError('Revision page not found', 404);
|
||||
}
|
||||
|
||||
return revisionPage;
|
||||
});
|
||||
return revisionPage;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getReusableContent(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const reusableContent = await getReusableContent(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.reusableContentId
|
||||
);
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const reusableContent = await getReusableContent(
|
||||
params.spaceId,
|
||||
params.revisionId,
|
||||
params.reusableContentId
|
||||
);
|
||||
|
||||
if (!reusableContent) {
|
||||
throw new DataFetcherError('Reusable content not found', 404);
|
||||
}
|
||||
if (!reusableContent) {
|
||||
throw new DataFetcherError('Reusable content not found', 404);
|
||||
}
|
||||
|
||||
return reusableContent;
|
||||
});
|
||||
return reusableContent;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getLatestOpenAPISpecVersionContent(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const openAPISpecVersionContent = await getLatestOpenAPISpecVersionContent(
|
||||
params.organizationId,
|
||||
params.slug
|
||||
);
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const openAPISpecVersionContent = await getLatestOpenAPISpecVersionContent(
|
||||
params.organizationId,
|
||||
params.slug
|
||||
);
|
||||
|
||||
if (!openAPISpecVersionContent) {
|
||||
throw new DataFetcherError('OpenAPI spec version content not found', 404);
|
||||
}
|
||||
if (!openAPISpecVersionContent) {
|
||||
throw new DataFetcherError('OpenAPI spec version content not found', 404);
|
||||
}
|
||||
|
||||
return openAPISpecVersionContent;
|
||||
});
|
||||
return openAPISpecVersionContent;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
getSiteRedirectBySource(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const siteRedirect = await getSiteRedirectBySource(params);
|
||||
if (!siteRedirect) {
|
||||
throw new DataFetcherError('Site redirect not found', 404);
|
||||
}
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const siteRedirect = await getSiteRedirectBySource(params);
|
||||
if (!siteRedirect) {
|
||||
throw new DataFetcherError('Site redirect not found', 404);
|
||||
}
|
||||
|
||||
return siteRedirect;
|
||||
});
|
||||
return siteRedirect;
|
||||
})
|
||||
);
|
||||
},
|
||||
getEmbedByUrl(params) {
|
||||
return wrapDataFetcherError(() => {
|
||||
return getEmbedByUrlInSpace(params.spaceId, params.url);
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(() => {
|
||||
return getEmbedByUrlInSpace(params.spaceId, params.url);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
searchSiteContent(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const { organizationId, siteId, query, cacheBust, scope } = params;
|
||||
const result = await searchSiteContent(
|
||||
organizationId,
|
||||
siteId,
|
||||
query,
|
||||
scope,
|
||||
cacheBust
|
||||
);
|
||||
return result.items;
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const { organizationId, siteId, query, cacheBust, scope } = params;
|
||||
const result = await searchSiteContent(
|
||||
organizationId,
|
||||
siteId,
|
||||
query,
|
||||
scope,
|
||||
cacheBust
|
||||
);
|
||||
return result.items;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
renderIntegrationUi(params) {
|
||||
return wrapDataFetcherError(async () => {
|
||||
const result = await renderIntegrationUi(params.integrationName, params.request);
|
||||
return result;
|
||||
});
|
||||
return withAPI(() =>
|
||||
wrapDataFetcherError(async () => {
|
||||
const result = await renderIntegrationUi(
|
||||
params.integrationName,
|
||||
params.request
|
||||
);
|
||||
return result;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
streamAIResponse() {
|
||||
|
||||
@@ -8,20 +8,23 @@ export async function serveRobotsTxt(context: GitBookSiteContext) {
|
||||
const { linker } = context;
|
||||
|
||||
const isRoot = checkIsRootSiteContext(context);
|
||||
const lines = [
|
||||
'User-agent: *',
|
||||
// Disallow dynamic routes / search queries
|
||||
'Disallow: /*?',
|
||||
...((await isSiteIndexable(context))
|
||||
? [
|
||||
'Allow: /',
|
||||
`Sitemap: ${linker.toAbsoluteURL(linker.toPathInSpace(isRoot ? '/sitemap.xml' : '/sitemap-pages.xml'))}`,
|
||||
]
|
||||
: ['Disallow: /']),
|
||||
];
|
||||
const content = lines.join('\n');
|
||||
const isIndexable = await isSiteIndexable(context);
|
||||
|
||||
return new Response(content, {
|
||||
const lines = isIndexable
|
||||
? [
|
||||
'User-agent: *',
|
||||
// Allow image resizing and icon generation routes for favicons and search results
|
||||
'Allow: /~gitbook/image?*',
|
||||
'Allow: /~gitbook/icon?*',
|
||||
// Disallow other dynamic routes / search queries
|
||||
'Disallow: /*?',
|
||||
'Allow: /',
|
||||
`Sitemap: ${linker.toAbsoluteURL(linker.toPathInSpace(isRoot ? '/sitemap.xml' : '/sitemap-pages.xml'))}`,
|
||||
]
|
||||
: ['User-agent: *', 'Disallow: /'];
|
||||
|
||||
const robotsTxt = lines.join('\n');
|
||||
return new Response(robotsTxt, {
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
},
|
||||
|
||||
@@ -141,7 +141,7 @@ function getUrlsFromSiteSpaces(context: GitBookSiteContext, siteSpaces: SiteSpac
|
||||
}
|
||||
const url = new URL(siteSpace.urls.published);
|
||||
url.pathname = joinPath(url.pathname, 'sitemap-pages.xml');
|
||||
return context.linker.toLinkForContent(url.toString());
|
||||
return context.linker.toAbsoluteURL(context.linker.toLinkForContent(url.toString()));
|
||||
}, []);
|
||||
return urls.filter(filterOutNullable);
|
||||
}
|
||||
|
||||
@@ -296,14 +296,14 @@ const config: Config = {
|
||||
},
|
||||
animation: {
|
||||
present: 'present 200ms cubic-bezier(0.25, 1, 0.5, 1) both',
|
||||
scaleIn: 'scaleIn 200ms ease',
|
||||
scaleOut: 'scaleOut 200ms ease',
|
||||
fadeIn: 'fadeIn 200ms ease forwards',
|
||||
fadeOut: 'fadeOut 200ms ease forwards',
|
||||
enterFromLeft: 'enterFromLeft 250ms ease',
|
||||
enterFromRight: 'enterFromRight 250ms ease',
|
||||
exitToLeft: 'exitToLeft 250ms ease',
|
||||
exitToRight: 'exitToRight 250ms ease',
|
||||
scaleIn: 'scaleIn 200ms ease both',
|
||||
scaleOut: 'scaleOut 200ms ease both',
|
||||
fadeIn: 'fadeIn 200ms ease both',
|
||||
fadeOut: 'fadeOut 200ms ease both',
|
||||
enterFromLeft: 'enterFromLeft 250ms ease both',
|
||||
enterFromRight: 'enterFromRight 250ms ease both',
|
||||
exitToLeft: 'exitToLeft 250ms ease both',
|
||||
exitToRight: 'exitToRight 250ms ease both',
|
||||
},
|
||||
keyframes: {
|
||||
pulseAlt: {
|
||||
@@ -443,6 +443,7 @@ const config: Config = {
|
||||
scale: {
|
||||
'98': '0.98',
|
||||
'102': '1.02',
|
||||
'104': '1.04',
|
||||
},
|
||||
},
|
||||
opacity: opacity(),
|
||||
@@ -464,6 +465,11 @@ const config: Config = {
|
||||
'body:has(.page-no-toc):has(#site-header:not(.mobile-only) #variants) &',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Variant when the adaptive pane is open.
|
||||
*/
|
||||
addVariant('adaptive-pane', 'body.adaptive-pane &');
|
||||
|
||||
const customisationVariants = {
|
||||
// Sidebar styles
|
||||
sidebar: ['sidebar-default', 'sidebar-filled'],
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# @gitbook/react-openapi
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ebc39e9: Missing select icon
|
||||
- b6b09d4: Fix OpenAPI responses select placement and icon
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- d67699a: Add OpenAPI Webhook block
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- eeb977f: Fix Python code example for JSON payload
|
||||
- 3363a18: Merge simple alternatives
|
||||
- 8ed1bda: Translate OpenAPI blocks
|
||||
- 7588cfe: Improve OpenAPIResponses examples and schemas
|
||||
- ad1dc0b: Bump scalar packages
|
||||
|
||||
## 1.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"version": "1.1.10",
|
||||
"version": "1.2.1",
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@gitbook/openapi-parser": "workspace:*",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user