Compare commits

..

35 Commits

Author SHA1 Message Date
Samy Pessé 7b34537bbe Version Packages (#3599)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-09-06 11:40:05 +02:00
conico974 145f385fdb Add pagination for llms-full.txt file (#3619)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2025-09-05 17:20:25 +02:00
Greg Bergé 360aa1c6d6 Upgrade Scalar dependencies (#3626) 2025-09-05 16:57:21 +02:00
conico974 ccc0975240 Fix error on parameters being an object instead of an array (#3623)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2025-09-05 16:17:50 +02:00
Zeno Kapitein 791135040a Add language selector to site header (#3622) 2025-09-05 12:15:07 +00:00
spastorelli 12c9d765ff Adapt OpenAPI to eval adaptive exprs & prefill TryIt config (#3607) 2025-09-05 13:39:12 +02:00
Greg Bergé 45207288a1 Support bold in headings (#3609) 2025-09-05 11:47:39 +02:00
Viktor Renkema 177afa5828 Handle non-defined objectFit on card cover images (#3625) 2025-09-05 10:42:57 +02:00
Zeno Kapitein d51b79edbb Fix "Search bar is broken on site with sections when header is disabled" (#3624) 2025-09-04 13:48:08 +02:00
conico974 a2720ac49d Update @opennextjs/cloudflare to version 1.7.1 (#3620)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2025-09-03 16:09:27 +02:00
Viktor Renkema 5f6853d812 Support new object-fit property on individual card cover image (#3594) 2025-09-03 09:11:17 +02:00
Zeno Kapitein 17dd382dc3 Add "original" color step and apply to bg-primary-solid elements (#3618) 2025-09-02 16:08:21 +02:00
Nolann B. 98e42cfe79 Handle OpenAPI ignored responses (#3614) 2025-09-01 14:25:35 +02:00
Samy Pessé c890e01004 Fix order in robots.txt preventing indexation of images by Google (#3617) 2025-09-01 11:21:11 +00:00
Samy Pessé 659be551bb Track insight event when embedded assistant is displayed (#3616) 2025-09-01 12:59:40 +02:00
Zeno Kapitein 78a632b7fe Fix Edit on GitHub button doesn't take you to GitHub (#3615) 2025-09-01 12:01:36 +02:00
spastorelli 4927e964b7 Add support for YAML content type in request body/example (#3612) 2025-09-01 10:56:09 +02:00
Samy Pessé 262a9b198b Fix embed script caching (#3611) 2025-08-29 22:35:14 +02:00
Samy Pessé 4f3588240c Unify layout and fix tracking of ask_question (#3610) 2025-08-29 16:10:28 +02:00
Nolann B. abbae3ec4d Remove scroll-nojump utility and update layout structure (#3494)
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2025-08-29 11:22:55 +02:00
conico974 1b8609ac60 fix next start not working (#3608)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2025-08-28 16:36:06 +02:00
Samy Pessé 193d591e9f Use space.language as source of truth (#3606) 2025-08-27 18:27:29 +02:00
Zeno Kapitein 1edc5d622a Assistant hold message (#3603) 2025-08-27 13:48:57 +00:00
Zeno Kapitein 61b8507996 OpenAPI: Make empty responses clickable (#3605) 2025-08-27 13:38:24 +00:00
Zeno Kapitein 6f368b5cf3 Fix embed assistant window width on small screens (#3604) 2025-08-27 15:33:37 +02:00
Brett Jephson 9201e2cf52 Add vertical align property to column block (#3596)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2025-08-27 13:58:26 +01:00
Zeno Kapitein 2e0d706d43 Fix corner radius of active section on "Line" sidebar style (#3601) 2025-08-27 13:15:07 +02:00
Nolann B. 7fefe4919c Catch OpenAPI validation errors (#3602) 2025-08-27 12:29:50 +02:00
Zeno Kapitein 729921f338 Move "Edit on Git" and "Export PDF" actions into page actions dropdown (#3574) 2025-08-27 11:32:55 +02:00
Zeno Kapitein 1839ea2678 Fix content min-height with sections (#3597) 2025-08-27 11:30:22 +02:00
Zeno Kapitein f08dd29364 Fix Search results are not clickable (#3595) 2025-08-26 20:33:37 +00:00
conico974 ca2dfa3065 Rollback to Next.js 15.3 (#3600)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2025-08-26 18:26:32 +02:00
Utku Ufuk 10ded437f0 Turn on the "noUncheckedIndexedAccess" flag in all TS config files (#3587) 2025-08-26 19:25:54 +03:00
Zeno Kapitein d1fdc13441 Remove ligatures from Lato font (#3592) 2025-08-26 15:04:22 +00:00
Zeno Kapitein a8fca0e033 Fix custom assistant keyboard shortcut (#3598) 2025-08-26 14:57:08 +00:00
150 changed files with 3519 additions and 1333 deletions
+560 -52
View File
@@ -12,7 +12,7 @@
}, },
"packages/browser-types": { "packages/browser-types": {
"name": "@gitbook/browser-types", "name": "@gitbook/browser-types",
"version": "0.0.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/icons": "workspace:", "@gitbook/icons": "workspace:",
@@ -41,7 +41,7 @@
}, },
"packages/embed": { "packages/embed": {
"name": "@gitbook/embed", "name": "@gitbook/embed",
"version": "0.0.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/icons": "workspace:", "@gitbook/icons": "workspace:",
@@ -64,7 +64,7 @@
}, },
"packages/expr": { "packages/expr": {
"name": "@gitbook/expr", "name": "@gitbook/expr",
"version": "0.0.1", "version": "1.0.0",
"dependencies": { "dependencies": {
"acorn": "^8.14.0", "acorn": "^8.14.0",
"acorn-loose": "8.4.0", "acorn-loose": "8.4.0",
@@ -92,20 +92,21 @@
}, },
"packages/gitbook": { "packages/gitbook": {
"name": "gitbook", "name": "gitbook",
"version": "0.15.0", "version": "0.16.0",
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/browser-types": "workspace:*", "@gitbook/browser-types": "workspace:*",
"@gitbook/cache-tags": "workspace:*", "@gitbook/cache-tags": "workspace:*",
"@gitbook/colors": "workspace:*", "@gitbook/colors": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*", "@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/expr": "workspace:*",
"@gitbook/fonts": "workspace:*", "@gitbook/fonts": "workspace:*",
"@gitbook/icons": "workspace:*", "@gitbook/icons": "workspace:*",
"@gitbook/openapi-parser": "workspace:*", "@gitbook/openapi-parser": "workspace:*",
"@gitbook/react-contentkit": "workspace:*", "@gitbook/react-contentkit": "workspace:*",
"@gitbook/react-math": "workspace:*", "@gitbook/react-math": "workspace:*",
"@gitbook/react-openapi": "workspace:*", "@gitbook/react-openapi": "workspace:*",
"@opennextjs/cloudflare": "^1.6.4", "@opennextjs/cloudflare": "^1.7.1",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.1.12", "@radix-ui/react-dropdown-menu": "^2.1.12",
"@radix-ui/react-hover-card": "^1.1.15", "@radix-ui/react-hover-card": "^1.1.15",
@@ -137,7 +138,7 @@
"memoizee": "^0.4.17", "memoizee": "^0.4.17",
"micromark-extension-frontmatter": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0",
"micromark-extension-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0",
"next": "^15.5.0", "next": "15.3.5",
"next-themes": "^0.2.1", "next-themes": "^0.2.1",
"nuqs": "^2.2.3", "nuqs": "^2.2.3",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
@@ -193,7 +194,7 @@
}, },
"packages/icons": { "packages/icons": {
"name": "@gitbook/icons", "name": "@gitbook/icons",
"version": "0.2.2", "version": "0.3.0",
"bin": { "bin": {
"gitbook-icons": "./bin/gitbook-icons.js", "gitbook-icons": "./bin/gitbook-icons.js",
}, },
@@ -213,10 +214,11 @@
}, },
"packages/openapi-parser": { "packages/openapi-parser": {
"name": "@gitbook/openapi-parser", "name": "@gitbook/openapi-parser",
"version": "3.0.0", "version": "3.0.1",
"dependencies": { "dependencies": {
"@scalar/openapi-parser": "^0.18.0", "@scalar/json-magic": "^0.3.1",
"@scalar/openapi-types": "^0.1.9", "@scalar/openapi-parser": "^0.20.1",
"@scalar/openapi-types": "^0.3.7",
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node20": "^20.1.4", "@tsconfig/node20": "^20.1.4",
@@ -228,7 +230,7 @@
}, },
"packages/react-contentkit": { "packages/react-contentkit": {
"name": "@gitbook/react-contentkit", "name": "@gitbook/react-contentkit",
"version": "0.7.3", "version": "0.7.4",
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/icons": "workspace:*", "@gitbook/icons": "workspace:*",
@@ -260,13 +262,16 @@
}, },
"packages/react-openapi": { "packages/react-openapi": {
"name": "@gitbook/react-openapi", "name": "@gitbook/react-openapi",
"version": "1.3.5", "version": "1.3.6",
"dependencies": { "dependencies": {
"@gitbook/expr": "workspace:*",
"@gitbook/openapi-parser": "workspace:*", "@gitbook/openapi-parser": "workspace:*",
"@scalar/api-client-react": "^1.3.16", "@scalar/api-client-react": "^1.3.16",
"@scalar/oas-utils": "^0.2.130", "@scalar/oas-utils": "^0.2.130",
"@scalar/types": "^0.1.9",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"flatted": "^3.2.9", "flatted": "^3.2.9",
"js-yaml": "^4.1.0",
"json-xml-parse": "^1.3.0", "json-xml-parse": "^1.3.0",
"react-aria": "^3.37.0", "react-aria": "^3.37.0",
"react-aria-components": "^1.6.0", "react-aria-components": "^1.6.0",
@@ -274,6 +279,7 @@
"zustand": "^5.0.3", "zustand": "^5.0.3",
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^4.0.9",
"bun-types": "^1.1.20", "bun-types": "^1.1.20",
"typescript": "^5.5.3", "typescript": "^5.5.3",
}, },
@@ -293,7 +299,7 @@
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
}, },
"catalog": { "catalog": {
"@gitbook/api": "^0.136.0", "@gitbook/api": "^0.139.0",
"bidc": "^0.0.2", "bidc": "^0.0.2",
}, },
"packages": { "packages": {
@@ -447,7 +453,7 @@
"@babel/highlight": ["@babel/highlight@7.25.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw=="], "@babel/highlight": ["@babel/highlight@7.25.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw=="],
"@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="], "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
"@babel/runtime": ["@babel/runtime@7.25.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w=="], "@babel/runtime": ["@babel/runtime@7.25.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w=="],
@@ -659,7 +665,7 @@
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="], "@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.136.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-IxNqmXE6yUEUq0IzbenN8S/PcMfgxr4+akY8xh6V5ShI/+U37ixujJHZp2zJq6NdZOdBQoR3UQmhPnvtWrkF7g=="], "@gitbook/api": ["@gitbook/api@0.139.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-6VqN4BVvOdaRng2xz5wh0gj6NJmJJZwtswKZ6g9RMWedp2UkeMXi+kcO3fBo2VYJsxhIgbtWikqGEePgHTx67g=="],
"@gitbook/browser-types": ["@gitbook/browser-types@workspace:packages/browser-types"], "@gitbook/browser-types": ["@gitbook/browser-types@workspace:packages/browser-types"],
@@ -795,23 +801,23 @@
"@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0-rc.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-nhSMNprz3WmeRvd8iUs5JqkKr0Ncx46JtPxM3AhXes84XpSJfmIwKeWXRpsr53S7kqPkQfPhzrMFUxSNb23qSA=="], "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0-rc.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-nhSMNprz3WmeRvd8iUs5JqkKr0Ncx46JtPxM3AhXes84XpSJfmIwKeWXRpsr53S7kqPkQfPhzrMFUxSNb23qSA=="],
"@next/env": ["@next/env@15.5.0", "", {}, "sha512-sDaprBAfzCQiOgo2pO+LhnV0Wt2wBgartjrr+dpcTORYVnnXD0gwhHhiiyIih9hQbq+JnbqH4odgcFWhqCGidw=="], "@next/env": ["@next/env@15.3.5", "", {}, "sha512-7g06v8BUVtN2njAX/r8gheoVffhiKFVt4nx74Tt6G4Hqw9HCLYQVx/GkH2qHvPtAHZaUNZ0VXAa0pQP6v1wk7g=="],
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.5.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v7Jj9iqC6enxIRBIScD/o0lH7QKvSxq2LM8UTyqJi+S2w2QzhMYjven4vgu/RzgsdtdbpkyCxBTzHl/gN5rTRg=="], "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-lM/8tilIsqBq+2nq9kbTW19vfwFve0NR7MxfkuSUbRSgXlMQoJYg+31+++XwKVSXk4uT23G2eF/7BRIKdn8t8w=="],
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.5.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-s2Nk6ec+pmYmAb/utawuURy7uvyYKDk+TRE5aqLRsdnj3AhwC9IKUBmhfnLmY/+P+DnwqpeXEFIKe9tlG0p6CA=="], "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-WhwegPQJ5IfoUNZUVsI9TRAlKpjGVK0tpJTL6KeiC4cux9774NYE9Wu/iCfIkL/5J8rPAkqZpG7n+EfiAfidXA=="],
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-mGlPJMZReU4yP5fSHjOxiTYvZmwPSWn/eF/dcg21pwfmiUCKS1amFvf1F1RkLHPIMPfocxLViNWFvkvDB14Isg=="], "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-LVD6uMOZ7XePg3KWYdGuzuvVboxujGjbcuP2jsPAN3MnLdLoZUXKRc6ixxfs03RH7qBdEHCZjyLP/jBdCJVRJQ=="],
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-biWqIOE17OW/6S34t1X8K/3vb1+svp5ji5QQT/IKR+VfM3B7GvlCwmz5XtlEan2ukOUf9tj2vJJBffaGH4fGRw=="], "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-k8aVScYZ++BnS2P69ClK7v4nOu702jcF9AIHKu6llhHEtBSmM2zkPGl9yoqbSU/657IIIb0QHpdxEr0iW9z53A=="],
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-zPisT+obYypM/l6EZ0yRkK3LEuoZqHaSoYKj+5jiD9ESHwdr6QhnabnNxYkdy34uCigNlWIaCbjFmQ8FY5AlxA=="], "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-2xYU0DI9DGN/bAHzVwADid22ba5d/xrbrQlr2U+/Q5WkFUzeL0TDR963BdrtLS/4bMmKZGptLeg6282H/S2i8A=="],
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-+t3+7GoU9IYmk+N+FHKBNFdahaReoAktdOpXHFIPOU1ixxtdge26NgQEEkJkCw2dHT9UwwK5zw4mAsURw4E8jA=="], "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-TRYIqAGf1KCbuAB0gjhdn5Ytd8fV+wJSM2Nh2is/xEqR8PZHxfQuaiNhoF50XfY90sNpaRMaGhF6E+qjV1b9Tg=="],
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.5.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-d8MrXKh0A+c9DLiy1BUFwtg3Hu90Lucj3k6iKTUdPOv42Ve2UiIG8HYi3UAb8kFVluXxEfdpCoPPCSODk5fDcw=="], "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.3.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-h04/7iMEUSMY6fDGCvdanKqlO1qYvzNxntZlCzfE8i5P0uqzVQWQquU1TIhlz0VqGQGXLrFDuTJVONpqGqjGKQ=="],
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.5.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Fe1tGHxOWEyQjmygWkkXSwhFcTJuimrNu52JEuwItrKJVV4iRjbWp9I7zZjwqtiNnQmxoEvoisn8wueFLrNpvQ=="], "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.5", "", { "os": "win32", "cpu": "x64" }, "sha512-5fhH6fccXxnX2KhllnGhkYMndhOiLOLEiVGYjP2nizqeGWkN10sA9taATlXwake2E2XMvYZjjz0Uj7T0y+z1yw=="],
"@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="], "@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="],
@@ -847,9 +853,9 @@
"@octokit/types": ["@octokit/types@14.1.0", "", { "dependencies": { "@octokit/openapi-types": "^25.1.0" } }, "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g=="], "@octokit/types": ["@octokit/types@14.1.0", "", { "dependencies": { "@octokit/openapi-types": "^25.1.0" } }, "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g=="],
"@opennextjs/aws": ["@opennextjs/aws@3.7.4", "", { "dependencies": { "@ast-grep/napi": "^0.35.0", "@aws-sdk/client-cloudfront": "3.398.0", "@aws-sdk/client-dynamodb": "^3.398.0", "@aws-sdk/client-lambda": "^3.398.0", "@aws-sdk/client-s3": "^3.398.0", "@aws-sdk/client-sqs": "^3.398.0", "@node-minify/core": "^8.0.6", "@node-minify/terser": "^8.0.6", "@tsconfig/node18": "^1.0.1", "aws4fetch": "^1.0.18", "chalk": "^5.3.0", "cookie": "^1.0.2", "esbuild": "0.25.4", "express": "5.0.1", "path-to-regexp": "^6.3.0", "urlpattern-polyfill": "^10.0.0", "yaml": "^2.7.0" }, "bin": { "open-next": "dist/index.js" } }, "sha512-s50dmKrgQ62GliffoI/hGGQVb3q/7ZN5VRa4jJw0ZsEGLfk25XuAulO/ySCYeE7/A23KoAYuhafnKr/h+vxOeQ=="], "@opennextjs/aws": ["@opennextjs/aws@3.7.6", "", { "dependencies": { "@ast-grep/napi": "^0.35.0", "@aws-sdk/client-cloudfront": "3.398.0", "@aws-sdk/client-dynamodb": "^3.398.0", "@aws-sdk/client-lambda": "^3.398.0", "@aws-sdk/client-s3": "^3.398.0", "@aws-sdk/client-sqs": "^3.398.0", "@node-minify/core": "^8.0.6", "@node-minify/terser": "^8.0.6", "@tsconfig/node18": "^1.0.1", "aws4fetch": "^1.0.18", "chalk": "^5.3.0", "cookie": "^1.0.2", "esbuild": "0.25.4", "express": "5.0.1", "path-to-regexp": "^6.3.0", "urlpattern-polyfill": "^10.0.0", "yaml": "^2.7.0" }, "bin": { "open-next": "dist/index.js" } }, "sha512-l4UGkmaZaAjWER+PuZ/zNziMnrbf6oA9B1RUDKcyKsX+hEES1b7h6kLgpo4a4maf01M+k0yJUZQyF4sf+vI+Iw=="],
"@opennextjs/cloudflare": ["@opennextjs/cloudflare@1.6.4", "", { "dependencies": { "@dotenvx/dotenvx": "1.31.0", "@opennextjs/aws": "3.7.4", "cloudflare": "^4.4.1", "enquirer": "^2.4.1", "glob": "^11.0.0", "ts-tqdm": "^0.8.6", "yargs": "^18.0.0" }, "peerDependencies": { "wrangler": "^4.24.4" }, "bin": { "opennextjs-cloudflare": "dist/cli/index.js" } }, "sha512-vGEHr1+Dli4BSrs+CM+b2bnXoUdY/GUFiLfdH28UTRHggLMG7cL49M39LtzIVR5D8eqzZ38PDB2CZMn1LJ2gSw=="], "@opennextjs/cloudflare": ["@opennextjs/cloudflare@1.7.1", "", { "dependencies": { "@dotenvx/dotenvx": "1.31.0", "@opennextjs/aws": "3.7.6", "cloudflare": "^4.4.1", "enquirer": "^2.4.1", "glob": "^11.0.0", "ts-tqdm": "^0.8.6", "yargs": "^18.0.0" }, "peerDependencies": { "wrangler": "^4.24.4" }, "bin": { "opennextjs-cloudflare": "dist/cli/index.js" } }, "sha512-g3d8LSpGGJzuCLuLYHAs7nGWFKK57qSOgxhpn3wwk6t/tXxsneXA3D5nbf6zLsAQQo8b6A8LDcT732U3rUXUeA=="],
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
@@ -1151,19 +1157,21 @@
"@scalar/draggable": ["@scalar/draggable@0.2.0", "", { "dependencies": { "vue": "^3.5.12" } }, "sha512-UetHRB5Bqo5egVYlS21roWBcICmyk8CKh2htsidO+bFGAjl2e7Te+rY0borhNrMclr0xezHlPuLpEs1dvgLS2g=="], "@scalar/draggable": ["@scalar/draggable@0.2.0", "", { "dependencies": { "vue": "^3.5.12" } }, "sha512-UetHRB5Bqo5egVYlS21roWBcICmyk8CKh2htsidO+bFGAjl2e7Te+rY0borhNrMclr0xezHlPuLpEs1dvgLS2g=="],
"@scalar/helpers": ["@scalar/helpers@0.0.4", "", {}, "sha512-AkWdiU8zhztb4bJ0U2LHgCtJs+kwWB5UFXebfy9QCLwCP0guhhFR2UJtRCU3QZ8xmZnI0AX0i7BjrxU/MN1roQ=="], "@scalar/helpers": ["@scalar/helpers@0.0.8", "", {}, "sha512-9A1CxL3jV7Kl9wGu86/cR/wiJN6J+3tK4WuW3252s2gF+upXsgQRx9WLhFF3xifOP1irIGusitZBiojiKmUSVg=="],
"@scalar/icons": ["@scalar/icons@0.4.4", "", { "dependencies": { "@phosphor-icons/core": "^2.1.1", "@types/node": "^20.17.10", "chalk": "^5.4.1", "vue": "^3.5.12" } }, "sha512-622QsIkRPw5UG4IU4QzcTUV1UHEw7aBaZMu6QYEHPO0Wn3ue1lfFIqLZOKsoXxvDuuXGvZUqyoZahkXdRHccmQ=="], "@scalar/icons": ["@scalar/icons@0.4.4", "", { "dependencies": { "@phosphor-icons/core": "^2.1.1", "@types/node": "^20.17.10", "chalk": "^5.4.1", "vue": "^3.5.12" } }, "sha512-622QsIkRPw5UG4IU4QzcTUV1UHEw7aBaZMu6QYEHPO0Wn3ue1lfFIqLZOKsoXxvDuuXGvZUqyoZahkXdRHccmQ=="],
"@scalar/import": ["@scalar/import@0.4.11", "", { "dependencies": { "@scalar/helpers": "0.0.4", "@scalar/openapi-parser": "0.18.0", "yaml": "^2.4.5" } }, "sha512-s8GRknImMjevimqv+jLkW+7LsBuOWgQPv/p29dukLqPtCGddIyNoWgVot6/IaREEXXeu5m/PmoG+uN58AVN4Vg=="], "@scalar/import": ["@scalar/import@0.4.11", "", { "dependencies": { "@scalar/helpers": "0.0.4", "@scalar/openapi-parser": "0.18.0", "yaml": "^2.4.5" } }, "sha512-s8GRknImMjevimqv+jLkW+7LsBuOWgQPv/p29dukLqPtCGddIyNoWgVot6/IaREEXXeu5m/PmoG+uN58AVN4Vg=="],
"@scalar/json-magic": ["@scalar/json-magic@0.3.1", "", { "dependencies": { "@scalar/helpers": "0.0.8", "vue": "^3.5.17", "yaml": "2.8.0" } }, "sha512-vQvl4TckiMT8Txo6S82ETJ4OI+K6iSxLZsjPaq4cEqY+9zVfmIMALFGPj/X5BB8tU3FdluV2yEa8LswsMQ68IA=="],
"@scalar/oas-utils": ["@scalar/oas-utils@0.2.130", "", { "dependencies": { "@hyperjump/json-schema": "^1.9.6", "@scalar/object-utils": "1.1.13", "@scalar/openapi-types": "0.2.0", "@scalar/themes": "0.9.86", "@scalar/types": "0.1.7", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "^3.23.8" } }, "sha512-sVpdc3+3c/WiNrKEIwzJ+ml2ZQBjarMOTDJCM/IrvYhrJE0nHrdkzxlJgNPi++vJbVl0saYt8LhEItALv7NziA=="], "@scalar/oas-utils": ["@scalar/oas-utils@0.2.130", "", { "dependencies": { "@hyperjump/json-schema": "^1.9.6", "@scalar/object-utils": "1.1.13", "@scalar/openapi-types": "0.2.0", "@scalar/themes": "0.9.86", "@scalar/types": "0.1.7", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "^3.23.8" } }, "sha512-sVpdc3+3c/WiNrKEIwzJ+ml2ZQBjarMOTDJCM/IrvYhrJE0nHrdkzxlJgNPi++vJbVl0saYt8LhEItALv7NziA=="],
"@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/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.18.0", "", { "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-qAWEfJR5f/LwSFULFeSkD56LHgU9ovyj+e1uqy9XaW9Hb9P0ewIGKi+Gd4wTyxfFkdPLXTFYXApjviP6jV+new=="], "@scalar/openapi-parser": ["@scalar/openapi-parser@0.20.1", "", { "dependencies": { "@scalar/json-magic": "0.3.1", "@scalar/openapi-types": "0.3.7", "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.8.0" } }, "sha512-rxtuBQ90YsUEDefWU3GAEmvjYr1CvGO6nkDVzbjmWv2aPB3mtK80bCRBgQGTdIdW5XQEWAAmflSKEhcj2Xo5QA=="],
"@scalar/openapi-types": ["@scalar/openapi-types@0.1.9", "", {}, "sha512-HQQudOSQBU7ewzfnBW9LhDmBE2XOJgSfwrh5PlUB7zJup/kaRkBGNgV2wMjNz9Af/uztiU/xNrO179FysmUT+g=="], "@scalar/openapi-types": ["@scalar/openapi-types@0.3.7", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-QHSvHBVDze3+dUwAhIGq6l1iOev4jdoqdBK7QpfeN1Q4h+6qpVEw3EEqBiH0AXUSh/iWwObBv4uMgfIx0aNZ5g=="],
"@scalar/postman-to-openapi": ["@scalar/postman-to-openapi@0.3.10", "", { "dependencies": { "@scalar/helpers": "0.0.4", "@scalar/oas-utils": "0.4.7", "@scalar/openapi-types": "0.3.3" } }, "sha512-Jg+uJg56VASihtfL0sOzB8onyt7lfz/8Ztwo57WIAxUTvLcwBeCBgdTvUIw+Z4h7E2KfmKQY9HdDP/GHWMv6DQ=="], "@scalar/postman-to-openapi": ["@scalar/postman-to-openapi@0.3.10", "", { "dependencies": { "@scalar/helpers": "0.0.4", "@scalar/oas-utils": "0.4.7", "@scalar/openapi-types": "0.3.3" } }, "sha512-Jg+uJg56VASihtfL0sOzB8onyt7lfz/8Ztwo57WIAxUTvLcwBeCBgdTvUIw+Z4h7E2KfmKQY9HdDP/GHWMv6DQ=="],
@@ -1171,7 +1179,7 @@
"@scalar/themes": ["@scalar/themes@0.9.86", "", { "dependencies": { "@scalar/types": "0.1.7" } }, "sha512-QUHo9g5oSWi+0Lm1vJY9TaMZRau8LHg+vte7q5BVTBnu6NuQfigCaN+ouQ73FqIVd96TwMO6Db+dilK1B+9row=="], "@scalar/themes": ["@scalar/themes@0.9.86", "", { "dependencies": { "@scalar/types": "0.1.7" } }, "sha512-QUHo9g5oSWi+0Lm1vJY9TaMZRau8LHg+vte7q5BVTBnu6NuQfigCaN+ouQ73FqIVd96TwMO6Db+dilK1B+9row=="],
"@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="], "@scalar/types": ["@scalar/types@0.1.16", "", { "dependencies": { "@scalar/openapi-types": "0.2.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-v1L96F8Inn27NUw5Xcl0iifw3SOX0R9WBV6GeswR23s8i1SJz7UiLEi8rLOqOB5DiLtC8hDK0kNl4TKn7MNJWQ=="],
"@scalar/use-codemirror": ["@scalar/use-codemirror@0.12.13", "", { "dependencies": { "@codemirror/autocomplete": "^6.18.3", "@codemirror/commands": "^6.7.1", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.8", "@codemirror/lang-json": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lang-yaml": "^6.1.2", "@codemirror/language": "^6.10.7", "@codemirror/lint": "^6.8.4", "@codemirror/state": "^6.5.0", "@codemirror/view": "^6.35.3", "@lezer/common": "^1.2.3", "@lezer/highlight": "^1.2.1", "@replit/codemirror-css-color-picker": "^6.3.0", "@scalar/components": "0.14.12", "codemirror": "^6.0.0", "vue": "^3.5.12" } }, "sha512-XOXCUT3b1l0gkp4CY51e7xMgR6IP/AMpYIZ97fBOOjnrUIJ8B/J+U/BMS6+lPKiN0hexaSALRWlVBf90txdT8w=="], "@scalar/use-codemirror": ["@scalar/use-codemirror@0.12.13", "", { "dependencies": { "@codemirror/autocomplete": "^6.18.3", "@codemirror/commands": "^6.7.1", "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-html": "^6.4.8", "@codemirror/lang-json": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lang-yaml": "^6.1.2", "@codemirror/language": "^6.10.7", "@codemirror/lint": "^6.8.4", "@codemirror/state": "^6.5.0", "@codemirror/view": "^6.35.3", "@lezer/common": "^1.2.3", "@lezer/highlight": "^1.2.1", "@replit/codemirror-css-color-picker": "^6.3.0", "@scalar/components": "0.14.12", "codemirror": "^6.0.0", "vue": "^3.5.12" } }, "sha512-XOXCUT3b1l0gkp4CY51e7xMgR6IP/AMpYIZ97fBOOjnrUIJ8B/J+U/BMS6+lPKiN0hexaSALRWlVBf90txdT8w=="],
@@ -1301,6 +1309,8 @@
"@smithy/util-waiter": ["@smithy/util-waiter@2.2.0", "", { "dependencies": { "@smithy/abort-controller": "^2.2.0", "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA=="], "@smithy/util-waiter": ["@smithy/util-waiter@2.2.0", "", { "dependencies": { "@smithy/abort-controller": "^2.2.0", "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA=="],
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
"@szmarczak/http-timer": ["@szmarczak/http-timer@1.1.2", "", { "dependencies": { "defer-to-connect": "^1.0.1" } }, "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA=="], "@szmarczak/http-timer": ["@szmarczak/http-timer@1.1.2", "", { "dependencies": { "defer-to-connect": "^1.0.1" } }, "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA=="],
@@ -1375,6 +1385,8 @@
"@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="], "@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="],
"@types/js-yaml": ["@types/js-yaml@4.0.9", "", {}, "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/jsontoxml": ["@types/jsontoxml@1.0.6", "", {}, "sha512-SoeEpHuqdZcpLxZr5uzpB6A/ICmzBOfluwMm59Bm6vDuiSRSv4M/z8hvS+YCRw4ZyGO5BhJ5oeJnrurSigg3Vw=="], "@types/jsontoxml": ["@types/jsontoxml@1.0.6", "", {}, "sha512-SoeEpHuqdZcpLxZr5uzpB6A/ICmzBOfluwMm59Bm6vDuiSRSv4M/z8hvS+YCRw4ZyGO5BhJ5oeJnrurSigg3Vw=="],
@@ -1457,25 +1469,25 @@
"@vercel/static-config": ["@vercel/static-config@3.0.0", "", { "dependencies": { "ajv": "8.6.3", "json-schema-to-ts": "1.6.4", "ts-morph": "12.0.0" } }, "sha512-2qtvcBJ1bGY0dYGYh3iM7yGKkk971FujLEDXzuW5wcZsPr1GSEjO/w2iSr3qve6nDDtBImsGoDEnus5FI4+fIw=="], "@vercel/static-config": ["@vercel/static-config@3.0.0", "", { "dependencies": { "ajv": "8.6.3", "json-schema-to-ts": "1.6.4", "ts-morph": "12.0.0" } }, "sha512-2qtvcBJ1bGY0dYGYh3iM7yGKkk971FujLEDXzuW5wcZsPr1GSEjO/w2iSr3qve6nDDtBImsGoDEnus5FI4+fIw=="],
"@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="], "@vue/compiler-core": ["@vue/compiler-core@3.5.21", "", { "dependencies": { "@babel/parser": "^7.28.3", "@vue/shared": "3.5.21", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw=="],
"@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="], "@vue/compiler-dom": ["@vue/compiler-dom@3.5.21", "", { "dependencies": { "@vue/compiler-core": "3.5.21", "@vue/shared": "3.5.21" } }, "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ=="],
"@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="], "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.21", "", { "dependencies": { "@babel/parser": "^7.28.3", "@vue/compiler-core": "3.5.21", "@vue/compiler-dom": "3.5.21", "@vue/compiler-ssr": "3.5.21", "@vue/shared": "3.5.21", "estree-walker": "^2.0.2", "magic-string": "^0.30.18", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ=="],
"@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="], "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.21", "", { "dependencies": { "@vue/compiler-dom": "3.5.21", "@vue/shared": "3.5.21" } }, "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w=="],
"@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="], "@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="],
"@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="], "@vue/reactivity": ["@vue/reactivity@3.5.21", "", { "dependencies": { "@vue/shared": "3.5.21" } }, "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA=="],
"@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="], "@vue/runtime-core": ["@vue/runtime-core@3.5.21", "", { "dependencies": { "@vue/reactivity": "3.5.21", "@vue/shared": "3.5.21" } }, "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA=="],
"@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="], "@vue/runtime-dom": ["@vue/runtime-dom@3.5.21", "", { "dependencies": { "@vue/reactivity": "3.5.21", "@vue/runtime-core": "3.5.21", "@vue/shared": "3.5.21", "csstype": "^3.1.3" } }, "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w=="],
"@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="], "@vue/server-renderer": ["@vue/server-renderer@3.5.21", "", { "dependencies": { "@vue/compiler-ssr": "3.5.21", "@vue/shared": "3.5.21" }, "peerDependencies": { "vue": "3.5.21" } }, "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA=="],
"@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="], "@vue/shared": ["@vue/shared@3.5.21", "", {}, "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw=="],
"@vueuse/core": ["@vueuse/core@10.11.1", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "10.11.1", "@vueuse/shared": "10.11.1", "vue-demi": ">=0.14.8" } }, "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww=="], "@vueuse/core": ["@vueuse/core@10.11.1", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "10.11.1", "@vueuse/shared": "10.11.1", "vue-demi": ">=0.14.8" } }, "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww=="],
@@ -1595,6 +1607,8 @@
"bun-types": ["bun-types@1.1.30", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-mGh7NLisOXskBU62DxLS+/nwmLlCYHYAkCzdo4DZ9+fzrpP41hAdOqaN4DO6tQfenHb4pYb0/shw29k4/6I2yQ=="], "bun-types": ["bun-types@1.1.30", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-mGh7NLisOXskBU62DxLS+/nwmLlCYHYAkCzdo4DZ9+fzrpP41hAdOqaN4DO6tQfenHb4pYb0/shw29k4/6I2yQ=="],
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
"bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="], "bytes": ["bytes@3.1.0", "", {}, "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="],
"cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
@@ -2453,7 +2467,7 @@
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
"next": ["next@15.5.0", "", { "dependencies": { "@next/env": "15.5.0", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.5.0", "@next/swc-darwin-x64": "15.5.0", "@next/swc-linux-arm64-gnu": "15.5.0", "@next/swc-linux-arm64-musl": "15.5.0", "@next/swc-linux-x64-gnu": "15.5.0", "@next/swc-linux-x64-musl": "15.5.0", "@next/swc-win32-arm64-msvc": "15.5.0", "@next/swc-win32-x64-msvc": "15.5.0", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "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-N1lp9Hatw3a9XLt0307lGB4uTKsXDhyOKQo7uYMzX4i0nF/c27grcGXkLdb7VcT8QPYLBa8ouIyEoUQJ2OyeNQ=="], "next": ["next@15.3.5", "", { "dependencies": { "@next/env": "15.3.5", "@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.5", "@next/swc-darwin-x64": "15.3.5", "@next/swc-linux-arm64-gnu": "15.3.5", "@next/swc-linux-arm64-musl": "15.3.5", "@next/swc-linux-x64-gnu": "15.3.5", "@next/swc-linux-x64-musl": "15.3.5", "@next/swc-win32-arm64-msvc": "15.3.5", "@next/swc-win32-x64-msvc": "15.3.5", "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-RkazLBMMDJSJ4XZQ81kolSpwiCt907l0xcgcpF4xC2Vml6QVcPNXW0NQRwQ80FFtSn7UM52XN0anaw8TEJXaiw=="],
"next-themes": ["next-themes@0.2.1", "", { "peerDependencies": { "next": "*", "react": "*", "react-dom": "*" } }, "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A=="], "next-themes": ["next-themes@0.2.1", "", { "peerDependencies": { "next": "*", "react": "*", "react-dom": "*" } }, "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A=="],
@@ -2797,6 +2811,8 @@
"stream-to-promise": ["stream-to-promise@2.2.0", "", { "dependencies": { "any-promise": "~1.3.0", "end-of-stream": "~1.1.0", "stream-to-array": "~2.3.0" } }, "sha512-HAGUASw8NT0k8JvIVutB2Y/9iBk7gpgEyAudXwNJmZERdMITGdajOa4VJfD/kNiA3TppQpTP4J+CtcHwdzKBAw=="], "stream-to-promise": ["stream-to-promise@2.2.0", "", { "dependencies": { "any-promise": "~1.3.0", "end-of-stream": "~1.1.0", "stream-to-array": "~2.3.0" } }, "sha512-HAGUASw8NT0k8JvIVutB2Y/9iBk7gpgEyAudXwNJmZERdMITGdajOa4VJfD/kNiA3TppQpTP4J+CtcHwdzKBAw=="],
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
@@ -3007,7 +3023,7 @@
"vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="], "vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="],
"vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="], "vue": ["vue@3.5.21", "", { "dependencies": { "@vue/compiler-dom": "3.5.21", "@vue/compiler-sfc": "3.5.21", "@vue/runtime-dom": "3.5.21", "@vue/server-renderer": "3.5.21", "@vue/shared": "3.5.21" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA=="],
"vue-demi": ["vue-demi@0.14.10", "", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="], "vue-demi": ["vue-demi@0.14.10", "", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="],
@@ -3059,7 +3075,7 @@
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="], "yaml": ["yaml@2.8.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ=="],
"yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
@@ -3681,8 +3697,6 @@
"@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], "@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
"@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@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=="], "@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=="],
"@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=="], "@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=="],
@@ -3789,6 +3803,8 @@
"@opennextjs/aws/path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], "@opennextjs/aws/path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
"@opennextjs/aws/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@playwright/test/playwright": ["playwright@1.54.2", "", { "dependencies": { "playwright-core": "1.54.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw=="], "@playwright/test/playwright": ["playwright@1.54.2", "", { "dependencies": { "playwright-core": "1.54.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw=="],
"@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.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-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], "@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.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-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
@@ -3945,40 +3961,80 @@
"@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], "@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"@scalar/api-client/@scalar/helpers": ["@scalar/helpers@0.0.4", "", {}, "sha512-AkWdiU8zhztb4bJ0U2LHgCtJs+kwWB5UFXebfy9QCLwCP0guhhFR2UJtRCU3QZ8xmZnI0AX0i7BjrxU/MN1roQ=="],
"@scalar/api-client/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="], "@scalar/api-client/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="],
"@scalar/api-client/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="], "@scalar/api-client/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="],
"@scalar/api-client/@scalar/openapi-parser": ["@scalar/openapi-parser@0.18.0", "", { "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-qAWEfJR5f/LwSFULFeSkD56LHgU9ovyj+e1uqy9XaW9Hb9P0ewIGKi+Gd4wTyxfFkdPLXTFYXApjviP6jV+new=="],
"@scalar/api-client/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="], "@scalar/api-client/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="],
"@scalar/api-client/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="], "@scalar/api-client/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="],
"@scalar/api-client/@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="],
"@scalar/api-client/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="], "@scalar/api-client/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="],
"@scalar/api-client/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/api-client/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@scalar/api-client/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/api-client/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/api-client-react/@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="],
"@scalar/api-client-react/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/components/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="], "@scalar/components/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="],
"@scalar/components/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="], "@scalar/components/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="],
"@scalar/components/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/draggable/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/icons/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/import/@scalar/helpers": ["@scalar/helpers@0.0.4", "", {}, "sha512-AkWdiU8zhztb4bJ0U2LHgCtJs+kwWB5UFXebfy9QCLwCP0guhhFR2UJtRCU3QZ8xmZnI0AX0i7BjrxU/MN1roQ=="],
"@scalar/import/@scalar/openapi-parser": ["@scalar/openapi-parser@0.18.0", "", { "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-qAWEfJR5f/LwSFULFeSkD56LHgU9ovyj+e1uqy9XaW9Hb9P0ewIGKi+Gd4wTyxfFkdPLXTFYXApjviP6jV+new=="],
"@scalar/import/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@scalar/oas-utils/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="], "@scalar/oas-utils/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
"@scalar/oas-utils/@scalar/types": ["@scalar/types@0.1.7", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw=="], "@scalar/oas-utils/@scalar/types": ["@scalar/types@0.1.7", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw=="],
"@scalar/oas-utils/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@scalar/object-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="], "@scalar/object-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
"@scalar/openapi-types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/postman-to-openapi/@scalar/helpers": ["@scalar/helpers@0.0.4", "", {}, "sha512-AkWdiU8zhztb4bJ0U2LHgCtJs+kwWB5UFXebfy9QCLwCP0guhhFR2UJtRCU3QZ8xmZnI0AX0i7BjrxU/MN1roQ=="],
"@scalar/postman-to-openapi/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="], "@scalar/postman-to-openapi/@scalar/oas-utils": ["@scalar/oas-utils@0.4.7", "", { "dependencies": { "@hyperjump/browser": "^1.1.0", "@hyperjump/json-schema": "^1.9.6", "@scalar/helpers": "0.0.4", "@scalar/object-utils": "1.2.1", "@scalar/openapi-types": "0.3.3", "@scalar/themes": "0.13.4", "@scalar/types": "0.2.3", "@types/har-format": "^1.2.15", "flatted": "^3.3.1", "microdiff": "^1.4.0", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "yaml": "^2.4.5", "zod": "3.24.1" } }, "sha512-Vp8iZZCjNKXcPpL0Yr6dmy+VOSN1LZ5CdlGAHtp+pxuQTeahV6FxiVjMc9kdFve77fTNyut4seVAD6d7rDUDcA=="],
"@scalar/postman-to-openapi/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="], "@scalar/postman-to-openapi/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="],
"@scalar/themes/@scalar/types": ["@scalar/types@0.1.7", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw=="], "@scalar/themes/@scalar/types": ["@scalar/types@0.1.7", "", { "dependencies": { "@scalar/openapi-types": "0.2.0", "@unhead/schema": "^1.11.11", "nanoid": "^5.1.5", "type-fest": "^4.20.0", "zod": "^3.23.8" } }, "sha512-irIDYzTQG2KLvFbuTI8k2Pz/R4JR+zUUSykVTbEMatkzMmVFnn1VzNSMlODbadycwZunbnL2tA27AXed9URVjw=="],
"@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="], "@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.2.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-O1GwqLpcRc3GKXTbeBZ5E12fXR2ltpqGWk4RfhoN4ebKZsPVknV5at5425G97E1SwMy12BporRvn90k1Z+MruQ=="],
"@scalar/types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/use-codemirror/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/use-hooks/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/use-hooks/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/use-hooks/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/use-toasts/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@scalar/use-tooltip/vue": ["vue@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/compiler-sfc": "3.5.12", "@vue/runtime-dom": "3.5.12", "@vue/server-renderer": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg=="],
"@shikijs/core/hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], "@shikijs/core/hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
"@smithy/abort-controller/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "@smithy/abort-controller/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
@@ -4209,9 +4265,9 @@
"@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="], "@vue/compiler-sfc/magic-string": ["magic-string@0.30.18", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ=="],
"@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="], "@vue/compiler-sfc/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"@vueuse/integrations/@vueuse/core": ["@vueuse/core@11.2.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "11.2.0", "@vueuse/shared": "11.2.0", "vue-demi": ">=0.14.10" } }, "sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA=="], "@vueuse/integrations/@vueuse/core": ["@vueuse/core@11.2.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.20", "@vueuse/metadata": "11.2.0", "@vueuse/shared": "11.2.0", "vue-demi": ">=0.14.10" } }, "sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA=="],
@@ -4949,10 +5005,6 @@
"@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="], "@babel/highlight/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
"@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@changesets/parse/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], "@changesets/parse/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
"@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=="], "@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=="],
@@ -5071,24 +5123,130 @@
"@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=="], "@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=="],
"@scalar/api-client-react/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="],
"@scalar/api-client-react/@scalar/types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/api-client-react/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/api-client-react/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/api-client-react/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/api-client-react/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/api-client/pretty-ms/parse-ms": ["parse-ms@3.0.0", "", {}, "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw=="], "@scalar/api-client/pretty-ms/parse-ms": ["parse-ms@3.0.0", "", {}, "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw=="],
"@scalar/api-client/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/api-client/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/api-client/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/api-client/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/api-client/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/components/@scalar/oas-utils/@scalar/helpers": ["@scalar/helpers@0.0.4", "", {}, "sha512-AkWdiU8zhztb4bJ0U2LHgCtJs+kwWB5UFXebfy9QCLwCP0guhhFR2UJtRCU3QZ8xmZnI0AX0i7BjrxU/MN1roQ=="],
"@scalar/components/@scalar/oas-utils/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="], "@scalar/components/@scalar/oas-utils/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="],
"@scalar/components/@scalar/oas-utils/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="], "@scalar/components/@scalar/oas-utils/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="],
"@scalar/components/@scalar/oas-utils/@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="],
"@scalar/components/@scalar/oas-utils/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@scalar/components/@scalar/oas-utils/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/components/@scalar/oas-utils/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/components/@scalar/themes/@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="],
"@scalar/components/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/components/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/components/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/components/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/components/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/draggable/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/draggable/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/draggable/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/draggable/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/draggable/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/icons/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/icons/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/icons/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/icons/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/icons/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/postman-to-openapi/@scalar/oas-utils/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="], "@scalar/postman-to-openapi/@scalar/oas-utils/@scalar/object-utils": ["@scalar/object-utils@1.2.1", "", { "dependencies": { "flatted": "^3.3.1", "just-clone": "^6.2.0", "ts-deepmerge": "^7.0.1", "type-fest": "^4.20.0" } }, "sha512-2P/0In6XSrV1Ye8yU3LyOWJKWkzXpxf0thHmTfJriqGBZz41s06td2KKqoqHSEEi+FAsl3O1ngmOOzLM3QUkkw=="],
"@scalar/postman-to-openapi/@scalar/oas-utils/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="], "@scalar/postman-to-openapi/@scalar/oas-utils/@scalar/themes": ["@scalar/themes@0.13.4", "", { "dependencies": { "@scalar/types": "0.2.3", "nanoid": "^5.1.5" } }, "sha512-PMiSqX+MZF29u32ogEjTVA5c/LBd5cE/QPF7lK0EJeemXRy2r/nWbvrXtqD9Y7Sw54g1caVNjK8yJcCYJdB6hw=="],
"@scalar/postman-to-openapi/@scalar/oas-utils/@scalar/types": ["@scalar/types@0.2.3", "", { "dependencies": { "@scalar/openapi-types": "0.3.3", "nanoid": "^5.1.5", "zod": "3.24.1" } }, "sha512-K1/Vp5xaQ8TEGDYwHg88OBuQWJRWrE3ToZ0Z2LJwskcY1Eg+uDiRQXKF4QPngZzu5rrWgRErAq4yte4Y7omqgA=="],
"@scalar/postman-to-openapi/@scalar/oas-utils/yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
"@scalar/postman-to-openapi/@scalar/oas-utils/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/postman-to-openapi/@scalar/oas-utils/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/postman-to-openapi/@scalar/openapi-types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], "@scalar/postman-to-openapi/@scalar/openapi-types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/themes/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="], "@scalar/themes/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-waiKk12cRCqyUCWTOX0K1WEVX46+hVUK+zRPzAahDJ7G0TApvbNkuy5wx7aoUyEk++HHde0XuQnshXnt8jsddA=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/use-codemirror/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/use-codemirror/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/use-codemirror/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/use-hooks/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/use-hooks/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/use-hooks/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/use-hooks/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/use-toasts/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/use-toasts/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/use-toasts/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/use-toasts/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom": ["@vue/compiler-dom@3.5.12", "", { "dependencies": { "@vue/compiler-core": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/compiler-core": "3.5.12", "@vue/compiler-dom": "3.5.12", "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", "source-map-js": "^1.2.0" } }, "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw=="],
"@scalar/use-tooltip/vue/@vue/runtime-dom": ["@vue/runtime-dom@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/runtime-core": "3.5.12", "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA=="],
"@scalar/use-tooltip/vue/@vue/server-renderer": ["@vue/server-renderer@3.5.12", "", { "dependencies": { "@vue/compiler-ssr": "3.5.12", "@vue/shared": "3.5.12" }, "peerDependencies": { "vue": "3.5.12" } }, "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg=="],
"@scalar/use-tooltip/vue/@vue/shared": ["@vue/shared@3.5.12", "", {}, "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="],
"@shikijs/core/hast-util-to-html/property-information": ["property-information@7.0.0", "", {}, "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg=="], "@shikijs/core/hast-util-to-html/property-information": ["property-information@7.0.0", "", {}, "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg=="],
"@smithy/chunked-blob-reader-native/@smithy/util-base64/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.0.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug=="], "@smithy/chunked-blob-reader-native/@smithy/util-base64/@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.0.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug=="],
@@ -5145,7 +5303,11 @@
"@vercel/routing-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "@vercel/routing-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
"@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], "@vue/compiler-sfc/magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"@vue/compiler-sfc/postcss/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"@vueuse/integrations/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@11.2.0", "", {}, "sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ=="], "@vueuse/integrations/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@11.2.0", "", {}, "sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ=="],
@@ -5429,6 +5591,172 @@
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot/@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-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot/@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=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/api-client-react/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/api-client-react/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/api-client-react/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/api-client/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/api-client/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/api-client/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/api-client/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/api-client/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/components/@scalar/themes/@scalar/types/@scalar/openapi-types": ["@scalar/openapi-types@0.3.3", "", { "dependencies": { "zod": "3.24.1" } }, "sha512-mr3OvbCyvuzSDgv9gR9D3pJAsl82BRNBp1P8ldgRgKF4Wiswfa7nQeKibpX0kHSGXLgiyvxWJULUFwgdWMXNNA=="],
"@scalar/components/@scalar/themes/@scalar/types/zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/components/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/components/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/components/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/components/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/components/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/components/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/components/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/components/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/draggable/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/draggable/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/draggable/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/draggable/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/draggable/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/icons/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/icons/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/icons/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/icons/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/icons/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/icons/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/icons/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/icons/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/use-codemirror/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/use-codemirror/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/use-codemirror/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/use-hooks/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/use-hooks/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/use-hooks/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/use-toasts/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/use-toasts/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/use-toasts/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@vue/compiler-core": ["@vue/compiler-core@3.5.12", "", { "dependencies": { "@babel/parser": "^7.25.3", "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/magic-string": ["magic-string@0.30.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="],
"@scalar/use-tooltip/vue/@vue/runtime-dom/@vue/reactivity": ["@vue/reactivity@3.5.12", "", { "dependencies": { "@vue/shared": "3.5.12" } }, "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg=="],
"@scalar/use-tooltip/vue/@vue/runtime-dom/@vue/runtime-core": ["@vue/runtime-core@3.5.12", "", { "dependencies": { "@vue/reactivity": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw=="],
"@scalar/use-tooltip/vue/@vue/server-renderer/@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.12", "", { "dependencies": { "@vue/compiler-dom": "3.5.12", "@vue/shared": "3.5.12" } }, "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA=="],
"@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg=="], "@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "@smithy/util-uri-escape": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg=="],
"@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g=="], "@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.0.1", "", { "dependencies": { "@smithy/types": "^4.1.0", "tslib": "^2.6.2" } }, "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g=="],
@@ -5483,6 +5811,96 @@
"@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/api-client/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/components/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/components/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/components/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/draggable/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/icons/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/icons/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/icons/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "^7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@vue/compiler-core/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="],
"@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], "@smithy/core/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="],
"@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], "@smithy/core/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="],
@@ -5498,5 +5916,95 @@
"@aws-sdk/middleware-sdk-sqs/@smithy/smithy-client/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], "@aws-sdk/middleware-sdk-sqs/@smithy/smithy-client/@smithy/util-stream/@smithy/fetch-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="],
"@aws-sdk/middleware-sdk-sqs/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="], "@aws-sdk/middleware-sdk-sqs/@smithy/smithy-client/@smithy/util-stream/@smithy/node-http-handler/@smithy/querystring-builder/@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/api-client-react/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/api-client/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/components/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/components/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/draggable/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/icons/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/icons/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-codemirror/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-hooks/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-toasts/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.7", "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-tooltip/vue/@vue/compiler-sfc/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/api-client-react/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/api-client/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/components/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/draggable/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/icons/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-codemirror/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-hooks/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-toasts/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
"@scalar/use-tooltip/vue/@vue/compiler-dom/@vue/compiler-core/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
} }
} }
+1 -1
View File
@@ -34,7 +34,7 @@
"workspaces": { "workspaces": {
"packages": ["packages/*"], "packages": ["packages/*"],
"catalog": { "catalog": {
"@gitbook/api": "^0.136.0", "@gitbook/api": "^0.139.0",
"bidc": "^0.0.2" "bidc": "^0.0.2"
} }
}, },
+1
View File
@@ -5,6 +5,7 @@
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true,
"noEmit": false, "noEmit": false,
"declaration": true, "declaration": true,
"outDir": "dist", "outDir": "dist",
+2 -14
View File
@@ -121,17 +121,6 @@ export function getCacheTag(
} }
} }
/**
* Get the cache tag for a given URL.
*/
export function getCacheTagForURL(url: string | URL) {
const parsedURL = url instanceof URL ? url : new URL(url);
return getCacheTag({
tag: 'url',
hostname: parsedURL.hostname,
});
}
/** /**
* Get the tags for a computed content source. * Get the tags for a computed content source.
*/ */
@@ -182,7 +171,7 @@ export function getComputedContentSourceCacheTags(
break; break;
default: default:
// Do not throw for unknown dependency types // Do not throw for unknown dependency types
// as it might mean we are lacking behind the API version // as it might mean we are lagging behind the API version
break; break;
} }
}); });
@@ -198,9 +187,8 @@ export function getComputedContentSourceCacheTags(
} }
// We invalidate the computed content when a new version of the integration is deployed. // We invalidate the computed content when a new version of the integration is deployed.
if (source.type.startsWith('integration:')) { if (source.type.startsWith('integration:')) {
const integration = source.type.split(':')[1]; const integration = source.type.split(':')[1]!;
tags.push( tags.push(
getCacheTag({ getCacheTag({
tag: 'integration', tag: 'integration',
+1
View File
@@ -5,6 +5,7 @@
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true,
"noEmit": false, "noEmit": false,
"declaration": true, "declaration": true,
"outDir": "dist", "outDir": "dist",
+10
View File
@@ -1,5 +1,15 @@
# @gitbook/colors # @gitbook/colors
## 0.4.0
### Minor Changes
- 17dd382: Add `original` background color step
### Patch Changes
- 193d591: Fix return type for `colorContrast`
## 0.3.3 ## 0.3.3
### Patch Changes ### Patch Changes
+1 -1
View File
@@ -8,7 +8,7 @@
"default": "./dist/index.js" "default": "./dist/index.js"
} }
}, },
"version": "0.3.3", "version": "0.4.0",
"devDependencies": { "devDependencies": {
"typescript": "^5.5.3" "typescript": "^5.5.3"
}, },
+16 -11
View File
@@ -8,7 +8,7 @@ type RGBColor = [number, number, number];
type OKLABColor = { L: number; A: number; B: number }; type OKLABColor = { L: number; A: number; B: number };
type OKLCHColor = { L: number; C: number; H: number }; type OKLCHColor = { L: number; C: number; H: number };
const D65 = [95.047, 100.0, 108.883]; // Reference white (D65) const D65 = [95.047, 100.0, 108.883] as const; // Reference white (D65)
export enum ColorCategory { export enum ColorCategory {
backgrounds = 'backgrounds', backgrounds = 'backgrounds',
@@ -19,7 +19,7 @@ export enum ColorCategory {
} }
type ColorSubScale = { type ColorSubScale = {
[key: string]: number; [key: string]: number | string;
}; };
/** /**
@@ -56,6 +56,8 @@ export const scale: Record<ColorCategory, ColorSubScale> = {
solid: 9, solid: 9,
/** Hovered solid backgrounds */ /** Hovered solid backgrounds */
'solid-hover': 10, 'solid-hover': 10,
/** Original color */
original: 'original',
}, },
[ColorCategory.text]: { [ColorCategory.text]: {
/** Very low-contrast text /** Very low-contrast text
@@ -211,8 +213,8 @@ export function colorScale(
const result = []; const result = [];
for (let index = 0; index < mapping.length; index++) { for (let index = 0; index < mapping.length; index++) {
const targetL = const step = mapping[index]!;
foregroundColor.L * mapping[index] + backgroundColor.L * (1 - mapping[index]); const targetL = foregroundColor.L * step + backgroundColor.L * (1 - step);
if ( if (
index === 8 && index === 8 &&
@@ -295,7 +297,7 @@ export function rgbArrayToHex(rgb: RGBColor): string {
export function getColor(percentage: number, start: RGBColor, end: RGBColor) { export function getColor(percentage: number, start: RGBColor, end: RGBColor) {
const rgb = end.map((channel, index) => { const rgb = end.map((channel, index) => {
return Math.round(channel + percentage * (start[index] - channel)); return Math.round(channel + percentage * (start[index]! - channel));
}); });
return rgbArrayToHex(rgb as RGBColor); return rgbArrayToHex(rgb as RGBColor);
@@ -392,14 +394,14 @@ export function xyzToLab65(xyz: [number, number, number]): {
B: number; B: number;
} { } {
const [x, y, z] = xyz.map((v, i) => { const [x, y, z] = xyz.map((v, i) => {
const scaled = v / D65[i]; const scaled = v / D65[i]!;
return scaled > 0.008856 ? Math.cbrt(scaled) : 7.787 * scaled + 16 / 116; return scaled > 0.008856 ? Math.cbrt(scaled) : 7.787 * scaled + 16 / 116;
}); });
return { return {
L: 116 * y - 16, L: 116 * y! - 16,
A: 500 * (x - y), A: 500 * (x! - y!),
B: 200 * (y - z), B: 200 * (y! - z!),
}; };
} }
@@ -419,7 +421,10 @@ export function dpsContrast(a: RGBColor, b: RGBColor) {
return contrast < 7.5 ? 0 : contrast; return contrast < 7.5 ? 0 : contrast;
} }
export function colorContrast(background: string, foreground: string[] = [LIGHT_BASE, DARK_BASE]) { export function colorContrast(
background: string,
foreground: string[] = [LIGHT_BASE, DARK_BASE]
): string {
const bg = hexToRgbArray(background); const bg = hexToRgbArray(background);
const best: { color?: RGBColor; contrast: number } = { const best: { color?: RGBColor; contrast: number } = {
@@ -436,5 +441,5 @@ export function colorContrast(background: string, foreground: string[] = [LIGHT_
} }
} }
return best.color ? rgbArrayToHex(best.color) : foreground[0]; return best.color ? rgbArrayToHex(best.color) : foreground[0] || LIGHT_BASE;
} }
+1
View File
@@ -5,6 +5,7 @@
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true,
"noEmit": false, "noEmit": false,
"declaration": true, "declaration": true,
"outDir": "dist", "outDir": "dist",
+6
View File
@@ -1,5 +1,11 @@
# @gitbook/embed # @gitbook/embed
## 0.1.1
### Patch Changes
- 6f368b5: Fix embed assistant window width on small screens
## 0.1.0 ## 0.1.0
### Minor Changes ### Minor Changes
+1 -1
View File
@@ -10,7 +10,7 @@
"react": "./dist/react/index.js" "react": "./dist/react/index.js"
} }
}, },
"version": "0.1.0", "version": "0.1.1",
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/icons": "workspace:", "@gitbook/icons": "workspace:",
+2 -1
View File
@@ -2,6 +2,7 @@
--gitbook-widget-top: 1rem; --gitbook-widget-top: 1rem;
--gitbook-widget-bottom: 1rem; --gitbook-widget-bottom: 1rem;
--gitbook-widget-right: 1rem; --gitbook-widget-right: 1rem;
--gitbook-widget-left: 1rem;
--gitbook-widget-button-height: 46px; --gitbook-widget-button-height: 46px;
@@ -117,7 +118,7 @@
bottom: var(--gitbook-widget-window-bottom); bottom: var(--gitbook-widget-window-bottom);
right: var(--gitbook-widget-right); right: var(--gitbook-widget-right);
z-index: 9998; z-index: 9998;
width: var(--gitbook-widget-window-width); width: calc(min(var(--gitbook-widget-window-width), calc(100vw - var(--gitbook-widget-right) - var(--gitbook-widget-left))));
height: calc(min(var(--gitbook-widget-window-height), calc(100vh - var(--gitbook-widget-window-bottom) - var(--gitbook-widget-top)))); height: calc(min(var(--gitbook-widget-window-height), calc(100vh - var(--gitbook-widget-window-bottom) - var(--gitbook-widget-top))));
background-color: var(--gitbook-widget-background-solid); background-color: var(--gitbook-widget-background-solid);
border: 1px solid var(--gitbook-widget-border-color); border: 1px solid var(--gitbook-widget-border-color);
+2 -2
View File
@@ -67,7 +67,7 @@ function getBestUnicodeRange(text: string, ranges: Record<string, string>): stri
const body = token.slice(2); // drop "U+" const body = token.slice(2); // drop "U+"
const [startHex, endHex] = body.split('-'); const [startHex, endHex] = body.split('-');
const start = Number.parseInt(startHex, 16); const start = Number.parseInt(startHex!, 16);
const end = endHex ? Number.parseInt(endHex, 16) : start; const end = endHex ? Number.parseInt(endHex, 16) : start;
if (Number.isNaN(start) || Number.isNaN(end) || end < start) return null; if (Number.isNaN(start) || Number.isNaN(end) || end < start) return null;
@@ -92,7 +92,7 @@ function getBestUnicodeRange(text: string, ranges: Record<string, string>): stri
for (const [label, rangesArr] of Object.entries(parsed)) { for (const [label, rangesArr] of Object.entries(parsed)) {
if (rangesArr.some(([lo, hi]) => cp >= lo && cp <= hi)) { if (rangesArr.some(([lo, hi]) => cp >= lo && cp <= hi)) {
hits[label]++; hits[label]!++;
} }
} }
} }
+1
View File
@@ -4,6 +4,7 @@
"module": "ESNext", "module": "ESNext",
"target": "es2022", "target": "es2022",
"strict": true, "strict": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
+39
View File
@@ -1,5 +1,44 @@
# gitbook # gitbook
## 0.17.0
### Minor Changes
- 12c9d76: Adapt OpenAPI blocks to eval adaptive exprs & prefill TryIt config
- 7911350: Add language selector to site header
- 659be55: Track insight event when embedded assistant is displayed.
### Patch Changes
- 2e0d706: Fix corner radius of active section on "Line" sidebar style
- 78a632b: Fix edit on GitHub button doesn't take you to GitHub
- 1edc5d6: Add "hold message" to Assistant
- 4520728: Support bold in headings
- 61b8507: OpenAPI: Make responses without objects clickable
- d1fdc13: Remove ligatures from Lato font
- a8fca0e: Fix custom assistant keyboard shortcut
- 262a9b1: Fix embed script and assets being cached for too long
- c890e01: Fix order in robots.txt preventing indexation of images by Google.
- 1839ea2: Fix content min-height with sections
- 9201e2c: Adds vertical align to column block
- 193d591: Use space language as source of truth for UI locale
- f08dd29: Fix Search results are not clickable on sites without header
- 17dd382: Add `original` background color step
- 4f35882: Fix event ask_question not being tracked
- d51b79e: Fix Search bar is broken on site with sections when header is disabled
- 6f368b5: Fix embed assistant window width on small screens
- Updated dependencies [193d591]
- Updated dependencies [12c9d76]
- Updated dependencies [4927e96]
- Updated dependencies [61b8507]
- Updated dependencies [7fefe49]
- Updated dependencies [360aa1c]
- Updated dependencies [98e42cf]
- Updated dependencies [17dd382]
- @gitbook/colors@0.4.0
- @gitbook/react-openapi@1.4.0
- @gitbook/openapi-parser@3.0.2
## 0.16.0 ## 0.16.0
### Minor Changes ### Minor Changes
@@ -11,7 +11,7 @@ const args = process.argv.slice(2);
const versionId = args[0]; const versionId = args[0];
// The preview URL is in the format https://<versionId>-gitbook-open-v2-server-preview.gitbook.workers.dev // The preview URL is in the format https://<versionId>-gitbook-open-v2-server-preview.gitbook.workers.dev
const previewHostname = `${versionId.split('-')[0]}-gitbook-open-v2-server-preview.gitbook.workers.dev`; const previewHostname = `${versionId?.split('-')[0]}-gitbook-open-v2-server-preview.gitbook.workers.dev`;
let updatedFile = file.replace( let updatedFile = file.replace(
/"PREVIEW_HOSTNAME": "TO_REPLACE"/, /"PREVIEW_HOSTNAME": "TO_REPLACE"/,
+9 -7
View File
@@ -1,12 +1,13 @@
{ {
"name": "gitbook", "name": "gitbook",
"version": "0.16.0", "version": "0.17.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@gitbook/api": "catalog:", "@gitbook/api": "catalog:",
"@gitbook/browser-types": "workspace:*",
"@gitbook/cache-tags": "workspace:*", "@gitbook/cache-tags": "workspace:*",
"@gitbook/colors": "workspace:*", "@gitbook/colors": "workspace:*",
"@gitbook/browser-types": "workspace:*", "@gitbook/expr": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*", "@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/fonts": "workspace:*", "@gitbook/fonts": "workspace:*",
"@gitbook/icons": "workspace:*", "@gitbook/icons": "workspace:*",
@@ -14,7 +15,7 @@
"@gitbook/react-contentkit": "workspace:*", "@gitbook/react-contentkit": "workspace:*",
"@gitbook/react-math": "workspace:*", "@gitbook/react-math": "workspace:*",
"@gitbook/react-openapi": "workspace:*", "@gitbook/react-openapi": "workspace:*",
"@opennextjs/cloudflare": "^1.6.4", "@opennextjs/cloudflare": "^1.7.1",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.1.12", "@radix-ui/react-dropdown-menu": "^2.1.12",
"@radix-ui/react-hover-card": "^1.1.15", "@radix-ui/react-hover-card": "^1.1.15",
@@ -27,6 +28,7 @@
"@tusbar/cache-control": "^1.0.2", "@tusbar/cache-control": "^1.0.2",
"ai": "^4.2.2", "ai": "^4.2.2",
"assert-never": "^1.2.1", "assert-never": "^1.2.1",
"bidc": "catalog:",
"bun-types": "^1.1.20", "bun-types": "^1.1.20",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"direction": "^2.0.1", "direction": "^2.0.1",
@@ -45,7 +47,7 @@
"memoizee": "^0.4.17", "memoizee": "^0.4.17",
"micromark-extension-frontmatter": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0",
"micromark-extension-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0",
"next": "^15.5.0", "next": "15.3.5",
"next-themes": "^0.2.1", "next-themes": "^0.2.1",
"nuqs": "^2.2.3", "nuqs": "^2.2.3",
"object-hash": "^3.0.0", "object-hash": "^3.0.0",
@@ -70,8 +72,7 @@
"url-join": "^5.0.0", "url-join": "^5.0.0",
"usehooks-ts": "^3.1.0", "usehooks-ts": "^3.1.0",
"warn-once": "^0.1.1", "warn-once": "^0.1.1",
"zustand": "^5.0.3", "zustand": "^5.0.3"
"bidc": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"@argos-ci/playwright": "^5.0.9", "@argos-ci/playwright": "^5.0.9",
@@ -104,7 +105,8 @@
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static/icons && rm -rf ./public/~gitbook/static/math", "clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static/icons && rm -rf ./public/~gitbook/static/math",
"dev": "env-cmd --silent -f ../../.env.local next", "dev": "env-cmd --silent -f ../../.env.local next",
"build": "next build", "build": "next build",
"start": "next start", "build:local": "GITBOOK_URL=http://localhost:3000 next build",
"start": "GITBOOK_URL=http://localhost:3000 next start",
"build:cloudflare": "opennextjs-cloudflare build", "build:cloudflare": "opennextjs-cloudflare build",
"dev:cloudflare": "wrangler dev --port 8771 --env preview", "dev:cloudflare": "wrangler dev --port 8771 --env preview",
"dev:cf:middleware": "wrangler dev --port 8771 --inspector-port 9230 --env dev --config ./openNext/customWorkers/middlewareWrangler.jsonc", "dev:cf:middleware": "wrangler dev --port 8771 --inspector-port 9230 --env dev --config ./openNext/customWorkers/middlewareWrangler.jsonc",
@@ -22,7 +22,7 @@ export default async function SiteDynamicLayout({
const withTracking = shouldTrackEvents(await headers()); const withTracking = shouldTrackEvents(await headers());
return ( return (
<CustomizationRootLayout forcedTheme={forcedTheme} customization={context.customization}> <CustomizationRootLayout forcedTheme={forcedTheme} context={context}>
<SiteLayout <SiteLayout
context={context} context={context}
forcedTheme={forcedTheme} forcedTheme={forcedTheme}
@@ -5,6 +5,8 @@ import {
generateEmbeddableViewport, generateEmbeddableViewport,
} from '@/components/Embeddable'; } from '@/components/Embeddable';
import { getEmbeddableStaticContext } from '@/lib/embeddable'; import { getEmbeddableStaticContext } from '@/lib/embeddable';
import { shouldTrackEvents } from '@/lib/tracking';
import { headers } from 'next/headers';
interface SiteStaticLayoutProps { interface SiteStaticLayoutProps {
params: Promise<RouteLayoutParams>; params: Promise<RouteLayoutParams>;
@@ -14,9 +16,18 @@ export default async function RootLayout({
params, params,
children, children,
}: React.PropsWithChildren<SiteStaticLayoutProps>) { }: React.PropsWithChildren<SiteStaticLayoutProps>) {
const { context } = await getEmbeddableStaticContext(await params); const { context, visitorAuthClaims } = await getEmbeddableStaticContext(await params);
const withTracking = shouldTrackEvents(await headers());
return <EmbeddableRootLayout context={context}>{children}</EmbeddableRootLayout>; return (
<EmbeddableRootLayout
context={context}
withTracking={withTracking}
visitorAuthClaims={visitorAuthClaims}
>
{children}
</EmbeddableRootLayout>
);
} }
export async function generateViewport({ params }: SiteStaticLayoutProps) { export async function generateViewport({ params }: SiteStaticLayoutProps) {
@@ -19,7 +19,7 @@ export default async function SiteStaticLayout({
const withTracking = shouldTrackEvents(); const withTracking = shouldTrackEvents();
return ( return (
<CustomizationRootLayout customization={context.customization}> <CustomizationRootLayout context={context}>
<SiteLayout <SiteLayout
context={context} context={context}
withTracking={withTracking} withTracking={withTracking}
@@ -0,0 +1,20 @@
import type { NextRequest } from 'next/server';
import { type RouteLayoutParams, getStaticSiteContext } from '@/app/utils';
import { serveLLMsFullTxt } from '@/routes/llms-full';
export const dynamic = 'force-static';
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<RouteLayoutParams & { page: string }> }
) {
const awaitedParams = await params;
const page = Number(awaitedParams.page);
// If page is not a number, not an integer, or less than 0, return an error
if (Number.isNaN(page) || !Number.isInteger(page) || page < 0) {
return new Response('Invalid page', { status: 400 });
}
const { context } = await getStaticSiteContext(awaitedParams);
return serveLLMsFullTxt(context, page);
}
@@ -5,6 +5,7 @@ import {
generateEmbeddableViewport, generateEmbeddableViewport,
} from '@/components/Embeddable'; } from '@/components/Embeddable';
import { getEmbeddableStaticContext } from '@/lib/embeddable'; import { getEmbeddableStaticContext } from '@/lib/embeddable';
import { shouldTrackEvents } from '@/lib/tracking';
interface SiteStaticLayoutProps { interface SiteStaticLayoutProps {
params: Promise<RouteLayoutParams>; params: Promise<RouteLayoutParams>;
@@ -14,9 +15,18 @@ export default async function RootLayout({
params, params,
children, children,
}: React.PropsWithChildren<SiteStaticLayoutProps>) { }: React.PropsWithChildren<SiteStaticLayoutProps>) {
const { context } = await getEmbeddableStaticContext(await params); const { context, visitorAuthClaims } = await getEmbeddableStaticContext(await params);
const withTracking = shouldTrackEvents();
return <EmbeddableRootLayout context={context}>{children}</EmbeddableRootLayout>; return (
<EmbeddableRootLayout
context={context}
withTracking={withTracking}
visitorAuthClaims={visitorAuthClaims}
>
{children}
</EmbeddableRootLayout>
);
} }
export async function generateViewport({ params }: SiteStaticLayoutProps) { export async function generateViewport({ params }: SiteStaticLayoutProps) {
@@ -1,5 +1,6 @@
import type { RouteLayoutParams } from '@/app/utils'; import type { RouteLayoutParams } from '@/app/utils';
import { getAssetURL } from '@/lib/assets'; import { getAssetURL } from '@/lib/assets';
import { buildVersion } from '@/lib/build';
import { getEmbeddableStaticContext } from '@/lib/embeddable'; import { getEmbeddableStaticContext } from '@/lib/embeddable';
import type { CreateGitBookOptions } from '@gitbook/embed'; import type { CreateGitBookOptions } from '@gitbook/embed';
import type { NextRequest } from 'next/server'; import type { NextRequest } from 'next/server';
@@ -14,7 +15,6 @@ export async function GET(
{ params }: { params: Promise<RouteLayoutParams> } { params }: { params: Promise<RouteLayoutParams> }
) { ) {
const { context } = await getEmbeddableStaticContext(await params); const { context } = await getEmbeddableStaticContext(await params);
const maxAge = 7 * 24 * 60 * 60;
const initOptions: CreateGitBookOptions = { const initOptions: CreateGitBookOptions = {
siteURL: context.linker.toAbsoluteURL(context.linker.toPathInSite('')), siteURL: context.linker.toAbsoluteURL(context.linker.toPathInSite('')),
}; };
@@ -45,13 +45,13 @@ export async function GET(
const load = function () { const load = function () {
const style = document.createElement('link'); const style = document.createElement('link');
style.rel = 'stylesheet'; style.rel = 'stylesheet';
style.href = ${JSON.stringify(getAssetURL('embed/index.css'))}; style.href = ${JSON.stringify(getAssetURL(`embed/index.css?v=${buildVersion()}`))};
document.head.appendChild(style); document.head.appendChild(style);
const script = d.createElement('script'); const script = d.createElement('script');
script.type = 'text/javascript'; script.type = 'text/javascript';
script.async = true; script.async = true;
script.src = ${JSON.stringify(getAssetURL('embed/index.js'))}; script.src = ${JSON.stringify(getAssetURL(`embed/index.js?v=${buildVersion()}`))};
var latestScript = d.getElementsByTagName('script')[0]; var latestScript = d.getElementsByTagName('script')[0];
latestScript.parentNode.insertBefore(script, latestScript); latestScript.parentNode.insertBefore(script, latestScript);
@@ -70,7 +70,7 @@ export async function GET(
{ {
headers: { headers: {
'Content-Type': 'application/javascript', 'Content-Type': 'application/javascript',
'Cache-Control': `public, max-age=${maxAge}, immutable`, 'Cache-Control': 'public, max-age=86400, stale-while-revalidate=604800',
}, },
} }
); );
@@ -1,2 +1,3 @@
export * from './useAI'; export * from './useAI';
export * from './useAIChat'; export * from './useAIChat';
export type { RenderAIMessageOptions } from './server-actions';
@@ -72,7 +72,7 @@ function DescriptionForPageContentToolCall(props: {
}) { }) {
const { toolCall, context } = props; const { toolCall, context } = props;
const language = getSpaceLanguage(context.customization); const language = getSpaceLanguage(context);
return ( return (
<p> <p>
@@ -102,7 +102,7 @@ function DescriptionForMCPToolCall(props: {
}) { }) {
const { toolCall, context } = props; const { toolCall, context } = props;
const language = getSpaceLanguage(context.customization); const language = getSpaceLanguage(context);
return ( return (
<p> <p>
@@ -130,7 +130,7 @@ async function DescriptionForSearchToolCall(props: {
}) { }) {
const { toolCall, context } = props; const { toolCall, context } = props;
const language = getSpaceLanguage(context.customization); const language = getSpaceLanguage(context);
// Resolve all hrefs for search results in parallel // Resolve all hrefs for search results in parallel
const searchResultsWithHrefs = await Promise.all( const searchResultsWithHrefs = await Promise.all(
@@ -187,7 +187,7 @@ async function DescriptionForSearchToolCall(props: {
) : null} ) : null}
</summary> </summary>
{hasResults ? ( {hasResults ? (
<div className="mt-1 max-h-0 overflow-y-auto circular-corners:rounded-2xl rounded-corners:rounded-lg border border-tint-subtle p-2 opacity-0 transition-all transition-discrete duration-500 group-open:max-h-96 group-open:opacity-11"> <div className="hide-scrollbar mt-1 max-h-0 overflow-y-auto circular-corners:rounded-2xl rounded-corners:rounded-lg border border-tint-subtle p-2 opacity-0 transition-all transition-discrete duration-500 group-open:max-h-96 group-open:opacity-11">
<ol className="space-y-1"> <ol className="space-y-1">
{searchResultsWithHrefs.map((result, index) => ( {searchResultsWithHrefs.map((result, index) => (
<li <li
@@ -241,7 +241,7 @@ function DescriptionForGetPagesToolCall(props: {
}) { }) {
const { toolCall, context } = props; const { toolCall, context } = props;
const language = getSpaceLanguage(context.customization); const language = getSpaceLanguage(context);
return ( return (
<p> <p>
@@ -39,7 +39,9 @@ export async function streamRenderAIMessage(
if (message.steps[stepIndex]) { if (message.steps[stepIndex]) {
message.steps = [...message.steps]; message.steps = [...message.steps];
// @ts-expect-error
message.steps[stepIndex] = { ...message.steps[stepIndex] }; message.steps[stepIndex] = { ...message.steps[stepIndex] };
// @ts-expect-error
callback(message.steps[stepIndex]); callback(message.steps[stepIndex]);
} else { } else {
message.steps = [ message.steps = [
@@ -52,6 +54,7 @@ export async function streamRenderAIMessage(
}, },
}, },
]; ];
// @ts-expect-error
callback(message.steps[stepIndex]); callback(message.steps[stepIndex]);
} }
}; };
@@ -20,6 +20,7 @@ import {
EmbeddableFrameSubtitle, EmbeddableFrameSubtitle,
EmbeddableFrameTitle, EmbeddableFrameTitle,
} from '../Embeddable/EmbeddableFrame'; } from '../Embeddable/EmbeddableFrame';
import { useTrackEvent } from '../Insights';
import { useNow } from '../hooks'; import { useNow } from '../hooks';
import { Button } from '../primitives'; import { Button } from '../primitives';
import { AIChatControlButton } from './AIChatControlButton'; import { AIChatControlButton } from './AIChatControlButton';
@@ -46,17 +47,6 @@ export function AIChat(props: { trademark: boolean }) {
} }
}, [chat.opened]); }, [chat.opened]);
useHotkeys(
'mod+i',
(e) => {
e.preventDefault();
chatController.open();
},
{
enableOnFormTags: true,
}
);
useHotkeys( useHotkeys(
'esc', 'esc',
() => { () => {
@@ -65,6 +55,16 @@ export function AIChat(props: { trademark: boolean }) {
[] []
); );
// Track the view of the AI chat
const trackEvent = useTrackEvent();
React.useEffect(() => {
if (chat.opened) {
trackEvent({
type: 'ask_view',
});
}
}, [chat.opened, trackEvent]);
if (!chat.opened) { if (!chat.opened) {
return null; return null;
} }
@@ -224,7 +224,7 @@ export function AIChatBody(props: {
<> <>
<div <div
ref={scrollContainerRef} ref={scrollContainerRef}
className="flex grow scroll-pt-4 flex-col gap-4 overflow-y-auto p-4" className="gutter-stable flex grow scroll-pt-4 flex-col gap-4 overflow-y-auto p-4"
style={{ style={{
paddingBottom: `${inputHeight}px`, paddingBottom: `${inputHeight}px`,
}} }}
@@ -12,8 +12,9 @@ import { KeyboardShortcut } from '../primitives/KeyboardShortcut';
export function AIChatButton(props: { export function AIChatButton(props: {
assistant: Assistant; assistant: Assistant;
showLabel?: boolean; showLabel?: boolean;
withShortcut?: boolean;
}) { }) {
const { assistant, showLabel = true } = props; const { assistant, showLabel = true, withShortcut = true } = props;
const language = useLanguage(); const language = useLanguage();
return ( return (
@@ -27,7 +28,12 @@ export function AIChatButton(props: {
label={ label={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{t(language, 'ai_chat_ask', assistant.label)} {t(language, 'ai_chat_ask', assistant.label)}
<KeyboardShortcut keys={['mod', 'i']} className="border-tint-11 text-tint-1" /> {withShortcut ? (
<KeyboardShortcut
keys={['mod', 'i']}
className="border-tint-11 text-tint-1"
/>
) : null}
</div> </div>
} }
onClick={() => assistant.open()} onClick={() => assistant.open()}
@@ -1,3 +1,5 @@
import { useLanguage } from '@/intl/client';
import { tString } from '@/intl/translate';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { AIMessageRole } from '@gitbook/api'; import { AIMessageRole } from '@gitbook/api';
import type React from 'react'; import type React from 'react';
@@ -46,17 +48,9 @@ export function AIChatMessages(props: {
{message.content ? message.content : null} {message.content ? message.content : null}
{isLastMessage && chat.loading ? ( {isLastMessage && chat.loading ? (
<div className="flex w-full animate-fade-in-slow flex-wrap gap-2"> <div className="flex w-full animate-fade-in-slow flex-col gap-2">
{Array.from({ length: 7 }).map((_, index) => ( {!message.content ? <HoldMessage /> : null}
<div <LoadingSkeleton />
key={index}
className="h-4 animate-[fadeIn_500ms_ease_both,pulse_1.5s_infinite] circular-corners:rounded-2xl rounded-corners:rounded-md bg-tint-4"
style={{
width: `calc(${(index % 4) * 20 + 10}% - 4px)`,
animationDelay: `${index * 0.1}s`,
}}
/>
))}
</div> </div>
) : null} ) : null}
@@ -86,3 +80,55 @@ export function AIChatMessages(props: {
</> </>
); );
} }
function HoldMessage() {
const language = useLanguage();
return (
<div className="animate-[heightIn_500ms_4500ms_ease_both] py-2 text-tint-subtle">
{tString(language, 'ai_chat_hold_message_1')
.split(' ')
.map((word, index) => (
<span
key={index}
className="animate-fade-in-slow"
style={{
animationDelay: `${5000 + index * 200}ms`,
}}
>
{word}{' '}
</span>
))}
{tString(language, 'ai_chat_hold_message_2')
.split(' ')
.map((word, index) => (
<span
key={index}
className="animate-fade-in-slow"
style={{
animationDelay: `${10000 + index * 200}ms`,
}}
>
{word}{' '}
</span>
))}
</div>
);
}
function LoadingSkeleton() {
return (
<div className="flex flex-wrap gap-2">
{Array.from({ length: 7 }).map((_, index) => (
<div
key={index}
className="h-4 animate-[fadeIn_500ms_ease_both,pulse_1.5s_infinite] circular-corners:rounded-2xl rounded-corners:rounded-md bg-tint-4"
style={{
width: `calc(${(index % 4) * 20 + 10}% - 4px)`,
animationDelay: `${index * 0.1}s`,
}}
/>
))}
</div>
);
}
@@ -0,0 +1,103 @@
'use client';
import type { GitBookSiteContext } from '@/lib/context';
import { OpenAPIPrefillContextProvider } from '@gitbook/react-openapi';
import * as React from 'react';
import { createContext, useContext } from 'react';
export type AdaptiveVisitorClaimsData = {
visitor: {
claims: Record<string, unknown> & { unsigned: Record<string, unknown> };
};
};
/**
* In-memory cache of visitor claim readers keyed by contextId.
*/
const adaptiveVisitorReaderCache = new Map<
string,
ReturnType<typeof createResourceReader<AdaptiveVisitorClaimsData | null>>
>();
function createResourceReader<T>(promise: Promise<T>) {
let result: T | null | undefined;
const suspender = (async () => {
try {
result = await promise;
} catch {
result = null;
}
})();
return {
read() {
if (result === undefined) {
throw suspender;
}
return result;
},
};
}
/**
* Return an adaptive visitor claims cached reader for a given endpoint URL and contextId.
*/
function getAdaptiveVisitorClaimsReader(url: string, contextId: string) {
let reader = adaptiveVisitorReaderCache.get(contextId);
if (!reader) {
const promise = (async () => {
try {
const res = await fetch(url);
if (!res.ok) {
return null;
}
return await res.json<AdaptiveVisitorClaimsData>();
} catch {
return null;
}
})();
reader = createResourceReader(promise);
adaptiveVisitorReaderCache.set(contextId, reader);
}
return reader;
}
export type AdaptiveVisitorContextValue = () => AdaptiveVisitorClaimsData | null;
const AdaptiveVisitorContext = createContext<AdaptiveVisitorContextValue>(() => null);
/**
* Provide context to adapt site based on visitor claims.
*/
export function AdaptiveVisitorContextProvider(
props: React.PropsWithChildren<{
visitorClaimsURL: string;
contextId: GitBookSiteContext['contextId'] | undefined;
}>
) {
const { visitorClaimsURL, contextId, children } = props;
const getAdaptiveVisitorClaims = React.useCallback(() => {
if (!contextId) {
return null;
}
return getAdaptiveVisitorClaimsReader(visitorClaimsURL, contextId).read();
}, [visitorClaimsURL, contextId]);
return (
<AdaptiveVisitorContext.Provider value={getAdaptiveVisitorClaims}>
<OpenAPIPrefillContextProvider getPrefillInputContextData={getAdaptiveVisitorClaims}>
{children}
</OpenAPIPrefillContextProvider>
</AdaptiveVisitorContext.Provider>
);
}
/**
* Hook that returns a suspensable getter for adaptive visitor claims data.
*/
export function useAdaptiveVisitor(): AdaptiveVisitorContextValue {
return useContext(AdaptiveVisitorContext);
}
@@ -0,0 +1 @@
export * from './AdaptiveVisitorContextProvider';
@@ -34,69 +34,67 @@ export function AnnouncementBanner(props: {
className="theme-bold:bg-header-background pt-4 pb-2" className="theme-bold:bg-header-background pt-4 pb-2"
data-nosnippet="" data-nosnippet=""
> >
<div className="scroll-nojump"> <div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96">
<div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96"> <div className={tcls('relative', CONTAINER_STYLE)}>
<div className={tcls('relative', CONTAINER_STYLE)}> <Tag
<Tag href={contentRef?.href ?? ''}
href={contentRef?.href ?? ''} className={tcls(
className={tcls( 'flex w-full items-start justify-center overflow-hidden circular-corners:rounded-xl rounded-md straight-corners:rounded-none px-4 py-3 text-neutral-strong text-sm theme-bold:ring-1 theme-gradient:ring-1 ring-inset transition-colors',
'flex w-full items-start justify-center overflow-hidden circular-corners:rounded-xl rounded-md straight-corners:rounded-none px-4 py-3 text-neutral-strong text-sm theme-bold:ring-1 theme-gradient:ring-1 ring-inset transition-colors', style.container,
style.container, closeable && 'pr-12',
closeable && 'pr-12', hasLink && style.hover
hasLink && style.hover )}
)} insights={
insights={ announcement.link
announcement.link ? {
? { type: 'link_click',
type: 'link_click', link: {
link: { target: announcement.link.to,
target: announcement.link.to, position: SiteInsightsLinkPosition.Announcement,
position: SiteInsightsLinkPosition.Announcement, },
}, }
} : undefined
: undefined }
} >
> <Icon
<Icon icon={style.icon as IconName}
icon={style.icon as IconName} className={`mt-0.5 mr-3 size-4 shrink-0 ${style.iconColor}`}
className={`mt-0.5 mr-3 size-4 shrink-0 ${style.iconColor}`} />
/> <div>
<div> {announcement.message}
{announcement.message} {hasLink ? (
{hasLink ? ( <div className={tcls(LinkStyles, style.link, 'ml-1 inline')}>
<div className={tcls(LinkStyles, style.link, 'ml-1 inline')}> {contentRef?.icon ? (
{contentRef?.icon ? ( <span className="mr-1 ml-2 *:inline">
<span className="mr-1 ml-2 *:inline"> {contentRef?.icon}
{contentRef?.icon} </span>
</span> ) : null}
) : null} {announcement.link?.title && (
{announcement.link?.title && ( <span className="mr-1">{announcement.link?.title}</span>
<span className="mr-1">{announcement.link?.title}</span> )}
)} <Icon
<Icon icon={
icon={ announcement.link?.to.kind === 'url'
announcement.link?.to.kind === 'url' ? 'arrow-up-right'
? 'arrow-up-right' : 'chevron-right'
: 'chevron-right' }
} className={tcls('mb-0.5 inline size-3')}
className={tcls('mb-0.5 inline size-3')} />
/> </div>
</div> ) : null}
) : null} </div>
</div> </Tag>
</Tag> {closeable ? (
{closeable ? ( <Button
<Button iconOnly
iconOnly icon="close"
icon="close" label={tString(language, 'close')}
label={tString(language, 'close')} variant="blank"
variant="blank" size="default"
size="default" onClick={dismissAnnouncement}
onClick={dismissAnnouncement} className={`absolute top-0 right-4 mt-2 mr-2 circular-corners:rounded-lg rounded-sm straight-corners:rounded-none p-1.5 transition-all hover:ring-1 sm:right-6 md:right-8 ${style.close}`}
className={`absolute top-0 right-4 mt-2 mr-2 circular-corners:rounded-lg rounded-sm straight-corners:rounded-none p-1.5 transition-all hover:ring-1 sm:right-6 md:right-8 ${style.close}`} />
/> ) : null}
) : null}
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -119,7 +119,7 @@ export async function highlight(
currentIndex += 1; // for the \n currentIndex += 1; // for the \n
return { return {
highlighted: Boolean(lineBlock.data.highlighted), highlighted: Boolean(lineBlock?.data.highlighted),
tokens: result, tokens: result,
}; };
}); });
@@ -1,5 +1,5 @@
import { type ClassValue, tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import type { DocumentBlockColumns, Length } from '@gitbook/api'; import { type DocumentBlockColumns, type Length, VerticalAlignment } from '@gitbook/api';
import type { BlockProps } from '../Block'; import type { BlockProps } from '../Block';
import { Blocks } from '../Blocks'; import { Blocks } from '../Blocks';
@@ -8,10 +8,12 @@ export function Columns(props: BlockProps<DocumentBlockColumns>) {
return ( return (
<div className={tcls('flex flex-col gap-x-8 md:flex-row', style)}> <div className={tcls('flex flex-col gap-x-8 md:flex-row', style)}>
{block.nodes.map((columnBlock) => { {block.nodes.map((columnBlock) => {
const width = columnBlock.data.width;
const { className, style } = transformLengthToCSS(width);
return ( return (
<Column key={columnBlock.key} className={className} style={style}> <Column
key={columnBlock.key}
width={columnBlock.data.width}
verticalAlignment={columnBlock.data.verticalAlignment}
>
<Blocks <Blocks
key={columnBlock.key} key={columnBlock.key}
nodes={columnBlock.nodes} nodes={columnBlock.nodes}
@@ -29,11 +31,23 @@ export function Columns(props: BlockProps<DocumentBlockColumns>) {
export function Column(props: { export function Column(props: {
children?: React.ReactNode; children?: React.ReactNode;
className?: ClassValue; width?: Length;
style?: React.CSSProperties; verticalAlignment?: VerticalAlignment;
}) { }) {
const { width, verticalAlignment } = props;
const { className, style } = transformLengthToCSS(width);
return ( return (
<div className={tcls('flex-col', props.className)} style={props.style}> <div
className={tcls(
'flex flex-col',
(verticalAlignment === VerticalAlignment.Top || !verticalAlignment) &&
'justify-start',
verticalAlignment === VerticalAlignment.Middle && 'justify-center',
verticalAlignment === VerticalAlignment.Bottom && 'justify-end',
className
)}
style={style}
>
{props.children} {props.children}
</div> </div>
); );
@@ -7,13 +7,16 @@ import { Block, type BlockProps } from './Block';
import { Blocks } from './Blocks'; import { Blocks } from './Blocks';
import { getBlockTextStyle } from './spacing'; import { getBlockTextStyle } from './spacing';
export function Hint(props: BlockProps<DocumentBlockHint>) { export function Hint({
const { block, style, ancestorBlocks, ...contextProps } = props; block,
style,
ancestorBlocks,
...contextProps
}: BlockProps<DocumentBlockHint>) {
const hintStyle = HINT_STYLES[block.data.style] ?? HINT_STYLES.info; const hintStyle = HINT_STYLES[block.data.style] ?? HINT_STYLES.info;
const firstLine = getBlockTextStyle(block.nodes[0]); const firstNode = block.nodes[0]!;
const firstLine = getBlockTextStyle(firstNode);
const firstNode = block.nodes[0]; const hasHeading = ['heading-1', 'heading-2', 'heading-3'].includes(firstNode.type);
const hasHeading = ['heading-1', 'heading-2', 'heading-3'].includes(block.nodes[0].type);
return ( return (
<div <div
@@ -20,10 +20,7 @@ export async function InlineLink(props: InlineProps<DocumentInlineLink>) {
: null; : null;
const { contentContext } = context; const { contentContext } = context;
const language = const language = contentContext ? getSpaceLanguage(contentContext) : languages.en;
contentContext && 'customization' in contentContext
? getSpaceLanguage(contentContext.customization)
: languages.en;
if (!contentContext || !resolved) { if (!contentContext || !resolved) {
return ( return (
@@ -99,7 +99,7 @@
} }
.contentkit-button-style-primary { .contentkit-button-style-primary {
@apply bg-primary-solid text-contrast-primary-solid hover:bg-primary-solid-hover hover:text-contrast-primary-solid-hover ring-0 contrast-more:ring-1; @apply bg-primary-original text-contrast-primary-original hover:bg-primary-solid-hover hover:text-contrast-primary-solid-hover ring-0 contrast-more:ring-1;
} }
.contentkit-button-style-secondary { .contentkit-button-style-secondary {
@@ -19,9 +19,9 @@ export function ListItem(props: BlockProps<DocumentBlockListItem>) {
const parent = ancestorBlocks[ancestorBlocks.length - 1]; const parent = ancestorBlocks[ancestorBlocks.length - 1];
assert( assert(
(parent && parent.type === 'list-ordered') || parent?.type === 'list-ordered' ||
parent.type === 'list-unordered' || parent?.type === 'list-unordered' ||
parent.type === 'list-tasks', parent?.type === 'list-tasks',
'Invalid parent list type' 'Invalid parent list type'
); );
@@ -112,11 +112,11 @@ function getListItemDepth(input: {
for (let i = ancestorBlocks.length - 1; i >= 0; i--) { for (let i = ancestorBlocks.length - 1; i >= 0; i--) {
const block = ancestorBlocks[i]; const block = ancestorBlocks[i];
if (block.type === type) { if (block?.type === type) {
depth = depth + 1; depth = depth + 1;
continue; continue;
} }
if (block.type === 'list-item') { if (block?.type === 'list-item') {
continue; continue;
} }
break; break;
@@ -11,7 +11,7 @@ import { Heading } from '../Heading';
import './scalar.css'; import './scalar.css';
import './style.css'; import './style.css';
import { DEFAULT_LOCALE, getCustomizationLocale } from '@/intl/server'; import { DEFAULT_LOCALE, getSpaceLocale } from '@/intl/server';
import type { GitBookAnyContext } from '@/lib/context'; import type { GitBookAnyContext } from '@/lib/context';
import type { import type {
AnyOpenAPIOperationsBlock, AnyOpenAPIOperationsBlock,
@@ -30,10 +30,7 @@ export function getOpenAPIContext(args: {
const { props, specUrl, context } = args; const { props, specUrl, context } = args;
const { block } = props; const { block } = props;
const customization = context && 'customization' in context ? context.customization : null; const customizationLocale = context ? getSpaceLocale(context) : DEFAULT_LOCALE;
const customizationLocale = customization
? getCustomizationLocale(customization)
: DEFAULT_LOCALE;
const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE; const locale = checkIsValidLocale(customizationLocale) ? customizationLocale : DEFAULT_LOCALE;
return { return {
@@ -272,9 +272,8 @@ body {
} }
.scalar-activate-button { .scalar-activate-button {
@apply flex gap-2 items-center; @apply flex gap-2 items-center;
@apply bg-primary-solid text-contrast-primary-solid hover:bg-primary-solid-hover hover:text-contrast-primary-solid-hover contrast-more:ring-1 rounded-md straight-corners:rounded-none circular-corners:rounded-full circular-corners:px-3 place-self-start; @apply bg-primary-original text-contrast-primary-original hover:bg-primary-solid-hover hover:text-contrast-primary-solid-hover contrast-more:ring-1 rounded-md straight-corners:rounded-none circular-corners:rounded-full circular-corners:px-3 place-self-start;
@apply ring-1 ring-tint hover:ring-tint-hover; @apply shadow-sm shadow-primary dark:shadow-primary-1 hover:shadow-md active:shadow-none;
@apply shadow-sm shadow-tint dark:shadow-tint-1 hover:shadow-md active:shadow-none;
@apply contrast-more:ring-tint-12 contrast-more:hover:ring-2 contrast-more:hover:ring-tint-12; @apply contrast-more:ring-tint-12 contrast-more:hover:ring-2 contrast-more:hover:ring-tint-12;
@apply hover:scale-105 active:scale-100 transition-all; @apply hover:scale-105 active:scale-100 transition-all;
@apply grow-0 shrink-0 truncate; @apply grow-0 shrink-0 truncate;
@@ -565,7 +565,7 @@
} }
.openapi-example-empty { .openapi-example-empty {
@apply relative text-tint bg-tint min-h-20 flex flex-col justify-center items-center; @apply relative text-tint min-h-20 flex flex-col justify-center items-center text-sm;
} }
/* Common Elements */ /* Common Elements */
@@ -746,6 +746,10 @@ body:has(.openapi-select-popover) {
@apply px-3 transition-all; @apply px-3 transition-all;
} }
.openapi-disclosure-group-trigger[aria-expanded="true"] > .openapi-disclosure-group-label {
@apply font-medium;
}
.openapi-disclosure-group-trigger[aria-expanded="true"] > .openapi-disclosure-group-icon > svg { .openapi-disclosure-group-trigger[aria-expanded="true"] > .openapi-disclosure-group-icon > svg {
@apply rotate-90; @apply rotate-90;
} }
@@ -10,7 +10,7 @@ export function StepperStep(props: BlockProps<DocumentBlockStepperStep>) {
const { block, style, ancestorBlocks, ...contextProps } = props; const { block, style, ancestorBlocks, ...contextProps } = props;
const ancestor = ancestorBlocks[ancestorBlocks.length - 1]; const ancestor = ancestorBlocks[ancestorBlocks.length - 1];
assert(ancestor.type === 'stepper', 'Ancestor block must be a stepper'); assert(ancestor?.type === 'stepper', 'Ancestor block must be a stepper');
const index = ancestor.nodes.indexOf(block); const index = ancestor.nodes.indexOf(block);
@@ -36,8 +36,8 @@ export function StepperStep(props: BlockProps<DocumentBlockStepperStep>) {
<div className="relative select-none"> <div className="relative select-none">
<div <div
className={tcls( className={tcls(
'can-override-bg can-override-text flex size-[calc(1.75rem+1px)] items-center justify-center rounded-full bg-primary-solid theme-muted:bg-primary-subtle tabular-nums', 'can-override-bg can-override-text flex size-[calc(1.75rem+1px)] items-center justify-center rounded-full bg-primary-original theme-muted:bg-primary-subtle tabular-nums contrast-more:bg-primary-solid',
'font-medium text-contrast-primary-solid theme-muted:text-primary' 'font-medium text-contrast-primary-original theme-muted:text-primary contrast-more:text-contrast-primary-solid'
)} )}
> >
{index + 1} {index + 1}
@@ -3,6 +3,7 @@ import { Image } from '@/components/utils';
import { type ResolvedContentRef, resolveContentRef } from '@/lib/references'; import { type ResolvedContentRef, resolveContentRef } from '@/lib/references';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { import {
CardsImageObjectFit,
type ContentRef, type ContentRef,
type DocumentTableViewCards, type DocumentTableViewCards,
SiteInsightsLinkPosition, SiteInsightsLinkPosition,
@@ -25,8 +26,12 @@ export async function RecordCard(
: null; : null;
const [lightCover, darkCover, target] = await Promise.all([ const [lightCover, darkCover, target] = await Promise.all([
light && context.contentContext ? resolveContentRef(light, context.contentContext) : null, light.contentRef && context.contentContext
dark && context.contentContext ? resolveContentRef(dark, context.contentContext) : null, ? resolveContentRef(light.contentRef, context.contentContext)
: null,
dark.contentRef && context.contentContext
? resolveContentRef(dark.contentRef, context.contentContext)
: null,
targetRef && context.contentContext targetRef && context.contentContext
? resolveContentRef(targetRef, context.contentContext) ? resolveContentRef(targetRef, context.contentContext)
: null, : null,
@@ -35,6 +40,10 @@ export async function RecordCard(
const darkCoverIsSquareOrPortrait = isSquareOrPortrait(darkCover); const darkCoverIsSquareOrPortrait = isSquareOrPortrait(darkCover);
const lightCoverIsSquareOrPortrait = isSquareOrPortrait(lightCover); const lightCoverIsSquareOrPortrait = isSquareOrPortrait(lightCover);
const darkObjectFit = `dark:${getObjectFitClass(dark.objectFit)}`;
const lightObjectFit = getObjectFitClass(light.objectFit);
const objectFits = `${lightObjectFit} ${darkObjectFit}`;
const body = ( const body = (
<div <div
className={tcls( className={tcls(
@@ -94,7 +103,7 @@ export async function RecordCard(
'min-w-0', 'min-w-0',
'w-full', 'w-full',
'h-full', 'h-full',
'object-cover', 'bg-tint-subtle',
lightCoverIsSquareOrPortrait || darkCoverIsSquareOrPortrait lightCoverIsSquareOrPortrait || darkCoverIsSquareOrPortrait
? [ ? [
lightCoverIsSquareOrPortrait lightCoverIsSquareOrPortrait
@@ -104,7 +113,8 @@ export async function RecordCard(
? 'dark:min-[432px]:aspect-video dark:min-[432px]:h-auto' ? 'dark:min-[432px]:aspect-video dark:min-[432px]:h-auto'
: '', : '',
].filter(Boolean) ].filter(Boolean)
: ['h-auto', 'aspect-video'] : ['h-auto', 'aspect-video'],
objectFits
)} )}
priority={isOffscreen ? 'lazy' : 'high'} priority={isOffscreen ? 'lazy' : 'high'}
preload preload
@@ -190,3 +200,23 @@ function isSquareOrPortrait(contentRef: ResolvedContentRef | null) {
return file.dimensions?.width / file.dimensions?.height <= 1; return file.dimensions?.width / file.dimensions?.height <= 1;
} }
/**
* Get the CSS class for object-fit based on the objectFit value.
*/
function getObjectFitClass(objectFit: CardsImageObjectFit | undefined): string {
if (!objectFit) {
return 'object-cover';
}
switch (objectFit) {
case CardsImageObjectFit.Contain:
return 'object-contain';
case CardsImageObjectFit.Fill:
return 'object-fill';
case CardsImageObjectFit.Cover:
return 'object-cover';
default:
throw new Error(`Unsupported object fit: ${objectFit}`);
}
}
@@ -26,6 +26,7 @@ export function RecordRow(
autoSizedColumns, autoSizedColumns,
fixedColumns, fixedColumns,
}); });
// @ts-expect-error
const verticalAlignment = getColumnVerticalAlignment(block.data.definition[column]); const verticalAlignment = getColumnVerticalAlignment(block.data.definition[column]);
return ( return (
@@ -25,7 +25,9 @@ export function ViewGrid(props: TableViewProps<DocumentTableViewGrid>) {
/* Only show the header when configured and not empty */ /* Only show the header when configured and not empty */
const withHeader = const withHeader =
!view.hideHeader && !view.hideHeader &&
view.columns.some((columnId) => block.data.definition[columnId].title.trim().length > 0); view.columns.some(
(columnId) => (block.data.definition[columnId]?.title.trim().length ?? 0) > 0
);
return ( return (
<div className={tcls(style, styles.tableWrapper)}> <div className={tcls(style, styles.tableWrapper)}>
@@ -43,28 +45,31 @@ export function ViewGrid(props: TableViewProps<DocumentTableViewGrid>) {
)} )}
> >
<div role="row" className={tcls('flex', 'w-full')}> <div role="row" className={tcls('flex', 'w-full')}>
{view.columns.map((column) => ( {view.columns.map((column) => {
<div const definition = block.data.definition[column]!;
key={column} return (
role="columnheader" <div
className={tcls( key={column}
styles.columnHeader, role="columnheader"
getColumnAlignment(block.data.definition[column]) className={tcls(
)} styles.columnHeader,
style={{ getColumnAlignment(definition)
width: getColumnWidth({ )}
column, style={{
columnWidths, width: getColumnWidth({
autoSizedColumns, column,
fixedColumns, columnWidths,
}), autoSizedColumns,
minWidth: columnWidths?.[column] || '100px', fixedColumns,
}} }),
title={block.data.definition[column].title} minWidth: columnWidths?.[column] || '100px',
> }}
{block.data.definition[column].title} title={definition.title}
</div> >
))} {definition.title}
</div>
);
})}
</div> </div>
</div> </div>
)} )}
@@ -1,8 +1,10 @@
import type { import type {
CardsImageObjectFit,
ContentRef, ContentRef,
ContentRefFile, ContentRefFile,
ContentRefURL, ContentRefURL,
DocumentTableDefinition, DocumentTableDefinition,
DocumentTableImageRecord,
DocumentTableRecord, DocumentTableRecord,
DocumentTableViewCards, DocumentTableViewCards,
} from '@gitbook/api'; } from '@gitbook/api';
@@ -21,53 +23,64 @@ export function getRecordValue<T extends number | string | boolean | string[] |
/** /**
* Get the covers for a record card. * Get the covers for a record card.
* Returns both the light and dark covers. * Returns both the light and dark covers with their content refs and optional object fit.
* The light cover is a string or a content ref (image or files column type). * The light cover is a string or a content ref (image or files column type).
* The dark cover is a content ref (image column type). * The dark cover is a content ref (image column type).
*/ */
export function getRecordCardCovers( export function getRecordCardCovers(
record: DocumentTableRecord, record: DocumentTableRecord,
view: DocumentTableViewCards view: DocumentTableViewCards
): { [key in 'light' | 'dark']: ContentRefFile | ContentRefURL | null } { ): {
return { [key in 'light' | 'dark']: {
light: (() => { contentRef: ContentRefFile | ContentRefURL | null;
if (!view.coverDefinition) { objectFit?: CardsImageObjectFit;
return null;
}
const value = getRecordValue(record, view.coverDefinition) as
| ContentRefFile
| ContentRefURL
| string[];
if (Array.isArray(value)) {
if (value.length === 0) {
return null;
}
if (typeof value[0] === 'string') {
return { kind: 'file', file: value[0] };
}
}
return value as ContentRefFile | ContentRefURL;
})(),
dark: (() => {
if (!view.coverDefinitionDark) {
return null;
}
const value = getRecordValue(record, view.coverDefinitionDark) as
| ContentRefFile
| ContentRefURL;
if (!value) {
return null;
}
return value;
})(),
}; };
} {
const lightValue = view.coverDefinition
? (getRecordValue(record, view.coverDefinition) as DocumentTableImageRecord | string[])
: null;
const darkValue = view.coverDefinitionDark
? (getRecordValue(record, view.coverDefinitionDark) as DocumentTableImageRecord)
: null;
return {
light: processCoverValue(lightValue),
dark: processCoverValue(darkValue),
};
}
/**
* Process a cover value and return the content ref and object fit.
*/
function processCoverValue(value: DocumentTableImageRecord | string[] | null | undefined): {
contentRef: ContentRefFile | ContentRefURL | null;
objectFit?: CardsImageObjectFit;
} {
if (!value) {
return { contentRef: null };
}
if (Array.isArray(value)) {
if (value.length === 0) {
return { contentRef: null };
}
if (typeof value[0] === 'string') {
return { contentRef: { kind: 'file', file: value[0] } };
}
}
// Check if it's the new schema with objectFit
if (value && typeof value === 'object' && 'ref' in value && 'objectFit' in value) {
return {
contentRef: value.ref,
objectFit: value.objectFit,
};
}
// It's a direct ContentRef
return { contentRef: value as ContentRefFile | ContentRefURL };
} }
/** /**
@@ -206,7 +206,7 @@ export function DynamicTabs(
'max-w-full', 'max-w-full',
'truncate', 'truncate',
active.id === tab.id active?.id === tab.id
? [ ? [
'shrink-0', 'shrink-0',
'active-tab', 'active-tab',
@@ -222,7 +222,7 @@ export function DynamicTabs(
<button <button
type="button" type="button"
role="tab" role="tab"
aria-selected={active.id === tab.id} aria-selected={active?.id === tab.id}
aria-controls={getTabPanelId(tab.id)} aria-controls={getTabPanelId(tab.id)}
id={getTabButtonId(tab.id)} id={getTabButtonId(tab.id)}
onClick={() => { onClick={() => {
@@ -255,7 +255,7 @@ export function DynamicTabs(
role="tabpanel" role="tabpanel"
id={getTabPanelId(tab.id)} id={getTabPanelId(tab.id)}
aria-labelledby={getTabButtonId(tab.id)} aria-labelledby={getTabButtonId(tab.id)}
className={tcls('p-4', tab.id !== active.id ? 'hidden' : null)} className={tcls('p-4', tab.id !== active?.id ? 'hidden' : null)}
> >
{tabsBody[index]} {tabsBody[index]}
</div> </div>
@@ -59,15 +59,15 @@ interface MarkedLeafProps<Mark extends DocumentTextMark> {
} }
function Bold(props: MarkedLeafProps<DocumentMarkBold>) { function Bold(props: MarkedLeafProps<DocumentMarkBold>) {
return <strong className={tcls('font-bold')}>{props.children}</strong>; return <strong className="font-bold">{props.children}</strong>;
} }
function Italic(props: MarkedLeafProps<DocumentMarkItalic>) { function Italic(props: MarkedLeafProps<DocumentMarkItalic>) {
return <i className={tcls('font-italic')}>{props.children}</i>; return <i className="font-italic">{props.children}</i>;
} }
function Strikethrough(props: MarkedLeafProps<DocumentMarkStrikethrough>) { function Strikethrough(props: MarkedLeafProps<DocumentMarkStrikethrough>) {
return <s className={tcls('line-through')}>{props.children}</s>; return <s className="line-through">{props.children}</s>;
} }
function Keyboard(props: MarkedLeafProps<DocumentMarkKeyboard>) { function Keyboard(props: MarkedLeafProps<DocumentMarkKeyboard>) {
@@ -43,9 +43,9 @@ export function getBlockTextStyle(block: DocumentBlock): {
case 'list-ordered': case 'list-ordered':
case 'list-tasks': case 'list-tasks':
case 'list-unordered': case 'list-unordered':
return getBlockTextStyle(block.nodes[0]); return getBlockTextStyle(block.nodes[0]!);
case 'list-item': case 'list-item':
return getBlockTextStyle(block.nodes[0]); return getBlockTextStyle(block.nodes[0]!);
default: default:
return { return {
textSize: 'text-base', textSize: 'text-base',
@@ -21,7 +21,7 @@ export function isBlockOffscreen(
const allAncestors = [document, ...ancestorBlocks]; const allAncestors = [document, ...ancestorBlocks];
for (let index = allAncestors.length - 1; index >= 0; index--) { for (let index = allAncestors.length - 1; index >= 0; index--) {
const parent = allAncestors[index]; const parent = allAncestors[index]!;
const offset = getBlockOffset({ block: current, parent }); const offset = getBlockOffset({ block: current, parent });
if (offset > screenHeight) { if (offset > screenHeight) {
@@ -7,6 +7,9 @@ import {
AIChatDynamicIcon, AIChatDynamicIcon,
AIChatSubtitle, AIChatSubtitle,
} from '@/components/AIChat'; } from '@/components/AIChat';
import * as api from '@gitbook/api';
import React from 'react';
import { useTrackEvent } from '../Insights';
import { import {
EmbeddableFrame, EmbeddableFrame,
EmbeddableFrameBody, EmbeddableFrameBody,
@@ -28,6 +31,20 @@ export function EmbeddableAIChat(props: {
const chatController = useAIChatController(); const chatController = useAIChatController();
const configuration = useEmbeddableConfiguration(); const configuration = useEmbeddableConfiguration();
// Track the view of the AI chat
const trackEvent = useTrackEvent();
React.useEffect(() => {
trackEvent(
{
type: 'ask_view',
},
{
pageId: null,
displayContext: api.SiteInsightsDisplayContext.Embed,
}
);
}, [trackEvent]);
return ( return (
<EmbeddableFrame> <EmbeddableFrame>
<EmbeddableFrameHeader> <EmbeddableFrameHeader>
@@ -2,6 +2,7 @@ import { type PagePathParams, getSitePageData } from '@/components/SitePage';
import { PageBody } from '@/components/PageBody'; import { PageBody } from '@/components/PageBody';
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import { SiteInsightsDisplayContext } from '@gitbook/api';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { Button } from '../primitives'; import { Button } from '../primitives';
import { import {
@@ -54,6 +55,7 @@ export async function EmbeddableDocsPage(props: EmbeddableDocsPageProps) {
ancestors={ancestors} ancestors={ancestors}
document={document} document={document}
withPageFeedback={withPageFeedback} withPageFeedback={withPageFeedback}
insightsDisplayContext={SiteInsightsDisplayContext.Embed}
/> />
</div> </div>
</EmbeddableFrameBody> </EmbeddableFrameBody>
@@ -1,16 +1,20 @@
import { AIChatProvider, AIContextProvider } from '@/components/AI'; import { AIContextProvider } from '@/components/AI';
import { CustomizationRootLayout } from '@/components/RootLayout'; import { CustomizationRootLayout } from '@/components/RootLayout';
import { import {
SiteLayoutClientContexts, SiteLayoutClientContexts,
generateSiteLayoutMetadata, generateSiteLayoutMetadata,
generateSiteLayoutViewport, generateSiteLayoutViewport,
} from '@/components/SiteLayout'; } from '@/components/SiteLayout';
import type { VisitorAuthClaims } from '@/lib/adaptive';
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import { CustomizationAIMode } from '@gitbook/api'; import { CustomizationAIMode } from '@gitbook/api';
import { SpaceLayoutServerContext } from '../SpaceLayout';
import { EmbeddableIframeAPI } from './EmbeddableIframeAPI'; import { EmbeddableIframeAPI } from './EmbeddableIframeAPI';
type EmbeddableRootLayoutProps = { type EmbeddableRootLayoutProps = {
context: GitBookSiteContext; context: GitBookSiteContext;
withTracking: boolean;
visitorAuthClaims: VisitorAuthClaims;
}; };
/** /**
@@ -18,10 +22,12 @@ type EmbeddableRootLayoutProps = {
*/ */
export async function EmbeddableRootLayout({ export async function EmbeddableRootLayout({
context, context,
withTracking,
visitorAuthClaims,
children, children,
}: React.PropsWithChildren<EmbeddableRootLayoutProps>) { }: React.PropsWithChildren<EmbeddableRootLayoutProps>) {
return ( return (
<CustomizationRootLayout customization={context.customization}> <CustomizationRootLayout context={context}>
<SiteLayoutClientContexts <SiteLayoutClientContexts
forcedTheme={context.customization.themes.default} forcedTheme={context.customization.themes.default}
externalLinksTarget={context.customization.externalLinks.target} externalLinksTarget={context.customization.externalLinks.target}
@@ -31,8 +37,11 @@ export async function EmbeddableRootLayout({
aiMode={CustomizationAIMode.Assistant} aiMode={CustomizationAIMode.Assistant}
trademark={context.customization.trademark.enabled} trademark={context.customization.trademark.enabled}
> >
<AIChatProvider <SpaceLayoutServerContext
renderMessageOptions={{ context={context}
withTracking={withTracking}
visitorAuthClaims={visitorAuthClaims}
aiChatRenderMessageOptions={{
withLinkPreviews: false, withLinkPreviews: false,
asEmbeddable: true, asEmbeddable: true,
}} }}
@@ -41,17 +50,17 @@ export async function EmbeddableRootLayout({
<EmbeddableIframeAPI <EmbeddableIframeAPI
baseURL={context.linker.toPathInSpace('~gitbook/embed/')} baseURL={context.linker.toPathInSpace('~gitbook/embed/')}
/> />
</AIChatProvider> </SpaceLayoutServerContext>
</AIContextProvider> </AIContextProvider>
</SiteLayoutClientContexts> </SiteLayoutClientContexts>
</CustomizationRootLayout> </CustomizationRootLayout>
); );
} }
export async function generateEmbeddableViewport({ context }: EmbeddableRootLayoutProps) { export async function generateEmbeddableViewport({ context }: { context: GitBookSiteContext }) {
return generateSiteLayoutViewport(context); return generateSiteLayoutViewport(context);
} }
export async function generateEmbeddableMetadata({ context }: EmbeddableRootLayoutProps) { export async function generateEmbeddableMetadata({ context }: { context: GitBookSiteContext }) {
return generateSiteLayoutMetadata(context); return generateSiteLayoutMetadata(context);
} }
+98 -100
View File
@@ -32,111 +32,109 @@ export function Footer(props: { context: GitBookSiteContext }) {
mobileOnly ? 'xl:hidden' : null mobileOnly ? 'xl:hidden' : null
)} )}
> >
<div className="scroll-nojump"> <div className={tcls(CONTAINER_STYLE, 'px-4', 'py-8', 'lg:py-12', 'mx-auto')}>
<div className={tcls(CONTAINER_STYLE, 'px-4', 'py-8', 'lg:py-12', 'mx-auto')}> <div
<div className={tcls(
className={tcls( 'mx-auto grid max-w-3xl site-width-wide:max-w-screen-2xl justify-between gap-12 lg:max-w-none!',
'mx-auto grid max-w-3xl site-width-wide:max-w-screen-2xl justify-between gap-12 lg:max-w-none!', 'grid-cols-[auto_auto]',
'grid-cols-[auto_auto]', 'lg:grid-cols-[18rem_minmax(auto,48rem)_auto]',
'lg:grid-cols-[18rem_minmax(auto,48rem)_auto]', 'xl:grid-cols-[18rem_minmax(auto,48rem)_14rem]',
'xl:grid-cols-[18rem_minmax(auto,48rem)_14rem]', 'lg:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_auto]',
'lg:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_auto]', 'xl:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_14rem]',
'xl:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_14rem]', 'lg:page-no-toc:grid-cols-[minmax(auto,48rem)_auto]',
'lg:page-no-toc:grid-cols-[minmax(auto,48rem)_auto]', 'xl:page-no-toc:grid-cols-[14rem_minmax(auto,48rem)_14rem]',
'xl:page-no-toc:grid-cols-[14rem_minmax(auto,48rem)_14rem]', 'lg:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[minmax(auto,90rem)_auto]',
'lg:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[minmax(auto,90rem)_auto]', 'xl:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[14rem_minmax(auto,90rem)_14rem]'
'xl:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[14rem_minmax(auto,90rem)_14rem]' )}
)} >
> {
{ // Footer Logo
// Footer Logo customization.footer.logo ? (
customization.footer.logo ? ( <div className="col-start-1 row-start-1">
<div className="col-start-1 row-start-1"> <Image
<Image alt="Logo"
alt="Logo" resize={context.imageResizer}
resize={context.imageResizer} sources={{
sources={{ light: {
light: { src: customization.footer.logo.light,
src: customization.footer.logo.light, },
}, dark: customization.footer.logo.dark
dark: customization.footer.logo.dark ? {
? { src: customization.footer.logo.dark,
src: customization.footer.logo.dark, }
} : null,
: null, }}
}} priority="lazy"
priority="lazy" style={[
style={[ 'w-auto',
'w-auto', 'max-w-40',
'max-w-40', 'lg:max-w-64',
'lg:max-w-64', 'max-h-10',
'max-h-10', 'lg:max-h-12',
'lg:max-h-12', 'object-contain',
'object-contain', 'object-left',
'object-left', 'rounded-sm',
'rounded-sm', 'straight-corners:rounded-xs',
'straight-corners:rounded-xs', ]}
]} sizes={[
sizes={[ {
{ width: 320,
width: 320, },
}, ]}
]} />
/> </div>
</div> ) : null
) : null }
}
{ {
// Theme Toggle // Theme Toggle
customization.themes.toggeable ? ( customization.themes.toggeable ? (
<div className="-col-start-2 row-start-1 flex items-start justify-end xl:hidden"> <div className="-col-start-2 row-start-1 flex items-start justify-end xl:hidden">
<React.Suspense fallback={null}> <React.Suspense fallback={null}>
<ThemeToggler /> <ThemeToggler />
</React.Suspense> </React.Suspense>
</div> </div>
) : null ) : null
} }
{ {
// Navigation groups (split into equal columns) // Navigation groups (split into equal columns)
customization.footer.groups?.length > 0 ? ( customization.footer.groups?.length > 0 ? (
<div <div
className={tcls( className={tcls(
'col-span-2 lg:page-has-toc:col-span-1 lg:page-has-toc:col-start-2 xl:page-no-toc:col-span-1 xl:page-no-toc:col-start-2' 'col-span-2 lg:page-has-toc:col-span-1 lg:page-has-toc:col-start-2 xl:page-no-toc:col-span-1 xl:page-no-toc:col-start-2'
)}
>
<div className="mx-auto flex max-w-3xl site-width-wide:max-w-screen-2xl flex-col gap-10 sm:flex-row sm:gap-6">
{partition(customization.footer.groups, FOOTER_COLUMNS).map(
(column, columnIndex) => (
<div
key={columnIndex}
className="flex flex-1 grow flex-col gap-10"
>
{column.map((group, groupIndex) => (
<FooterLinksGroup
key={groupIndex}
group={group}
context={context}
/>
))}
</div>
)
)} )}
>
<div className="mx-auto flex max-w-3xl site-width-wide:max-w-screen-2xl flex-col gap-10 sm:flex-row sm:gap-6">
{partition(customization.footer.groups, FOOTER_COLUMNS).map(
(column, columnIndex) => (
<div
key={columnIndex}
className="flex flex-1 grow flex-col gap-10"
>
{column.map((group, groupIndex) => (
<FooterLinksGroup
key={groupIndex}
group={group}
context={context}
/>
))}
</div>
)
)}
</div>
</div> </div>
) : null </div>
} ) : null
}
{ {
// Legal // Legal
customization.footer.copyright ? ( customization.footer.copyright ? (
<div className="order-last col-span-full flex w-full grow flex-col items-center gap-2 text-center text-tint text-xs"> <div className="order-last col-span-full flex w-full grow flex-col items-center gap-2 text-center text-tint text-xs">
<p>{customization.footer.copyright}</p> <p>{customization.footer.copyright}</p>
</div> </div>
) : null ) : null
} }
</div>
</div> </div>
</div> </div>
</footer> </footer>
+128 -117
View File
@@ -3,13 +3,14 @@ import type { GitBookSiteContext } from '@/lib/context';
import { CONTAINER_STYLE, HEADER_HEIGHT_DESKTOP } from '@/components/layout'; import { CONTAINER_STYLE, HEADER_HEIGHT_DESKTOP } from '@/components/layout';
import { getSpaceLanguage, t } from '@/intl/server'; import { getSpaceLanguage, t } from '@/intl/server';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { SearchContainer } from '../Search';
import { SiteSectionTabs, encodeClientSiteSections } from '../SiteSections'; import { SiteSectionTabs, encodeClientSiteSections } from '../SiteSections';
import { HeaderLink } from './HeaderLink'; import { HeaderLink } from './HeaderLink';
import { HeaderLinkMore } from './HeaderLinkMore'; import { HeaderLinkMore } from './HeaderLinkMore';
import { HeaderLinks } from './HeaderLinks'; import { HeaderLinks } from './HeaderLinks';
import { HeaderLogo } from './HeaderLogo'; import { HeaderLogo } from './HeaderLogo';
import { HeaderMobileMenu } from './HeaderMobileMenu'; import { HeaderMobileMenu } from './HeaderMobileMenu';
import { SpacesDropdown } from './SpacesDropdown'; import { TranslationsDropdown } from './SpacesDropdown';
/** /**
* Render the header for the space. * Render the header for the space.
@@ -17,9 +18,9 @@ import { SpacesDropdown } from './SpacesDropdown';
export function Header(props: { export function Header(props: {
context: GitBookSiteContext; context: GitBookSiteContext;
withTopHeader?: boolean; withTopHeader?: boolean;
search?: React.ReactNode; withVariants?: 'generic' | 'translations';
}) { }) {
const { context, withTopHeader, search } = props; const { context, withTopHeader, withVariants } = props;
const { siteSpace, siteSpaces, sections, customization } = context; const { siteSpace, siteSpaces, sections, customization } = context;
return ( return (
@@ -56,135 +57,145 @@ export function Header(props: {
'theme-bold:shadow-tint-12/2' 'theme-bold:shadow-tint-12/2'
)} )}
> >
<div className="scroll-nojump"> <div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96">
<div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96"> <div
className={tcls(
'gap-4',
'lg:gap-6',
'flex',
'items-center',
'justify-between',
'w-full',
'py-3',
'min-h-16',
'sm:h-16',
CONTAINER_STYLE
)}
>
<div <div
className={tcls( className={tcls(
'gap-4', 'flex max-w-full lg:basis-72',
'lg:gap-6', 'min-w-0 shrink items-center justify-start gap-2 lg:gap-4'
'flex',
'items-center',
'justify-between',
'w-full',
'py-3',
'min-h-16',
'sm:h-16',
CONTAINER_STYLE
)} )}
> >
<div <HeaderMobileMenu
className={tcls( className={tcls(
'flex max-w-full lg:basis-72', 'lg:hidden',
'min-w-0 shrink items-center justify-start gap-2 lg:gap-4' '-ml-2',
'text-tint-strong',
'theme-bold:text-header-link',
'hover:bg-tint-hover',
'hover:theme-bold:bg-header-link/3',
withVariants === 'generic' ? '' : 'page-no-toc:hidden'
)} )}
> />
<HeaderMobileMenu <HeaderLogo context={context} />
className={tcls(
'lg:hidden',
'-ml-2',
'text-tint-strong',
'theme-bold:text-header-link',
'hover:bg-tint-hover',
'hover:theme-bold:bg-header-link/3',
'page-no-toc:hidden'
)}
/>
<HeaderLogo context={context} />
</div>
<div
className={tcls(
'flex',
'grow-0',
'shrink-0',
'md:basis-56',
'justify-self-end',
'items-center',
'gap-2',
'search' in customization.styling &&
customization.styling.search === 'prominent'
? [
'md:grow-[0.8]',
'lg:basis-40',
'md:max-w-[40%]',
'lg:max-w-lg',
'lg:ml-[max(calc((100%-18rem-48rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem)
'xl:ml-[max(calc((100%-18rem-48rem-14rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - outline (14rem) - margin (3rem)
'md:mr-auto',
'order-last',
'md:order-[unset]',
]
: ['order-last']
)}
>
{search}
</div>
{customization.header.links.length > 0 && (
<HeaderLinks>
{customization.header.links.map((link) => {
return (
<HeaderLink
key={link.title}
link={link}
context={context}
/>
);
})}
<HeaderLinkMore
label={t(getSpaceLanguage(customization), 'more')}
links={customization.header.links}
context={context}
/>
</HeaderLinks>
)}
</div> </div>
<div
className={tcls(
'flex',
'grow-0',
'shrink-0',
'md:basis-56',
'justify-self-end',
'items-center',
'gap-2',
'search' in customization.styling &&
customization.styling.search === 'prominent'
? [
'md:grow-[0.8]',
'lg:basis-40',
'md:max-w-[40%]',
'lg:max-w-lg',
'lg:ml-[max(calc((100%-18rem-48rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem)
'xl:ml-[max(calc((100%-18rem-48rem-14rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - outline (14rem) - margin (3rem)
'md:mr-auto',
'order-last',
'md:order-[unset]',
]
: ['order-last']
)}
>
<SearchContainer
style={customization.styling.search}
isMultiVariants={siteSpaces.length > 1}
spaceTitle={siteSpace.title}
siteSpaceId={siteSpace.id}
viewport={!withTopHeader ? 'mobile' : undefined}
/>
</div>
{customization.header.links.length > 0 ||
(!sections && withVariants === 'translations') ? (
<HeaderLinks>
{customization.header.links.length > 0 ? (
<>
{customization.header.links.map((link) => {
return (
<HeaderLink
key={link.title}
link={link}
context={context}
/>
);
})}
<HeaderLinkMore
label={t(getSpaceLanguage(context), 'more')}
links={customization.header.links}
context={context}
/>
</>
) : null}
{!sections && withVariants === 'translations' ? (
<TranslationsDropdown
context={context}
siteSpace={siteSpace}
siteSpaces={siteSpaces}
className="flex! theme-bold:text-header-link hover:theme-bold:bg-header-link/3"
/>
) : null}
</HeaderLinks>
) : null}
</div> </div>
</div> </div>
</div> </div>
{sections || siteSpaces.length > 1 ? ( {sections ? (
<div className="scroll-nojump"> <div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96">
<div className="transition-all duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96"> <div
className={tcls(
'w-full',
'overflow-x-auto',
'no-scrollbar',
'-mb-4 pb-4', // Positive padding / negative margin allows the navigation menu indicator to show in a scroll viewƒ
!sections ? ['hidden', 'page-no-toc:flex'] : 'flex'
)}
>
<div <div
className={tcls( className={tcls(
'w-full', CONTAINER_STYLE,
'overflow-x-auto', 'grow',
'no-scrollbar', 'flex',
'-mb-4 pb-4', // Positive padding / negative margin allows the navigation menu indicator to show in a scroll viewƒ 'items-end',
!sections ? ['hidden', 'page-no-toc:flex'] : 'flex' 'page-default-width:2xl:px-[calc((100%-1536px+4rem)/2)]'
)} )}
> >
<div {sections.list.some((s) => s.object === 'site-section-group') || // If there's even a single group, show the tabs
className={tcls( sections.list.length > 1 ? ( // Otherwise, show the tabs if there's more than one section
CONTAINER_STYLE, <SiteSectionTabs
'grow', sections={encodeClientSiteSections(context, sections)}
'flex', />
'items-end', ) : null}
'page-default-width:2xl:px-[calc((100%-1536px+4rem)/2)]' {withVariants === 'translations' ? (
)} <div className="site-background before:contents[] -mr-4 sm:-mr-6 md:-mr-8 sticky inset-y-0 right-0 z-10 ml-6 flex h-full items-center py-2 pr-4 before:mr-4 before:h-full before:border-tint before:border-l sm:pr-6 md:pr-8">
> <TranslationsDropdown
{siteSpaces.length > 1 && ( context={context}
<div siteSpace={siteSpace}
id="variants" siteSpaces={siteSpaces}
className="my-2 mr-5 grow border-tint border-r pr-5 *:grow only:mr-0 only:border-none only:pr-0 sm:max-w-64" />
> </div>
<SpacesDropdown ) : null}
context={context}
siteSpace={siteSpace}
siteSpaces={siteSpaces}
className="w-full grow py-1"
/>
</div>
)}
{sections &&
(sections.list.some((s) => s.object === 'site-section-group') || // If there's even a single group, show the tabs
sections.list.length > 1) && ( // Otherwise, show the tabs if there's more than one section
<SiteSectionTabs
sections={encodeClientSiteSections(context, sections)}
/>
)}
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -138,7 +138,7 @@ function HeaderItemButton(
function getHeaderLinkClassName(_props: { headerPreset: CustomizationHeaderPreset }) { function getHeaderLinkClassName(_props: { headerPreset: CustomizationHeaderPreset }) {
return tcls( return tcls(
'flex items-center', 'flex items-center gap-1',
'shrink', 'shrink',
'contrast-more:underline', 'contrast-more:underline',
'truncate', 'truncate',
@@ -1,18 +1,29 @@
import type { SiteSpace } from '@gitbook/api'; import type { SiteSpace } from '@gitbook/api';
import { useMemo } from 'react';
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import { getSiteSpaceURL } from '@/lib/sites'; import { getSiteSpaceURL } from '@/lib/sites';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { Button, type ButtonProps } from '../primitives';
import { DropdownChevron, DropdownMenu } from '../primitives/DropdownMenu'; import { DropdownChevron, DropdownMenu } from '../primitives/DropdownMenu';
import { SpacesDropdownMenuItems } from './SpacesDropdownMenuItem'; import { SpacesDropdownMenuItems } from './SpacesDropdownMenuItem';
// Memoized regex for checking if a string starts with an emoji
const EMOJI_REGEX = /^\p{Emoji}/u;
function startsWithEmoji(text: string): boolean {
return EMOJI_REGEX.test(text);
}
export function SpacesDropdown(props: { export function SpacesDropdown(props: {
context: GitBookSiteContext; context: GitBookSiteContext;
siteSpace: SiteSpace; siteSpace: SiteSpace;
siteSpaces: SiteSpace[]; siteSpaces: SiteSpace[];
className?: string; className?: string;
variant?: ButtonProps['variant'];
icon?: ButtonProps['icon'];
}) { }) {
const { context, siteSpace, siteSpaces, className } = props; const { context, siteSpace, siteSpaces, className, variant = 'secondary', icon } = props;
return ( return (
<DropdownMenu <DropdownMenu
@@ -21,48 +32,16 @@ export function SpacesDropdown(props: {
'group-focus-within/dropdown:group-hover/dropdown:visible' // When the dropdown is already open, it should remain visible when hovered 'group-focus-within/dropdown:group-hover/dropdown:visible' // When the dropdown is already open, it should remain visible when hovered
)} )}
button={ button={
<div <Button
icon={icon}
data-testid="space-dropdown-button" data-testid="space-dropdown-button"
className={tcls( size="medium"
'flex', variant={variant}
'flex-row', trailing={<DropdownChevron />}
'items-center', className={tcls('bg-tint-base', className)}
'transition-all',
'hover:cursor-pointer',
'px-3',
'py-2',
'gap-2',
'rounded-md',
'straight-corners:rounded-none',
'bg-tint-base',
'text-sm',
'text-tint',
'hover:text-tint-strong',
'data-[state=open]:text-tint-strong',
'ring-1',
'ring-tint-subtle',
'hover:ring-tint-hover',
'data-[state=open]:ring-tint-hover',
'contrast-more:bg-tint-base',
'contrast-more:ring-1',
'contrast-more:hover:ring-2',
'contrast-more:data-[state=open]:ring-2',
'contrast-more:ring-tint',
'contrast-more:hover:ring-tint-hover',
'contrast-more:data-[state=open]:ring-tint-hover',
className
)}
> >
<span className={tcls('truncate', 'grow')}>{siteSpace.title}</span> <span className="button-content">{siteSpace.title}</span>
<DropdownChevron /> </Button>
</div>
} }
> >
<SpacesDropdownMenuItems <SpacesDropdownMenuItems
@@ -77,3 +56,32 @@ export function SpacesDropdown(props: {
</DropdownMenu> </DropdownMenu>
); );
} }
export function TranslationsDropdown(props: {
context: GitBookSiteContext;
siteSpace: SiteSpace;
siteSpaces: SiteSpace[];
className?: string;
}) {
const { context, siteSpace, siteSpaces, className } = props;
// Memoize the emoji check to avoid repeated regex execution
const hasEmojiPrefix = useMemo(() => startsWithEmoji(siteSpace.title), [siteSpace.title]);
return (
<SpacesDropdown
icon="globe"
context={context}
siteSpace={siteSpace}
siteSpaces={siteSpaces}
variant="blank"
className={tcls(
'-mx-2 bg-transparent px-2 py-1 lg:max-w-64 max-md:[&_.button-content]:hidden',
hasEmojiPrefix
? 'md:[&_.button-leading-icon]:hidden' // If the title starts with an emoji, don't show the icon (on desktop)
: '',
className
)}
/>
);
}
@@ -16,6 +16,7 @@ export type InsightsEventName = api.SiteInsightsEvent['type'];
* Context for an event on a page. * Context for an event on a page.
*/ */
export interface InsightsEventPageContext { export interface InsightsEventPageContext {
displayContext: api.SiteInsightsDisplayContext;
pageId: string | null; pageId: string | null;
} }
@@ -46,7 +47,9 @@ type TrackEventCallback = <EventName extends InsightsEventName>(
options?: InsightsEventOptions options?: InsightsEventOptions
) => void; ) => void;
const InsightsContext = React.createContext<TrackEventCallback>(() => {}); const InsightsContext = React.createContext<TrackEventCallback>(() => {
console.error('useTrackEvent must be used within an InsightsProvider');
});
interface InsightsProviderProps { interface InsightsProviderProps {
/** If true, the events will be sent to the server. */ /** If true, the events will be sent to the server. */
@@ -263,6 +266,7 @@ function transformEvents(input: {
siteShareKey: input.context.siteShareKey ?? null, siteShareKey: input.context.siteShareKey ?? null,
revision: input.context.revisionId, revision: input.context.revisionId,
page: input.pageContext.pageId, page: input.pageContext.pageId,
displayContext: input.pageContext.displayContext,
}; };
return input.events.map((partialEvent) => { return input.events.map((partialEvent) => {
@@ -1,5 +1,6 @@
'use client'; 'use client';
import type { SiteInsightsDisplayContext } from '@gitbook/api';
import * as React from 'react'; import * as React from 'react';
import { useCurrentPage } from '../hooks'; import { useCurrentPage } from '../hooks';
@@ -8,7 +9,10 @@ import { useTrackEvent } from './InsightsProvider';
/** /**
* Track a page view event. * Track a page view event.
*/ */
export function TrackPageViewEvent() { export function TrackPageViewEvent(props: {
displayContext: SiteInsightsDisplayContext;
}) {
const { displayContext } = props;
const page = useCurrentPage(); const page = useCurrentPage();
const trackEvent = useTrackEvent(); const trackEvent = useTrackEvent();
@@ -19,9 +23,10 @@ export function TrackPageViewEvent() {
}, },
{ {
pageId: page?.pageId ?? null, pageId: page?.pageId ?? null,
displayContext,
} }
); );
}, [page, trackEvent]); }, [page, trackEvent, displayContext]);
return null; return null;
} }
@@ -57,7 +57,7 @@ export async function PDFPage(props: {
const customization = const customization =
'customization' in baseContext ? baseContext.customization : defaultCustomization(); 'customization' in baseContext ? baseContext.customization : defaultCustomization();
const language = getSpaceLanguage(customization); const language = getSpaceLanguage(baseContext);
// Compute the pages to render // Compute the pages to render
const { pages, total } = selectPages(baseContext.revision.pages, pdfParams); const { pages, total } = selectPages(baseContext.revision.pages, pdfParams);
@@ -149,8 +149,7 @@ export async function PDFPage(props: {
trademark={ trademark={
customization.trademark.enabled ? ( customization.trademark.enabled ? (
<TrademarkLink <TrademarkLink
space={context.space} context={context}
customization={customization}
placement={SiteInsightsTrademarkPlacement.Pdf} placement={SiteInsightsTrademarkPlacement.Pdf}
/> />
) : null ) : null
@@ -1,6 +1,5 @@
import { CustomizationRootLayout } from '@/components/RootLayout'; import { CustomizationRootLayout } from '@/components/RootLayout';
import type { GitBookSiteContext, GitBookSpaceContext } from '@/lib/context'; import type { GitBookSiteContext, GitBookSpaceContext } from '@/lib/context';
import { defaultCustomization } from '@/lib/utils';
import { CustomizationThemeMode } from '@gitbook/api'; import { CustomizationThemeMode } from '@gitbook/api';
/** /**
@@ -13,12 +12,7 @@ export async function PDFRootLayout(props: {
const { context, children } = props; const { context, children } = props;
return ( return (
<CustomizationRootLayout <CustomizationRootLayout context={context} forcedTheme={CustomizationThemeMode.Light}>
customization={
'customization' in context ? context.customization : defaultCustomization()
}
forcedTheme={CustomizationThemeMode.Light}
>
{children} {children}
</CustomizationRootLayout> </CustomizationRootLayout>
); );
@@ -2,31 +2,32 @@
import { useAIChatState } from '@/components/AI'; import { useAIChatState } from '@/components/AI';
import type { Assistant } from '@/components/AI'; import type { Assistant } from '@/components/AI';
import { ChatGPTIcon } from '@/components/AIActions/assets/ChatGPTIcon'; import { ChatGPTIcon } from '@/components/PageActions/assets/ChatGPTIcon';
import { ClaudeIcon } from '@/components/AIActions/assets/ClaudeIcon'; import { ClaudeIcon } from '@/components/PageActions/assets/ClaudeIcon';
import { MarkdownIcon } from '@/components/AIActions/assets/MarkdownIcon'; import { MarkdownIcon } from '@/components/PageActions/assets/MarkdownIcon';
import { Button } from '@/components/primitives/Button'; import { Button } from '@/components/primitives/Button';
import { DropdownMenuItem, useDropdownMenuClose } from '@/components/primitives/DropdownMenu'; import { DropdownMenuItem, useDropdownMenuClose } from '@/components/primitives/DropdownMenu';
import { tString, useLanguage } from '@/intl/client'; import { tString, useLanguage } from '@/intl/client';
import type { TranslationLanguage } from '@/intl/translations'; import type { TranslationLanguage } from '@/intl/translations';
import type { GitSyncState } from '@gitbook/api';
import { Icon, type IconName, IconStyle } from '@gitbook/icons'; import { Icon, type IconName, IconStyle } from '@gitbook/icons';
import assertNever from 'assert-never'; import assertNever from 'assert-never';
import QuickLRU from 'quick-lru'; import QuickLRU from 'quick-lru';
import type React from 'react'; import type React from 'react';
import { create } from 'zustand'; import { create } from 'zustand';
type AIActionType = 'button' | 'dropdown-menu-item'; type PageActionType = 'button' | 'dropdown-menu-item';
/** /**
* Opens our AI Docs Assistant. * Opens our AI Docs Assistant.
*/ */
export function OpenAIAssistant(props: { assistant: Assistant; type: AIActionType }) { export function OpenAIAssistant(props: { assistant: Assistant; type: PageActionType }) {
const { assistant, type } = props; const { assistant, type } = props;
const chat = useAIChatState(); const chat = useAIChatState();
const language = useLanguage(); const language = useLanguage();
return ( return (
<AIActionWrapper <PageActionWrapper
type={type} type={type}
icon={assistant.icon} icon={assistant.icon}
label={assistant.label} label={assistant.label}
@@ -90,7 +91,7 @@ const markdownCache = new QuickLRU<string, string>({ maxSize: 10 });
*/ */
export function CopyMarkdown(props: { export function CopyMarkdown(props: {
markdownPageUrl: string; markdownPageUrl: string;
type: AIActionType; type: PageActionType;
isDefaultAction?: boolean; isDefaultAction?: boolean;
}) { }) {
const { markdownPageUrl, type, isDefaultAction } = props; const { markdownPageUrl, type, isDefaultAction } = props;
@@ -130,7 +131,7 @@ export function CopyMarkdown(props: {
}; };
return ( return (
<AIActionWrapper <PageActionWrapper
type={type} type={type}
icon={copied ? 'check' : 'copy'} icon={copied ? 'check' : 'copy'}
label={copied ? tString(language, 'code_copied') : tString(language, 'copy_page')} label={copied ? tString(language, 'code_copied') : tString(language, 'copy_page')}
@@ -145,12 +146,12 @@ export function CopyMarkdown(props: {
/** /**
* Redirects to the markdown version of the page. * Redirects to the markdown version of the page.
*/ */
export function ViewAsMarkdown(props: { markdownPageUrl: string; type: AIActionType }) { export function ViewAsMarkdown(props: { markdownPageUrl: string; type: PageActionType }) {
const { markdownPageUrl, type } = props; const { markdownPageUrl, type } = props;
const language = useLanguage(); const language = useLanguage();
return ( return (
<AIActionWrapper <PageActionWrapper
type={type} type={type}
icon={<MarkdownIcon className="size-4 fill-current" />} icon={<MarkdownIcon className="size-4 fill-current" />}
label={tString(language, 'view_page_markdown')} label={tString(language, 'view_page_markdown')}
@@ -166,7 +167,7 @@ export function ViewAsMarkdown(props: { markdownPageUrl: string; type: AIActionT
export function OpenInLLM(props: { export function OpenInLLM(props: {
provider: 'chatgpt' | 'claude'; provider: 'chatgpt' | 'claude';
url: string; url: string;
type: AIActionType; type: PageActionType;
}) { }) {
const { provider, url, type } = props; const { provider, url, type } = props;
const language = useLanguage(); const language = useLanguage();
@@ -174,7 +175,7 @@ export function OpenInLLM(props: {
const providerLabel = provider === 'chatgpt' ? 'ChatGPT' : 'Claude'; const providerLabel = provider === 'chatgpt' ? 'ChatGPT' : 'Claude';
return ( return (
<AIActionWrapper <PageActionWrapper
type={type} type={type}
icon={ icon={
provider === 'chatgpt' ? ( provider === 'chatgpt' ? (
@@ -191,11 +192,48 @@ export function OpenInLLM(props: {
); );
} }
export function GitEditLink(props: {
type: PageActionType;
provider: GitSyncState['installationProvider'];
url: string;
}) {
const { type, provider, url } = props;
const language = useLanguage();
const providerName =
provider === 'github' ? 'GitHub' : provider === 'gitlab' ? 'GitLab' : 'Git';
return (
<PageActionWrapper
type={type}
icon={provider === 'gitlab' ? 'gitlab' : 'github'}
label={tString(language, 'edit_on_git', providerName)}
shortLabel={tString(language, 'edit')}
href={url}
/>
);
}
export function ViewAsPDF(props: { url: string; type: PageActionType }) {
const { url, type } = props;
const language = useLanguage();
return (
<PageActionWrapper
type={type}
icon="file-pdf"
label={tString(language, 'pdf_download')}
href={url}
target="_self"
/>
);
}
/** /**
* Wraps an action in a button (for the default action) or dropdown menu item. * Wraps an action in a button (for the default action) or dropdown menu item.
*/ */
function AIActionWrapper(props: { function PageActionWrapper(props: {
type: AIActionType; type: PageActionType;
icon: IconName | React.ReactNode; icon: IconName | React.ReactNode;
label: string; label: string;
/** /**
@@ -205,10 +243,22 @@ function AIActionWrapper(props: {
onClick?: (e: React.MouseEvent) => void; onClick?: (e: React.MouseEvent) => void;
description?: string; description?: string;
href?: string; href?: string;
target?: React.HTMLAttributeAnchorTarget;
disabled?: boolean; disabled?: boolean;
loading?: boolean; loading?: boolean;
}) { }) {
const { type, icon, label, shortLabel, onClick, href, description, disabled, loading } = props; const {
type,
icon,
label,
shortLabel,
onClick,
href,
target = '_blank',
description,
disabled,
loading,
} = props;
if (type === 'button') { if (type === 'button') {
return ( return (
@@ -222,7 +272,7 @@ function AIActionWrapper(props: {
className="bg-tint-base text-sm" className="bg-tint-base text-sm"
onClick={onClick} onClick={onClick}
href={href} href={href}
target={href ? '_blank' : undefined} target={href ? target : undefined}
disabled={disabled || loading} disabled={disabled || loading}
> >
{shortLabel} {shortLabel}
@@ -234,7 +284,7 @@ function AIActionWrapper(props: {
<DropdownMenuItem <DropdownMenuItem
className="flex items-stretch gap-2.5 p-2" className="flex items-stretch gap-2.5 p-2"
href={href} href={href}
target="_blank" target={target}
onClick={onClick} onClick={onClick}
disabled={disabled || loading} disabled={disabled || loading}
> >
@@ -255,9 +305,11 @@ function AIActionWrapper(props: {
</div> </div>
<div className="flex flex-1 flex-col gap-0.5"> <div className="flex flex-1 flex-col gap-0.5">
<span className="flex items-center gap-2 text-tint-strong"> <span className="flex items-center gap-1 text-tint-strong">
<span className="truncate font-medium text-sm">{label}</span> <span className="truncate font-medium text-sm">{label}</span>
{href ? <Icon icon="arrow-up-right" className="size-3 shrink-0" /> : null} {href && target === '_blank' ? (
<Icon icon="arrow-up-right" className="size-3 shrink-0 text-tint-subtle" />
) : null}
</span> </span>
{description && <span className="text-tint text-xs">{description}</span>} {description && <span className="text-tint text-xs">{description}</span>}
</div> </div>
@@ -2,38 +2,50 @@
import { import {
CopyMarkdown, CopyMarkdown,
GitEditLink,
OpenAIAssistant, OpenAIAssistant,
OpenInLLM, OpenInLLM,
ViewAsMarkdown, ViewAsMarkdown,
} from '@/components/AIActions/AIActions'; ViewAsPDF,
} from '@/components/PageActions/PageActions';
import { Button, ButtonGroup } from '@/components/primitives/Button'; import { Button, ButtonGroup } from '@/components/primitives/Button';
import { DropdownMenu, DropdownMenuSeparator } from '@/components/primitives/DropdownMenu'; import { DropdownMenu, DropdownMenuSeparator } from '@/components/primitives/DropdownMenu';
import { tString, useLanguage } from '@/intl/client'; import { tString, useLanguage } from '@/intl/client';
import type { SiteCustomizationSettings } from '@gitbook/api'; import type { GitSyncState, SiteCustomizationSettings } from '@gitbook/api';
import { Icon } from '@gitbook/icons'; import { Icon } from '@gitbook/icons';
import { useRef } from 'react'; import { useRef } from 'react';
import { useAI } from '../AI'; import { useAI } from '../AI';
interface AIActionsDropdownProps { interface PageActionsDropdownProps {
markdownPageUrl: string; markdownPageUrl: string;
className?: string; className?: string;
actions: SiteCustomizationSettings['pageActions']; actions: SiteCustomizationSettings['pageActions'];
editOnGit?: {
provider: GitSyncState['installationProvider'];
url: string;
};
pdfUrl?: string;
} }
/** /**
* Dropdown menu for the AI Actions (Ask Docs Assistant, Copy page, View as Markdown, Open in LLM). * Dropdown menu for the AI Actions (Ask Docs Assistant, Copy page, View as Markdown, Open in LLM).
*/ */
export function AIActionsDropdown(props: AIActionsDropdownProps) { export function PageActionsDropdown(props: PageActionsDropdownProps) {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const assistants = useAI().assistants.filter( const assistants = useAI().assistants.filter(
(assistant) => assistant.ui === true && assistant.pageAction (assistant) => assistant.ui === true && assistant.pageAction
); );
const language = useLanguage(); const language = useLanguage();
return assistants.length > 0 || props.actions.markdown || props.actions.externalAI ? ( const defaultActions = [assistants.length > 0, props.actions.markdown, props.editOnGit].filter(
Boolean
);
const dropdownActions = [props.actions.externalAI, props.pdfUrl].filter(Boolean);
return [...defaultActions, ...dropdownActions].length > 0 ? (
<ButtonGroup ref={ref} className={props.className}> <ButtonGroup ref={ref} className={props.className}>
<DefaultAction {...props} /> {defaultActions.length > 0 ? <DefaultAction {...props} /> : null}
{props.actions.markdown || props.actions.externalAI ? ( {dropdownActions.length > 0 ? (
<DropdownMenu <DropdownMenu
align="end" align="end"
className="!min-w-60 max-w-max" className="!min-w-60 max-w-max"
@@ -45,15 +57,18 @@ export function AIActionsDropdown(props: AIActionsDropdownProps) {
className="size-3 transition-transform group-data-[state=open]/button:rotate-180" className="size-3 transition-transform group-data-[state=open]/button:rotate-180"
/> />
} }
label={tString(language, 'more')} label={tString(
iconOnly language,
defaultActions.some(Boolean) ? 'more' : 'actions'
)}
iconOnly={defaultActions.some(Boolean)}
size="xsmall" size="xsmall"
variant="secondary" variant="secondary"
className="bg-tint-base text-sm" className="bg-tint-base text-sm"
/> />
} }
> >
<AIActionsDropdownMenuContent {...props} /> <PageActionsDropdownMenuContent {...props} />
</DropdownMenu> </DropdownMenu>
) : null} ) : null}
</ButtonGroup> </ButtonGroup>
@@ -63,7 +78,7 @@ export function AIActionsDropdown(props: AIActionsDropdownProps) {
/** /**
* The content of the dropdown menu. * The content of the dropdown menu.
*/ */
function AIActionsDropdownMenuContent(props: AIActionsDropdownProps) { function PageActionsDropdownMenuContent(props: PageActionsDropdownProps) {
const { markdownPageUrl, actions } = props; const { markdownPageUrl, actions } = props;
const assistants = useAI().assistants.filter( const assistants = useAI().assistants.filter(
(assistant) => assistant.ui === true && assistant.pageAction (assistant) => assistant.ui === true && assistant.pageAction
@@ -98,6 +113,22 @@ function AIActionsDropdownMenuContent(props: AIActionsDropdownProps) {
<OpenInLLM provider="claude" url={markdownPageUrl} type="dropdown-menu-item" /> <OpenInLLM provider="claude" url={markdownPageUrl} type="dropdown-menu-item" />
</> </>
) : null} ) : null}
{props.editOnGit || props.pdfUrl ? (
<>
<DropdownMenuSeparator className="first:hidden" />
{props.editOnGit ? (
<GitEditLink
type="dropdown-menu-item"
provider={props.editOnGit.provider}
url={props.editOnGit.url}
/>
) : null}
{props.pdfUrl ? (
<ViewAsPDF url={props.pdfUrl} type="dropdown-menu-item" />
) : null}
</>
) : null}
</> </>
); );
} }
@@ -105,31 +136,34 @@ function AIActionsDropdownMenuContent(props: AIActionsDropdownProps) {
/** /**
* A default action shown as a quick-access button beside the dropdown menu * A default action shown as a quick-access button beside the dropdown menu
*/ */
function DefaultAction(props: AIActionsDropdownProps) { function DefaultAction(props: PageActionsDropdownProps) {
const { markdownPageUrl, actions } = props; const { markdownPageUrl, actions } = props;
const assistants = useAI().assistants.filter( const assistants = useAI().assistants.filter(
(assistant) => assistant.ui === true && assistant.pageAction (assistant) => assistant.ui === true && assistant.pageAction
); );
if (assistants.length) { const assistant = assistants[0];
return <OpenAIAssistant assistant={assistants[0]} type="button" />; if (assistant) {
return <OpenAIAssistant assistant={assistant} type="button" />;
}
if (props.editOnGit) {
return (
<GitEditLink
type="button"
provider={props.editOnGit.provider}
url={props.editOnGit.url}
/>
);
} }
if (actions.markdown) { if (actions.markdown) {
return ( return (
<CopyMarkdown <CopyMarkdown
isDefaultAction={!assistants.length} isDefaultAction={!assistant}
markdownPageUrl={markdownPageUrl} markdownPageUrl={markdownPageUrl}
type="button" type="button"
/> />
); );
} }
if (actions.externalAI) {
return (
<>
<OpenInLLM provider="chatgpt" url={markdownPageUrl} type="button" />
</>
);
}
} }
@@ -25,7 +25,7 @@ export const AsideSectionHighlight = React.memo(
'rounded-md', 'rounded-md',
'straight-corners:rounded-none', 'straight-corners:rounded-none',
'circular-corners:rounded-2xl', 'circular-corners:rounded-2xl',
'sidebar-list-line:rounded-l-none', 'sidebar-list-line:rounded-l-none!',
'sidebar-list-pill:bg-primary', 'sidebar-list-pill:bg-primary',
'[html.theme-muted.sidebar-list-pill_&]:bg-primary-hover', '[html.theme-muted.sidebar-list-pill_&]:bg-primary-hover',
@@ -4,18 +4,15 @@ import {
type RevisionPageDocument, type RevisionPageDocument,
SiteAdsStatus, SiteAdsStatus,
SiteInsightsAdPlacement, SiteInsightsAdPlacement,
type Space,
} from '@gitbook/api'; } from '@gitbook/api';
import { Icon } from '@gitbook/icons'; import { Icon } from '@gitbook/icons';
import React from 'react'; import React from 'react';
import urlJoin from 'url-join';
import { getSpaceLanguage, t } from '@/intl/server'; import { getSpaceLanguage, t } from '@/intl/server';
import { getDocumentSections } from '@/lib/document-sections'; import { getDocumentSections } from '@/lib/document-sections';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { Ad } from '../Ads'; import { Ad } from '../Ads';
import { getPDFURLSearchParams } from '../PDF';
import { PageFeedbackForm } from '../PageFeedback'; import { PageFeedbackForm } from '../PageFeedback';
import { ThemeToggler } from '../ThemeToggler'; import { ThemeToggler } from '../ThemeToggler';
import { ScrollSectionsList } from './ScrollSectionsList'; import { ScrollSectionsList } from './ScrollSectionsList';
@@ -118,11 +115,7 @@ export function PageAside(props: {
<PageAsideSections document={document} context={context} /> <PageAsideSections document={document} context={context} />
</React.Suspense> </React.Suspense>
) : null} ) : null}
<PageAsideActions <PageAsideActions page={page} withPageFeedback={withPageFeedback} />
page={page}
withPageFeedback={withPageFeedback}
context={context}
/>
</div> </div>
) : null} ) : null}
{customization.themes.toggeable || site.ads ? ( {customization.themes.toggeable || site.ads ? (
@@ -135,7 +128,7 @@ export function PageAside(props: {
function PageAsideHeader(props: { context: GitBookSiteContext }) { function PageAsideHeader(props: { context: GitBookSiteContext }) {
const { context } = props; const { context } = props;
const language = getSpaceLanguage(context.customization); const language = getSpaceLanguage(context);
return ( return (
<div <div
@@ -171,34 +164,16 @@ async function PageAsideSections(props: { document: JSONDocument; context: GitBo
function PageAsideActions(props: { function PageAsideActions(props: {
withPageFeedback: boolean; withPageFeedback: boolean;
context: GitBookSiteContext;
page: RevisionPageDocument; page: RevisionPageDocument;
}) { }) {
const { page, withPageFeedback, context } = props; const { page, withPageFeedback } = 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 ( return (
<div <div
className={tcls( className={tcls(
'flex', 'flex flex-col gap-3',
'flex-col', 'border-tint-subtle border-t first:border-none',
'gap-3', 'sidebar-list-default:px-3 pt-5 first:pt-0 xl:max-2xl:page-api-block:p-5',
'sidebar-list-default:px-3',
'border-t',
'first:border-none',
'border-tint-subtle',
'pt-5',
'first:pt-0',
'xl:max-2xl:page-api-block:p-5',
'empty:hidden' 'empty:hidden'
)} )}
> >
@@ -207,57 +182,6 @@ function PageAsideActions(props: {
<PageFeedbackForm pageId={page.id} /> <PageFeedbackForm pageId={page.id} />
</React.Suspense> </React.Suspense>
) : null} ) : 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>
); );
} }
@@ -296,14 +220,3 @@ async function PageAsideFooter(props: { context: GitBookSiteContext }) {
</div> </div>
); );
} }
function getGitSyncName(space: Space): string {
if (space.gitSync?.installationProvider === 'github') {
return 'GitHub';
}
if (space.gitSync?.installationProvider === 'gitlab') {
return 'GitLab';
}
return 'Git';
}
@@ -19,14 +19,8 @@ const SECTION_INTERSECTING_THRESHOLD = 0.9;
*/ */
const ACTIVE_ITEM_OFFSET = 100; const ACTIVE_ITEM_OFFSET = 100;
export function ScrollSectionsList(props: { sections: DocumentSection[] }) { export function ScrollSectionsList({ sections }: { sections: DocumentSection[] }) {
const { sections } = props; const ids = React.useMemo(() => sections.map(({ id }) => id), [sections]);
const ids = React.useMemo(() => {
return sections.map((section) => {
return section.id;
});
}, [sections]);
const enabled = useBodyLoaded(); const enabled = useBodyLoaded();
@@ -101,7 +95,7 @@ export function ScrollSectionsList(props: { sections: DocumentSection[] }) {
'rounded-md', 'rounded-md',
'straight-corners:rounded-none', 'straight-corners:rounded-none',
'circular-corners:rounded-2xl', 'circular-corners:rounded-2xl',
'sidebar-list-line:rounded-l-none', 'sidebar-list-line:rounded-l-none!',
'hover:bg-tint-hover', 'hover:bg-tint-hover',
'theme-gradient:hover:bg-tint-12/1', 'theme-gradient:hover:bg-tint-12/1',
@@ -1,5 +1,5 @@
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import type { JSONDocument, RevisionPageDocument } from '@gitbook/api'; import type { JSONDocument, RevisionPageDocument, SiteInsightsDisplayContext } from '@gitbook/api';
import React from 'react'; import React from 'react';
import { getSpaceLanguage } from '@/intl/server'; import { getSpaceLanguage } from '@/intl/server';
@@ -26,8 +26,9 @@ export function PageBody(props: {
ancestors: AncestorRevisionPage[]; ancestors: AncestorRevisionPage[];
document: JSONDocument | null; document: JSONDocument | null;
withPageFeedback: boolean; withPageFeedback: boolean;
insightsDisplayContext: SiteInsightsDisplayContext;
}) { }) {
const { page, context, ancestors, document, withPageFeedback } = props; const { page, context, ancestors, document, withPageFeedback, insightsDisplayContext } = props;
const { customization } = context; const { customization } = context;
const contentFullWidth = document ? hasFullWidthBlock(document) : false; const contentFullWidth = document ? hasFullWidthBlock(document) : false;
@@ -42,7 +43,7 @@ export function PageBody(props: {
: false; : false;
const pageWidthWide = page.layout.width === 'wide'; const pageWidthWide = page.layout.width === 'wide';
const siteWidthWide = pageWidthWide || contentFullWidth; const siteWidthWide = pageWidthWide || contentFullWidth;
const language = getSpaceLanguage(customization); const language = getSpaceLanguage(context);
const updatedAt = page.updatedAt ?? page.createdAt; const updatedAt = page.updatedAt ?? page.createdAt;
return ( return (
@@ -117,7 +118,7 @@ export function PageBody(props: {
} }
</main> </main>
<TrackPageViewEvent /> <TrackPageViewEvent displayContext={insightsDisplayContext} />
</CurrentPageProvider> </CurrentPageProvider>
); );
} }
@@ -17,9 +17,9 @@ export async function PageFooterNavigation(props: {
page: RevisionPageDocument; page: RevisionPageDocument;
}) { }) {
const { context, page } = props; const { context, page } = props;
const { customization, revision, linker } = context; const { revision, linker } = context;
const { previous, next } = resolvePrevNextPages(revision.pages, page); const { previous, next } = resolvePrevNextPages(revision.pages, page);
const language = getSpaceLanguage(customization); const language = getSpaceLanguage(context);
const previousHref = previous const previousHref = previous
? linker.toPathForPage({ pages: revision.pages, page: previous }) ? linker.toPathForPage({ pages: revision.pages, page: previous })
: ''; : '';
@@ -1,9 +1,11 @@
import { AIActionsDropdown } from '@/components/AIActions/AIActionsDropdown';
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import type { AncestorRevisionPage } from '@/lib/pages'; import type { AncestorRevisionPage } from '@/lib/pages';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import type { RevisionPageDocument } from '@gitbook/api'; import type { RevisionPageDocument } from '@gitbook/api';
import { Icon } from '@gitbook/icons'; import { Icon } from '@gitbook/icons';
import urlJoin from 'url-join';
import { getPDFURLSearchParams } from '../PDF';
import { PageActionsDropdown } from '../PageActions/PageActionsDropdown';
import { PageIcon } from '../PageIcon'; import { PageIcon } from '../PageIcon';
import { StyledLink } from '../primitives'; import { StyledLink } from '../primitives';
@@ -19,8 +21,6 @@ export async function PageHeader(props: {
return null; return null;
} }
const pageActions = context.customization.pageActions;
const hasAncestors = ancestors.length > 0; const hasAncestors = ancestors.length > 0;
return ( return (
@@ -38,9 +38,30 @@ export async function PageHeader(props: {
> >
{page.layout.tableOfContents ? ( {page.layout.tableOfContents ? (
// Show page actions if *any* of the actions are enabled // Show page actions if *any* of the actions are enabled
<AIActionsDropdown <PageActionsDropdown
markdownPageUrl={`${context.linker.toAbsoluteURL(context.linker.toPathInSpace(page.path))}.md`} markdownPageUrl={`${context.linker.toAbsoluteURL(context.linker.toPathInSpace(page.path))}.md`}
actions={pageActions} editOnGit={
context.customization.git.showEditLink &&
context.space.gitSync?.url &&
page.git
? {
provider: context.space?.gitSync?.installationProvider,
url: urlJoin(context.space.gitSync.url, page.git.path),
}
: undefined
}
pdfUrl={
context.customization.pdf.enabled
? context.linker.toPathInSpace(
`~gitbook/pdf?${getPDFURLSearchParams({
page: page.id,
only: true,
limit: 100,
}).toString()}`
)
: undefined
}
actions={context.customization.pageActions}
className={tcls( className={tcls(
'float-right ml-4 xl:max-2xl:page-api-block:mr-62', 'float-right ml-4 xl:max-2xl:page-api-block:mr-62',
hasAncestors ? '-my-1.5' : '-mt-3 xs:mt-2' hasAncestors ? '-my-1.5' : '-mt-3 xs:mt-2'
@@ -31,7 +31,9 @@ import { RootLayoutClientContexts } from './RootLayoutClientContexts';
import '@gitbook/icons/style.css'; import '@gitbook/icons/style.css';
import './globals.css'; import './globals.css';
import type { GitBookAnyContext } from '@/lib/context';
import { GITBOOK_FONTS_URL, GITBOOK_ICONS_TOKEN, GITBOOK_ICONS_URL } from '@/lib/env'; import { GITBOOK_FONTS_URL, GITBOOK_ICONS_TOKEN, GITBOOK_ICONS_URL } from '@/lib/env';
import { defaultCustomization } from '@/lib/utils';
import { AnnouncementDismissedScript } from '../Announcement'; import { AnnouncementDismissedScript } from '../Announcement';
function preloadFont(fontData: FontData) { function preloadFont(fontData: FontData) {
@@ -56,12 +58,14 @@ function preloadFont(fontData: FontData) {
*/ */
export async function CustomizationRootLayout(props: { export async function CustomizationRootLayout(props: {
forcedTheme?: CustomizationThemeMode | null; forcedTheme?: CustomizationThemeMode | null;
customization: SiteCustomizationSettings; context: GitBookAnyContext;
children: React.ReactNode; children: React.ReactNode;
}) { }) {
const { customization, forcedTheme, children } = props; const { context, forcedTheme, children } = props;
const customization =
'customization' in context ? context.customization : defaultCustomization();
const language = getSpaceLanguage(customization); const language = getSpaceLanguage(context);
const tintColor = getTintColor(customization); const tintColor = getTintColor(customization);
const mixColor = getTintMixColor(customization.styling.primaryColor, tintColor); const mixColor = getTintMixColor(customization.styling.primaryColor, tintColor);
const sidebarStyles = getSidebarStyles(customization); const sidebarStyles = getSidebarStyles(customization);
@@ -94,7 +98,9 @@ export async function CustomizationRootLayout(props: {
'depth' in customization.styling && `depth-${customization.styling.depth}`, 'depth' in customization.styling && `depth-${customization.styling.depth}`,
fontNotoColorEmoji.variable, fontNotoColorEmoji.variable,
monospaceFontData.type === 'default' ? monospaceFontData.variable : null, monospaceFontData.type === 'default' ? monospaceFontData.variable : null,
fontData.type === 'default' ? fontData.variable : null, fontData.type === 'default'
? [fontData.variable, `font-${customization.styling.font}`]
: null,
// Set the dark/light class statically to avoid flashing and make it work when JS is disabled // Set the dark/light class statically to avoid flashing and make it work when JS is disabled
(forcedTheme ?? customization.themes.default) === CustomizationThemeMode.Dark (forcedTheme ?? customization.themes.default) === CustomizationThemeMode.Dark
@@ -138,7 +144,12 @@ export async function CustomizationRootLayout(props: {
customization.styling.primaryColor.light customization.styling.primaryColor.light
) )
}; };
--header-link: ${hexToRgb(customization.header.linkColor?.light ?? colorContrast(tintColor?.light ?? customization.styling.primaryColor.light))}; --header-link: ${hexToRgb(
customization.header.linkColor?.light ??
colorContrast(
tintColor?.light ?? customization.styling.primaryColor.light
)
)};
${generateColorVariable('info', infoColor.light)} ${generateColorVariable('info', infoColor.light)}
${generateColorVariable('warning', warningColor.light)} ${generateColorVariable('warning', warningColor.light)}
@@ -152,7 +163,12 @@ export async function CustomizationRootLayout(props: {
${generateColorVariable('neutral', DEFAULT_TINT_COLOR, { darkMode: true })} ${generateColorVariable('neutral', DEFAULT_TINT_COLOR, { darkMode: true })}
--header-background: ${hexToRgb(customization.header.backgroundColor?.dark ?? tintColor?.dark ?? customization.styling.primaryColor.dark)}; --header-background: ${hexToRgb(customization.header.backgroundColor?.dark ?? tintColor?.dark ?? customization.styling.primaryColor.dark)};
--header-link: ${hexToRgb(customization.header.linkColor?.dark ?? colorContrast(tintColor?.dark ?? customization.styling.primaryColor.dark))}; --header-link: ${hexToRgb(
customization.header.linkColor?.dark ??
colorContrast(
tintColor?.dark ?? customization.styling.primaryColor.dark
)
)};
${generateColorVariable('info', infoColor.dark, { darkMode: true })} ${generateColorVariable('info', infoColor.dark, { darkMode: true })}
${generateColorVariable('warning', warningColor.dark, { darkMode: true })} ${generateColorVariable('warning', warningColor.dark, { darkMode: true })}
@@ -161,16 +177,7 @@ export async function CustomizationRootLayout(props: {
} }
`}</style> `}</style>
</head> </head>
<body <body className="site-background">
className={tcls(
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
'bg-tint-base',
'theme-muted:bg-tint-subtle',
'theme-gradient:bg-gradient-primary',
'theme-gradient-tint:bg-gradient-tint'
)}
>
<IconsProvider <IconsProvider
assetsURL={GITBOOK_ICONS_URL} assetsURL={GITBOOK_ICONS_URL}
assetsURLToken={GITBOOK_ICONS_TOKEN} assetsURLToken={GITBOOK_ICONS_TOKEN}
@@ -20,8 +20,7 @@
} }
} }
@utility hide-scroll { @utility no-scrollbar {
/* hide scroll bar but still scroll */
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }
@@ -29,6 +28,22 @@
-ms-overflow-style: none; -ms-overflow-style: none;
} }
@utility hide-scrollbar {
/* Hide scrollbar by default */
scrollbar-color: transparent transparent;
transition: scrollbar-color 0.2s ease-in-out;
&:hover {
/* Show scrollbar on hover */
scrollbar-color: unset;
}
@media (prefers-contrast: more) {
/* Always show scrollbar in high contrast mode */
scrollbar-color: unset;
}
}
@utility linear-mask-gradient { @utility linear-mask-gradient {
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 96px, rgba(0, 0, 0, 0)); mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 96px, rgba(0, 0, 0, 0));
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 96px, rgba(0, 0, 0, 0)); mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 96px, rgba(0, 0, 0, 0));
@@ -46,7 +61,6 @@
@utility gutter-stable { @utility gutter-stable {
scrollbar-gutter: stable; scrollbar-gutter: stable;
scrollbar-gutter: stable;
} }
@utility triangle { @utility triangle {
@@ -143,45 +157,13 @@
@apply bg-linear-to-bl from-tint-4 to-tint-base to-60% bg-fixed; @apply bg-linear-to-bl from-tint-4 to-tint-base to-60% bg-fixed;
} }
@utility scroll-nojump { @utility site-background {
/** @apply [html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle;
* Utility to prevent horizontal jumps when the vertical scrollbar appears @apply bg-tint-base;
* It should be used on main containers of the layout, while preserving horizontal delimiters. @apply theme-muted:bg-tint-subtle;
* It basically adds a margin-left with the width of the scrollbar, and a width that compensates for it; when a scrollbar is displayed.
* Inspired by https://aykevl.nl/2014/09/fix-jumping-scrollbar, but adapted to work on child elements of "html"
*/
width: 100%;
@media screen and (min-width: 1536px) {
margin-left: var(--scrollbar-width);
margin-right: 0;
width: calc(100% - var(--scrollbar-width));
body:has(.page-full-width) & {
margin-left: 0;
width: 100%;
}
}
/** @apply theme-gradient:bg-gradient-primary;
* Utility to prevent horizontal jumps when the vertical scrollbar appears @apply theme-gradient-tint:bg-gradient-tint;
* It should be used on main containers of the layout, while preserving horizontal delimiters.
* It basically adds a margin-left with the width of the scrollbar, and a width that compensates for it; when a scrollbar is displayed.
* Inspired by https://aykevl.nl/2014/09/fix-jumping-scrollbar, but adapted to work on child elements of "html"
*/
width: 100%;
@media screen and (min-width: 1536px) {
margin-left: var(--scrollbar-width);
margin-right: 0;
width: calc(100% - var(--scrollbar-width));
}
}
@utility page-full-width {
@media screen and (min-width: 1536px) {
body:has(&) .scroll-nojump {
margin-left: 0;
width: 100%;
}
}
} }
@utility elevate-link { @utility elevate-link {
@@ -211,14 +193,59 @@
@layer base { @layer base {
:root { :root {
--scrollbar-width: calc(100vw - 100%);
@apply leading-relaxed; @apply leading-relaxed;
interpolate-size: allow-keywords; /* Opt-in for modern browsers to interpolate "auto" values in transitions/animations. */
} }
/* Modern browsers with `scrollbar-*` support */
@supports (scrollbar-color: auto) {
* {
scrollbar-color: theme("colors.tint.7") transparent;
scrollbar-width: thin;
}
@media (prefers-contrast: more) {
* {
scrollbar-color: theme("colors.tint.11") transparent;
scrollbar-width: auto;
}
}
}
/* Otherwise, use `::-webkit-scrollbar-*` pseudo-elements */
@supports selector(::-webkit-scrollbar) {
::-webkit-scrollbar {
background: transparent;
max-width: 8px;
}
::-webkit-scrollbar-thumb {
background: theme("colors.tint.7");
border-radius: 8px;
transition: background 0.2s ease-in-out;
}
::-webkit-scrollbar-thumb:hover {
background: theme("colors.tint.8");
}
@media (prefers-contrast: more) {
::-webkit-scrollbar-thumb {
background: theme("colors.tint.11");
}
::-webkit-scrollbar-thumb:hover {
background: theme("colors.tint.12");
}
}
}
body { body {
@apply text-tint-strong antialiased; @apply text-tint-strong antialiased;
} }
html { html {
@apply gutter-stable; scrollbar-width: auto;
} }
h1 { h1 {
@apply tracking-[-0.025em] text-tint-strong text-balance; @apply tracking-[-0.025em] text-tint-strong text-balance;
@@ -249,22 +276,6 @@
@apply subpixel-antialiased; @apply subpixel-antialiased;
} }
/* Light mode */
::-webkit-scrollbar {
@apply bg-tint-subtle;
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb {
@apply bg-tint-7;
border-radius: 8px;
}
::-webkit-scrollbar-thumb:hover {
@apply bg-tint-8;
}
.flip-heading-hash { .flip-heading-hash {
@apply [h1,h2,h3,h4]:content-start; @apply [h1,h2,h3,h4]:content-start;
@apply [h1,h2,h3,h4]:auto-cols-[auto_1fr]; @apply [h1,h2,h3,h4]:auto-cols-[auto_1fr];
@@ -357,6 +368,11 @@ html.dark.code-monochrome {
--shiki-token-function: rgb(var(--primary-10)); --shiki-token-function: rgb(var(--primary-10));
} }
html.font-Lato {
/* Lato's default ligatures impact readability, so we turn them off */
font-variant-ligatures: no-common-ligatures;
}
/* Code blocks */ /* Code blocks */
.highlight-line { .highlight-line {
@apply grid grid-cols-subgrid col-span-2 relative ring-1 ring-transparent hover:ring-tint-hover hover:z-1 rounded-sm; @apply grid grid-cols-subgrid col-span-2 relative ring-1 ring-transparent hover:ring-tint-hover hover:z-1 rounded-sm;
@@ -23,13 +23,14 @@ interface SearchContainerProps {
isMultiVariants: boolean; isMultiVariants: boolean;
style: CustomizationSearchStyle; style: CustomizationSearchStyle;
className?: string; className?: string;
viewport?: 'desktop' | 'mobile';
} }
/** /**
* Client component to render the search input and results. * Client component to render the search input and results.
*/ */
export function SearchContainer(props: SearchContainerProps) { export function SearchContainer(props: SearchContainerProps) {
const { siteSpaceId, spaceTitle, isMultiVariants, style, className } = props; const { siteSpaceId, spaceTitle, isMultiVariants, style, className, viewport } = props;
const { assistants } = useAI(); const { assistants } = useAI();
@@ -55,7 +56,7 @@ export function SearchContainer(props: SearchContainerProps) {
initialRef.current = true; initialRef.current = true;
// For simplicity we're only triggering the first assistant // For simplicity we're only triggering the first assistant
assistants[0].open(state?.ask ?? undefined); assistants[0]?.open(state?.ask ?? undefined);
}, [state?.ask, assistants.length, assistants[0]?.open]); }, [state?.ask, assistants.length, assistants[0]?.open]);
const onClose = React.useCallback( const onClose = React.useCallback(
@@ -88,6 +89,19 @@ export function SearchContainer(props: SearchContainerProps) {
} }
); );
useHotkeys(
'mod+i',
(e) => {
e.preventDefault();
if (assistants) {
assistants[0]?.open();
}
},
{
enableOnFormTags: true,
}
);
const onOpen = React.useCallback(() => { const onOpen = React.useCallback(() => {
if (state?.open) { if (state?.open) {
return; return;
@@ -145,6 +159,8 @@ export function SearchContainer(props: SearchContainerProps) {
const showAsk = withSearchAI && normalizedAsk; // withSearchAI && normalizedAsk; const showAsk = withSearchAI && normalizedAsk; // withSearchAI && normalizedAsk;
const visible = viewport === 'desktop' ? !isMobile : viewport === 'mobile' ? isMobile : true;
return ( return (
<SearchAskProvider value={searchAsk}> <SearchAskProvider value={searchAsk}>
<Popover <Popover
@@ -168,7 +184,7 @@ export function SearchContainer(props: SearchContainerProps) {
) : null ) : null
} }
rootProps={{ rootProps={{
open: state?.open ?? false, open: visible && (state?.open ?? false),
onOpenChange: (open) => { onOpenChange: (open) => {
open ? onOpen() : onClose(); open ? onOpen() : onClose();
}, },
@@ -178,7 +194,7 @@ export function SearchContainer(props: SearchContainerProps) {
onOpenAutoFocus: (event) => event.preventDefault(), onOpenAutoFocus: (event) => event.preventDefault(),
align: 'start', align: 'start',
className: className:
'bg-tint-base has-[.empty]:hidden scroll-py-2 w-128 p-2 max-h-[min(32rem,var(--radix-popover-content-available-height))] max-w-[min(var(--radix-popover-content-available-width),32rem)]', 'bg-tint-base has-[.empty]:hidden gutter-stable scroll-py-2 w-128 p-2 pr-1 max-h-[min(32rem,var(--radix-popover-content-available-height))] max-w-[min(var(--radix-popover-content-available-width),32rem)]',
onInteractOutside: (event) => { onInteractOutside: (event) => {
// Don't close if clicking on the search input itself // Don't close if clicking on the search input itself
if (searchInputRef.current?.contains(event.target as Node)) { if (searchInputRef.current?.contains(event.target as Node)) {
@@ -211,10 +227,11 @@ export function SearchContainer(props: SearchContainerProps) {
</Popover> </Popover>
{assistants {assistants
.filter((assistant) => assistant.ui === true) .filter((assistant) => assistant.ui === true)
.map((assistant) => ( .map((assistant, index) => (
<AIChatButton <AIChatButton
key={assistant.id} key={assistant.id}
assistant={assistant} assistant={assistant}
withShortcut={index === 0}
showLabel={ showLabel={
assistants.filter((assistant) => assistant.ui === true).length === 1 && assistants.filter((assistant) => assistant.ui === true).length === 1 &&
style === CustomizationSearchStyle.Prominent style === CustomizationSearchStyle.Prominent
@@ -46,7 +46,7 @@ export const SearchInput = React.forwardRef<HTMLDivElement, SearchInputProps>(
}, [isOpen, value]); }, [isOpen, value]);
return ( return (
<div className="relative flex size-9 grow"> <div className={tcls('relative flex size-9 grow', className)}>
{/* biome-ignore lint/a11y/useKeyWithClickEvents: this div needs an onClick to show the input on mobile, where it's normally hidden. {/* biome-ignore lint/a11y/useKeyWithClickEvents: this div needs an onClick to show the input on mobile, where it's normally hidden.
Normally you'd also need to add a keyboard trigger to do the same without a pointer, but in this case the input already be focused on its own. */} Normally you'd also need to add a keyboard trigger to do the same without a pointer, but in this case the input already be focused on its own. */}
<div <div
@@ -62,8 +62,7 @@ export const SearchInput = React.forwardRef<HTMLDivElement, SearchInputProps>(
'theme-bold:border-header-link/3 has-[input:focus-visible]:theme-bold:border-header-link/5 has-[input:focus-visible]:theme-bold:bg-header-link/3 has-[input:focus-visible]:theme-bold:ring-header-link/5', 'theme-bold:border-header-link/3 has-[input:focus-visible]:theme-bold:border-header-link/5 has-[input:focus-visible]:theme-bold:bg-header-link/3 has-[input:focus-visible]:theme-bold:ring-header-link/5',
'theme-bold:before:absolute theme-bold:before:inset-0 theme-bold:before:bg-header-background/7 theme-bold:before:backdrop-blur-xl ', // Special overlay to make the transparent colors of theme-bold visible. 'theme-bold:before:absolute theme-bold:before:inset-0 theme-bold:before:bg-header-background/7 theme-bold:before:backdrop-blur-xl ', // Special overlay to make the transparent colors of theme-bold visible.
'relative z-30 shrink grow justify-start max-md:absolute max-md:right-0', 'relative z-30 shrink grow justify-start max-md:absolute max-md:right-0',
isOpen ? 'max-md:w-56' : 'max-md:w-[38px]', isOpen ? 'max-md:w-56' : 'max-md:w-[38px]'
className
)} )}
> >
{value && isOpen ? ( {value && isOpen ? (
@@ -296,7 +296,7 @@ export const SearchResults = React.forwardRef(function SearchResults(
key={item.id} key={item.id}
question={item.question} question={item.question}
active={index === cursor} active={index === cursor}
assistant={assistants[0]} assistant={assistants[0]!}
recommended recommended
/> />
); );
@@ -71,8 +71,7 @@ export interface AskAnswerResult {
export async function searchAllSiteContent(query: string): Promise<OrderedComputedResult[]> { export async function searchAllSiteContent(query: string): Promise<OrderedComputedResult[]> {
return traceErrorOnly('Search.searchAllSiteContent', async () => { return traceErrorOnly('Search.searchAllSiteContent', async () => {
const context = await getServerActionBaseContext(); const context = await getServerActionBaseContext();
return searchSiteContent(context, {
return await searchSiteContent(context, {
query, query,
scope: { mode: 'all' }, scope: { mode: 'all' },
}); });
@@ -270,7 +269,7 @@ async function searchSiteContent(
return ( return (
await Promise.all( await Promise.all(
searchResults.map(async (spaceItem) => { searchResults.map((spaceItem) => {
const found = findSiteSpaceBy( const found = findSiteSpaceBy(
structure, structure,
(siteSpace) => siteSpace.space.id === spaceItem.id (siteSpace) => siteSpace.space.id === spaceItem.id
@@ -13,7 +13,7 @@ import { buildVersion } from '@/lib/build';
import { GITBOOK_API_PUBLIC_URL, GITBOOK_ASSETS_URL, GITBOOK_ICONS_URL } from '@/lib/env'; import { GITBOOK_API_PUBLIC_URL, GITBOOK_ASSETS_URL, GITBOOK_ICONS_URL } from '@/lib/env';
import { getResizedImageURL } from '@/lib/images'; import { getResizedImageURL } from '@/lib/images';
import { isSiteIndexable } from '@/lib/seo'; import { isSiteIndexable } from '@/lib/seo';
import { AIChatProvider, AIContextProvider } from '../AI'; import { AIContextProvider } from '../AI';
import { RocketLoaderDetector } from './RocketLoaderDetector'; import { RocketLoaderDetector } from './RocketLoaderDetector';
import { SiteLayoutClientContexts } from './SiteLayoutClientContexts'; import { SiteLayoutClientContexts } from './SiteLayoutClientContexts';
@@ -58,15 +58,13 @@ export async function SiteLayout(props: {
aiMode={customization.ai?.mode} aiMode={customization.ai?.mode}
trademark={customization.trademark.enabled} trademark={customization.trademark.enabled}
> >
<AIChatProvider> <SpaceLayout
<SpaceLayout context={context}
context={context} withTracking={withTracking}
withTracking={withTracking} visitorAuthClaims={visitorAuthClaims}
visitorAuthClaims={visitorAuthClaims} >
> {children}
{children} </SpaceLayout>
</SpaceLayout>
</AIChatProvider>
</AIContextProvider> </AIContextProvider>
{scripts.length > 0 ? ( {scripts.length > 0 ? (
@@ -1,6 +1,10 @@
import type { GitBookSiteContext } from '@/lib/context'; import type { GitBookSiteContext } from '@/lib/context';
import { getPageDocument } from '@/lib/data'; import { getPageDocument } from '@/lib/data';
import { CustomizationHeaderPreset, CustomizationThemeMode } from '@gitbook/api'; import {
CustomizationHeaderPreset,
CustomizationThemeMode,
SiteInsightsDisplayContext,
} from '@gitbook/api';
import type { Metadata, Viewport } from 'next'; import type { Metadata, Viewport } from 'next';
import { notFound, redirect } from 'next/navigation'; import { notFound, redirect } from 'next/navigation';
import React from 'react'; import React from 'react';
@@ -65,6 +69,7 @@ export async function SitePage(props: SitePageProps) {
ancestors={ancestors} ancestors={ancestors}
document={document} document={document}
withPageFeedback={withPageFeedback} withPageFeedback={withPageFeedback}
insightsDisplayContext={SiteInsightsDisplayContext.Site}
/> />
</div> </div>
<React.Suspense fallback={null}> <React.Suspense fallback={null}>
@@ -3,6 +3,7 @@
import { TrackPageViewEvent } from '@/components/Insights'; import { TrackPageViewEvent } from '@/components/Insights';
import { t, useLanguage } from '@/intl/client'; import { t, useLanguage } from '@/intl/client';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { SiteInsightsDisplayContext } from '@gitbook/api';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useSpaceBasePath } from '../SpaceLayout/SpaceLayoutContext'; import { useSpaceBasePath } from '../SpaceLayout/SpaceLayoutContext';
@@ -46,7 +47,7 @@ export function SitePageNotFound() {
</div> </div>
{/* Track the page not found as a page view */} {/* Track the page not found as a page view */}
<TrackPageViewEvent /> <TrackPageViewEvent displayContext={SiteInsightsDisplayContext.Site} />
</div> </div>
</CurrentPageProvider> </CurrentPageProvider>
); );
@@ -38,7 +38,7 @@ export function SiteSectionList(props: { sections: ClientSiteSections; className
> >
<TOCScrollContainer <TOCScrollContainer
style={{ maxHeight: `${MAX_ITEMS * 3 + 2}rem` }} style={{ maxHeight: `${MAX_ITEMS * 3 + 2}rem` }}
className="gutter-stable overflow-y-auto px-2 pb-6" className="overflow-y-auto px-2 pb-4"
> >
{sectionsAndGroups.map((item) => { {sectionsAndGroups.map((item) => {
if (item.object === 'site-section-group') { if (item.object === 'site-section-group') {
@@ -110,7 +110,7 @@ export function SiteSectionListItem(props: {
className={tcls( className={tcls(
'flex size-8 shrink-0 items-center justify-center rounded-md straight-corners:rounded-none bg-tint-subtle text-lg text-tint leading-none shadow-tint shadow-xs ring-1 ring-tint-subtle transition-transform group-hover/section-link:scale-110 group-hover/section-link:ring-tint-hover group-active/section-link:scale-90 group-active/section-link:shadow-none contrast-more:text-tint-strong dark:shadow-none', 'flex size-8 shrink-0 items-center justify-center rounded-md straight-corners:rounded-none bg-tint-subtle text-lg text-tint leading-none shadow-tint shadow-xs ring-1 ring-tint-subtle transition-transform group-hover/section-link:scale-110 group-hover/section-link:ring-tint-hover group-active/section-link:scale-90 group-active/section-link:shadow-none contrast-more:text-tint-strong dark:shadow-none',
isActive isActive
? 'bg-primary tint:bg-primary-solid text-primary-subtle tint:text-contrast-primary-solid shadow-md shadow-primary ring-primary group-hover/section-link:ring-primary-hover, contrast-more:text-primary contrast-more:ring-2 contrast-more:ring-primary' ? 'bg-primary tint:bg-primary-original text-primary-subtle tint:text-contrast-primary-original shadow-md shadow-primary ring-primary group-hover/section-link:ring-primary-hover, contrast-more:text-primary contrast-more:ring-2 contrast-more:ring-primary'
: null : null
)} )}
> >
@@ -4,7 +4,7 @@ import {
CustomizationHeaderPreset, CustomizationHeaderPreset,
CustomizationSearchStyle, CustomizationSearchStyle,
} from '@gitbook/api'; } from '@gitbook/api';
import React from 'react'; import type React from 'react';
import { Footer } from '@/components/Footer'; import { Footer } from '@/components/Footer';
import { Header, HeaderLogo } from '@/components/Header'; import { Header, HeaderLogo } from '@/components/Header';
@@ -12,9 +12,13 @@ import { TableOfContents } from '@/components/TableOfContents';
import { CONTAINER_STYLE } from '@/components/layout'; import { CONTAINER_STYLE } from '@/components/layout';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { getSpaceLanguage } from '@/intl/server';
import type { VisitorAuthClaims } from '@/lib/adaptive'; import type { VisitorAuthClaims } from '@/lib/adaptive';
import { GITBOOK_APP_URL } from '@/lib/env'; import { GITBOOK_APP_URL } from '@/lib/env';
import { AIChatProvider } from '../AI';
import type { RenderAIMessageOptions } from '../AI';
import { AIChat } from '../AIChat'; import { AIChat } from '../AIChat';
import { AdaptiveVisitorContextProvider } from '../Adaptive';
import { Announcement } from '../Announcement'; import { Announcement } from '../Announcement';
import { SpacesDropdown } from '../Header/SpacesDropdown'; import { SpacesDropdown } from '../Header/SpacesDropdown';
import { InsightsProvider } from '../Insights'; import { InsightsProvider } from '../Insights';
@@ -23,10 +27,7 @@ import { SiteSectionList, encodeClientSiteSections } from '../SiteSections';
import { CurrentContentProvider } from '../hooks'; import { CurrentContentProvider } from '../hooks';
import { SpaceLayoutContextProvider } from './SpaceLayoutContext'; import { SpaceLayoutContextProvider } from './SpaceLayoutContext';
/** type SpaceLayoutProps = {
* Render the entire layout of the space (header, table of contents, footer).
*/
export function SpaceLayout(props: {
context: GitBookSiteContext; context: GitBookSiteContext;
/** Whether to enable tracking of events into site insights. */ /** Whether to enable tracking of events into site insights. */
@@ -35,39 +36,21 @@ export function SpaceLayout(props: {
/** The visitor auth claims. */ /** The visitor auth claims. */
visitorAuthClaims: VisitorAuthClaims; visitorAuthClaims: VisitorAuthClaims;
/** The options for rendering AI messages. */
aiChatRenderMessageOptions?: RenderAIMessageOptions;
/** The children of the layout. */ /** The children of the layout. */
children: React.ReactNode; children: React.ReactNode;
}) { };
const { context, withTracking, visitorAuthClaims, children } = props;
const { siteSpace, customization, sections, siteSpaces } = context;
const withTopHeader = customization.header.preset !== CustomizationHeaderPreset.None; /**
* Provide all contexts for a space.
*/
export function SpaceLayoutServerContext(props: SpaceLayoutProps) {
const { context, withTracking, visitorAuthClaims, aiChatRenderMessageOptions, children } =
props;
const withSections = Boolean(sections && sections.list.length > 1); const { customization } = context;
const isMultiVariants = Boolean(siteSpaces.length > 1);
const withFooter =
customization.themes.toggeable ||
customization.footer.copyright ||
customization.footer.logo ||
customization.footer.groups?.length;
const search = (
<div className="flex grow items-center gap-2">
<React.Suspense fallback={null}>
<SearchContainer
style={
customization.header.preset === CustomizationHeaderPreset.None
? CustomizationSearchStyle.Subtle
: customization.styling.search
}
isMultiVariants={siteSpaces.length > 1}
spaceTitle={siteSpace.title}
siteSpaceId={siteSpace.id}
/>
</React.Suspense>
</div>
);
const eventUrl = new URL( const eventUrl = new URL(
context.linker.toAbsoluteURL(context.linker.toPathInSite('/~gitbook/__evt')) context.linker.toAbsoluteURL(context.linker.toPathInSite('/~gitbook/__evt'))
@@ -75,99 +58,150 @@ export function SpaceLayout(props: {
eventUrl.searchParams.set('o', context.organizationId); eventUrl.searchParams.set('o', context.organizationId);
eventUrl.searchParams.set('s', context.site.id); eventUrl.searchParams.set('s', context.site.id);
const getVisitorClaimsUrl = context.linker.toAbsoluteURL(
context.linker.toPathInSite('/~gitbook/visitor')
);
return ( return (
<SpaceLayoutContextProvider basePath={context.linker.toPathInSpace('')}> <SpaceLayoutContextProvider basePath={context.linker.toPathInSpace('')}>
<CurrentContentProvider <AdaptiveVisitorContextProvider
organizationId={context.organizationId} contextId={context.contextId}
siteId={context.site.id} visitorClaimsURL={getVisitorClaimsUrl}
siteSectionId={context.sections?.current?.id ?? null}
siteSpaceId={context.siteSpace.id}
siteShareKey={context.shareKey ?? null}
spaceId={context.space.id}
revisionId={context.revisionId}
visitorAuthClaims={visitorAuthClaims}
> >
<InsightsProvider <CurrentContentProvider
enabled={withTracking} organizationId={context.organizationId}
appURL={GITBOOK_APP_URL} siteId={context.site.id}
eventUrl={eventUrl.toString()} siteSectionId={context.sections?.current?.id ?? null}
visitorCookieTrackingEnabled={customization.insights?.trackingCookie} siteSpaceId={context.siteSpace.id}
siteShareKey={context.shareKey ?? null}
spaceId={context.space.id}
revisionId={context.revisionId}
visitorAuthClaims={visitorAuthClaims}
> >
<Announcement context={context} /> <InsightsProvider
<Header withTopHeader={withTopHeader} context={context} search={search} /> enabled={withTracking}
{customization.ai?.mode === CustomizationAIMode.Assistant ? ( appURL={GITBOOK_APP_URL}
<AIChat trademark={customization.trademark.enabled} /> eventUrl={eventUrl.toString()}
) : null} visitorCookieTrackingEnabled={customization.insights?.trackingCookie}
<div className="scroll-nojump"> >
<div className="motion-safe:transition-all motion-safe:duration-300 lg:chat-open:mr-80 xl:chat-open:mr-96"> <AIChatProvider renderMessageOptions={aiChatRenderMessageOptions}>
<div {children}
className={tcls( </AIChatProvider>
'flex', </InsightsProvider>
'flex-col', </CurrentContentProvider>
'lg:flex-row', </AdaptiveVisitorContextProvider>
CONTAINER_STYLE,
'site-width-wide:max-w-full',
// Ensure the footer is display below the viewport even if the content is not enough
withFooter && 'min-h-[calc(100vh-64px)]',
withTopHeader ? null : 'lg:min-h-screen'
)}
>
<TableOfContents
context={context}
header={
withTopHeader ? null : (
<div
className={tcls(
'hidden',
'pr-4',
'md:flex',
'grow-0',
'flex-wrap',
'dark:shadow-light/1',
'text-base/tight'
)}
>
<HeaderLogo context={context} />
</div>
)
}
innerHeader={
// displays the search button and/or the space dropdown in the ToC according to the header/variant settings. E.g if there is no header, the search button will be displayed in the ToC.
<>
{!withTopHeader && search}
{!withTopHeader && withSections && sections && (
<SiteSectionList
className={tcls('hidden', 'lg:block')}
sections={encodeClientSiteSections(
context,
sections
)}
/>
)}
{isMultiVariants && !sections && (
<SpacesDropdown
context={context}
siteSpace={siteSpace}
siteSpaces={siteSpaces}
className={tcls(
'w-full',
'page-no-toc:hidden',
'page-no-toc:site-header-none:flex'
)}
/>
)}
</>
}
/>
<div className="flex min-w-0 flex-1 flex-col">{children}</div>
</div>
</div>
</div>
{withFooter ? <Footer context={context} /> : null}
</InsightsProvider>
</CurrentContentProvider>
</SpaceLayoutContextProvider> </SpaceLayoutContextProvider>
); );
} }
/**
* Render the entire layout of the space (header, table of contents, footer).
*/
export function SpaceLayout(props: SpaceLayoutProps) {
const { context, children } = props;
const { siteSpace, customization, sections, siteSpaces } = context;
const withTopHeader = customization.header.preset !== CustomizationHeaderPreset.None;
const withSections = Boolean(sections && sections.list.length > 1);
const currentLanguage = getSpaceLanguage(context);
const withVariants: 'generic' | 'translations' | undefined =
siteSpaces.length > 1
? siteSpaces.some(
(space) => space.space.language && space.space.language !== currentLanguage.locale
)
? 'translations'
: 'generic'
: undefined;
const withFooter =
customization.themes.toggeable ||
customization.footer.copyright ||
customization.footer.logo ||
customization.footer.groups?.length;
return (
<SpaceLayoutServerContext {...props}>
<Announcement context={context} />
<Header withTopHeader={withTopHeader} withVariants={withVariants} context={context} />
{customization.ai?.mode === CustomizationAIMode.Assistant ? (
<AIChat trademark={customization.trademark.enabled} />
) : null}
<div className="motion-safe:transition-all motion-safe:duration-300 lg:chat-open:mr-80 xl:chat-open:mr-96">
<div
className={tcls(
'flex',
'flex-col',
'lg:flex-row',
CONTAINER_STYLE,
'site-width-wide:max-w-full',
// Ensure the footer is display below the viewport even if the content is not enough
withFooter && [
'site-header:min-h-[calc(100vh-64px)]',
'site-header-sections:min-h-[calc(100vh-108px)]',
],
withTopHeader ? null : 'lg:min-h-screen'
)}
>
<TableOfContents
context={context}
header={
withTopHeader ? null : (
<div
className={tcls(
'hidden',
'pr-4',
'lg:flex',
'grow-0',
'flex-wrap',
'dark:shadow-light/1',
'text-base/tight'
)}
>
<HeaderLogo context={context} />
</div>
)
}
innerHeader={
// displays the search button and/or the space dropdown in the ToC according to the header/variant settings. E.g if there is no header, the search button will be displayed in the ToC.
<>
{!withTopHeader && (
<div className="flex gap-2">
<SearchContainer
style={CustomizationSearchStyle.Subtle}
isMultiVariants={siteSpaces.length > 1}
spaceTitle={siteSpace.title}
siteSpaceId={siteSpace.id}
className="max-lg:hidden"
viewport="desktop"
/>
</div>
)}
{!withTopHeader && withSections && sections && (
<SiteSectionList
className={tcls('hidden', 'lg:block')}
sections={encodeClientSiteSections(context, sections)}
/>
)}
{withVariants === 'generic' && (
<SpacesDropdown
context={context}
siteSpace={siteSpace}
siteSpaces={siteSpaces}
className="w-full px-3 py-2"
/>
)}
</>
}
/>
<div className="flex min-w-0 flex-1 flex-col">{children}</div>
</div>
</div>
{withFooter ? <Footer context={context} /> : null}
</SpaceLayoutServerContext>
);
}
@@ -3,7 +3,6 @@ import { SiteInsightsTrademarkPlacement } from '@gitbook/api';
import type React from 'react'; import type React from 'react';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import { PagesList } from './PagesList'; import { PagesList } from './PagesList';
import { TOCScrollContainer } from './TOCScroller'; import { TOCScrollContainer } from './TOCScroller';
import { TableOfContentsScript } from './TableOfContentsScript'; import { TableOfContentsScript } from './TableOfContentsScript';
@@ -16,7 +15,7 @@ export async function TableOfContents(props: {
innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list
}) { }) {
const { innerHeader, context, header } = props; const { innerHeader, context, header } = props;
const { space, customization, revision } = context; const { customization, revision } = context;
const pages = await encodeClientTableOfContents(context, revision.pages, revision.pages); const pages = await encodeClientTableOfContents(context, revision.pages, revision.pages);
@@ -57,6 +56,8 @@ export async function TableOfContents(props: {
// Client-side dynamic positioning (CSS vars applied by script) // Client-side dynamic positioning (CSS vars applied by script)
'lg:[html[style*="--toc-top-offset"]_&]:top-(--toc-top-offset)!', 'lg:[html[style*="--toc-top-offset"]_&]:top-(--toc-top-offset)!',
'lg:[html[style*="--toc-height"]_&]:h-(--toc-height)!', 'lg:[html[style*="--toc-height"]_&]:h-(--toc-height)!',
'lg:page-no-toc:[html[style*="--outline-top-offset"]_&]:top-(--outline-top-offset)!',
'lg:page-no-toc:[html[style*="--outline-height"]_&]:top-(--outline-height)!',
'pt-6', 'pt-6',
'pb-4', 'pb-4',
@@ -96,17 +97,16 @@ export async function TableOfContents(props: {
'page-has-toc:[html.sidebar-filled.circular-corners_&]:rounded-3xl' 'page-has-toc:[html.sidebar-filled.circular-corners_&]:rounded-3xl'
)} )}
> >
{innerHeader && <div className="px-5 *:my-4">{innerHeader}</div>} {innerHeader ? (
<div className="my-4 flex flex-col space-y-4 px-5 empty:hidden">
{innerHeader}
</div>
) : null}
<TOCScrollContainer // The scrollview inside the sidebar <TOCScrollContainer // The scrollview inside the sidebar
className={tcls( className={tcls(
'flex grow flex-col p-2', 'flex grow flex-col p-2',
customization.trademark.enabled && 'lg:pb-20', customization.trademark.enabled && 'lg:pb-20',
'lg:gutter-stable overflow-y-auto', 'hide-scrollbar overflow-y-auto'
'[&::-webkit-scrollbar]:bg-transparent',
'[&::-webkit-scrollbar-thumb]:bg-transparent',
'[&::-webkit-scrollbar]:group-hover:bg-tint-subtle',
'[&::-webkit-scrollbar-thumb]:group-hover:bg-tint-7',
'[&::-webkit-scrollbar-thumb:hover]:group-hover:bg-tint-8'
)} )}
> >
<PagesList <PagesList
@@ -115,8 +115,7 @@ export async function TableOfContents(props: {
/> />
{customization.trademark.enabled ? ( {customization.trademark.enabled ? (
<Trademark <Trademark
space={space} context={context}
customization={customization}
placement={SiteInsightsTrademarkPlacement.Sidebar} placement={SiteInsightsTrademarkPlacement.Sidebar}
/> />
) : null} ) : null}
@@ -1,21 +1,17 @@
import type { import type { SiteInsightsTrademarkPlacement } from '@gitbook/api';
SiteCustomizationSettings,
SiteInsightsTrademarkPlacement,
Space,
} from '@gitbook/api';
import { Icon } from '@gitbook/icons'; import { Icon } from '@gitbook/icons';
import { getSpaceLanguage, t } from '@/intl/server'; import { getSpaceLanguage, t } from '@/intl/server';
import { tcls } from '@/lib/tailwind'; import { tcls } from '@/lib/tailwind';
import type { GitBookSpaceContext } from '@/lib/context';
import { Link } from '../primitives'; import { Link } from '../primitives';
/** /**
* Trademark link to the GitBook. * Trademark link to the GitBook.
*/ */
export function Trademark(props: { export function Trademark(props: {
space: Space; context: GitBookSpaceContext;
customization: SiteCustomizationSettings;
placement: SiteInsightsTrademarkPlacement; placement: SiteInsightsTrademarkPlacement;
}) { }) {
return ( return (
@@ -71,12 +67,12 @@ export function Trademark(props: {
* Trademark link to the GitBook. * Trademark link to the GitBook.
*/ */
export function TrademarkLink(props: { export function TrademarkLink(props: {
space: Space; context: GitBookSpaceContext;
customization: SiteCustomizationSettings;
placement: SiteInsightsTrademarkPlacement; placement: SiteInsightsTrademarkPlacement;
}) { }) {
const { space, customization, placement } = props; const { context, placement } = props;
const language = getSpaceLanguage(customization); const { space } = context;
const language = getSpaceLanguage(context);
const url = new URL('https://www.gitbook.com'); const url = new URL('https://www.gitbook.com');
url.searchParams.set('utm_source', 'content'); url.searchParams.set('utm_source', 'content');
@@ -25,7 +25,7 @@ export function useHasBeenInViewport(
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
([entry]) => { ([entry]) => {
if (entry.isIntersecting) { if (entry?.isIntersecting) {
setVisible(true); setVisible(true);
observer.disconnect(); observer.disconnect();
} }
@@ -30,8 +30,9 @@ export function useInViewportListener(
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
([entry]) => { ([entry]) => {
isIntersectingRef.current = entry.isIntersecting; const isIntersecting = entry?.isIntersecting ?? false;
listenerRef.current(entry.isIntersecting, () => { isIntersectingRef.current = isIntersecting;
listenerRef.current(isIntersecting, () => {
observer.disconnect(); observer.disconnect();
}); });
}, },
@@ -2,7 +2,7 @@
import * as React from 'react'; import * as React from 'react';
export function useIsMobile(breakpoint = 640): boolean { export function useIsMobile(breakpoint = 1024): boolean {
const [isMobile, setIsMobile] = React.useState(false); const [isMobile, setIsMobile] = React.useState(false);
React.useEffect(() => { React.useEffect(() => {
@@ -5,19 +5,22 @@ import React from 'react';
*/ */
export function useScrollActiveId( export function useScrollActiveId(
ids: string[], ids: string[],
options: { {
rootMargin,
threshold = 0.5,
enabled,
}: {
rootMargin?: string; rootMargin?: string;
threshold?: number; threshold?: number;
enabled: boolean; enabled: boolean;
} = { enabled: true } } = { enabled: true }
) { ) {
const { rootMargin, threshold = 0.5, enabled } = options; const [activeId, setActiveId] = React.useState<string>(ids[0]!);
const [activeId, setActiveId] = React.useState<string>(ids[0]);
const sectionsIntersectingMap = React.useRef<Map<string, boolean>>(new Map()); const sectionsIntersectingMap = React.useRef<Map<string, boolean>>(new Map());
React.useEffect(() => { React.useEffect(() => {
const defaultActiveId = ids[0]; const defaultActiveId = ids[0];
// @ts-expect-error
setActiveId((activeId) => (ids.indexOf(activeId) !== -1 ? activeId : defaultActiveId)); setActiveId((activeId) => (ids.indexOf(activeId) !== -1 ? activeId : defaultActiveId));
if (!enabled) { if (!enabled) {
return; return;
@@ -9,7 +9,7 @@ import { Link, type LinkInsightsProps } from './Link';
import { useClassnames } from './StyleProvider'; import { useClassnames } from './StyleProvider';
import { Tooltip } from './Tooltip'; import { Tooltip } from './Tooltip';
type ButtonProps = { export type ButtonProps = {
href?: string; href?: string;
variant?: 'primary' | 'secondary' | 'blank' | 'header'; variant?: 'primary' | 'secondary' | 'blank' | 'header';
icon?: IconName | React.ReactNode; icon?: IconName | React.ReactNode;
@@ -25,11 +25,13 @@ type ButtonProps = {
export const variantClasses = { export const variantClasses = {
primary: [ primary: [
'bg-primary-solid', 'bg-primary-original',
'text-contrast-primary-solid', 'text-contrast-primary-original',
'hover:bg-primary-solid-hover', 'hover:bg-primary-solid-hover',
'hover:text-contrast-primary-solid-hover', 'hover:text-contrast-primary-solid-hover',
'border-0', 'border-0',
'contrast-more:bg-primary-solid',
'contrast-more:text-contrast-primary-solid',
'contrast-more:border', 'contrast-more:border',
'disabled:bg-primary-subtle', 'disabled:bg-primary-subtle',
'disabled:text-primary/8', 'disabled:text-primary/8',
@@ -130,7 +132,10 @@ export const Button = React.forwardRef<
<> <>
{icon ? ( {icon ? (
typeof icon === 'string' ? ( typeof icon === 'string' ? (
<Icon icon={icon as IconName} className={tcls('size-[1em]')} /> <Icon
icon={icon as IconName}
className={tcls('button-leading-icon size-[1em]')}
/>
) : ( ) : (
icon icon
) )
@@ -139,36 +144,32 @@ export const Button = React.forwardRef<
</> </>
); );
if (href) { const button = href ? (
return ( <Link
<Link ref={ref as React.Ref<HTMLAnchorElement>}
ref={ref as React.Ref<HTMLAnchorElement>} href={href}
href={href} className={domClassName}
className={domClassName} classNames={['ButtonStyles']}
classNames={['ButtonStyles']} insights={insights}
insights={insights} aria-label={label?.toString()}
aria-label={label?.toString()} aria-pressed={active}
aria-pressed={active === undefined ? undefined : active} target={target}
target={target} {...rest}
{...rest} >
> {content}
{content} </Link>
</Link> ) : (
);
}
const button = (
<button <button
ref={ref as React.Ref<HTMLButtonElement>} ref={ref as React.Ref<HTMLButtonElement>}
type="button" type="button"
className={tcls(buttonOnlyClassNames, domClassName)} className={tcls(buttonOnlyClassNames, domClassName)}
aria-label={label?.toString()} aria-label={label?.toString()}
aria-pressed={active === undefined ? undefined : active} aria-pressed={active}
disabled={disabled} disabled={disabled}
{...rest} {...rest}
> >
{content} {content}
{trailing} {trailing ? <span className="button-trailing-icon ms-auto">{trailing}</span> : null}
</button> </button>
); );
@@ -31,8 +31,8 @@ export const Checkbox = React.forwardRef<
'flex', 'flex',
'items-center', 'items-center',
'justify-center', 'justify-center',
'data-[state=checked]:bg-primary-solid', 'data-[state=checked]:bg-primary-original',
'data-[state=checked]:text-contrast-primary-solid', 'data-[state=checked]:text-contrast-primary-original',
'contrast-more:ring-tint-12', 'contrast-more:ring-tint-12',
{ small: 'size-4', medium: 'size-5' }[size], { small: 'size-4', medium: 'size-5' }[size],
className className
@@ -86,7 +86,7 @@ export function DropdownMenu(props: {
> >
<div <div
className={tcls( className={tcls(
'flex max-h-96 min-w-40 max-w-[40vw] flex-col gap-1 overflow-auto circular-corners:rounded-xl rounded-md straight-corners:rounded-none border border-tint bg-tint-base p-2 shadow-lg sm:min-w-52 sm:max-w-80', 'flex max-h-[30rem] min-w-40 max-w-[40vw] flex-col gap-1 overflow-auto circular-corners:rounded-xl rounded-md straight-corners:rounded-none border border-tint bg-tint-base p-2 shadow-lg sm:min-w-52 sm:max-w-80',
className className
)} )}
> >
@@ -110,7 +110,6 @@ export function DropdownChevron() {
'shrink-0', 'shrink-0',
'opacity-6', 'opacity-6',
'size-3', 'size-3',
'ms-1',
'transition-all', 'transition-all',
'group-hover/dropdown:opacity-11', 'group-hover/dropdown:opacity-11',
'group-data-[state=open]/dropdown:opacity-11', 'group-data-[state=open]/dropdown:opacity-11',
@@ -28,6 +28,7 @@ export const ButtonStyles = [
'hover:depth-subtle:-translate-y-px', 'hover:depth-subtle:-translate-y-px',
'focus-visible:depth-subtle:-translate-y-px', 'focus-visible:depth-subtle:-translate-y-px',
'data-[state=open]:depth-subtle:-translate-y-px',
'active:depth-subtle:translate-y-0', 'active:depth-subtle:translate-y-0',
'transition-all', 'transition-all',
@@ -41,8 +41,8 @@ export function ZoomImage(
// Since the image is removed from the DOM when the modal is opened, // Since the image is removed from the DOM when the modal is opened,
// We only care when the size is defined. // We only care when the size is defined.
if (imgEntry && imgEntry.contentRect.width !== 0) { if (imgEntry && imgEntry.contentRect.width !== 0) {
viewWidth = entries[0]?.contentRect.width; viewWidth = imgEntry.contentRect.width;
setPlaceholderRect(entries[0].contentRect); setPlaceholderRect(imgEntry.contentRect);
onChange(); onChange();
} }
}) })
+169 -190
View File
@@ -3,201 +3,180 @@ import type { CustomizationFontDefinition } from '@gitbook/api';
import stylelint from 'stylelint'; import stylelint from 'stylelint';
import { generateFontFacesCSS, getFontSourcesToPreload } from './custom'; import { generateFontFacesCSS, getFontSourcesToPreload } from './custom';
const TEST_FONTS: { [key in string]: CustomizationFontDefinition } = { const TEST_FONTS_BASIC: CustomizationFontDefinition = {
basic: { id: 'open-sans',
id: 'open-sans', custom: true,
custom: true, fontFamily: 'Open Sans',
fontFamily: 'Open Sans', fontFaces: [
fontFaces: [ {
{ weight: 400,
weight: 400, sources: [
sources: [ {
{ url: 'https://example.com/fonts/opensans-regular.woff2',
url: 'https://example.com/fonts/opensans-regular.woff2', format: 'woff2',
format: 'woff2', },
}, ],
],
},
{
weight: 700,
sources: [
{
url: 'https://example.com/fonts/opensans-bold.woff2',
format: 'woff2',
},
],
},
],
permissions: {
edit: false,
}, },
{
weight: 700,
sources: [
{
url: 'https://example.com/fonts/opensans-bold.woff2',
format: 'woff2',
},
],
},
],
permissions: {
edit: false,
}, },
};
multiWeight: { const TEST_FONTS_MULTI_WEIGHT: CustomizationFontDefinition = {
id: 'roboto', id: 'roboto',
custom: true, custom: true,
fontFamily: 'Roboto', fontFamily: 'Roboto',
fontFaces: [ fontFaces: [
{ {
weight: 300, weight: 300,
sources: [ sources: [
{ {
url: 'https://example.com/fonts/roboto-light.woff2', url: 'https://example.com/fonts/roboto-light.woff2',
format: 'woff2', format: 'woff2',
}, },
], ],
},
{
weight: 400,
sources: [
{
url: 'https://example.com/fonts/roboto-regular.woff2',
format: 'woff2',
},
],
},
{
weight: 500,
sources: [
{
url: 'https://example.com/fonts/roboto-medium.woff2',
format: 'woff2',
},
],
},
{
weight: 700,
sources: [
{
url: 'https://example.com/fonts/roboto-bold.woff2',
format: 'woff2',
},
],
},
{
weight: 900,
sources: [
{
url: 'https://example.com/fonts/roboto-black.woff2',
format: 'woff2',
},
],
},
],
permissions: {
edit: false,
}, },
{
weight: 400,
sources: [
{
url: 'https://example.com/fonts/roboto-regular.woff2',
format: 'woff2',
},
],
},
{
weight: 500,
sources: [
{
url: 'https://example.com/fonts/roboto-medium.woff2',
format: 'woff2',
},
],
},
{
weight: 700,
sources: [
{
url: 'https://example.com/fonts/roboto-bold.woff2',
format: 'woff2',
},
],
},
{
weight: 900,
sources: [
{
url: 'https://example.com/fonts/roboto-black.woff2',
format: 'woff2',
},
],
},
],
permissions: {
edit: false,
}, },
};
multiSource: { const TEST_FONTS_MULTI_SOURCE: CustomizationFontDefinition = {
id: 'lato', id: 'lato',
custom: true, custom: true,
fontFamily: 'Lato', fontFamily: 'Lato',
fontFaces: [ fontFaces: [
{ {
weight: 400, weight: 400,
sources: [ sources: [
{ {
url: 'https://example.com/fonts/lato-regular.woff2', url: 'https://example.com/fonts/lato-regular.woff2',
format: 'woff2', format: 'woff2',
}, },
{ url: 'https://example.com/fonts/lato-regular.woff', format: 'woff' }, { url: 'https://example.com/fonts/lato-regular.woff', format: 'woff' },
], ],
},
],
permissions: {
edit: false,
}, },
],
permissions: {
edit: false,
}, },
};
missingFormat: { const TEST_FONTS_MISSING_FORMAT: CustomizationFontDefinition = {
id: 'source-sans', id: 'source-sans',
custom: true, custom: true,
fontFamily: 'Source Sans Pro', fontFamily: 'Source Sans Pro',
fontFaces: [ fontFaces: [
{ {
weight: 400, weight: 400,
sources: [ sources: [
{ url: 'https://example.com/fonts/sourcesans-regular.woff2' }, { url: 'https://example.com/fonts/sourcesans-regular.woff2' },
{ {
url: 'https://example.com/fonts/sourcesans-regular.woff', url: 'https://example.com/fonts/sourcesans-regular.woff',
format: 'woff', format: 'woff',
}, },
], ],
},
],
permissions: {
edit: false,
}, },
],
permissions: {
edit: false,
}, },
};
empty: { const TEST_FONTS_EMPTY: CustomizationFontDefinition = {
id: 'empty-font', id: 'empty-font',
custom: true, custom: true,
fontFamily: 'Empty Font', fontFamily: 'Empty Font',
fontFaces: [], fontFaces: [],
permissions: { permissions: {
edit: false, edit: false,
},
}, },
};
specialChars: { const TEST_FONTS_SPECIAL_CHARS: CustomizationFontDefinition = {
id: 'special-font', id: 'special-font',
custom: true, custom: true,
fontFamily: 'Special Font & Co.', fontFamily: 'Special Font & Co.',
fontFaces: [ fontFaces: [
{ {
weight: 400, weight: 400,
sources: [{ url: 'https://example.com/fonts/special.woff2', format: 'woff2' }], sources: [{ url: 'https://example.com/fonts/special.woff2', format: 'woff2' }],
},
],
permissions: {
edit: false,
}, },
],
permissions: {
edit: false,
}, },
};
complex: { const TEST_FONTS_COMPLEX: CustomizationFontDefinition = {
id: 'complex-font', id: 'complex-font',
custom: true, custom: true,
fontFamily: 'Complex Font', fontFamily: 'Complex Font',
fontFaces: [ fontFaces: [
{ {
weight: 400, weight: 400,
sources: [ sources: [
{ url: 'https://example.com/fonts/regular.woff2' }, { url: 'https://example.com/fonts/regular.woff2' },
{ url: 'https://example.com/fonts/regular.woff' }, { url: 'https://example.com/fonts/regular.woff' },
], ],
},
{
weight: 700,
sources: [
{ url: 'https://example.com/fonts/bold.woff2' },
{ url: 'https://example.com/fonts/bold.woff' },
],
},
],
permissions: {
edit: false,
}, },
}, {
weight: 700,
variousURLs: { sources: [
id: 'various-urls', { url: 'https://example.com/fonts/bold.woff2' },
custom: true, { url: 'https://example.com/fonts/bold.woff' },
fontFamily: 'Various URLs Font', ],
fontFaces: [
{
weight: 400,
sources: [
{ url: 'https://example.com/fonts.woff2' },
{ url: 'https://example.com/fonts.woff' },
{ url: 'https://example.com/fonts.woff2' },
],
},
],
permissions: {
edit: false,
}, },
],
permissions: {
edit: false,
}, },
}; };
@@ -229,7 +208,7 @@ async function isCSSValid(css: string): Promise<boolean> {
describe('generateFontFacesCSS', () => { describe('generateFontFacesCSS', () => {
test('basic case with regular and bold weights', async () => { test('basic case with regular and bold weights', async () => {
const css = generateFontFacesCSS(TEST_FONTS.basic, 'content'); const css = generateFontFacesCSS(TEST_FONTS_BASIC, 'content');
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
expect(isValid).toBe(true); expect(isValid).toBe(true);
@@ -244,7 +223,7 @@ describe('generateFontFacesCSS', () => {
}); });
test('mono type', async () => { test('mono type', async () => {
const css = generateFontFacesCSS(TEST_FONTS.basic, 'mono'); const css = generateFontFacesCSS(TEST_FONTS_BASIC, 'mono');
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
expect(isValid).toBe(true); expect(isValid).toBe(true);
@@ -259,7 +238,7 @@ describe('generateFontFacesCSS', () => {
}); });
test('multiple font weights', async () => { test('multiple font weights', async () => {
const css = generateFontFacesCSS(TEST_FONTS.multiWeight, 'content'); const css = generateFontFacesCSS(TEST_FONTS_MULTI_WEIGHT, 'content');
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
expect(isValid).toBe(true); expect(isValid).toBe(true);
@@ -270,7 +249,7 @@ describe('generateFontFacesCSS', () => {
}); });
test('multiple sources for a single weight', async () => { test('multiple sources for a single weight', async () => {
const css = generateFontFacesCSS(TEST_FONTS.multiSource, 'content'); const css = generateFontFacesCSS(TEST_FONTS_MULTI_SOURCE, 'content');
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
expect(isValid).toBe(true); expect(isValid).toBe(true);
@@ -281,7 +260,7 @@ describe('generateFontFacesCSS', () => {
}); });
test('missing format property', async () => { test('missing format property', async () => {
const css = generateFontFacesCSS(TEST_FONTS.missingFormat, 'content'); const css = generateFontFacesCSS(TEST_FONTS_MISSING_FORMAT, 'content');
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
expect(isValid).toBe(true); expect(isValid).toBe(true);
@@ -292,13 +271,13 @@ describe('generateFontFacesCSS', () => {
}); });
test('empty font faces array', async () => { test('empty font faces array', async () => {
const css = generateFontFacesCSS(TEST_FONTS.empty, 'content'); const css = generateFontFacesCSS(TEST_FONTS_EMPTY, 'content');
expect(css).toBe(''); expect(css).toBe('');
}); });
test('font with special characters in name', async () => { test('font with special characters in name', async () => {
const css = generateFontFacesCSS(TEST_FONTS.specialChars, 'content'); const css = generateFontFacesCSS(TEST_FONTS_SPECIAL_CHARS, 'content');
// Validate CSS syntax // Validate CSS syntax
const isValid = await isCSSValid(css); const isValid = await isCSSValid(css);
@@ -308,13 +287,13 @@ describe('generateFontFacesCSS', () => {
describe('getFontSourcesToPreload', () => { describe('getFontSourcesToPreload', () => {
const preloadTestCases = [ const preloadTestCases = [
{ name: 'basic case', font: TEST_FONTS.basic, expectedCount: 2 }, { name: 'basic case', font: TEST_FONTS_BASIC, expectedCount: 2 },
{ name: 'multiple weights', font: TEST_FONTS.multiWeight, expectedCount: 2 }, { name: 'multiple weights', font: TEST_FONTS_MULTI_WEIGHT, expectedCount: 2 },
{ name: 'multiple sources', font: TEST_FONTS.multiSource, expectedCount: 2 }, { name: 'multiple sources', font: TEST_FONTS_MULTI_SOURCE, expectedCount: 2 },
{ name: 'missing format', font: TEST_FONTS.missingFormat, expectedCount: 2 }, { name: 'missing format', font: TEST_FONTS_MISSING_FORMAT, expectedCount: 2 },
{ name: 'empty font faces', font: TEST_FONTS.empty, expectedCount: 0 }, { name: 'empty font faces', font: TEST_FONTS_EMPTY, expectedCount: 0 },
{ name: 'special characters', font: TEST_FONTS.specialChars, expectedCount: 1 }, { name: 'special characters', font: TEST_FONTS_SPECIAL_CHARS, expectedCount: 1 },
{ name: 'complex case', font: TEST_FONTS.complex, expectedCount: 4 }, { name: 'complex case', font: TEST_FONTS_COMPLEX, expectedCount: 4 },
]; ];
preloadTestCases.forEach(({ name, font, expectedCount }) => { preloadTestCases.forEach(({ name, font, expectedCount }) => {
+1 -1
View File
@@ -121,7 +121,7 @@ const raleway = Raleway({
}); });
const roboto = Roboto({ const roboto = Roboto({
weight: ['400', '500', '700'], weight: ['400', '500', '600', '700'],
variable: '--font-content', variable: '--font-content',
preload: false, preload: false,
display: 'swap', display: 'swap',
+31 -8
View File
@@ -1,25 +1,44 @@
import type { SiteCustomizationSettings } from '@gitbook/api'; import type { GitBookAnyContext } from '@/lib/context';
import { type TranslationLanguage, languages } from './translations'; import { type TranslationLanguage, languages } from './translations';
export * from './translate'; export * from './translate';
export const DEFAULT_LOCALE = 'en'; type TranslationLocale = keyof typeof languages;
export const DEFAULT_LOCALE = 'en' satisfies TranslationLocale;
/** /**
* Get the locale of the customization. * Get the locale to use for a space.
*/ */
export function getCustomizationLocale(customization: SiteCustomizationSettings): string { export function getSpaceLocale(context: GitBookAnyContext): TranslationLocale {
return customization.internationalization.locale; const { space } = context;
const customization = 'site' in context ? context.customization : null;
// If the language is configured in the space, use it in priority
if (space.language) {
if (checkIsValidLocale(space.language)) {
return space.language;
}
return DEFAULT_LOCALE;
}
// Otherwise fallback to the deprecated customization settings
if (customization) {
return checkIsValidLocale(customization.internationalization.locale)
? customization.internationalization.locale
: DEFAULT_LOCALE;
}
return DEFAULT_LOCALE;
} }
/** /**
* Create the translation context for a space to use in the server components. * Create the translation context for a space to use in the server components.
*/ */
export function getSpaceLanguage(customization: SiteCustomizationSettings): TranslationLanguage { export function getSpaceLanguage(context: GitBookAnyContext): TranslationLanguage {
const fallback = languages[DEFAULT_LOCALE]; const fallback = languages[DEFAULT_LOCALE];
const locale = getCustomizationLocale(customization); const locale = getSpaceLocale(context);
let language = fallback; let language = fallback;
// @ts-ignore // @ts-ignore
@@ -33,3 +52,7 @@ export function getSpaceLanguage(customization: SiteCustomizationSettings): Tran
...language, ...language,
}; };
} }
function checkIsValidLocale(locale: string): locale is TranslationLocale {
return locale in languages;
}
+1
View File
@@ -28,6 +28,7 @@ export function t(
const [partToPush, partToReplace] = currentStringToReplace.split(`\${${i + 1}}`); const [partToPush, partToReplace] = currentStringToReplace.split(`\${${i + 1}}`);
parts.push(<React.Fragment key={`string-${i}`}>{partToPush}</React.Fragment>); parts.push(<React.Fragment key={`string-${i}`}>{partToPush}</React.Fragment>);
parts.push(<React.Fragment key={`arg-${i}`}>{arg}</React.Fragment>); parts.push(<React.Fragment key={`arg-${i}`}>{arg}</React.Fragment>);
// @ts-expect-error
currentStringToReplace = partToReplace; currentStringToReplace = partToReplace;
} }
}); });
@@ -48,6 +48,7 @@ export const de = {
close: 'Schließen', close: 'Schließen',
view: 'Anzeigen', view: 'Anzeigen',
edit_on_git: 'Bearbeiten auf ${1}', edit_on_git: 'Bearbeiten auf ${1}',
edit: 'Bearbeiten',
notfound_title: 'Seite nicht gefunden', notfound_title: 'Seite nicht gefunden',
notfound_link: notfound_link:
'Dieser Link verweist auf eine Seite, die entfernt wurde oder nicht mehr existiert.', 'Dieser Link verweist auf eine Seite, die entfernt wurde oder nicht mehr existiert.',
@@ -81,6 +82,8 @@ export const de = {
ai_chat_working: 'Arbeite...', ai_chat_working: 'Arbeite...',
ai_chat_context_badge: 'KI', ai_chat_context_badge: 'KI',
ai_chat_error: 'Etwas ist schief gelaufen.', ai_chat_error: 'Etwas ist schief gelaufen.',
ai_chat_hold_message_1: 'Überlege es mir durch…',
ai_chat_hold_message_2: 'Einen Moment…',
ai_chat_context_title: 'Basierend auf Ihrem Kontext', ai_chat_context_title: 'Basierend auf Ihrem Kontext',
ai_chat_context_description: ai_chat_context_description:
'Der Assistent verwendet KI und Ihren Kontext, um Antworten zu generieren und Aktionen durchzuführen.', 'Der Assistent verwendet KI und Ihren Kontext, um Antworten zu generieren und Aktionen durchzuführen.',

Some files were not shown because too many files have changed in this diff Show More