diff --git a/.gitignore b/.gitignore index 514308770..5aeef2348 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ web_modules/ .env.test.local .env.production.local .env.local -.contentlayer \ No newline at end of file +.contentlayer +sites/docs/.velite \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index b261fb449..6d7f39df8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,6 +15,7 @@ yarn.lock package.json .vercel .contentlayer +.velite **/dist CHANGELOG.md diff --git a/eslint.config.js b/eslint.config.js index 1492bd7e2..102aa1933 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,6 @@ import config, { DEFAULT_IGNORES } from "@huntabyte/eslint-config"; -const ignores = ["**/extended-types"]; +const ignores = ["**/extended-types", "**/.velite"]; export default config({ svelte: true, ignores: [...DEFAULT_IGNORES, ...ignores] }) .override("antfu/typescript/rules", { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46fe0b9cd..111ceb316 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,13 +74,13 @@ importers: devDependencies: '@sveltejs/kit': specifier: ^2.5.28 - version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) '@sveltejs/package': specifier: ^2.3.5 version: 2.3.5(svelte@5.0.0-next.260)(typescript@5.6.2) '@sveltejs/vite-plugin-svelte': specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) '@types/node': specifier: ^20.14.10 version: 20.14.10 @@ -113,10 +113,10 @@ importers: version: 5.6.2 vite: specifier: ^5.4.6 - version: 5.4.6(@types/node@20.14.10) + version: 5.4.6(@types/node@20.14.10)(terser@5.34.1) vitest: specifier: ^2.1.1 - version: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + version: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) packages/tests: dependencies: @@ -129,22 +129,22 @@ importers: devDependencies: '@sveltejs/adapter-auto': specifier: ^3.0.0 - version: 3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))) + version: 3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))) '@sveltejs/kit': specifier: ^2.0.0 - version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) '@sveltejs/vite-plugin-svelte': specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) '@testing-library/dom': specifier: ^10.3.1 version: 10.3.1 '@testing-library/jest-dom': specifier: ^6.4.6 - version: 6.4.6(@types/jest@29.5.12)(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)) + version: 6.4.6(@types/jest@29.5.12)(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1)) '@testing-library/svelte': specifier: ^5.2.1 - version: 5.2.1(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)) + version: 5.2.1(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1)) '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@10.3.1) @@ -180,10 +180,10 @@ importers: version: 5.6.2 vite: specifier: ^5.4.6 - version: 5.4.6(@types/node@20.14.10) + version: 5.4.6(@types/node@20.14.10)(terser@5.34.1) vitest: specifier: ^2.1.1 - version: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + version: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) sites/docs: dependencies: @@ -208,13 +208,13 @@ importers: version: 0.3.0(prettier@3.3.2) '@sveltejs/adapter-cloudflare': specifier: ^4.2.0 - version: 4.6.1(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(wrangler@3.64.0(@cloudflare/workers-types@4.20240701.0)) + version: 4.6.1(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(wrangler@3.64.0(@cloudflare/workers-types@4.20240701.0)) '@sveltejs/kit': specifier: ^2.5.28 - version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) '@sveltejs/vite-plugin-svelte': specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + version: 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) '@tailwindcss/typography': specifier: ^0.5.10 version: 0.5.13(tailwindcss@3.4.4) @@ -239,9 +239,6 @@ importers: concurrently: specifier: ^8.2.2 version: 8.2.2 - contentlayer: - specifier: ^0.3.4 - version: 0.3.4(esbuild@0.23.0) eruda: specifier: ^3.0.1 version: 3.1.0 @@ -314,9 +311,12 @@ importers: unist-util-visit: specifier: ^5.0.0 version: 5.0.0 + velite: + specifier: ^0.1.1 + version: 0.1.1 vite: specifier: ^5.2.8 - version: 5.3.3(@types/node@20.14.10) + version: 5.3.3(@types/node@20.14.10)(terser@5.34.1) packages: @@ -515,72 +515,12 @@ packages: '@cloudflare/workers-types@4.20240701.0': resolution: {integrity: sha512-6Cu6NIAicmb8H6CkzFdQG5Ib+TDs9HU8AKQEGlxnbvEBDmhUNpmL30ETXpLS0asdeyc+rTb2xag0hSv0Z1BflQ==} - '@contentlayer/cli@0.3.4': - resolution: {integrity: sha512-vNDwgLuhYNu+m70NZ3XK9kexKNguuxPXg7Yvzj3B34cEilQjjzSrcTY/i+AIQm9V7uT5GGshx9ukzPf+SmoszQ==} - - '@contentlayer/client@0.3.4': - resolution: {integrity: sha512-QSlLyc3y4PtdC5lFw0L4wTZUH8BQnv2nk37hNCsPAqGf+dRO7TLAzdc+2/mVIRgK+vSH+pSOzjLsQpFxxXRTZA==} - - '@contentlayer/core@0.3.4': - resolution: {integrity: sha512-o68oBLwfYZ+2vtgfk1lgHxOl3LoxvRNiUfeQ8IWFWy/L4wnIkKIqLZX01zlRE5IzYM+ZMMN5V0cKQlO7DsyR9g==} - peerDependencies: - esbuild: 0.17.x || 0.18.x - markdown-wasm: 1.x - peerDependenciesMeta: - esbuild: - optional: true - markdown-wasm: - optional: true - - '@contentlayer/source-files@0.3.4': - resolution: {integrity: sha512-4njyn0OFPu7WY4tAjMxiJgWOKeiHuBOGdQ36EYE03iij/pPPRbiWbL+cmLccYXUFEW58mDwpqROZZm6pnxjRDQ==} - - '@contentlayer/source-remote-files@0.3.4': - resolution: {integrity: sha512-cyiv4sNUySZvR0uAKlM+kSAELzNd2h2QT1R2e41dRKbwOUVxeLfmGiLugr0aVac6Q3xYcD99dbHyR1xWPV+w9w==} - - '@contentlayer/utils@0.3.4': - resolution: {integrity: sha512-ZWWOhbUWYQ2QHoLIlcUnEo7X4ZbwcyFPuzVQWWMkK43BxCveyQtZwBIzfyx54sqVzi0GUmKP8bHzsLQT0QxaLQ==} - peerDependencies: - '@effect-ts/otel-node': '*' - peerDependenciesMeta: - '@effect-ts/otel-node': - optional: true - '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@effect-ts/core@0.60.5': - resolution: {integrity: sha512-qi1WrtJA90XLMnj2hnUszW9Sx4dXP03ZJtCc5DiUBIOhF4Vw7plfb65/bdBySPoC9s7zy995TdUX1XBSxUkl5w==} - - '@effect-ts/otel-exporter-trace-otlp-grpc@0.15.1': - resolution: {integrity: sha512-47gAg0O2pW5Jlo86jfzjdkwL5a7Bzb+Kj5WTmdu4CxYRfWn9ytKjuuYIfsNDW8neuhdKzn+P5wCddgEh0glYyQ==} - peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/exporter-trace-otlp-grpc': ^0.39.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 - - '@effect-ts/otel-sdk-trace-node@0.15.1': - resolution: {integrity: sha512-a2sF0ylmn8xOJs8fNeT/spJ1gUcsksAJCALxo9WOfuTCMtTwMVtVhCKEPEeQoL7wFqU+JgPkVdP91+FJ/Rkeow==} - peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 - '@opentelemetry/sdk-trace-node': ^1.13.0 - - '@effect-ts/otel@0.15.1': - resolution: {integrity: sha512-AmZJHl7t0+Peh7Yb2+hqn6r9+rd9/UfeA4AMV9h0YGTdOyouyFfD3wzWlxnAUzAQ4Lrod4kC7Noruret4EpqpA==} - peerDependencies: - '@effect-ts/core': ^0.60.2 - '@opentelemetry/api': ^1.4.0 - '@opentelemetry/core': ^1.13.0 - '@opentelemetry/sdk-trace-base': ^1.13.0 - - '@effect-ts/system@0.57.5': - resolution: {integrity: sha512-/crHGujo0xnuHIYNc1VgP0HGJGFSoSqq88JFXe6FmFyXPpWt8Xu39LyLg7rchsxfXFeEdA9CrIZvLV5eswXV5g==} + '@emnapi/runtime@1.3.0': + resolution: {integrity: sha512-XMBySMuNZs3DM96xcJmLW4EfGnf+uGmFNjzpehMjuX5PLB5j87ar2Zc4e3PVeZ3I5g3tYtAqskB28manlF69Zw==} '@es-joy/jsdoccomment@0.43.1': resolution: {integrity: sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==} @@ -600,11 +540,6 @@ packages: peerDependencies: esbuild: '*' - '@esbuild-plugins/node-resolve@0.1.4': - resolution: {integrity: sha512-haFQ0qhxEpqtWWY0kx1Y5oE3sMyO1PcoSiWEPrAw6tm/ZOOLXjSs6Q+v1v9eyuVF0nNt50YEvrcrvENmyoMv5g==} - peerDependencies: - esbuild: '*' - '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -1045,9 +980,6 @@ packages: resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@fal-works/esbuild-plugin-global-externals@2.1.2': - resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} - '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} @@ -1061,15 +993,6 @@ packages: '@floating-ui/utils@0.2.4': resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==} - '@grpc/grpc-js@1.10.11': - resolution: {integrity: sha512-3RaoxOqkHHN2c05bwtBNVJmOf/UwMam0rZYtdl7dsRpsvDwcNpv6LkGgzltQ7xVf822LzBoKEPRvf4D7+xeIDw==} - engines: {node: '>=12.10.0'} - - '@grpc/proto-loader@0.7.13': - resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} - engines: {node: '>=6'} - hasBin: true - '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -1091,6 +1014,111 @@ packages: peerDependencies: eslint: '*' + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@internationalized/date@3.5.6': resolution: {integrity: sha512-jLxQjefH9VI5P9UQuqB6qNKnvFt1Ky1TPIzHGsIlCi7sZZoMR8SdYbBGRvM0y+Jtb+ez4ieBzmiAUcpmPYpyOw==} @@ -1122,6 +1150,9 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} @@ -1131,13 +1162,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@js-sdsl/ordered-map@4.4.2': - resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} - - '@js-temporal/polyfill@0.4.4': - resolution: {integrity: sha512-2X6bvghJ/JAoZO52lbgyAPFj8uCflhTo2g7nkFzEQdXd/D8rEeD4HtmTEpmtGCva260fcd66YNXBOYdnmHqSOg==} - engines: {node: '>=12'} - '@jsdevtools/ez-spawn@3.0.4': resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==} engines: {node: '>=10'} @@ -1148,13 +1172,8 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@mdx-js/esbuild@2.3.0': - resolution: {integrity: sha512-r/vsqsM0E+U4Wr0DK+0EfmABE/eg+8ITW4DjvYdh3ve/tK2safaqHArNnaqbOk1DjYGrhxtoXoGaM3BY8fGBTA==} - peerDependencies: - esbuild: '>=0.11.0' - - '@mdx-js/mdx@2.3.0': - resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} + '@mdx-js/mdx@3.0.1': + resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==} '@melt-ui/pp@0.3.2': resolution: {integrity: sha512-xKkPvaIAFinklLXcQOpwZ8YSpqAFxykjWf8Y/fSJQwsixV/0rcFs07hJ49hJjPy5vItvw5Qa0uOjzFUbXzBypQ==} @@ -1179,119 +1198,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@opentelemetry/api-logs@0.39.1': - resolution: {integrity: sha512-9BJ8lMcOzEN0lu+Qji801y707oFO4xT3db6cosPvl+k7ItUHKN5ofWqtSbM9gbt1H4JJ/4/2TVrqI9Rq7hNv6Q==} - engines: {node: '>=14'} - - '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} - engines: {node: '>=8.0.0'} - - '@opentelemetry/context-async-hooks@1.25.1': - resolution: {integrity: sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/core@1.13.0': - resolution: {integrity: sha512-2dBX3Sj99H96uwJKvc2w9NOiNgbvAO6mOFJFramNkKfS9O4Um+VWgpnlAazoYjT6kUJ1MP70KQ5ngD4ed+4NUw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.5.0' - - '@opentelemetry/core@1.25.1': - resolution: {integrity: sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/exporter-trace-otlp-grpc@0.39.1': - resolution: {integrity: sha512-l5RhLKx6U+yuLhMrtgavTDthX50E1mZM3/SSySC7OPZiArFHV/b/9x9jxAzrOgIQUDxyj4N0V9aLKSA2t7Qzxg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/otlp-exporter-base@0.39.1': - resolution: {integrity: sha512-Pv5X8fbi6jD/RJBePyn7MnCSuE6MbPB6dl+7YYBWJ5RcMGYMwvLXjd4h2jWsPV2TSUg38H/RoSP0aXvQ06Y7iw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/otlp-grpc-exporter-base@0.39.1': - resolution: {integrity: sha512-u3ErFRQqQFKjjIMuwLWxz/tLPYInfmiAmSy//fGSCzCh2ZdJgqQjMOAxBgqFtCF2xFL+OmMhyuC2ThMzceGRWA==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/otlp-transformer@0.39.1': - resolution: {integrity: sha512-0hgVnXXz5efI382B/24NxD4b6Zxlh7nxCdJkxkdmQMbn0yRiwoq/ZT+QG8eUL6JNzsBAV1WJlF5aJNsL8skHvw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.5.0' - - '@opentelemetry/propagator-b3@1.25.1': - resolution: {integrity: sha512-p6HFscpjrv7//kE+7L+3Vn00VEDUJB0n6ZrjkTYHrJ58QZ8B3ajSJhRbCcY6guQ3PDjTbxWklyvIN2ojVbIb1A==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/propagator-jaeger@1.25.1': - resolution: {integrity: sha512-nBprRf0+jlgxks78G/xq72PipVK+4or9Ypntw0gVZYNTCSK8rg5SeaGV19tV920CMqBD/9UIOiFr23Li/Q8tiA==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/resources@1.13.0': - resolution: {integrity: sha512-euqjOkiN6xhjE//0vQYGvbStxoD/WWQRhDiO0OTLlnLBO9Yw2Gd/VoSx2H+svsebjzYk5OxLuREBmcdw6rbUNg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.5.0' - - '@opentelemetry/resources@1.25.1': - resolution: {integrity: sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/sdk-logs@0.39.1': - resolution: {integrity: sha512-/gmgKfZ1ZVFporKuwsewqIyvaUIGpv76JZ7lBpHQQPb37IMpaXO6pdqFI4ebHAWfNIm3akMyhmdtzivcgF3lgw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.4.0 <1.5.0' - '@opentelemetry/api-logs': '>=0.38.0' - - '@opentelemetry/sdk-metrics@1.13.0': - resolution: {integrity: sha512-MOjZX6AnSOqLliCcZUrb+DQKjAWXBiGeICGbHAGe5w0BB18PJIeIo995lO5JSaFfHpmUMgJButTPfJJD27W3Vg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.5.0' - - '@opentelemetry/sdk-trace-base@1.13.0': - resolution: {integrity: sha512-moTiQtc0uPR1hQLt6gLDJH9IIkeBhgRb71OKjNHZPE1VF45fHtD6nBDi5J/DkTHTwYP5X3kBJLa3xN7ub6J4eg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.5.0' - - '@opentelemetry/sdk-trace-base@1.25.1': - resolution: {integrity: sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/sdk-trace-node@1.25.1': - resolution: {integrity: sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.10.0' - - '@opentelemetry/semantic-conventions@1.13.0': - resolution: {integrity: sha512-LMGqfSZkaMQXqewO0o1wvWr/2fQdCh4a3Sqlxka/UsJCe0cfLulh6x2aqnKLnsrSGiCq5rSCwvINd152i0nCqw==} - engines: {node: '>=14'} - - '@opentelemetry/semantic-conventions@1.25.1': - resolution: {integrity: sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==} - engines: {node: '>=14'} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1308,36 +1214,6 @@ packages: peerDependencies: prettier: ^3.0.0 - '@protobufjs/aspromise@1.1.2': - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - - '@protobufjs/base64@1.1.2': - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - - '@protobufjs/codegen@2.0.4': - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - - '@protobufjs/eventemitter@1.1.0': - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - - '@protobufjs/fetch@1.1.0': - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - - '@protobufjs/float@1.0.2': - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - - '@protobufjs/inquire@1.1.0': - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - - '@protobufjs/path@1.1.2': - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - - '@protobufjs/pool@1.1.0': - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - - '@protobufjs/utf8@1.1.0': - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@rollup/rollup-android-arm-eabi@4.18.1': resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==} cpu: [arm] @@ -1652,9 +1528,6 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/hast@2.3.10': - resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -1700,15 +1573,9 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/parse5@6.0.3': - resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} - '@types/resize-observer-browser@0.1.11': resolution: {integrity: sha512-cNw5iH8JkMkb3QkCoe7DaZiawbDQEUX8t7iuQaRTyLOyQCR2h+ibBD4GJt7p5yhUHrlOeL7ZtbxNHeipqNsBzQ==} - '@types/resolve@1.20.6': - resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -2006,9 +1873,6 @@ packages: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} - array-timsort@1.0.3: - resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -2099,9 +1963,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} @@ -2187,11 +2048,6 @@ packages: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - clipanion@3.2.1: - resolution: {integrity: sha512-dYFdjLb7y1ajfxQopN05mylEpK9ZX0sO1/RfMXdfmwjlIsPkbh4p7A682x++zFPLDCo1x3p82dtljHf5cW2LKA==} - peerDependencies: - typanion: '*' - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2200,6 +2056,9 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -2213,6 +2072,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2220,14 +2086,13 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - comment-json@4.2.4: - resolution: {integrity: sha512-E5AjpSW+O+N5T2GsOQMHLLsJvrYw6G/AFt9GvU6NguEAfzKShh7hRiLtVo6S9KbRpFMGqE5ojo0/hE+sdteWvQ==} - engines: {node: '>= 6'} - comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -2247,11 +2112,6 @@ packages: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} engines: {node: ^14.18.0 || >=16.10.0} - contentlayer@0.3.4: - resolution: {integrity: sha512-FYDdTUFaN4yqep0waswrhcXjmMJnPD5iXDTtxcUCGdklfuIrXM2xLx51xl748cHmGA6IsC+27YZFxU6Ym13QIA==} - engines: {node: '>=14.18'} - hasBin: true - cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} @@ -2263,9 +2123,6 @@ packages: core-js-compat@3.37.1: resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -2291,10 +2148,6 @@ packages: data-uri-to-buffer@2.0.2: resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} - data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -2370,6 +2223,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + devalue@5.1.1: resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} @@ -2383,10 +2240,6 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -2695,27 +2548,20 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-util-attach-comments@2.1.1: - resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==} + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} - estree-util-build-jsx@2.2.2: - resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==} + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} - estree-util-is-identifier-name@1.1.0: - resolution: {integrity: sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ==} + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - estree-util-is-identifier-name@2.1.0: - resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==} + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} - estree-util-to-js@1.2.0: - resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==} - - estree-util-value-to-estree@1.3.0: - resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==} - engines: {node: '>=12.0.0'} - - estree-util-visit@1.2.1: - resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==} + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} estree-walker@0.6.1: resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} @@ -2738,10 +2584,6 @@ packages: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -2768,9 +2610,6 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fault@2.0.1: - resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} - fdir@6.3.0: resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==} peerDependencies: @@ -2779,10 +2618,6 @@ packages: picomatch: optional: true - fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -2830,14 +2665,6 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} - format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - - formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -2849,9 +2676,6 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} - fs-monkey@1.0.6: - resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2927,10 +2751,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} - has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -2939,13 +2759,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-own-prop@2.0.0: - resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} - engines: {node: '>=8'} - - hash-wasm@4.11.0: - resolution: {integrity: sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -2953,38 +2766,26 @@ packages: hast-util-from-html@2.0.1: resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} - hast-util-from-parse5@7.1.2: - resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} - hast-util-from-parse5@8.0.1: resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} hast-util-heading-rank@3.0.0: resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} - hast-util-parse-selector@3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} - hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} - hast-util-raw@7.2.3: - resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==} - hast-util-raw@9.0.4: resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} - hast-util-to-estree@2.3.3: - resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==} - - hast-util-to-html@8.0.4: - resolution: {integrity: sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==} + hast-util-to-estree@3.1.0: + resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} hast-util-to-html@9.0.1: resolution: {integrity: sha512-hZOofyZANbyWo+9RP75xIDV/gq+OUKx+T46IlwERnKmfpwp81XBFbT9mi26ws+SJchA4RVUQwIBJpqEOBhMzEQ==} - hast-util-to-parse5@7.1.0: - resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==} + hast-util-to-jsx-runtime@2.3.0: + resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} hast-util-to-parse5@8.0.0: resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} @@ -2992,15 +2793,9 @@ packages: hast-util-to-string@3.0.0: resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} - hast-util-whitespace@2.0.1: - resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} - hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - hastscript@7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} - hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} @@ -3011,9 +2806,6 @@ packages: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} - html-void-elements@2.0.1: - resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} - html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -3044,10 +2836,6 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - imagescript@1.3.0: - resolution: {integrity: sha512-lCYzQrWzdnA68K03oMj/BUlBJrVBnslzDOgGFymAp49NmdGEJxGeN7sHh5mCva0nQkq+kkKSuru2zLf1m04+3A==} - engines: {node: '>=14.0.0'} - import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -3063,10 +2851,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - inflection@2.0.1: - resolution: {integrity: sha512-wzkZHqpb4eGrOKBl34xy3umnYHx8Si5R1U4fwmdxLo5gdH6mEK8gclckTj/qWqy4Je0bsDYe/qazZYuO7xe3XQ==} - engines: {node: '>=14.0.0'} - inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -3095,14 +2879,13 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -3117,10 +2900,6 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3147,10 +2926,6 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - is-plain-obj@3.0.0: - resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} - engines: {node: '>=10'} - is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -3218,9 +2993,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbi@4.3.0: - resolution: {integrity: sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==} - jsdoc-type-pratt-parser@4.0.0: resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} engines: {node: '>=12.0.0'} @@ -3265,10 +3037,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -3314,9 +3082,6 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - lodash.castarray@4.4.0: resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} @@ -3332,9 +3097,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -3363,9 +3125,9 @@ packages: magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} - markdown-extensions@1.1.1: - resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} - engines: {node: '>=0.10.0'} + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} @@ -3375,24 +3137,15 @@ packages: engines: {node: '>= 18'} hasBin: true - mdast-util-definitions@5.1.2: - resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} - mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} mdast-util-from-markdown@0.8.5: resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} - mdast-util-from-markdown@1.3.1: - resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} - mdast-util-from-markdown@2.0.1: resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} - mdast-util-frontmatter@1.0.1: - resolution: {integrity: sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==} - mdast-util-gfm-autolink-literal@2.0.0: resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} @@ -3411,42 +3164,30 @@ packages: mdast-util-gfm@3.0.0: resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} - mdast-util-mdx-expression@1.3.2: - resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==} - - mdast-util-mdx-jsx@2.1.4: - resolution: {integrity: sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==} + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - mdast-util-mdx@2.0.1: - resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==} + mdast-util-mdx-jsx@3.1.3: + resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} - mdast-util-mdxjs-esm@1.3.1: - resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==} + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} - mdast-util-phrasing@3.0.1: - resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - mdast-util-to-hast@12.3.0: - resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} - mdast-util-to-hast@13.2.0: resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} - mdast-util-to-markdown@1.5.0: - resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} - mdast-util-to-markdown@2.1.0: resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} mdast-util-to-string@2.0.0: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} - mdast-util-to-string@3.2.0: - resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} - mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} @@ -3455,29 +3196,13 @@ packages: peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.1 - mdx-bundler@9.2.1: - resolution: {integrity: sha512-hWEEip1KU9MCNqeH2rqwzAZ1pdqPPbfkx9OTJjADqGPQz4t9BO85fhI7AP9gVYrpmfArf9/xJZUN0yBErg/G/Q==} - engines: {node: '>=14', npm: '>=6'} - peerDependencies: - esbuild: 0.* - - memfs@3.5.3: - resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} - engines: {node: '>= 4.0.0'} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromark-core-commonmark@1.1.0: - resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} - micromark-core-commonmark@2.0.1: resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} - micromark-extension-frontmatter@1.1.1: - resolution: {integrity: sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==} - micromark-extension-gfm-autolink-literal@2.1.0: resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} @@ -3499,147 +3224,87 @@ packages: micromark-extension-gfm@3.0.0: resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - micromark-extension-mdx-expression@1.0.8: - resolution: {integrity: sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==} - - micromark-extension-mdx-jsx@1.0.5: - resolution: {integrity: sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==} + micromark-extension-mdx-expression@3.0.0: + resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} - micromark-extension-mdx-md@1.0.1: - resolution: {integrity: sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==} + micromark-extension-mdx-jsx@3.0.1: + resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} - micromark-extension-mdxjs-esm@1.0.5: - resolution: {integrity: sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==} + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} - micromark-extension-mdxjs@1.0.1: - resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==} + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} - micromark-factory-destination@1.1.0: - resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} micromark-factory-destination@2.0.0: resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} - micromark-factory-label@1.1.0: - resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} - micromark-factory-label@2.0.0: resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} - micromark-factory-mdx-expression@1.0.9: - resolution: {integrity: sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==} - - micromark-factory-space@1.1.0: - resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} + micromark-factory-mdx-expression@2.0.2: + resolution: {integrity: sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==} micromark-factory-space@2.0.0: resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} - micromark-factory-title@1.1.0: - resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} - micromark-factory-title@2.0.0: resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} - micromark-factory-whitespace@1.1.0: - resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} - micromark-factory-whitespace@2.0.0: resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} - micromark-util-character@1.2.0: - resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} - micromark-util-character@2.1.0: resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} - micromark-util-chunked@1.1.0: - resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} - micromark-util-chunked@2.0.0: resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} - micromark-util-classify-character@1.1.0: - resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} - micromark-util-classify-character@2.0.0: resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} - micromark-util-combine-extensions@1.1.0: - resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} - micromark-util-combine-extensions@2.0.0: resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} - micromark-util-decode-numeric-character-reference@1.1.0: - resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} - micromark-util-decode-numeric-character-reference@2.0.1: resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} - micromark-util-decode-string@1.1.0: - resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} - micromark-util-decode-string@2.0.0: resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} - micromark-util-encode@1.1.0: - resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} - micromark-util-encode@2.0.0: resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} - micromark-util-events-to-acorn@1.2.3: - resolution: {integrity: sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==} - - micromark-util-html-tag-name@1.2.0: - resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} + micromark-util-events-to-acorn@2.0.2: + resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} micromark-util-html-tag-name@2.0.0: resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} - micromark-util-normalize-identifier@1.1.0: - resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} - micromark-util-normalize-identifier@2.0.0: resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} - micromark-util-resolve-all@1.1.0: - resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} - micromark-util-resolve-all@2.0.0: resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} - micromark-util-sanitize-uri@1.2.0: - resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} - micromark-util-sanitize-uri@2.0.0: resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} - micromark-util-subtokenize@1.1.0: - resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} - micromark-util-subtokenize@2.0.1: resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} - micromark-util-symbol@1.1.0: - resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} - micromark-util-symbol@2.0.0: resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} - micromark-util-types@1.1.0: - resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} - micromark-util-types@2.0.0: resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} - micromark@3.2.0: - resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} - micromark@4.0.0: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} @@ -3732,10 +3397,6 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} @@ -3748,10 +3409,6 @@ packages: encoding: optional: true - node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -3800,10 +3457,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - oo-ascii-tree@1.101.0: - resolution: {integrity: sha512-hNE9Nfvo4HLa9/dAiaiXUm64KHUvgBa7jPftsb8gZdTv1G1wSMMnd9j7SMcRzaMbDEqi+0cfgeBSIcsKy+k0vA==} - engines: {node: '>= 14.17.0'} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3879,9 +3532,6 @@ packages: parse-numeric-range@1.3.0: resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} - parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} @@ -4144,10 +3794,6 @@ packages: property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} - protobufjs@7.3.2: - resolution: {integrity: sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==} - engines: {node: '>=12.0.0'} - pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} @@ -4240,31 +3886,15 @@ packages: rehype-stringify@10.0.0: resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} - rehype-stringify@9.0.4: - resolution: {integrity: sha512-Uk5xu1YKdqobe5XpSskwPvo1XeHUUucWEQSl8hTrXt5selvca1e8K1EZ37E6YoZ4BT8BCqCdVfQW7OfHfthtVQ==} - - remark-frontmatter@4.0.1: - resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} - remark-gfm@4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} - remark-mdx-frontmatter@1.1.1: - resolution: {integrity: sha512-7teX9DW4tI2WZkXS4DBxneYSY7NHiXl4AKdWDO9LXVweULlCT8OPWsOjLEnMIXViN1j+QcY8mfbq3k0EK6x3uA==} - engines: {node: '>=12.2.0'} - - remark-mdx@2.3.0: - resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==} - - remark-parse@10.0.2: - resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} + remark-mdx@3.0.1: + resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==} remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - remark-rehype@10.1.0: - resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} - remark-rehype@11.1.0: resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} @@ -4274,10 +3904,6 @@ packages: remove-markdown@0.5.5: resolution: {integrity: sha512-lMR8tOtDqazFT6W2bZidoXwkptMdF3pCxpri0AEokHg0sZlC2GdoLqnoaxsEj1o7/BtXV1MKtT3YviA1t7rW7g==} - repeat-string@1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -4366,10 +3992,6 @@ packages: scule@1.3.0: resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} - section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - selfsigned@2.4.1: resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} engines: {node: '>=10'} @@ -4383,9 +4005,18 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + set-cookie-parser@2.6.0: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -4418,6 +4049,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} @@ -4525,10 +4159,6 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -4653,6 +4283,11 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} + terser@5.34.1: + resolution: {integrity: sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==} + engines: {node: '>=10'} + hasBin: true + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -4704,9 +4339,6 @@ packages: resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - toml@3.0.0: - resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -4741,18 +4373,12 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-pattern@4.3.0: - resolution: {integrity: sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==} - tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - typanion@3.14.0: - resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4773,10 +4399,6 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - typescript@5.6.2: resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} @@ -4799,54 +4421,30 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} - unified@10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} unist-builder@4.0.0: resolution: {integrity: sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==} - unist-util-generated@2.0.1: - resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} - - unist-util-is@5.2.1: - resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} - unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} - unist-util-position-from-estree@1.1.2: - resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==} - - unist-util-position@4.0.4: - resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} - unist-util-remove-position@4.0.2: - resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==} - unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} - unist-util-stringify-position@3.0.3: - resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} - unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - unist-util-visit-parents@5.1.3: - resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} - unist-util-visit-parents@6.0.1: resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} - unist-util-visit@4.1.2: - resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} - unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} @@ -4873,33 +4471,20 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - uvu@0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - vfile-location@4.1.0: - resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} + velite@0.1.1: + resolution: {integrity: sha512-t9TEzggWLDafkdNhCRPqdn/utlyZGpuq5Wz149164fVrIgHs39WdYFRre6vpQx1+PhxslqhvSpvRApGEXlwGfQ==} + engines: {node: ^18.17.0 || >=20.3.0} + hasBin: true vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} - vfile-message@3.1.4: - resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} - vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - vfile@5.3.7: - resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} - vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} @@ -5013,10 +4598,6 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -5455,133 +5036,14 @@ snapshots: '@cloudflare/workers-types@4.20240701.0': {} - '@contentlayer/cli@0.3.4(esbuild@0.23.0)': - dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.23.0) - '@contentlayer/utils': 0.3.4 - clipanion: 3.2.1(typanion@3.14.0) - typanion: 3.14.0 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color - - '@contentlayer/client@0.3.4(esbuild@0.23.0)': - dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.23.0) - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color - - '@contentlayer/core@0.3.4(esbuild@0.23.0)': - dependencies: - '@contentlayer/utils': 0.3.4 - camel-case: 4.1.2 - comment-json: 4.2.4 - gray-matter: 4.0.3 - mdx-bundler: 9.2.1(esbuild@0.23.0) - rehype-stringify: 9.0.4 - remark-frontmatter: 4.0.1 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - source-map-support: 0.5.21 - type-fest: 3.13.1 - unified: 10.1.2 - optionalDependencies: - esbuild: 0.23.0 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - supports-color - - '@contentlayer/source-files@0.3.4(esbuild@0.23.0)': - dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.23.0) - '@contentlayer/utils': 0.3.4 - chokidar: 3.6.0 - fast-glob: 3.3.2 - gray-matter: 4.0.3 - imagescript: 1.3.0 - micromatch: 4.0.7 - ts-pattern: 4.3.0 - unified: 10.1.2 - yaml: 2.4.5 - zod: 3.23.8 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color - - '@contentlayer/source-remote-files@0.3.4(esbuild@0.23.0)': - dependencies: - '@contentlayer/core': 0.3.4(esbuild@0.23.0) - '@contentlayer/source-files': 0.3.4(esbuild@0.23.0) - '@contentlayer/utils': 0.3.4 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color - - '@contentlayer/utils@0.3.4': - dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)) - '@effect-ts/otel-exporter-trace-otlp-grpc': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/exporter-trace-otlp-grpc@0.39.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)) - '@effect-ts/otel-sdk-trace-node': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.9.0)) - '@js-temporal/polyfill': 0.4.4 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.25.1 - chokidar: 3.6.0 - hash-wasm: 4.11.0 - inflection: 2.0.1 - memfs: 3.5.3 - oo-ascii-tree: 1.101.0 - ts-pattern: 4.3.0 - type-fest: 3.13.1 - '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@effect-ts/core@0.60.5': - dependencies: - '@effect-ts/system': 0.57.5 - - '@effect-ts/otel-exporter-trace-otlp-grpc@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/exporter-trace-otlp-grpc@0.39.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))': - dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)) - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-grpc': 0.39.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - - '@effect-ts/otel-sdk-trace-node@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.9.0))': - dependencies: - '@effect-ts/core': 0.60.5 - '@effect-ts/otel': 0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)) - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 1.25.1(@opentelemetry/api@1.9.0) - - '@effect-ts/otel@0.15.1(@effect-ts/core@0.60.5)(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))': + '@emnapi/runtime@1.3.0': dependencies: - '@effect-ts/core': 0.60.5 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - - '@effect-ts/system@0.57.5': {} + tslib: 2.7.0 + optional: true '@es-joy/jsdoccomment@0.43.1': dependencies: @@ -5608,16 +5070,6 @@ snapshots: escape-string-regexp: 4.0.0 rollup-plugin-node-polyfills: 0.2.1 - '@esbuild-plugins/node-resolve@0.1.4(esbuild@0.23.0)': - dependencies: - '@types/resolve': 1.20.6 - debug: 4.3.7 - esbuild: 0.23.0 - escape-string-regexp: 4.0.0 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - '@esbuild/aix-ppc64@0.21.5': optional: true @@ -5858,8 +5310,6 @@ snapshots: '@eslint/object-schema@2.1.4': {} - '@fal-works/esbuild-plugin-global-externals@2.1.2': {} - '@fastify/busboy@2.1.1': {} '@floating-ui/core@1.6.4': @@ -5873,18 +5323,6 @@ snapshots: '@floating-ui/utils@0.2.4': {} - '@grpc/grpc-js@1.10.11': - dependencies: - '@grpc/proto-loader': 0.7.13 - '@js-sdsl/ordered-map': 4.4.2 - - '@grpc/proto-loader@0.7.13': - dependencies: - lodash.camelcase: 4.3.0 - long: 5.2.3 - protobufjs: 7.3.2 - yargs: 17.7.2 - '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.3.0': {} @@ -5927,6 +5365,81 @@ snapshots: dependencies: eslint: 9.6.0 + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.0 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + '@internationalized/date@3.5.6': dependencies: '@swc/helpers': 0.5.11 @@ -5967,6 +5480,11 @@ snapshots: '@jridgewell/set-array@1.2.1': {} + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': @@ -5979,13 +5497,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@js-sdsl/ordered-map@4.4.2': {} - - '@js-temporal/polyfill@0.4.4': - dependencies: - jsbi: 4.3.0 - tslib: 2.7.0 - '@jsdevtools/ez-spawn@3.0.4': dependencies: call-me-maybe: 1.0.2 @@ -6009,34 +5520,31 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@mdx-js/esbuild@2.3.0(esbuild@0.23.0)': - dependencies: - '@mdx-js/mdx': 2.3.0 - esbuild: 0.23.0 - node-fetch: 3.3.2 - vfile: 5.3.7 - transitivePeerDependencies: - - supports-color - - '@mdx-js/mdx@2.3.0': + '@mdx-js/mdx@3.0.1': dependencies: + '@types/estree': 1.0.5 '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 '@types/mdx': 2.0.13 - estree-util-build-jsx: 2.2.2 - estree-util-is-identifier-name: 2.1.0 - estree-util-to-js: 1.2.0 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-build-jsx: 3.0.1 + estree-util-is-identifier-name: 3.0.0 + estree-util-to-js: 2.0.0 estree-walker: 3.0.3 - hast-util-to-estree: 2.3.3 - markdown-extensions: 1.1.1 + hast-util-to-estree: 3.1.0 + hast-util-to-jsx-runtime: 2.3.0 + markdown-extensions: 2.0.0 periscopic: 3.1.0 - remark-mdx: 2.3.0 - remark-parse: 10.0.2 - remark-rehype: 10.1.0 - unified: 10.1.2 - unist-util-position-from-estree: 1.1.2 - unist-util-stringify-position: 3.0.3 - unist-util-visit: 4.1.2 - vfile: 5.3.7 + remark-mdx: 3.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.0 + source-map: 0.7.4 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 transitivePeerDependencies: - supports-color @@ -6069,123 +5577,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@opentelemetry/api-logs@0.39.1': - dependencies: - '@opentelemetry/api': 1.9.0 - - '@opentelemetry/api@1.9.0': {} - - '@opentelemetry/context-async-hooks@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - - '@opentelemetry/core@1.13.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.13.0 - - '@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.25.1 - - '@opentelemetry/exporter-trace-otlp-grpc@0.39.1(@opentelemetry/api@1.9.0)': - dependencies: - '@grpc/grpc-js': 1.10.11 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.39.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.39.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/otlp-exporter-base@0.39.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/otlp-grpc-exporter-base@0.39.1(@opentelemetry/api@1.9.0)': - dependencies: - '@grpc/grpc-js': 1.10.11 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.39.1(@opentelemetry/api@1.9.0) - protobufjs: 7.3.2 - - '@opentelemetry/otlp-transformer@0.39.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.39.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.39.1(@opentelemetry/api-logs@0.39.1)(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.13.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/propagator-b3@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - - '@opentelemetry/propagator-jaeger@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - - '@opentelemetry/resources@1.13.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.13.0 - - '@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.25.1 - - '@opentelemetry/sdk-logs@0.39.1(@opentelemetry/api-logs@0.39.1)(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.39.1 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/sdk-metrics@1.13.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.9.0) - lodash.merge: 4.6.2 - - '@opentelemetry/sdk-trace-base@1.13.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.13.0 - - '@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.25.1 - - '@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - semver: 7.6.2 - - '@opentelemetry/semantic-conventions@1.13.0': {} - - '@opentelemetry/semantic-conventions@1.25.1': {} - '@pkgjs/parseargs@0.11.0': optional: true @@ -6197,29 +5588,6 @@ snapshots: dependencies: prettier: 3.3.2 - '@protobufjs/aspromise@1.1.2': {} - - '@protobufjs/base64@1.1.2': {} - - '@protobufjs/codegen@2.0.4': {} - - '@protobufjs/eventemitter@1.1.0': {} - - '@protobufjs/fetch@1.1.0': - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - - '@protobufjs/float@1.0.2': {} - - '@protobufjs/inquire@1.1.0': {} - - '@protobufjs/path@1.1.2': {} - - '@protobufjs/pool@1.1.0': {} - - '@protobufjs/utf8@1.1.0': {} - '@rollup/rollup-android-arm-eabi@4.18.1': optional: true @@ -6369,22 +5737,22 @@ snapshots: - supports-color - typescript - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))': dependencies: - '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-cloudflare@4.6.1(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(wrangler@3.64.0(@cloudflare/workers-types@4.20240701.0))': + '@sveltejs/adapter-cloudflare@4.6.1(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(wrangler@3.64.0(@cloudflare/workers-types@4.20240701.0))': dependencies: '@cloudflare/workers-types': 4.20240701.0 - '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) esbuild: 0.21.5 worktop: 0.8.0-next.18 wrangler: 3.64.0(@cloudflare/workers-types@4.20240701.0) - '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10))': + '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -6398,11 +5766,11 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.260 tiny-glob: 0.2.9 - vite: 5.3.3(@types/node@20.14.10) + vite: 5.3.3(@types/node@20.14.10)(terser@5.34.1) - '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))': + '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -6416,7 +5784,7 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.260 tiny-glob: 0.2.9 - vite: 5.4.6(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) '@sveltejs/package@2.3.5(svelte@5.0.0-next.260)(typescript@5.6.2)': dependencies: @@ -6429,47 +5797,47 @@ snapshots: transitivePeerDependencies: - typescript - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) debug: 4.3.7 svelte: 5.0.0-next.260 - vite: 5.3.3(@types/node@20.14.10) + vite: 5.3.3(@types/node@20.14.10)(terser@5.34.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) debug: 4.3.7 svelte: 5.0.0-next.260 - vite: 5.4.6(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) debug: 4.3.7 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.260 - vite: 5.3.3(@types/node@20.14.10) - vitefu: 1.0.2(vite@5.3.3(@types/node@20.14.10)) + vite: 5.3.3(@types/node@20.14.10)(terser@5.34.1) + vitefu: 1.0.2(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)))(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) debug: 4.3.7 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.260 - vite: 5.4.6(@types/node@20.14.10) - vitefu: 1.0.2(vite@5.4.6(@types/node@20.14.10)) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) + vitefu: 1.0.2(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)) transitivePeerDependencies: - supports-color @@ -6503,7 +5871,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.6(@types/jest@29.5.12)(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0))': + '@testing-library/jest-dom@6.4.6(@types/jest@29.5.12)(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1))': dependencies: '@adobe/css-tools': 4.4.0 '@babel/runtime': 7.24.8 @@ -6515,15 +5883,15 @@ snapshots: redent: 3.0.0 optionalDependencies: '@types/jest': 29.5.12 - vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) - '@testing-library/svelte@5.2.1(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10))(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0))': + '@testing-library/svelte@5.2.1(svelte@5.0.0-next.260)(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1))(vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1))': dependencies: '@testing-library/dom': 10.3.1 svelte: 5.0.0-next.260 optionalDependencies: - vite: 5.4.6(@types/node@20.14.10) - vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) + vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) '@testing-library/user-event@14.5.2(@testing-library/dom@10.3.1)': dependencies: @@ -6552,10 +5920,6 @@ snapshots: '@types/estree@1.0.5': {} - '@types/hast@2.3.10': - dependencies: - '@types/unist': 2.0.10 - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.2 @@ -6606,12 +5970,8 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/parse5@6.0.3': {} - '@types/resize-observer-browser@0.1.11': {} - '@types/resolve@1.20.6': {} - '@types/semver@7.5.8': {} '@types/stack-utils@2.0.3': {} @@ -6845,7 +6205,7 @@ snapshots: estree-walker: 3.0.3 magic-string: 0.30.11 optionalDependencies: - vite: 5.4.6(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) '@vitest/pretty-format@2.1.1': dependencies: @@ -6875,7 +6235,7 @@ snapshots: sirv: 2.0.4 tinyglobby: 0.2.6 tinyrainbow: 1.2.0 - vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) optional: true '@vitest/utils@2.1.1': @@ -6984,8 +6344,6 @@ snapshots: aria-query@5.3.1: {} - array-timsort@1.0.3: {} - array-union@2.1.0: {} as-table@1.0.55: @@ -7058,11 +6416,6 @@ snapshots: callsites@3.1.0: {} - camel-case@4.1.2: - dependencies: - pascal-case: 3.1.2 - tslib: 2.7.0 - camelcase-css@2.0.1: {} caniuse-lite@1.0.30001641: {} @@ -7148,10 +6501,6 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - clipanion@3.2.1(typanion@3.14.0): - dependencies: - typanion: 3.14.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -7160,6 +6509,8 @@ snapshots: clsx@2.1.1: {} + collapse-white-space@2.1.0: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -7172,21 +6523,25 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 comma-separated-tokens@2.0.3: {} - commander@4.1.1: {} + commander@2.20.3: {} - comment-json@4.2.4: - dependencies: - array-timsort: 1.0.3 - core-util-is: 1.0.3 - esprima: 4.0.1 - has-own-prop: 2.0.0 - repeat-string: 1.6.1 + commander@4.1.1: {} comment-parser@1.4.1: {} @@ -7208,20 +6563,6 @@ snapshots: consola@3.2.3: {} - contentlayer@0.3.4(esbuild@0.23.0): - dependencies: - '@contentlayer/cli': 0.3.4(esbuild@0.23.0) - '@contentlayer/client': 0.3.4(esbuild@0.23.0) - '@contentlayer/core': 0.3.4(esbuild@0.23.0) - '@contentlayer/source-files': 0.3.4(esbuild@0.23.0) - '@contentlayer/source-remote-files': 0.3.4(esbuild@0.23.0) - '@contentlayer/utils': 0.3.4 - transitivePeerDependencies: - - '@effect-ts/otel-node' - - esbuild - - markdown-wasm - - supports-color - cookie@0.5.0: {} cookie@0.6.0: {} @@ -7230,8 +6571,6 @@ snapshots: dependencies: browserslist: 4.23.2 - core-util-is@1.0.3: {} - cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 @@ -7256,8 +6595,6 @@ snapshots: data-uri-to-buffer@2.0.2: {} - data-uri-to-buffer@4.0.1: {} - data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -7305,6 +6642,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@2.0.3: {} + devalue@5.1.1: {} devlop@1.1.0: @@ -7315,8 +6654,6 @@ snapshots: diff-sequences@29.6.3: {} - diff@5.2.0: {} - dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -7653,7 +6990,7 @@ snapshots: eslint: 9.6.0 optionalDependencies: '@typescript-eslint/eslint-plugin': 8.0.0-alpha.40(@typescript-eslint/parser@7.16.0(eslint@9.6.0)(typescript@5.6.2))(eslint@9.6.0)(typescript@5.6.2) - vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0) + vitest: 2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1) transitivePeerDependencies: - supports-color - typescript @@ -7774,34 +7111,29 @@ snapshots: estraverse@5.3.0: {} - estree-util-attach-comments@2.1.1: + estree-util-attach-comments@3.0.0: dependencies: '@types/estree': 1.0.5 - estree-util-build-jsx@2.2.2: + estree-util-build-jsx@3.0.1: dependencies: '@types/estree-jsx': 1.0.5 - estree-util-is-identifier-name: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 estree-walker: 3.0.3 - estree-util-is-identifier-name@1.1.0: {} - - estree-util-is-identifier-name@2.1.0: {} + estree-util-is-identifier-name@3.0.0: {} - estree-util-to-js@1.2.0: + estree-util-to-js@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 astring: 1.8.6 source-map: 0.7.4 - estree-util-value-to-estree@1.3.0: - dependencies: - is-plain-obj: 3.0.0 - - estree-util-visit@1.2.1: + estree-util-visit@2.0.0: dependencies: '@types/estree-jsx': 1.0.5 - '@types/unist': 2.0.10 + '@types/unist': 3.0.2 estree-walker@0.6.1: {} @@ -7823,10 +7155,6 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 - extend-shallow@2.0.1: - dependencies: - is-extendable: 0.1.1 - extend@3.0.2: {} extendable-error@0.1.7: {} @@ -7855,19 +7183,10 @@ snapshots: dependencies: reusify: 1.0.4 - fault@2.0.1: - dependencies: - format: 0.2.2 - fdir@6.3.0(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 - fetch-blob@3.2.0: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - fflate@0.8.2: optional: true @@ -7924,12 +7243,6 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - format@0.2.2: {} - - formdata-polyfill@4.0.10: - dependencies: - fetch-blob: 3.2.0 - fraction.js@4.3.7: {} fs-extra@7.0.1: @@ -7944,8 +7257,6 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - fs-monkey@1.0.6: {} - fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -8020,21 +7331,10 @@ snapshots: graphemer@1.4.0: {} - gray-matter@4.0.3: - dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - has-flag@3.0.0: {} has-flag@4.0.0: {} - has-own-prop@2.0.0: {} - - hash-wasm@4.11.0: {} - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -8048,16 +7348,6 @@ snapshots: vfile: 6.0.1 vfile-message: 4.0.2 - hast-util-from-parse5@7.1.2: - dependencies: - '@types/hast': 2.3.10 - '@types/unist': 2.0.10 - hastscript: 7.2.0 - property-information: 6.5.0 - vfile: 5.3.7 - vfile-location: 4.1.0 - web-namespaces: 2.0.1 - hast-util-from-parse5@8.0.1: dependencies: '@types/hast': 3.0.4 @@ -8073,28 +7363,10 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hast-util-parse-selector@3.1.1: - dependencies: - '@types/hast': 2.3.10 - hast-util-parse-selector@4.0.0: dependencies: '@types/hast': 3.0.4 - hast-util-raw@7.2.3: - dependencies: - '@types/hast': 2.3.10 - '@types/parse5': 6.0.3 - hast-util-from-parse5: 7.1.2 - hast-util-to-parse5: 7.1.0 - html-void-elements: 2.0.1 - parse5: 6.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 - vfile: 5.3.7 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - hast-util-raw@9.0.4: dependencies: '@types/hast': 3.0.4 @@ -8111,40 +7383,27 @@ snapshots: web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-to-estree@2.3.3: + hast-util-to-estree@3.1.0: dependencies: '@types/estree': 1.0.5 '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/unist': 2.0.10 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 - estree-util-attach-comments: 2.1.1 - estree-util-is-identifier-name: 2.1.0 - hast-util-whitespace: 2.0.1 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdxjs-esm: 1.3.1 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 property-information: 6.5.0 space-separated-tokens: 2.0.2 style-to-object: 0.4.4 - unist-util-position: 4.0.4 + unist-util-position: 5.0.0 zwitch: 2.0.4 transitivePeerDependencies: - supports-color - hast-util-to-html@8.0.4: - dependencies: - '@types/hast': 2.3.10 - '@types/unist': 2.0.10 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-raw: 7.2.3 - hast-util-whitespace: 2.0.1 - html-void-elements: 2.0.1 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.4 - zwitch: 2.0.4 - hast-util-to-html@9.0.1: dependencies: '@types/hast': 3.0.4 @@ -8160,14 +7419,25 @@ snapshots: stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-parse5@7.1.0: + hast-util-to-jsx-runtime@2.3.0: dependencies: - '@types/hast': 2.3.10 + '@types/estree': 1.0.5 + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 property-information: 6.5.0 space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 + style-to-object: 1.0.6 + unist-util-position: 5.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color hast-util-to-parse5@8.0.0: dependencies: @@ -8183,20 +7453,10 @@ snapshots: dependencies: '@types/hast': 3.0.4 - hast-util-whitespace@2.0.1: {} - hast-util-whitespace@3.0.0: dependencies: '@types/hast': 3.0.4 - hastscript@7.2.0: - dependencies: - '@types/hast': 2.3.10 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - hastscript@8.0.0: dependencies: '@types/hast': 3.0.4 @@ -8211,8 +7471,6 @@ snapshots: dependencies: whatwg-encoding: 3.1.1 - html-void-elements@2.0.1: {} - html-void-elements@3.0.0: {} http-proxy-agent@7.0.2: @@ -8245,8 +7503,6 @@ snapshots: ignore@5.3.1: {} - imagescript@1.3.0: {} - import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -8258,8 +7514,6 @@ snapshots: indent-string@4.0.0: {} - inflection@2.0.1: {} - inflight@1.0.6: dependencies: once: 1.4.0 @@ -8287,12 +7541,12 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - is-buffer@2.0.5: {} - is-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 @@ -8305,8 +7559,6 @@ snapshots: is-decimal@2.0.1: {} - is-extendable@0.1.1: {} - is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -8323,8 +7575,6 @@ snapshots: is-path-inside@3.0.3: {} - is-plain-obj@3.0.0: {} - is-plain-obj@4.1.0: {} is-potential-custom-element-name@1.0.1: {} @@ -8411,8 +7661,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsbi@4.3.0: {} - jsdoc-type-pratt-parser@4.0.0: {} jsdom@24.1.0: @@ -8470,8 +7718,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - kleur@4.1.5: {} known-css-properties@0.34.0: {} @@ -8513,8 +7759,6 @@ snapshots: dependencies: p-locate: 6.0.0 - lodash.camelcase@4.3.0: {} - lodash.castarray@4.4.0: {} lodash.isplainobject@4.0.6: {} @@ -8525,8 +7769,6 @@ snapshots: lodash@4.17.21: {} - long@5.2.3: {} - longest-streak@3.1.0: {} loupe@3.1.1: @@ -8558,18 +7800,12 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - markdown-extensions@1.1.1: {} + markdown-extensions@2.0.0: {} markdown-table@3.0.3: {} marked@14.1.2: {} - mdast-util-definitions@5.1.2: - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 - unist-util-visit: 4.1.2 - mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.4 @@ -8587,23 +7823,6 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-from-markdown@1.3.1: - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 - decode-named-character-reference: 1.0.2 - mdast-util-to-string: 3.2.0 - micromark: 3.2.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-decode-string: 1.1.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-stringify-position: 3.0.3 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - mdast-util-from-markdown@2.0.1: dependencies: '@types/mdast': 4.0.4 @@ -8621,12 +7840,6 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-frontmatter@1.0.1: - dependencies: - '@types/mdast': 3.0.15 - mdast-util-to-markdown: 1.5.0 - micromark-extension-frontmatter: 1.1.1 - mdast-util-gfm-autolink-literal@2.0.0: dependencies: '@types/mdast': 4.0.4 @@ -8684,74 +7897,60 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-mdx-expression@1.3.2: + mdast-util-mdx-expression@2.0.1: dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - mdast-util-mdx-jsx@2.1.4: + mdast-util-mdx-jsx@3.1.3: dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.2 ccount: 2.0.1 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 parse-entities: 4.0.1 stringify-entities: 4.0.4 - unist-util-remove-position: 4.0.2 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 transitivePeerDependencies: - supports-color - mdast-util-mdx@2.0.1: + mdast-util-mdx@3.0.0: dependencies: - mdast-util-from-markdown: 1.3.1 - mdast-util-mdx-expression: 1.3.2 - mdast-util-mdx-jsx: 2.1.4 - mdast-util-mdxjs-esm: 1.3.1 - mdast-util-to-markdown: 1.5.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - mdast-util-mdxjs-esm@1.3.1: + mdast-util-mdxjs-esm@2.0.1: dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - mdast-util-to-markdown: 1.5.0 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - mdast-util-phrasing@3.0.1: - dependencies: - '@types/mdast': 3.0.15 - unist-util-is: 5.2.1 - mdast-util-phrasing@4.1.0: dependencies: '@types/mdast': 4.0.4 unist-util-is: 6.0.0 - mdast-util-to-hast@12.3.0: - dependencies: - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-definitions: 5.1.2 - micromark-util-sanitize-uri: 1.2.0 - trim-lines: 3.0.1 - unist-util-generated: 2.0.1 - unist-util-position: 4.0.4 - unist-util-visit: 4.1.2 - mdast-util-to-hast@13.2.0: dependencies: '@types/hast': 3.0.4 @@ -8764,17 +7963,6 @@ snapshots: unist-util-visit: 5.0.0 vfile: 6.0.1 - mdast-util-to-markdown@1.5.0: - dependencies: - '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 - longest-streak: 3.1.0 - mdast-util-phrasing: 3.0.1 - mdast-util-to-string: 3.2.0 - micromark-util-decode-string: 1.1.0 - unist-util-visit: 4.1.2 - zwitch: 2.0.4 - mdast-util-to-markdown@2.1.0: dependencies: '@types/mdast': 4.0.4 @@ -8788,10 +7976,6 @@ snapshots: mdast-util-to-string@2.0.0: {} - mdast-util-to-string@3.2.0: - dependencies: - '@types/mdast': 3.0.15 - mdast-util-to-string@4.0.0: dependencies: '@types/mdast': 4.0.4 @@ -8814,46 +7998,8 @@ snapshots: transitivePeerDependencies: - supports-color - mdx-bundler@9.2.1(esbuild@0.23.0): - dependencies: - '@babel/runtime': 7.24.8 - '@esbuild-plugins/node-resolve': 0.1.4(esbuild@0.23.0) - '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@mdx-js/esbuild': 2.3.0(esbuild@0.23.0) - esbuild: 0.23.0 - gray-matter: 4.0.3 - remark-frontmatter: 4.0.1 - remark-mdx-frontmatter: 1.1.1 - uuid: 8.3.2 - vfile: 5.3.7 - transitivePeerDependencies: - - supports-color - - memfs@3.5.3: - dependencies: - fs-monkey: 1.0.6 - merge2@1.4.1: {} - micromark-core-commonmark@1.1.0: - dependencies: - decode-named-character-reference: 1.0.2 - micromark-factory-destination: 1.1.0 - micromark-factory-label: 1.1.0 - micromark-factory-space: 1.1.0 - micromark-factory-title: 1.1.0 - micromark-factory-whitespace: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-chunked: 1.1.0 - micromark-util-classify-character: 1.1.0 - micromark-util-html-tag-name: 1.2.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-resolve-all: 1.1.0 - micromark-util-subtokenize: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - micromark-core-commonmark@2.0.1: dependencies: decode-named-character-reference: 1.0.2 @@ -8873,13 +8019,6 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-frontmatter@1.1.1: - dependencies: - fault: 2.0.1 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - micromark-extension-gfm-autolink-literal@2.1.0: dependencies: micromark-util-character: 2.1.0 @@ -8938,62 +8077,57 @@ snapshots: micromark-util-combine-extensions: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-mdx-expression@1.0.8: + micromark-extension-mdx-expression@3.0.0: dependencies: '@types/estree': 1.0.5 - micromark-factory-mdx-expression: 1.0.9 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 - micromark-extension-mdx-jsx@1.0.5: + micromark-extension-mdx-jsx@3.0.1: dependencies: '@types/acorn': 4.0.6 '@types/estree': 1.0.5 - estree-util-is-identifier-name: 2.1.0 - micromark-factory-mdx-expression: 1.0.9 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - vfile-message: 3.1.4 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 - micromark-extension-mdx-md@1.0.1: + micromark-extension-mdx-md@2.0.0: dependencies: - micromark-util-types: 1.1.0 + micromark-util-types: 2.0.0 - micromark-extension-mdxjs-esm@1.0.5: + micromark-extension-mdxjs-esm@3.0.0: dependencies: '@types/estree': 1.0.5 - micromark-core-commonmark: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 - micromark-extension-mdxjs@1.0.1: + micromark-extension-mdxjs@3.0.0: dependencies: acorn: 8.12.1 acorn-jsx: 5.3.2(acorn@8.12.1) - micromark-extension-mdx-expression: 1.0.8 - micromark-extension-mdx-jsx: 1.0.5 - micromark-extension-mdx-md: 1.0.1 - micromark-extension-mdxjs-esm: 1.0.5 - micromark-util-combine-extensions: 1.1.0 - micromark-util-types: 1.1.0 - - micromark-factory-destination@1.1.0: - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 + micromark-extension-mdx-expression: 3.0.0 + micromark-extension-mdx-jsx: 3.0.1 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 micromark-factory-destination@2.0.0: dependencies: @@ -9001,13 +8135,6 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-factory-label@1.1.0: - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - micromark-factory-label@2.0.0: dependencies: devlop: 1.1.0 @@ -9015,34 +8142,23 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-factory-mdx-expression@1.0.9: + micromark-factory-mdx-expression@2.0.2: dependencies: '@types/estree': 1.0.5 - micromark-util-character: 1.2.0 - micromark-util-events-to-acorn: 1.2.3 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - unist-util-position-from-estree: 1.1.2 - uvu: 0.5.6 - vfile-message: 3.1.4 - - micromark-factory-space@1.1.0: - dependencies: - micromark-util-character: 1.2.0 - micromark-util-types: 1.1.0 + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 micromark-factory-space@2.0.0: dependencies: micromark-util-character: 2.1.0 micromark-util-types: 2.0.0 - micromark-factory-title@1.1.0: - dependencies: - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - micromark-factory-title@2.0.0: dependencies: micromark-factory-space: 2.0.0 @@ -9050,13 +8166,6 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-factory-whitespace@1.1.0: - dependencies: - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - micromark-factory-whitespace@2.0.0: dependencies: micromark-factory-space: 2.0.0 @@ -9064,61 +8173,30 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-character@1.2.0: - dependencies: - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - micromark-util-character@2.1.0: dependencies: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-chunked@1.1.0: - dependencies: - micromark-util-symbol: 1.1.0 - micromark-util-chunked@2.0.0: dependencies: micromark-util-symbol: 2.0.0 - micromark-util-classify-character@1.1.0: - dependencies: - micromark-util-character: 1.2.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - micromark-util-classify-character@2.0.0: dependencies: micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-combine-extensions@1.1.0: - dependencies: - micromark-util-chunked: 1.1.0 - micromark-util-types: 1.1.0 - micromark-util-combine-extensions@2.0.0: dependencies: micromark-util-chunked: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-decode-numeric-character-reference@1.1.0: - dependencies: - micromark-util-symbol: 1.1.0 - micromark-util-decode-numeric-character-reference@2.0.1: dependencies: micromark-util-symbol: 2.0.0 - micromark-util-decode-string@1.1.0: - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 1.2.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-decode-string@2.0.0: dependencies: decode-named-character-reference: 1.0.2 @@ -9126,60 +8204,35 @@ snapshots: micromark-util-decode-numeric-character-reference: 2.0.1 micromark-util-symbol: 2.0.0 - micromark-util-encode@1.1.0: {} - micromark-util-encode@2.0.0: {} - micromark-util-events-to-acorn@1.2.3: + micromark-util-events-to-acorn@2.0.2: dependencies: '@types/acorn': 4.0.6 '@types/estree': 1.0.5 - '@types/unist': 2.0.10 - estree-util-visit: 1.2.1 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - vfile-message: 3.1.4 - - micromark-util-html-tag-name@1.2.0: {} + '@types/unist': 3.0.2 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 micromark-util-html-tag-name@2.0.0: {} - micromark-util-normalize-identifier@1.1.0: - dependencies: - micromark-util-symbol: 1.1.0 - micromark-util-normalize-identifier@2.0.0: dependencies: micromark-util-symbol: 2.0.0 - micromark-util-resolve-all@1.1.0: - dependencies: - micromark-util-types: 1.1.0 - micromark-util-resolve-all@2.0.0: dependencies: micromark-util-types: 2.0.0 - micromark-util-sanitize-uri@1.2.0: - dependencies: - micromark-util-character: 1.2.0 - micromark-util-encode: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-sanitize-uri@2.0.0: dependencies: micromark-util-character: 2.1.0 micromark-util-encode: 2.0.0 micromark-util-symbol: 2.0.0 - micromark-util-subtokenize@1.1.0: - dependencies: - micromark-util-chunked: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - micromark-util-subtokenize@2.0.1: dependencies: devlop: 1.1.0 @@ -9187,12 +8240,8 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-symbol@1.1.0: {} - micromark-util-symbol@2.0.0: {} - micromark-util-types@1.1.0: {} - micromark-util-types@2.0.0: {} micromark@2.11.4: @@ -9202,28 +8251,6 @@ snapshots: transitivePeerDependencies: - supports-color - micromark@3.2.0: - dependencies: - '@types/debug': 4.1.12 - debug: 4.3.7 - decode-named-character-reference: 1.0.2 - micromark-core-commonmark: 1.1.0 - micromark-factory-space: 1.1.0 - micromark-util-character: 1.2.0 - micromark-util-chunked: 1.1.0 - micromark-util-combine-extensions: 1.1.0 - micromark-util-decode-numeric-character-reference: 1.1.0 - micromark-util-encode: 1.1.0 - micromark-util-normalize-identifier: 1.1.0 - micromark-util-resolve-all: 1.1.0 - micromark-util-sanitize-uri: 1.2.0 - micromark-util-subtokenize: 1.1.0 - micromark-util-symbol: 1.1.0 - micromark-util-types: 1.1.0 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - micromark@4.0.0: dependencies: '@types/debug': 4.1.12 @@ -9334,20 +8361,12 @@ snapshots: lower-case: 2.0.2 tslib: 2.7.0 - node-domexception@1.0.0: {} - node-fetch-native@1.6.4: {} node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 - node-fetch@3.3.2: - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - node-forge@1.3.1: {} node-releases@2.0.14: {} @@ -9390,8 +8409,6 @@ snapshots: dependencies: wrappy: 1.0.2 - oo-ascii-tree@1.101.0: {} - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -9479,8 +8496,6 @@ snapshots: parse-numeric-range@1.3.0: {} - parse5@6.0.1: {} - parse5@7.1.2: dependencies: entities: 4.5.0 @@ -9658,21 +8673,6 @@ snapshots: property-information@6.5.0: {} - protobufjs@7.3.2: - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 20.14.10 - long: 5.2.3 - pseudomap@1.0.2: {} psl@1.9.0: {} @@ -9777,19 +8777,6 @@ snapshots: hast-util-to-html: 9.0.1 unified: 11.0.5 - rehype-stringify@9.0.4: - dependencies: - '@types/hast': 2.3.10 - hast-util-to-html: 8.0.4 - unified: 10.1.2 - - remark-frontmatter@4.0.1: - dependencies: - '@types/mdast': 3.0.15 - mdast-util-frontmatter: 1.0.1 - micromark-extension-frontmatter: 1.1.1 - unified: 10.1.2 - remark-gfm@4.0.0: dependencies: '@types/mdast': 4.0.4 @@ -9801,25 +8788,10 @@ snapshots: transitivePeerDependencies: - supports-color - remark-mdx-frontmatter@1.1.1: - dependencies: - estree-util-is-identifier-name: 1.1.0 - estree-util-value-to-estree: 1.3.0 - js-yaml: 4.1.0 - toml: 3.0.0 - - remark-mdx@2.3.0: - dependencies: - mdast-util-mdx: 2.0.1 - micromark-extension-mdxjs: 1.0.1 - transitivePeerDependencies: - - supports-color - - remark-parse@10.0.2: + remark-mdx@3.0.1: dependencies: - '@types/mdast': 3.0.15 - mdast-util-from-markdown: 1.3.1 - unified: 10.1.2 + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 transitivePeerDependencies: - supports-color @@ -9832,13 +8804,6 @@ snapshots: transitivePeerDependencies: - supports-color - remark-rehype@10.1.0: - dependencies: - '@types/hast': 2.3.10 - '@types/mdast': 3.0.15 - mdast-util-to-hast: 12.3.0 - unified: 10.1.2 - remark-rehype@11.1.0: dependencies: '@types/hast': 3.0.4 @@ -9855,8 +8820,6 @@ snapshots: remove-markdown@0.5.5: {} - repeat-string@1.6.1: {} - require-directory@2.1.1: {} requires-port@1.0.0: {} @@ -9972,11 +8935,6 @@ snapshots: scule@1.3.0: {} - section-matter@1.0.0: - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 - selfsigned@2.4.1: dependencies: '@types/node-forge': 1.3.11 @@ -9986,8 +8944,36 @@ snapshots: semver@7.6.2: {} + semver@7.6.3: {} + set-cookie-parser@2.6.0: {} + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -10013,6 +8999,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + sirv@2.0.4: dependencies: '@polka/url': 1.0.0-next.25 @@ -10114,8 +9104,6 @@ snapshots: dependencies: ansi-regex: 6.0.1 - strip-bom-string@1.0.0: {} - strip-bom@3.0.0: {} strip-indent@3.0.0: @@ -10272,6 +9260,13 @@ snapshots: term-size@2.2.1: {} + terser@5.34.1: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.12.1 + commander: 2.20.3 + source-map-support: 0.5.21 + text-table@0.2.0: {} thenify-all@1.6.0: @@ -10317,8 +9312,6 @@ snapshots: dependencies: eslint-visitor-keys: 3.4.3 - toml@3.0.0: {} - totalist@3.0.1: {} tough-cookie@4.1.4: @@ -10346,14 +9339,10 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-pattern@4.3.0: {} - tslib@2.6.3: {} tslib@2.7.0: {} - typanion@3.14.0: {} - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -10366,8 +9355,6 @@ snapshots: type-fest@0.8.1: {} - type-fest@3.13.1: {} - typescript@5.6.2: {} ufo@1.5.3: {} @@ -10389,16 +9376,6 @@ snapshots: unicorn-magic@0.1.0: {} - unified@10.1.2: - dependencies: - '@types/unist': 2.0.10 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 5.3.7 - unified@11.0.5: dependencies: '@types/unist': 3.0.2 @@ -10413,61 +9390,31 @@ snapshots: dependencies: '@types/unist': 3.0.2 - unist-util-generated@2.0.1: {} - - unist-util-is@5.2.1: - dependencies: - '@types/unist': 2.0.10 - unist-util-is@6.0.0: dependencies: '@types/unist': 3.0.2 - unist-util-position-from-estree@1.1.2: + unist-util-position-from-estree@2.0.0: dependencies: - '@types/unist': 2.0.10 - - unist-util-position@4.0.4: - dependencies: - '@types/unist': 2.0.10 + '@types/unist': 3.0.2 unist-util-position@5.0.0: dependencies: '@types/unist': 3.0.2 - unist-util-remove-position@4.0.2: - dependencies: - '@types/unist': 2.0.10 - unist-util-visit: 4.1.2 - unist-util-stringify-position@2.0.3: dependencies: '@types/unist': 2.0.10 - unist-util-stringify-position@3.0.3: - dependencies: - '@types/unist': 2.0.10 - unist-util-stringify-position@4.0.0: dependencies: '@types/unist': 3.0.2 - unist-util-visit-parents@5.1.3: - dependencies: - '@types/unist': 2.0.10 - unist-util-is: 5.2.1 - unist-util-visit-parents@6.0.1: dependencies: '@types/unist': 3.0.2 unist-util-is: 6.0.0 - unist-util-visit@4.1.2: - dependencies: - '@types/unist': 2.0.10 - unist-util-is: 5.2.1 - unist-util-visit-parents: 5.1.3 - unist-util-visit@5.0.0: dependencies: '@types/unist': 3.0.2 @@ -10495,59 +9442,42 @@ snapshots: util-deprecate@1.0.2: {} - uuid@8.3.2: {} - - uvu@0.5.6: - dependencies: - dequal: 2.0.3 - diff: 5.2.0 - kleur: 4.1.5 - sade: 1.8.1 - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vfile-location@4.1.0: + velite@0.1.1: dependencies: - '@types/unist': 2.0.10 - vfile: 5.3.7 + '@mdx-js/mdx': 3.0.1 + esbuild: 0.23.0 + sharp: 0.33.5 + terser: 5.34.1 + transitivePeerDependencies: + - supports-color vfile-location@5.0.2: dependencies: '@types/unist': 3.0.2 vfile: 6.0.1 - vfile-message@3.1.4: - dependencies: - '@types/unist': 2.0.10 - unist-util-stringify-position: 3.0.3 - vfile-message@4.0.2: dependencies: '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 - vfile@5.3.7: - dependencies: - '@types/unist': 2.0.10 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 - vfile@6.0.1: dependencies: '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-node@2.1.1(@types/node@20.14.10): + vite-node@2.1.1(@types/node@20.14.10)(terser@5.34.1): dependencies: cac: 6.7.14 debug: 4.3.7 pathe: 1.1.2 - vite: 5.4.6(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) transitivePeerDependencies: - '@types/node' - less @@ -10559,7 +9489,7 @@ snapshots: - supports-color - terser - vite@5.3.3(@types/node@20.14.10): + vite@5.3.3(@types/node@20.14.10)(terser@5.34.1): dependencies: esbuild: 0.21.5 postcss: 8.4.39 @@ -10567,8 +9497,9 @@ snapshots: optionalDependencies: '@types/node': 20.14.10 fsevents: 2.3.3 + terser: 5.34.1 - vite@5.4.6(@types/node@20.14.10): + vite@5.4.6(@types/node@20.14.10)(terser@5.34.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 @@ -10576,16 +9507,17 @@ snapshots: optionalDependencies: '@types/node': 20.14.10 fsevents: 2.3.3 + terser: 5.34.1 - vitefu@1.0.2(vite@5.3.3(@types/node@20.14.10)): + vitefu@1.0.2(vite@5.3.3(@types/node@20.14.10)(terser@5.34.1)): optionalDependencies: - vite: 5.3.3(@types/node@20.14.10) + vite: 5.3.3(@types/node@20.14.10)(terser@5.34.1) - vitefu@1.0.2(vite@5.4.6(@types/node@20.14.10)): + vitefu@1.0.2(vite@5.4.6(@types/node@20.14.10)(terser@5.34.1)): optionalDependencies: - vite: 5.4.6(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) - vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0): + vitest@2.1.1(@types/node@20.14.10)(@vitest/ui@2.1.1)(jsdom@24.1.0)(terser@5.34.1): dependencies: '@vitest/expect': 2.1.1 '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.6) @@ -10603,8 +9535,8 @@ snapshots: tinyexec: 0.3.0 tinypool: 1.0.0 tinyrainbow: 1.2.0 - vite: 5.4.6(@types/node@20.14.10) - vite-node: 2.1.1(@types/node@20.14.10) + vite: 5.4.6(@types/node@20.14.10)(terser@5.34.1) + vite-node: 2.1.1(@types/node@20.14.10)(terser@5.34.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.14.10 @@ -10640,8 +9572,6 @@ snapshots: web-namespaces@2.0.1: {} - web-streams-polyfill@3.3.3: {} - webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} diff --git a/sites/docs/.gitignore b/sites/docs/.gitignore index 960408672..4f6ddde04 100644 --- a/sites/docs/.gitignore +++ b/sites/docs/.gitignore @@ -10,6 +10,7 @@ node_modules vite.config.js.timestamp-* vite.config.ts.timestamp-* .vercel +.velite ## contentlayer build output .contentlayer \ No newline at end of file diff --git a/sites/docs/.prettierignore b/sites/docs/.prettierignore index 098635ac2..c62da399a 100644 --- a/sites/docs/.prettierignore +++ b/sites/docs/.prettierignore @@ -16,6 +16,7 @@ yarn.lock package.json .vercel .contentlayer +.velite dist vite.config.js.timestamp-* diff --git a/sites/docs/contentlayer.config.js b/sites/docs/contentlayer.config.js deleted file mode 100644 index 1a2aad857..000000000 --- a/sites/docs/contentlayer.config.js +++ /dev/null @@ -1,108 +0,0 @@ -import path from "node:path"; -import { defineDocumentType, makeSource } from "contentlayer/source-files"; - -/** @type {import('contentlayer/source-files').ComputedFields} */ -const computedFields = { - slug: { - type: "string", - resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"), - }, - slugFull: { - type: "string", - resolve: (doc) => `/${doc._raw.flattenedPath}`, - }, - fileName: { - type: "string", - resolve: (doc) => path.parse(doc._raw.sourceFilePath.split("/").slice(-1).join("/")).name, - }, - suffix: { - type: "string", - resolve: (doc) => path.parse(doc._raw.sourceFilePath.split("/").slice(-1).join("/")).ext, - }, -}; - -export const Doc = defineDocumentType(() => ({ - name: "Doc", - filePathPattern: `./*.md`, - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - navLabel: { - type: "string", - required: false, - }, - }, - computedFields, -})); - -export const ComponentDoc = defineDocumentType(() => ({ - name: "ComponentDoc", - filePathPattern: "components/**/*.md", - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - navLabel: { - type: "string", - required: false, - }, - }, - computedFields, -})); - -export const UtilityDoc = defineDocumentType(() => ({ - name: "UtilityDoc", - filePathPattern: `./utilities/**/*.md`, - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - navLabel: { - type: "string", - required: false, - }, - }, - computedFields, -})); - -export const TypeHelperDoc = defineDocumentType(() => ({ - name: "TypeHelperDoc", - filePathPattern: `./type-helpers/**/*.md`, - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - navLabel: { - type: "string", - required: false, - }, - }, - computedFields, -})); - -export default makeSource({ - contentDirPath: "./content", - documentTypes: [Doc, ComponentDoc, UtilityDoc, TypeHelperDoc], - disableImportAliasWarning: true, -}); diff --git a/sites/docs/mdsx.config.js b/sites/docs/mdsx.config.js index f0d001c61..101a9ccee 100644 --- a/sites/docs/mdsx.config.js +++ b/sites/docs/mdsx.config.js @@ -157,10 +157,10 @@ export function rehypeComponentExample() { // @ts-expect-error - we're using an untyped node here if (node?.type === "raw" && node?.value?.startsWith(" ({ + const components = componentDocs.map((doc) => ({ title: doc.title, - content: cleanMd(doc.body.raw), + content: cleanMd(doc.raw), description: doc.description, href: `/docs/components/${doc.slug}`, })); - const utilities = allUtilityDocs.map((doc) => ({ + const utilities = utilityDocs.map((doc) => ({ title: doc.title, - content: cleanMd(doc.body.raw), + content: cleanMd(doc.raw), description: doc.description, href: `/docs/utilities/${doc.slug}`, })); - const typeHelpers = allTypeHelperDocs.map((doc) => ({ + const typeHelpers = typeHelperDocs.map((doc) => ({ title: doc.title, - content: cleanMd(doc.body.raw), + content: cleanMd(doc.raw), description: doc.description, href: `/docs/type-helpers/${doc.slug}`, })); - const mainPages = allDocs.map((doc) => ({ + const mainPages = docs.map((doc) => ({ title: doc.title, - content: cleanMd(doc.body.raw), + content: cleanMd(doc.raw), description: doc.description, href: `/docs${doc.slugFull}`, })); diff --git a/sites/docs/other/update-velite-output.js b/sites/docs/other/update-velite-output.js new file mode 100644 index 000000000..2ff0a62f2 --- /dev/null +++ b/sites/docs/other/update-velite-output.js @@ -0,0 +1,38 @@ +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const dtsPath = join(__dirname, "../.velite/index.d.ts"); +const indexPath = join(__dirname, "../.velite/index.js"); + +async function replaceContents() { + const data = await readFile(dtsPath, "utf8").catch((err) => { + console.error("Error reading file:", err); + }); + if (!data) return; + + const updatedContent = data.replace("'../velite.config'", "'../velite.config.js'"); + if (updatedContent === data) return; + + await writeFile(dtsPath, updatedContent, "utf8").catch((err) => { + console.error("Error writing file:", err); + }); +} + +async function replaceIndexContents() { + const data = await readFile(indexPath, "utf8").catch((err) => { + console.error("Error reading file:", err); + }); + if (!data) return; + + const updatedContent = data.replaceAll(".json'", ".json' with { type: 'json' }"); + if (updatedContent === data) return; + + await writeFile(indexPath, updatedContent, "utf8").catch((err) => { + console.error("Error writing file:", err); + }); +} + +await replaceContents(); +await replaceIndexContents(); diff --git a/sites/docs/other/watch-velite-output.js b/sites/docs/other/watch-velite-output.js new file mode 100644 index 000000000..52a7e7a33 --- /dev/null +++ b/sites/docs/other/watch-velite-output.js @@ -0,0 +1,67 @@ +import { watch } from "node:fs"; +import { readFile, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +// Configuration +const __dirname = fileURLToPath(new URL(".", import.meta.url)); +const dtsPath = join(__dirname, "../.velite/index.d.ts"); +const indexPath = join(__dirname, "../.velite/index.js"); +let isUpdatingDts = false; +let isUpdatingIndex = false; + +async function replaceIndexDtsContents() { + isUpdatingDts = true; + + const data = await readFile(dtsPath, "utf8").catch((err) => { + console.error("Error reading file:", err); + isUpdatingDts = false; + }); + if (!data) return; + + const updatedContent = data.replace("'../velite.config'", "'../velite.config.js'"); + if (updatedContent === data) { + isUpdatingDts = false; + return; + } + + await writeFile(dtsPath, updatedContent, "utf8").catch((err) => { + console.error("Error writing file:", err); + }); + isUpdatingDts = false; +} + +async function replaceIndexContents() { + isUpdatingIndex = true; + + const data = await readFile(indexPath, "utf8").catch((err) => { + console.error("Error reading file:", err); + isUpdatingIndex = false; + }); + if (!data) return; + + const updatedContent = data.replaceAll(".json'", ".json' with { type: 'json' }"); + if (updatedContent === data) { + isUpdatingIndex = false; + return; + } + + await writeFile(indexPath, updatedContent, "utf8").catch((err) => { + console.error("Error writing file:", err); + }); + isUpdatingIndex = false; +} + +watch(dtsPath, async (eventType, filename) => { + if (eventType === "change" && !isUpdatingDts) { + console.info(`File ${filename} has been modified`); + replaceIndexDtsContents(); + } +}); + +watch(indexPath, async (eventType, filename) => { + if (eventType === "change" && !isUpdatingIndex) { + console.info(`File ${filename} has been modified`); + replaceIndexContents(); + } +}); diff --git a/sites/docs/package.json b/sites/docs/package.json index 2a32ca42e..963489df9 100644 --- a/sites/docs/package.json +++ b/sites/docs/package.json @@ -5,12 +5,12 @@ "license": "MIT", "private": true, "scripts": { - "dev": "concurrently \"pnpm:dev:content\" \"pnpm:dev:svelte\"", - "dev:content": "contentlayer dev", + "dev": "concurrently \"pnpm:dev:content\" \"pnpm:dev:svelte\" \"pnpm:replace:velite\"", + "dev:content": "velite dev --watch", "dev:svelte": "vite dev", - "build": "contentlayer build && pnpm build:search && vite build", - "build:content": "contentlayer build", - "build:content-cachebust": "contentlayer build --clearCache", + "build": "velite && node ./other/update-velite-output.js && pnpm build:search && vite build", + "replace:velite": "node ./other/watch-velite-output.js", + "build:content": "velite", "preview": "vite preview", "build:search": "node ./other/build-search-data.js", "check": "pnpm build:content && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json" @@ -29,7 +29,6 @@ "autoprefixer": "^10.4.17", "clsx": "^2.1.0", "concurrently": "^8.2.2", - "contentlayer": "^0.3.4", "eruda": "^3.0.1", "marked": "^14.1.2", "mdsx": "^0.0.6", @@ -54,6 +53,7 @@ "unified": "^11.0.4", "unist-builder": "^4.0.0", "unist-util-visit": "^5.0.0", + "velite": "^0.1.1", "vite": "^5.2.8" }, "type": "module", diff --git a/sites/docs/src/lib/config/navigation.ts b/sites/docs/src/lib/config/navigation.ts index a5ed6058d..73910ffaa 100644 --- a/sites/docs/src/lib/config/navigation.ts +++ b/sites/docs/src/lib/config/navigation.ts @@ -7,11 +7,7 @@ import CalendarBlank from "phosphor-svelte/lib/CalendarBlank"; import CableCar from "phosphor-svelte/lib/CableCar"; import Leaf from "phosphor-svelte/lib/Leaf"; import Joystick from "phosphor-svelte/lib/Joystick"; -import { - allComponentDocs, - allTypeHelperDocs, - allUtilityDocs, -} from "../../../.contentlayer/generated/index.mjs"; +import { componentDocs, typeHelperDocs, utilityDocs } from "$content/index.js"; export type NavItem = { title: string; @@ -35,7 +31,7 @@ export type Navigation = { sidebar: SidebarNavItem[]; }; -const filteredComponents = allComponentDocs; +const filteredComponents = componentDocs; /** * Generates the navigation items for the components section of the sidebar. @@ -62,7 +58,7 @@ function generateComponentsNav() { function generateUtilitiesNav(): SidebarNavItem[] { const utilityNavItems: SidebarNavItem[] = []; - for (const comp of allUtilityDocs) { + for (const comp of utilityDocs) { utilityNavItems.push({ title: comp.title, href: `/docs/utilities/${comp.slug}`, @@ -80,7 +76,7 @@ function generateUtilitiesNav(): SidebarNavItem[] { function generateTypeHelpersNav(): SidebarNavItem[] { const utilityNavItems: SidebarNavItem[] = []; - for (const comp of allTypeHelperDocs) { + for (const comp of typeHelperDocs) { utilityNavItems.push({ title: comp.title, href: `/docs/type-helpers/${comp.slug}`, diff --git a/sites/docs/src/lib/scripts/build-search.ts b/sites/docs/src/lib/scripts/build-search.ts index 4ffed05b6..5cd2e7234 100644 --- a/sites/docs/src/lib/scripts/build-search.ts +++ b/sites/docs/src/lib/scripts/build-search.ts @@ -1,13 +1,8 @@ -import { - allComponentDocs, - allDocs, - allTypeHelperDocs, - allUtilityDocs, -} from "contentlayer/generated/index.mjs"; import removeMd from "remove-markdown"; +import { componentDocs, docs, typeHelperDocs, utilityDocs } from "$content/index.js"; export function buildDocsIndex() { - const components = allComponentDocs.map((doc) => { + const components = componentDocs.map((doc) => { const content = removeMd(doc.body.raw, { replaceLinksWithURL: true, gfm: true, @@ -22,7 +17,7 @@ export function buildDocsIndex() { }; }); - const utilities = allUtilityDocs.map((doc) => { + const utilities = utilityDocs.map((doc) => { const content = removeMd(doc.body.raw, { replaceLinksWithURL: true, gfm: true, @@ -37,7 +32,7 @@ export function buildDocsIndex() { }; }); - const typeHelpers = allTypeHelperDocs.map((doc) => { + const typeHelpers = typeHelperDocs.map((doc) => { const content = removeMd(doc.body.raw, { replaceLinksWithURL: true, gfm: true, @@ -52,7 +47,7 @@ export function buildDocsIndex() { }; }); - const mainPages = allDocs.map((doc) => { + const mainPages = docs.map((doc) => { const content = removeMd(doc.body.raw, { replaceLinksWithURL: true, gfm: true, diff --git a/sites/docs/src/lib/utils/docs.ts b/sites/docs/src/lib/utils/docs.ts index 6f8445a70..34e0865b9 100644 --- a/sites/docs/src/lib/utils/docs.ts +++ b/sites/docs/src/lib/utils/docs.ts @@ -1,6 +1,6 @@ import { error, redirect } from "@sveltejs/kit"; -import type { Doc } from "contentlayer/generated/index.js"; import type { Component } from "svelte"; +import type { Doc } from "$content/index.js"; import { getAPISchemas, isBit } from "$lib/content/api-reference/index.js"; import type { APISchema } from "$lib/types/index.js"; diff --git a/sites/docs/src/routes/api/search.json/search.json b/sites/docs/src/routes/api/search.json/search.json index 1d622f89f..3d110b523 100644 --- a/sites/docs/src/routes/api/search.json/search.json +++ b/sites/docs/src/routes/api/search.json/search.json @@ -1 +1 @@ -[{"title":"Accordion","content":" import { APISection, ComponentPreviewV2, AccordionDemo, AccordionDemoTransitions, AccordionDemoCustom, Callout } from '$lib/components/index.js' export let schemas {#snippet preview()} {/snippet} Overview The Accordion component is a versatile UI element that organizes content into collapsible sections, enabling users to focus on specific information while reducing visual clutter. It's particularly useful for presenting large amounts of related content in a compact, navigable format. Key Features Customizable Behavior**: Can be configured for single or multiple open sections. Accessibility**: ARIA attributes for screen reader compatibility and keyboard navigation. Transition Support**: CSS variables and data attributes for smooth transitions between states. Flexible State Management**: Supports controlled and uncontrolled state, take control if needed. Compound Component Structure**: Provides a set of subcomponents that work together to create a fully-featured accordion. Architecture The Accordion component is composed of several subcomponents, each with a specific role: Root**: The root element that wraps all accordion items and manages the overall state. Item**: Individual sections within the accordion. Trigger**: The button that toggles the visibility of the content. Header**: The title or heading of each item. Content**: The expandable/collapsible body of each item. Structure Here's an overview of how the Accordion component is structured in code: import { Accordion } from \"bits-ui\"; Reusable Components If you're planning to use the Accordion component throughout your application, it's recommended to create reusable wrapper components to reduce the amount of code you need to write each time. For each invidual item, you need an Accordion.Item, Accordion.Header, Accordion.Trigger and Accordion.Content component. We can combine these into a single MyccordionItem component that makes it easier to reuse. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { title: string; content: string; }; let { title, content, ...restProps }: Props = $props(); {item.title} {content} We used the $2 type helper to omit the child and children snippet props from Accordion.ItemProps, since we are opting out of using $2 and are already taking care of rendering the children as text via the content prop. For our MyAccordion component, we'll accept all the props that Accordion.Root accepts, as well as an additional items prop that will be used to render the MyAccordionItem components. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; import MyAccordionItem from \"$lib/components/MyAccordionItem.svelte\"; type Item = { value?: string; title: string; content: string; disabled?: boolean; }; let { value = $bindable(), ref = $bindable(null), ...restProps }: WithoutChildrenOrChild & { items: Item[]; } = $props(); {#each items as item, i (item.title + i)} {/each} import { MyAccordion, MyAccordionItem } from \"$lib/components\"; Content 1 Content 2 Content 3 Managing Value State Bits UI offers several approaches to manage and synchronize the Accordion's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the accordion's internal state. import { Accordion } from \"bits-ui\"; let myValue = $state([]); { myValue = [\"item-1\", \"item-2\"]; }} Open Items 1 and 2 Key Benefits Simplifies state management Automatically updates myValue when the accordion changes (e.g., via clicking on an item's trigger) Allows external control (e.g., opening an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Accordion } from \"bits-ui\"; let myValue = $state([]); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the accordion's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the accordion responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Accordion.Root component. Provide a value prop to Accordion.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Accordion } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Single Type Set the type prop to \"single\" to allow only one accordion item to be open at a time. Multiple Type Set the type prop to \"multiple\" to allow multiple accordion items to be open at the same time. Default Open Items To set default open items, pass them as the value prop, which will be an array if the type is \"multiple\", or a string if the type is \"single\". Disable Items To disable an individual accordion item, set the disabled prop to true. This will prevent users from interacting with the item. Svelte Transitions The Accordion component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Accordion components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of the Accordion.Content. {#snippet child({ props, open })} {#if open} This is the accordion content that will transition in and out. {/if} {/snippet} In this example: The forceMount prop ensures the components are always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directives (transition:fade and transition:fly) apply the animations. {#snippet preview()} {/snippet} Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; import type { Snippet } from \"svelte\"; import { fade } from \"svelte/transition\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyAccordionContent component alongside the other Accordion primitives throughout your application: A ","description":"Organizes content into collapsible sections, allowing users to focus on one or more sections at a time.","href":"/docs/components/accordion"},{"title":"Alert Dialog","content":" import { APISection, ComponentPreviewV2, AlertDialogDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Key Features Compound Component Structure**: Offers a set of subcomponents that work together to create a fully-featured alert dialog. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Customizable**: Each subcomponent can be styled and configured independently. Portal Support**: Content can be rendered in a portal, ensuring proper stacking context. Managed Focus**: Automatically manages focus, with the option to take control if needed. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the dialog's open state. Architecture The Alert Dialog component is composed of several subcomponents, each with a specific role: Root**: The main container component that manages the state of the dialog. Provides context for all child components. Trigger**: A button that toggles the dialog's open state. Portal**: Renders its children in a portal, outside the normal DOM hierarchy. Overlay**: A backdrop that sits behind the dialog content. Content**: The main container for the dialog's content. Title**: Renders the dialog's title. Description**: Renders a description or additional context for the dialog. Cancel**: A button that closes the dialog by cancelling the action. Action**: A button that closes the dialog by taking an action. Structure import { AlertDialog } from \"bits-ui\"; Reusable Components Bits UI provides a decent number of components to construct an Alert Dialog. The idea is to provide a set of building blocks that can be used to create a variety of different components. It's recommended to use these components to build your own reusable Alert Dialog components that can be used throughout your application. The following example shows at a high level how you might create a reusable Alert Dialog component. We've mixed and matched string props and snippets to demonstrate the flexibility of the component API. Use whatever makes sense for you. This example is used in a few places throughout this documentation page to give you a better idea of how it's used. import type { Snippet } from \"svelte\"; import { AlertDialog, type WithoutChild } from \"bits-ui\"; type Props = AlertDialog.RootProps & { buttonText: string; title: Snippet; description: Snippet; contentProps?: WithoutChild; // ...other component props if you wish to pass them }; let { open = $bindable(false), children, buttonText, contentProps, title, description, ...restProps }: Props = $props(); {buttonText} {@render title()} {@render description()} {@render children?.()} Cancel Confirm You can then use the MyAlertDialog component in your application like so: import MyAlertDialog from \"$lib/components/MyAlertDialog.svelte\"; {#snippet title()} Delete your account {/snippet} {#snippet description()} This action cannot be undone. {/snippet} Alternatively, you can define the snippets separately and pass them as props to the component: import MyAlertDialog from \"$lib/components/MyAlertDialog.svelte\"; {#snippet title()} Delete your account {/snippet} {#snippet description()} This action cannot be undone. {/snippet} Managing Open State Bits UI offers several approaches to manage and synchronize the Alert Dialog's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { AlertDialog } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Dialog Key Benefits Simplifies state management Automatically updates isOpen when the dialog closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { AlertDialog } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. import { AlertDialog } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Focus Focus Trap By default, when a dialog is opened, focus will be trapped within the Dialog, preventing the user from interacting with the rest of the page. This follows the $2 for alert dialogs. Although it isn't recommended unless absolutely necessary, you can disabled this beahvior by setting the trapFocus prop to false on the AlertDialog.Content component. Open Focus By default, when a dialog is opened, focus will be set to the AlertDialog.Cancel button if it exists, or the first focusable element within the AlertDialog.Content. This ensures that users navigating my keyboard end up somewhere within the Dialog that they can interact with. You can override this behavior using the onOpenAutoFocus prop on the AlertDialog.Content component. It's highly recommended that you use this prop to focus something within the Dialog. You'll first need to cancel the default behavior of focusing the first focusable element by cancelling the event passed to the onOpenAutoFocus callback. You can then focus whatever you wish. import { AlertDialog } from \"bits-ui\"; let nameInput = $state(); Open AlertDialog { e.preventDefault(); nameInput?.focus(); }} Close Focus By default, when a dialog is closed, focus will be set to the trigger element of the dialog. You can override this behavior using the onCloseAutoFocus prop on the AlertDialog.Content component. You'll need to cancel the default behavior of focusing the trigger element by cancelling the event passed to the onCloseAutoFocus callback, and then focus whatever you wish. import { AlertDialog } from \"bits-ui\"; let nameInput = $state(); Open AlertDialog { e.preventDefault(); nameInput?.focus(); }} Advanced Behaviors The Alert Dialog component offers several advanced features to customize its behavior and enhance user experience. This section covers scroll locking, escape key handling, and interaction outside the dialog. Scroll Lock By default, when an Alert Dialog opens, scrolling the body is disabled. This provides a more native-like experience, focusing user attention on the dialog content. Customizing Scroll Behavior To allow body scrolling while the dialog is open, use the preventScroll prop on AlertDialog.Content: Enabling body scroll may affect user focus and accessibility. Use this option judiciously. Escape Key Handling By default, pressing the Escape key closes an open Alert Dialog. Bits UI provides two methods to customize this behavior. Method 1: escapeKeydownBehavior The escapeKeydownBehavior prop allows you to customize the behavior taken by the component when the Escape key is pressed. It accepts one of the following values: 'close' (default): Closes the Alert Dialog immediately. 'ignore': Prevents the Alert Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the key press and not close. To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onEscapeKeydown For more granular control, override the default behavior using the onEscapeKeydown prop: { e.preventDefault(); // do something else instead }} This method allows you to implement custom logic when the Escape key is pressed. Interaction Outside By default, interacting outside the Alert Dialog content area closes the Alert Dialog. Bits UI offers two ways to modify this behavior. Method 1: interactOutsideBehavior The interactOutsideBehavior prop allows you to customize the behavior taken by the component when an interaction (touch, mouse, or pointer event) occurs outside the content. It accepts one of the following values: 'close' (default): Closes the Alert Dialog immediately. 'ignore': Prevents the Alert Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the event and not close. To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Alert.Content: Method 2: onInteractOutside For custom handling of outside interactions, you can override the default behavior using the onInteractOutside prop: { e.preventDefault(); // do something else instead }} This approach allows you to implement specific behaviors when users interact outside the Alert Dialog content. Best Practices Scroll Lock**: Consider your use case carefully before disabling scroll lock. It may be necessary for dialogs with scrollable content or for specific UX requirements. Escape Keydown**: Overriding the default escape key behavior should be done thoughtfully. Users often expect the escape key to close modals. Outside Interactions**: Ignoring outside interactions can be useful for important dialogs or multi-step processes, but be cautious not to trap users unintentionally. Accessibility**: Always ensure that any customizations maintain or enhance the dialog's accessibility. User Expectations**: Try to balance custom behaviors with common UX patterns to avoid confusing users. By leveraging these advanced features, you can create highly customized dialog experiences while maintaining usability and accessibility standards. Nested Dialogs Dialogs can be nested within each other to create more complex layouts. See the $2 component for more information on nested dialogs. Svelte Transitions See the $2 component for more information on Svelte Transitions with dialog components. ","description":"A modal window that alerts users with important information and awaits their acknowledgment or action.","href":"/docs/components/alert-dialog"},{"title":"Aspect Ratio","content":" import { APISection, ComponentPreviewV2, AspectRatioDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Architecture Root**: The root component which contains the aspect ratio logic Structure Here's an overview of how the Aspect Ratio component is structured in code: import { AspectRatio } from \"bits-ui\"; Reusable Component If you plan on using a lot of AspectRatio components throughout your application, you can create a reusable component that combines the AspectRatio.Root and whatever other elements you'd like to render within it. In the following example, we're creating a reusable MyAspectRatio component that takes in a src prop and renders an img element with the src prop. import { AspectRatio, type WithoutChildrenOrChild } from \"bits-ui\"; let { src, alt, ref = $bindable(null), imageRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { src: string; alt: string; imageRef?: HTMLImageElement | null; } = $props(); You can then use the MyAspectRatio component in your application like so: import MyAspectRatio from \"$lib/components/MyAspectRatio.svelte\"; Custom Ratio Use the ratio prop to set a custom aspect ratio for the image. ","description":"Displays content while maintaining a specified aspect ratio, ensuring consistent visual proportions.","href":"/docs/components/aspect-ratio"},{"title":"Avatar","content":" import { APISection, ComponentPreviewV2, AvatarDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Avatar component is designed to represent a user or entity within your application's user interface. It provides a flexible and accessible way to display profile pictures or placeholder images. Key Features Compound Component Structure**: Offers a set of subcomponents that work together to create a fully-featured avatar. Fallback Mechanism**: Provides a fallback when the primary image is unavailable or loading. Customizable**: Each subcomponent can be styled and configured independently to match your design system. Architecture The Avatar component is composed of several subcomponents, each with a specific role: Root**: The main container component that manages the state of the avatar. Image**: The primary image element that displays the user's profile picture or a representative image. Fallback**: The fallback element that displays alternative content when the primary image is unavailable or loading. Structure Here's an overview of how the Avatar component is structured in code: import { Avatar } from \"bits-ui\"; Reusable Components You can create your own reusable components that combine the Avatar primitives and simplify the usage throughout your application. In the following example, we're creating a reusable MyAvatar component that takes in a src and fallback prop and renders an Avatar.Root component with an Avatar.Image and Avatar.Fallback component. import { Avatar, type WithoutChildrenOrChild } from \"bits-ui\"; let { src, alt, fallback, ref = $bindable(null), imageRef = $bindable(null), fallbackRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { src: string; alt: string; fallback: string; imageRef?: HTMLImageElement | null; fallbackRef?: HTMLElement | null; } = $props(); {fallback} You could then use the MyAvatar component in your application like so: import MyAvatar from \"$lib/components/MyAvatar.svelte\"; ","description":"Represents a user or entity with a recognizable image or placeholder in UI elements.","href":"/docs/components/avatar"},{"title":"Button","content":" import { APISection, ComponentPreviewV2, ButtonDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Button } from \"bits-ui\"; ","description":"A component that if passed a `href` prop will render an anchor element instead of a button element.","href":"/docs/components/button"},{"title":"Calendar","content":" import { APISection, ComponentPreviewV2, CalendarDemo, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { Calendar } from \"bits-ui\"; {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} Placeholder The placeholder prop for the Calendar.Root component determines what date our calendar should start with when the user hasn't selected a date yet. It also determines the current \"view\" of the calendar. As the user navigates through the calendar, the placeholder will be updated to reflect the currently focused date in that view. By default, the placeholder will be set to the current date, and be of type CalendarDate. Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the Calendar.Root component. Provide a placeholder prop to Calendar.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { Calendar } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the Calendar.Root component. Provide a value prop to Calendar.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Calendar } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Default Value Often, you'll want to start the Calendar.Root component with a default value. Likely this value will come from a database in the format of an ISO 8601 string. You can use the parseDate function from the @internationalized/date package to parse the string into a CalendarDate object. import { Calendar } from \"bits-ui\"; import { parseDate } from \"@internationalized/date\"; // this came from a database/API call const date = \"2024-08-03\"; let value = $state(parseDate(date)); Validation Minimum Value You can set a minimum value for the calendar by using the minValue prop on Calendar.Root. If a user selects a date that is less than the minimum value, the calendar will be marked as invalid. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const yesterday = todayDate.subtract({ days: 1 }); Maximum Value You can set a maximum value for the calendar by using the maxValue prop on Calendar.Root. If a user selects a date that is greater than the maximum value, the calendar will be marked as invalid. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); Unavailable Dates You can specify speciifc dates that are unavailable for selection by using the isDateUnavailable prop. This prop accepts a function that returns a boolean value indicating whether a date is unavailable or not. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, isNotNull } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); function isDateUnavailable(date: DateValue) { return date.day === 1; } Disabled Dates You can specify speciifc dates that are disabled for selection by using the isDateDisabled prop. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, isNotNull } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); function isDateDisabled(date: DateValue) { return date.day === 1; } ","description":"Displays dates and days of the week, facilitating date-related interactions.","href":"/docs/components/calendar"},{"title":"Checkbox","content":" import { APISection, ComponentPreviewV2, CheckboxDemo, CheckboxDemoCustom, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Checkbox component provides a flexible and accessible way to create checkbox inputs in your Svelte applications. It supports three states: checked, unchecked, and indeterminate, allowing for complex form interactions and data representations. Key Features Tri-State Support**: Handles checked, unchecked, and indeterminate states, providing versatility in form design. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the checkbox's checked state. Architecture The Checkbox component is composed of the following parts: Root**: The main component that manages the state and behavior of the checkbox. Structure Here's an overview of how the Checkbox component is structured in code: import { Checkbox } from \"bits-ui\"; {#snippet children({ checked })} {#if checked === \"indeterminate\"} {:else if checked} ✅ {:else} ❌ {/if} {/snippet} Reusable Components It's recommended to use the Checkbox primitive to create your own custom checkbox component that can be used throughout your application. In the example below, we're using the Checkbox and $2 components to create a custom checkbox component. import { Checkbox, Label, useId, type WithoutChildrenOrChild } from \"bits-ui\"; let { id = useId(), checked = $bindable(false), ref = $bindable(null), labelRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { labelText: string; labelRef?: HTMLLabelElement | null; } = $props(); {#snippet children({ checked })} {#if checked === \"indeterminate\"} {:else if checked} ✅ {:else} ❌ {/if} {/snippet} {labelText} You can then use the MyCheckbox component in your application like so: import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; Managing Checked State Bits UI offers several approaches to manage and synchronize the Checkbox's checked state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:checked directive. This method automatically keeps your local state in sync with the checkbox's internal state. import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; let myChecked = $state(false); (myChecked = false)}> uncheck Key Benefits Simplifies state management Automatically updates myChecked when the checkbox changes (e.g., via clicking on the checkbox) Allows external control (e.g., checking via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onCheckedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; let myChecked = $state(false); { myChecked = checked; if (checked === \"indeterminate\") { // do something different } // additional logic here. }} /> Use Cases Implementing custom behaviors on checked/unchecked Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the checkbox's checked state, use the controlledChecked prop. This approach requires you to manually manage the checked state, giving you full control over when and how the checkbox responds to change events. To implement controlled state: Set the controlledChecked prop to true on the Checkbox.Root component. Provide a checked prop to Checkbox.Root, which should be a variable holding the current state. Implement an onCheckedChange handler to update the state when the internal state changes. import { Checkbox } from \"bits-ui\"; let myChecked = $state(false); (myChecked = c)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Disabled State You can disable the checkbox by setting the disabled prop to true. HTML Forms If you set the name prop, a hidden checkbox input will be rendered to submit the value of the checkbox with a form. By default, the checkbox will be submitted with default checkbox value of 'on' if the checked prop is true. Custom Input Value If you'd prefer to submit a different value, you can use the value prop to set the value of the hidden input. For example, if you wanted to submit a string value, you could do the following: Required If you want to make the checkbox required, you can use the required prop. This will apply the required attribute to the hidden input element, ensuring that proper form submission is enforced. ","description":"Allow users to switch between checked, unchecked, and indeterminate states.","href":"/docs/components/checkbox"},{"title":"Collapsible","content":" import { APISection, ComponentPreviewV2, CollapsibleDemo, CollapsibleDemoTransitions, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Collapsible component enables you to create expandable and collapsible content sections. It provides an efficient way to manage space and organize information in user interfaces, enabling users to show or hide content as needed. Key Features Accessibility**: ARIA attributes for screen reader compatibility and keyboard navigation. Transition Support**: CSS variables and data attributes for smooth transitions between states. Flexible State Management**: Supports controlled and uncontrolled state, take control if needed. Compound Component Structure**: Provides a set of subcomponents that work together to create a fully-featured collapsible. Architecture The Accordion component is composed of a few subcomponents, each with a specific role: Root**: The parent container that manages the state and context for the collapsible functionality. Trigger**: The interactive element (e.g., button) that toggles the expanded/collapsed state of the content. Content**: The container for the content that will be shown or hidden based on the collapsible state. Structure Here's an overview of how the Collapsible component is structured in code: import { Collapsible } from \"bits-ui\"; Reusable Components It's recommended to use the Collapsible primitives to create your own custom collapsible component that can be used throughout your application. import { Collapsible, type WithoutChild } from \"bits-ui\"; type Props = WithoutChild & { buttonText: string; }; let { open = $bindable(false), ref = $bindable(null), buttonText, children, ...restProps }: Props = $props(); {buttonText} {@render children?.()} You can then use the MyCollapsible component in your application like so: import MyCollapsible from \"$lib/components/MyCollapsible.svelte\"; Here is my collapsible content. Managing Open State Bits UI offers several approaches to manage and synchronize the Collapsible's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the Collapsible's internal state. import { Collapsible } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Collapsible Key Benefits Simplifies state management Automatically updates isOpen when the collapsible closes (e.g., via trigger press) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Collapsible } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the Collapsible's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the collapsible responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Collapsible.Root component. Provide an open prop to Collapsible.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Collapsible } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Svelte Transitions The Collapsible component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Collapsible components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of the Collapsible.Content. import { Collapsible } from \"bits-ui\"; import { fade } from \"svelte/transition\"; Open {#snippet child({ props, open })} {#if open} {/if} {/snippet} In this example: The forceMount prop ensures the content is always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directive (transition:fade) apply the animations. Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Collapsible, type WithoutChildrenOrChild } from \"bits-ui\"; import { fade } from \"svelte/transition\"; import type { Snippet } from \"svelte\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyCollapsibleContent component alongside the other Collapsible primitives throughout your application: import { Collapsible } from \"bits-ui\"; import { MyCollapsibleContent } from \"$lib/components\"; Open ","description":"Conceals or reveals content sections, enhancing space utilization and organization.","href":"/docs/components/collapsible"},{"title":"Combobox","content":" import { APISection, ComponentPreviewV2, ComboboxDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Combobox component combines the functionality of an input field with a dropdown list of selectable options. It provides users with the ability to search, filter, and select from a predefined set of choices. Key Features Keyboard Navigation**: Full support for keyboard interactions, allowing users to navigate and select options without using a mouse. Customizable Rendering**: Flexible architecture for rendering options, including support for grouped items. Accessibility**: Built with ARIA attributes and keyboard interactions to ensure screen reader compatibility and accessibility standards. Portal Support**: Ability to render the dropdown content in a portal, preventing layout issues in complex UI structures. Architecture The Combobox component is composed of several subcomponents, each with a specific role: Root**: The main container component that manages the state and context for the combobox. Input**: The input field that allows users to enter search queries. Trigger**: The button or element that opens the dropdown list. Portal**: Responsible for portaling the dropdown content to the body or a custom target. Group**: A container for grouped items, used to group related items. GroupHeading**: A heading for a group of items, providing a descriptive label for the group. Item**: An individual item within the list. Separator**: A visual separator between items. Content**: The dropdown container that displays the items. It uses $2 to position the content relative to the trigger. ContentStatic**: An alternative to the Content component, that enables you to opt-out of Floating UI and position the content yourself. Arrow**: An arrow element that points to the trigger when using the Combobox.Content component. Structure Here's an overview of how the Combobox component is structured in code: import { Combobox } from \"bits-ui\"; Reusable Components It's recommended to use the Combobox primitives to build your own custom combobox component that can be reused throughout your application. import { Combobox, type WithoutChildrenOrChild, mergeProps } from \"bits-ui\"; type Item = { value: string; label: string; }; type Props = Combobox.RootProps & { items: Item[]; inputProps?: WithoutChildrenOrChild; contentProps?: WithoutChildrenOrChild; } let { items, value = $bindable(), open = $bindable(false), inputProps, contentProps, ...restProps }: Props = $props(); let searchValue = $state(\"\"); const filteredItems = $derived.by(() => { if (searchValue === \"\") return items; return items.filter((item) => item.label.toLowerCase().includes(searchValue.toLowerCase())); }) function handleInput(e: Event & { currentTarget: HTMLInputElement }) { searchValue = e.currentTarget.value; } function handleOpenChange(newOpen: boolean) { if (!newOpen) searchValue = \"\"; } const mergedRootProps = $derived(mergeProps(restProps, { onOpenChange: handleOpenChange })) const mergedInputProps = $derived(mergeProps(inputProps, { oninput: handleInput } )) Open {#each filteredItems as item, i (i + item.value)} {#snippet children({ selected })} {item.label} {selected ? \"✅\" : \"\"} {/snippet} {:else} No results found {/each} import { CustomCombobox } from \"$lib/components\"; const items = [ { value: \"mango\", label: \"Mango\" }, { value: \"watermelon\", label: \"Watermelon\" }, { value: \"apple\", label: \"Apple\" }, // ... ]; Managing Value State Bits UI offers several approaches to manage and synchronize the Combobox's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Combobox.Root component. Provide a value prop to Combobox.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the Combobox's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = true)}> Open Key Benefits Simplifies state management Automatically updates myOpen when the internal state changes (e.g., via clicking on the trigger/input) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); { myOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledOpen prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledOpen prop to true on the Combobox.Root component. Provide an open prop to Combobox.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Opt-out of Floating UI When you use the Combobox.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Combobox.ContentStatic component. When using this component, you'll need to handle the positioning of the content yourself. Keep in mind that using Combobox.Portal alongside Combobox.ContentStatic may result in some unexpected positioning behavior, feel free to not use the portal or work around it. Custom Anchor By default, the Combobox.Content is anchored to the Combobox.Trigger component, which determines where the content is positioned. If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the Combobox.Content component. import { Combobox } from \"bits-ui\"; let customAnchor = $state(null!); What is the Viewport? The Combobox.Viewport component is used to determine the size of the content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Combobox.Viewport component. Scroll Up/Down Buttons The Combobox.ScrollUpButton and Combobox.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. You must use the Combobox.Viewport component when using the scroll buttons. Native Scrolling/Overflow If you don't want to use the scroll buttons and prefer to use the standard scrollbar/overflow behavior, you can omit the Combobox.Scroll[Up|Down]Button components and the Combobox.Viewport component. You'll need to set a height on the Combobox.Content component and appropriate overflow styles to enable scrolling. Scroll Lock By default, when a user opens the Combobox, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. Highlighted Items The Combobox component follows the $2 for highlighting items. This means that the Combobox.Input retains focus the entire time, even when navigating with the keyboard, and items are highlighted as the user navigates them. Styling Highlighted Items You can use the data-highlighted attribute on the Combobox.Item component to style the item differently when it is highlighted. onHighlight / onUnhighlight To trigger side effects when an item is highlighted or unhighlighted, you can use the onHighlight and onUnhighlight props. console.log('I am highlighted!')} onUnhighlight={() => console.log('I am unhighlighted!')} /> ","description":"Enables users to pick from a list of options displayed in a dropdown.","href":"/docs/components/combobox"},{"title":"Command","content":" import { APISection, ComponentPreviewV2, CommandDemo, CommandDemoDialog, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Command component, also known as a command menu, is designed to provide users with a quick and efficient way to search, filter, and select items within an application. It combines the functionality of a search input with a dynamic, filterable list of commands or options, making it ideal for applications that require fast navigation or action execution. Key Features Dynamic Filtering**: As users type in the input field, the list of commands or items is instantly filtered and sorted based on an (overridable) scoring algorithm. Keyboard Navigation**: Full support for keyboard interactions, allowing users to quickly navigate and select items without using a mouse. Grouped Commands**: Ability to organize commands into logical groups, enhancing readability and organization. Empty and Loading States**: Built-in components to handle scenarios where no results are found or when results are being loaded. Accessibility**: Designed with ARIA attributes and keyboard interactions to ensure screen reader compatibility and accessibility standards. Architecture The Command component is composed of several subcomponents, each with a specific role: Root**: The main container that manages the overall state and context of the command menu. Input**: The text input field where users can type to search or filter commands. List**: The container for the list of commands or items. Viewport**: The visible area of the command list, which applies CSS variables to handle dynamic resizing/animations based on the height of the list. Empty**: A component to display when no results are found. Loading**: A component to display while results are being fetched or processed. Group**: A container for a group of items within the command menu. GroupHeading**: A header element to provide an accessible label for a group of items. GroupItems**: A container for the items within a group. Item**: Individual selectable command or item. LinkItem**: A variant of Command.Item specifically for link-based actions. Separator**: A visual separator to divide different sections of the command list. Structure Here's an overview of how the Command component is structured in code: import { Combobox } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the Command's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Command.Root component. Provide a value prop to Command.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex value change logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. In a Modal You can combine the Command component with the Dialog component to display the command menu within a modal. {#snippet preview()} {/snippet} Filtering Custom Filter By default, the Command component uses a scoring algorithm to determine how the items should be sorted/filtered. You can provide a custom filter function to override this behavior. The function should return a number between 0 and 1, with 1 being a perfect match, and 0 being no match, resulting in the item being hidden entirely. The following example shows how you might implement a strict substring match filter: import { Command } from \"bits-ui\"; function customFilter(value: string, search: string, keywords?: string[]): number { return value.includes(search) ? 1 : 0; } Disable Filtering You can disable filtering by setting the shouldFilter prop to false. This is useful when you have a lot of custom logic, need to fetch items asynchronously, or just want to handle filtering yourself. You'll be responsible for iterating over the items and determining which ones should be shown. Item Selection You can use the onSelect prop to handle the selection of items. console.log(\"selected something!\")} /> Links If you want one of the items to get all the benefits of a link (prefetching, etc.), you should use the Command.LinkItem component instead of the Command.Item component. The only difference is that the Command.LinkItem component will render an a element instead of a div element. ","description":"A command menu component that can be used to search, filter, and select items.","href":"/docs/components/command"},{"title":"Context Menu","content":" import { APISection, ComponentPreviewV2, ContextMenuDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { ContextMenu } from \"bits-ui\"; {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} Reusable Components If you're planning to use Context Menu in multiple places, you can create a reusable component that wraps the Context Menu component. This example shows you how to create a Context Menu component that accepts a few custom props that make it more capable. import type { Snippet } from \"svelte\"; import { ContextMenu, type WithoutChild } from \"bits-ui\"; type Props = ContextMenu.Props & { trigger: Snippet; items: string[]; contentProps?: WithoutChild; // other component props if needed }; let { open = $bindable(false), children, trigger, items, contentProps, ...restProps }: Props = $props(); {@render trigger()} Select an Office {#each items as item} {item} {/each} You can then use the CustomContextMenu component like this: import CustomContextMenu from \"./CustomContextMenu.svelte\"; {#snippet triggerArea()} Right-click me {/snippet} Alternatively, you can define the snippet(s) separately and pass them as props to the component: import CustomContextMenu from \"./CustomContextMenu.svelte\"; {#snippet triggerArea()} Right-click me {/snippet} Managing Open State Bits UI offers several approaches to manage and synchronize the Context Menu's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { ContextMenu } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Context Menu Key Benefits Simplifies state management Automatically updates isOpen when the menu closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { ContextMenu } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the ContextMenu.Root component. Provide an open prop to ContextMenu.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { ContextMenu } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Checkbox Items You can use the ContextMenu.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { ContextMenu } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} See the $2 for more information. Radio Groups You can combine the ContextMenu.RadioGroup and ContextMenu.RadioItem components to create a radio group within a menu. import { ContextMenu } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} See the $2 and $2 APIs for more information. Nested Menus You can create nested menus using the ContextMenu.Sub component to create complex menu structures. import { ContextMenu } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the ContextMenu.Content component to use Svelte Transitions or another animation library that requires more control. import { ContextMenu } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Displays options or actions relevant to a specific context or selected item, triggered by a right-click.","href":"/docs/components/context-menu"},{"title":"Date Field","content":" import { CalendarDateTime, CalendarDate, now, getLocalTimeZone, parseDate, today } from \"@internationalized/date\"; import { APISection, ComponentPreviewV2, DateFieldDemo, DateFieldDemoCustom, DemoContainer, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Overview The DateField component is an alternative to the native `` element. It provides a more flexible and customizable way to select dates within a designated field. Before jumping into the DateField component, it's important to understand how dates and times are handled in Bits UI. You can learn more about this on the $2 page. Structure import { DateField } from \"$lib\"; Check-in date {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} Reusable Components It's recommended to use the DateField primitives to build your own custom date field component that can be used throughout your application. The following example shows how you might create a reusable MyDateField component that can be used throughout your application. For style inspiration, reference the featured demo at the top of this page. import { DateField, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { labelText: string; }; let { value, placeholder, name, ...restProps }: Props = $props(); {labelText} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {#snippet preview()} {/snippet} We'll be using this newly created MyDateField component in the following demos and examples to prevent repeating the same code, so be sure to reference it as you go through the documentation. Segments A segment of the DateField represents a not only a specific part of the date, such as the day, month, year, hour, but can also reference a \"literal\" which is typically a separator between the different parts of the date, and varies based on the locale. Notice that in the MyDateField component we created, we're styling the DateField.Segment components differently based on whether they are a \"literal\" or not. Placeholder The placeholder prop for the DateField.Root component isn't what is displayed when the field is empty, but rather what date our field should start with when the user attempts to cycle through the segments. The placeholder can also be used to set a granularity for the date field, which will determine which type of DateValue object is used for the value. By default, the placeholder will be set to the current date, and be of type CalendarDate. However, if we wanted this date field to also allow for selecting a time, we could set the placeholder to a CalendarDateTime object. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDateTime } from \"@internationalized/date\"; If we're collecting a date from the user where we want the timezone as well, we can use a ZonedDateTime object instead. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { now, getLocalTimeZone } from \"@internationalized/date\"; NOTE: If you're creating a date field for something like a birthday, ensure your placeholder is set in a leap year to ensure users born on a leap year will be able to select the correct date. Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateField.Root component. Provide a placeholder prop to DateField.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateField } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateField.Root component. Provide a value prop to DateField.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateField } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Default Value Often, you'll want to start the DateField.Root component with a default value. Likely this value will come from a database in the format of an ISO 8601 string. You can use the parseDate function from the @internationalized/date package to parse the string into a CalendarDate object. import { DateField } from \"bits-ui\"; import { parseDate } from \"@internationalized/date\"; // this came from a database/API call const date = \"2024-08-03\"; let value = $state(parseDate(date)); Now our input is populated with the default value. In addition to the parseDate function, you can also use parseDateTime or parseZonedDateTime to parse the string into a CalendarDateTime or ZonedDateTime object respectively. Validation Minimum Value You can set a minimum value for the DateField.Root component by using the minValue prop. If a user selects a date that is less than the minimum value, the date field will be marked as invalid. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const yesterday = todayDate.subtract({ days: 1 }); In the example above, we're setting the minimum value to today, and the default value to yesterday. This causes the date field to be marked as invalid, and we can style it accordingly. If you adjust the date to be greater than the minimum value, the invalid state will be cleared. Maximum Value You can set a maximum value for the DateField.Root component by using the maxValue prop. If a user selects a date that is greater than the maximum value, the date field will be marked as invalid. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); In the example above, we're setting the maximum value to today, and the default value to tomorrow. This causes the date field to be marked as invalid, and we can style it accordingly. If you adjust the date to be less than the maximum value, the invalid state will be cleared. Unavailable Dates You can specify speciifc dates that are unavailable for selection by using the isDateUnavailable prop. This prop accepts a function that returns a boolean value indicating whether a date is unavailable or not. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDate, type DateValue } from \"@internationalized/date\"; const value = new CalendarDate(2024, 8, 2); function isDateUnavailable(date: DateValue) { return date.day === 1; } date.day === 1} value={new CalendarDate(2024, 8, 2)} /> In the example above, we're setting the isDateUnavailable prop to a function that returns true for the first day of the month. Try selecting a date that is the first day of the month to see the date field marked as invalid. Granularity The granularity prop sets the granularity of the date field, which determines which segments are rendered in the date field. The granularity can be set to either 'day', 'hour', 'minute', or 'second'. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDate } from \"@internationalized/date\"; const value = new CalendarDateTime(2024, 8, 2, 12, 30); In the example above, we're setting the granularity to 'second', which means that the date field will include an additional segment for the seconds. ","description":"Enables users to input specific dates within a designated field.","href":"/docs/components/date-field"},{"title":"Date Picker","content":" import { APISection, ComponentPreviewV2, DatePickerDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DatePicker } from \"bits-ui\"; {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DatePicker.Root component. Provide a placeholder prop to DatePicker.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DatePicker.Root component. Provide a value prop to DatePicker.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the component's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open DatePicker Key Benefits Simplifies state management Automatically updates isOpen when the picker closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DatePicker.Root component. Provide an open prop to DatePicker.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Facilitates the selection of dates through an input and calendar-based interface.","href":"/docs/components/date-picker"},{"title":"Date Range Field","content":" import { APISection, ComponentPreviewV2, DateRangeFieldDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DateRangeField } from \"$lib\"; Check-in date {#each [\"start\", \"end\"] as const as type} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {/each} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangeField } from \"bits-ui\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { myPlaceholder = p.set({ year: 2025 }); }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateRangeField.Root component. Provide a placeholder prop to DateRangeField.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateRangeField } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: value.start.add({ days: 1 }), end: value.end.add({ days: 1 }), }; }} Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: v.start?.set({ hour: v.start.hour + 1 }), end: v.end?.set({ hour: v.end.hour + 1 }), }; }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateRangeField.Root component. Provide a value prop to DateRangeField.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateRangeField } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Allows users to input a range of dates within a designated field.","href":"/docs/components/date-range-field"},{"title":"Date Range Picker","content":" import { APISection, ComponentPreviewV2, DateRangePickerDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DateRangePicker } from \"bits-ui\"; {#each [\"start\", \"end\"] as const as type} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {/each} {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {date.day} {/each} {/each} {/each} {/snippet} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { myPlaceholder = p.set({ year: 2025 }); }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateRangePicker.Root component. Provide a placeholder prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: value.start.add({ days: 1 }), end: value.end.add({ days: 1 }), }; }} Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: v.start?.set({ hour: v.start.hour + 1 }), end: v.end?.set({ hour: v.end.hour + 1 }), }; }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateRangePicker.Root component. Provide a value prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the component's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open DateRangePicker Key Benefits Simplifies state management Automatically updates isOpen when the picker closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DateRangePicker.Root component. Provide an open prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Facilitates the selection of date ranges through an input and calendar-based interface.","href":"/docs/components/date-range-picker"},{"title":"Dialog","content":" import { APISection, ComponentPreviewV2, DialogDemo, DialogDemoCustom, DialogDemoNested, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Dialog component in Bits UI provides a flexible and accessible way to create modal dialogs in your Svelte applications. It follows a compound component pattern, allowing for fine-grained control over the dialog's structure and behavior while maintaining accessibility and ease of use. Key Features Compound Component Structure**: Offers a set of subcomponents that work together to create a fully-featured dialog. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Customizable**: Each subcomponent can be styled and configured independently. Portal Support**: Content can be rendered in a portal, ensuring proper stacking context. Managed Focus**: Automatically manages focus, with the option to take control if needed. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the dialog's open state. Architecture The Dialog component is composed of several subcomponents, each with a specific role: Root**: The main container component that manages the state of the dialog. Provides context for all child components. Trigger**: A button that toggles the dialog's open state. Portal**: Renders its children in a portal, outside the normal DOM hierarchy. Overlay**: A backdrop that sits behind the dialog content. Content**: The main container for the dialog's content. Title**: Renders the dialog's title. Description**: Renders a description or additional context for the dialog. Close**: A button that closes the dialog. Structure Here's an overview of how the Dialog component is structured in code: import { Dialog } from \"bits-ui\"; Reusable Components Bits UI provides a comprehensive set of Dialog components that serve as building blocks for creating customized, reusable Dialog implementations. This approach offers flexibility in design while maintaining consistency and accessibility across your application. Building a Reusable Dialog The following example demonstrates how to create a versatile, reusable Dialog component using Bits UI building blocks. This implementation showcases the flexibility of the component API by combining props and snippets. import type { Snippet } from \"svelte\"; import { Dialog, type WithoutChild } from \"bits-ui\"; type Props = Dialog.RootProps & { buttonText: string; title: Snippet; description: Snippet; contentProps?: WithoutChild; // ...other component props if you wish to pass them }; let { open = $bindable(false), children, buttonText, contentProps, title, description, ...restProps }: Props = $props(); {buttonText} {@render title()} {@render description()} {@render children?.()} Close Dialog Usage with Inline Snippets import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} Account settings {/snippet} {#snippet description()} Manage your account settings and preferences. {/snippet} Usage with Separate Snippets import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} Account settings {/snippet} {#snippet description()} Manage your account settings and preferences. {/snippet} Best Practices Prop Flexibility**: Design your component to accept props for any nested components for maximum flexibility Styling Options**: Use tools like clsx to merge class overrides Binding Props**: Use bind: and expose $bindable props to provide consumers with full control Type Safety**: Use the exported types from Bits UI to type your component props Managing Open State Bits UI offers several approaches to manage and synchronize the Alert Dialog's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { Dialog } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Dialog Key Benefits Simplifies state management Automatically updates isOpen when the dialog closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Dialog } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Dialog.Root component. Provide an open prop to Dialog.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Dialog } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Focus Management Proper focus management is crucial for accessibility and user experience in modal dialogs. Bits UI's Dialog component provides several features to help you manage focus effectively. Focus Trap By default, the Dialog implements a focus trap, adhering to the WAI-ARIA design pattern for modal dialogs. This ensures that keyboard focus remains within the Dialog while it's open, preventing users from interacting with the rest of the page. Disabling the Focus Trap While not recommended, you can disable the focus trap if absolutely necessary: Disabling the focus trap may compromise accessibility. Only do this if you have a specific reason and implement an alternative focus management strategy. Open Focus When a Dialog opens, focus is automatically set to the first focusable element within Dialog.Content. This ensures keyboard users can immediately interact with the Dialog contents. Customizing Initial Focus To specify which element receives focus when the Dialog opens, use the onOpenAutoFocus prop on Dialog.Content: import { Dialog } from \"bits-ui\"; let nameInput = $state(); Open Dialog { e.preventDefault(); nameInput?.focus(); }} Always ensure that something within the Dialog receives focus when it opens. This is crucial for maintaining keyboard navigation context and makes your users happy. Close Focus When a Dialog closes, focus returns to the element that triggered its opening (typically the Dialog.Trigger). Customizing Close Focus To change which element receives focus when the Dialog closes, use the onCloseAutoFocus prop on Dialog.Content: import { Dialog } from \"bits-ui\"; let nameInput = $state(); Open Dialog { e.preventDefault(); nameInput?.focus(); }} Best Practices Always maintain a clear focus management strategy for your Dialogs. Ensure that focus is predictable and logical for keyboard users. Test your focus management with keyboard navigation to verify its effectiveness. Advanced Behaviors Bits UI's Dialog component offers several advanced features to customize its behavior and enhance user experience. This section covers scroll locking, escape key handling, and interaction outside the dialog. Scroll Lock By default, when a Dialog opens, scrolling the body is disabled. This provides a more native-like experience, focusing user attention on the dialog content. Customizing Scroll Behavior To allow body scrolling while the dialog is open, use the preventScroll prop on Dialog.Content: Enabling body scroll may affect user focus and accessibility. Use this option judiciously. Escape Key Handling By default, pressing the Escape key closes an open Dialog. Bits UI provides two methods to customize this behavior. Method 1: escapeKeydownBehavior The escapeKeydownBehavior prop allows you to customize the behavior taken by the component when the Escape key is pressed. It accepts one of the following values: 'close' (default): Closes the Dialog immediately. 'ignore': Prevents the Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will ignore the key press and not close. To always prevent the Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onEscapeKeydown For more granular control, override the default behavior using the onEscapeKeydown prop: { e.preventDefault(); // do something else instead }} This method allows you to implement custom logic when the Escape key is pressed. Interaction Outside By default, interacting outside the Dialog content area closes the Dialog. Bits UI offers two ways to modify this behavior. Method 1: interactOutsideBehavior The interactOutsideBehavior prop allows you to customize the behavior taken by the component when an interaction (touch, mouse, or pointer event) occurs outside the content. It accepts one of the following values: 'close' (default): Closes the Dialog immediately. 'ignore': Prevents the Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will ignore the event and not close. To always prevent the Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onInteractOutside For custom handling of outside interactions, you can override the default behavior using the onInteractOutside prop: { e.preventDefault(); // do something else instead }} This approach allows you to implement specific behaviors when users interact outside the Dialog content. Best Practices Scroll Lock**: Consider your use case carefully before disabling scroll lock. It may be necessary for dialogs with scrollable content or for specific UX requirements. Escape Keydown**: Overriding the default escape key behavior should be done thoughtfully. Users often expect the escape key to close modals. Outside Interactions**: Ignoring outside interactions can be useful for important dialogs or multi-step processes, but be cautious not to trap users unintentionally. Accessibility**: Always ensure that any customizations maintain or enhance the dialog's accessibility. User Expectations**: Try to balance custom behaviors with common UX patterns to avoid confusing users. By leveraging these advanced features, you can create highly customized dialog experiences while maintaining usability and accessibility standards. Nested Dialogs Dialogs can be nested within each other to create more complex user interfaces: import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} First Dialog {/snippet} {#snippet description()} This is the first dialog. {/snippet} {#snippet title()} Second Dialog {/snippet} {#snippet description()} This is the second dialog. {/snippet} Svelte Transitions The Dialog component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Dialog components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of Dialog.Content and Dialog.Overlay. import { Dialog } from \"bits-ui\"; import { fly, fade } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} {#snippet child({ props, open })} {#if open} {/if} {/snippet} In this example: The forceMount prop ensures the components are always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directives (transition:fade and transition:fly) apply the animations. Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Dialog, type WithoutChildrenOrChild } from \"bits-ui\"; import { fade } from \"svelte/transition\"; import type { Snippet } from \"svelte\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyDialogOverlay component alongside the other Dialog primitives throughout your application: import { Dialog } from \"bits-ui\"; import { MyDialogOverlay } from \"$lib/components\"; Open ","description":"A modal window presenting content or seeking user input without navigating away from the current context.","href":"/docs/components/dialog"},{"title":"Dropdown Menu","content":" import { APISection, ComponentPreviewV2, DropdownMenuDemo, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { DropdownMenu } from \"bits-ui\"; Reusable Components If you're planning to use Dropdown Menu in multiple places, you can create a reusable component that wraps the Dropdown Menu component. This example shows you how to create a Dropdown Menu component that accepts a few custom props that make it more capable. import type { Snippet } from \"svelte\"; import { DropdownMenu, type WithoutChild } from \"bits-ui\"; type Props = DropdownMenu.Props & { buttonText: string; items: string[]; contentProps?: WithoutChild; // other component props if needed }; let { open = $bindable(false), children, buttonText, items, contentProps, ...restProps }: Props = $props(); {buttonText} {#each items as item} {item} {/each} You can then use the MyDropdownMenu component like this: import MyDropdownMenu from \"./MyDropdownMenu.svelte\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Dropdown Menu's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DropdownMenu } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Context Menu Key Benefits Simplifies state management Automatically updates isOpen when the menu closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DropdownMenu } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DropdownMenu.Root component. Provide an open prop to DropdownMenu.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DropdownMenu } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Groups To group related menu items, you can use the DropdownMenu.Group component along with either a DropdownMenu.GroupHeading or an aria-label attribute on the DropdownMenu.Group component. File New Open Save Save As New Open Save Save As Group Heading The DropdownMenu.GroupHeading component must be a child of either a DropdownMenu.Group or DropdownMenu.RadioGroup component. If used on its own, an error will be thrown during development. File Favorite color Checkbox Items You can use the DropdownMenu.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { DropdownMenu } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} The checked state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the checked prop. Radio Groups You can combine the DropdownMenu.RadioGroup and DropdownMenu.RadioItem components to create a radio group within a menu. import { DropdownMenu } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); Favorite number {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} The value state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the value prop. Nested Menus You can create nested menus using the DropdownMenu.Sub component to create complex menu structures. import { DropdownMenu } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the DropdownMenu.Content component to use Svelte Transitions or another animation library that requires more control. import { DropdownMenu } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Displays a menu of items that users can select from when triggered.","href":"/docs/components/dropdown-menu"},{"title":"Label","content":" import { APISection, ComponentPreviewV2, LabelDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Label } from \"bits-ui\"; ","description":"Identifies or describes associated UI elements.","href":"/docs/components/label"},{"title":"Link Preview","content":" import { APISection, ComponentPreviewV2, LinkPreviewDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview A component that lets users preview a link before they decide to follow it. This is useful for providing non-essential context or additional information about a link without having to navigate away from the current page. This component is only intended to be used with a mouse or other pointing device. It doesn't respond to touch events, and the preview content cannot be accessed via the keyboard. On touch devices, the link will be followed immediately. As it is not accessible to all users, the preview should not contain vital information. Structure import { LinkPreview } from \"bits-ui\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Link Preview's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { LinkPreview } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Link Preview Key Benefits Simplifies state management Automatically updates isOpen when the preview closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { LinkPreview } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the LinkPreview.Root component. Provide an open prop to LinkPreview.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { LinkPreview } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Opt-out of Floating UI When you use the LinkPreview.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the LinkPreview.ContentStatic component. This component does not use Floating UI and leaves positioning the content entirely up to you. The LinkPreview.Arrow component is designed to be used with Floating UI and LinkPreview.Content, so you may experience unexpected behavior if you attempt to use it with LinkPreview.ContentStatic. ","description":"Displays a summarized preview of a linked content's details or information.","href":"/docs/components/link-preview"},{"title":"Listbox","content":" import { APISection, ComponentPreviewV2, ListboxDemo, ListboxDemoCustomAnchor, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Overview The Listbox component provides users with a selectable list of options. It's designed to offer an enhanced selection experience with features like typeahead search, keyboard navigation, and customizable grouping. This component is particularly useful for scenarios where users need to choose from a predefined set of options, offering more functionality than a standard select element. Key Features Typeahead Search**: Users can quickly find options by typing Keyboard Navigation**: Full support for keyboard interactions, allowing users to navigate through options using arrow keys, enter to select, and more. Grouped Options**: Ability to organize options into logical groups, enhancing readability and organization of large option sets. Scroll Management**: Includes scroll up/down buttons for easy navigation in long lists. Accessibility**: Built-in ARIA attributes and keyboard support ensure compatibility with screen readers and adherence to accessibility standards. Portal Support**: Option to render the listbox content in a portal, preventing layout issues in complex UI structures. Architecture The Listbox component is composed of several subcomponents, each with a specific role: Root**: The main container component that manages the state and context for the combobox. Trigger**: The button or element that opens the dropdown list. Portal**: Responsible for portaling the dropdown content to the body or a custom target. Group**: A container for grouped items, used to group related items. GroupHeading**: A heading for a group of items, providing a descriptive label for the group. Item**: An individual item within the list. Separator**: A visual separator between items. Content**: The dropdown container that displays the items. It uses $2 to position the content relative to the trigger. ContentStatic** (Optional): An alternative to the Content component, that enables you to opt-out of Floating UI and position the content yourself. Arrow**: An arrow element that points to the trigger when using the Combobox.Content component. Structure Here's an overview of how the Listbox component is structured in code: import { Listbox } from \"bits-ui\"; Reusable Components As you can see from the structure above, there are a number of pieces that make up the Listbox component. These pieces are provided to give you maximum flexibility and customization options, but can be a burden to write out everywhere you need to use a listbox in your application. To ease this burden, it's recommended to create your own reusable listbox component that wraps the primitives and provides a more convenient API for your use cases. Here's an example of how you might create a reusable MyListbox component that receives a list of options and renders each of them as an item. import { Listbox, type WithoutChildren } from \"bits-ui\"; type Props = WithoutChildren & { placeholder?: string; items: { value: string; label: string; disabled?: boolean }[]; contentProps?: WithoutChildren; // any other specific component props if needed }; let { value = $bindable(\"\"), items, contentProps, placeholder, ...restProps }: Props = $props(); const selectedLabel = $derived(items.find((item) => item.value === value)?.label); {#if selectedLabel} {selectedLabel} {:else} {/if} up {#each items as { value, label, disabled } (value)} {#snippet children({ selected })} {selected ? \"✅\" : \"\"} {item.label} {/snippet} {/each} down You can then use the MyListbox component throughout your application like so: import MyListbox from \"$lib/components/MyListbox.svelte\"; const items = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let fruit = $state(\"apple\"); Managing Value State Bits UI offers several approaches to manage and synchronize the Listbox's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Listbox.Root component. Provide a value prop to Listbox.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the Listbox's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = true)}> Open Key Benefits Simplifies state management Automatically updates myOpen when the internal state changes (e.g., via clicking on the trigger/input) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); { myOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledOpen prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledOpen prop to true on the Listbox.Root component. Provide an open prop to Listbox.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Opt-out of Floating UI When you use the Listbox.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Listbox.ContentStatic component. When using this component, you'll need to handle the positioning of the content yourself. Keep in mind that using Listbox.Portal alongside Listbox.ContentStatic may result in some unexpected positioning behavior, feel free to not use the portal or work around it. Custom Anchor By default, the Listbox.Content is anchored to the Listbox.Trigger component, which determines where the content is positioned. If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the Listbox.Content component. import { Listbox } from \"bits-ui\"; let customAnchor = $state(null!); What is the Viewport? The Listbox.Viewport component is used to determine the size of the content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Listbox.Viewport component. Scroll Up/Down Buttons The Listbox.ScrollUpButton and Listbox.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. You must use the Listbox.Viewport component when using the scroll buttons. Native Scrolling/Overflow If you don't want to use the scroll buttons and prefer to use the standard scrollbar/overflow behavior, you can omit the Listbox.Scroll[Up|Down]Button components and the Listbox.Viewport component. You'll need to set a height on the Listbox.Content component and appropriate overflow styles to enable scrolling. Scroll Lock By default, when a user opens the listbox, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. Highlighted Items The Listbox component follows the $2 for highlighting items. This means that the Listbox.Trigger retains focus the entire time, even when navigating with the keyboard, and items are highlighted as the user navigates them. Styling Highlighted Items You can use the data-highlighted attribute on the Listbox.Item component to style the item differently when it is highlighted. onHighlight / onUnhighlight To trigger side effects when an item is highlighted or unhighlighted, you can use the onHighlight and onUnhighlight props. console.log('I am highlighted!')} onUnhighlight={() => console.log('I am unhighlighted!')} /> ","description":"A list of options that can be selected by the user.","href":"/docs/components/listbox"},{"title":"Menubar","content":" import { APISection, ComponentPreviewV2, MenubarDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Menubar } from \"bits-ui\"; {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} Reusable Components If you're planning to use Menubar in multiple places, you can create reusable components that wrap the different parts of the Menubar. In the following example, we're creating a reusable MyMenubarMenu component that contains the trigger, content, and items of a menu. import { Menubar, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { triggerText: string; items: { label: string; value: string; onSelect?: () => void }[]; contentProps?: WithoutChildrenOrChild; // other component props if needed }; let { triggerText, items, contentProps, ...restProps }: Props = $props(); {triggerText} {#each items as item} {item.label} {/each} Now, we can use the MyMenubarMenu component within a Menubar.Root component to render out the various menus. import { Menubar } from \"bits-ui\"; import MyMenubarMenu from \"./MyMenubarMenu.svelte\"; const sales = [ { label: \"Michael Scott\", value: \"michael\" }, { label: \"Dwight Schrute\", value: \"dwight\" }, { label: \"Jim Halpert\", value: \"jim\" }, { label: \"Stanley Hudson\", value: \"stanley\" }, { label: \"Phyllis Vance\", value: \"phyllis\" }, { label: \"Pam Beesly\", value: \"pam\" }, { label: \"Andy Bernard\", value: \"andy\" }, ]; const hr = [ { label: \"Toby Flenderson\", value: \"toby\" }, { label: \"Holly Flax\", value: \"holly\" }, { label: \"Jan Levinson\", value: \"jan\" }, ]; const accounting = [ { label: \"Angela Martin\", value: \"angela\" }, { label: \"Kevin Malone\", value: \"kevin\" }, { label: \"Oscar Martinez\", value: \"oscar\" }, ]; const menubarMenus = [ { title: \"Sales\", items: sales }, { title: \"HR\", items: hr }, { title: \"Accounting\", items: accounting }, ]; {#each menubarMenus as { title, items }} {/each} Value State Bits UI provides flexible options for controlling and synchronizing the menubar's active value state. The value represents the currently opened menu within the menubar. Two-Way Binding Use the bind:value directive for effortless two-way synchronization between your local state and the menubar's internal state. import { Menubar } from \"bits-ui\"; let activeValue = $state(\"\"); (activeValue = \"menu-1\")}>Open Menubar Menu Change Handler You can also use the onValueCHange prop to update local state when the menubar's active menu changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the menus open or close. import { Menubar } from \"bits-ui\"; let activeValue = $state(\"\"); { activeValue = value; // additional logic here. }} Checkbox Items You can use the Menubar.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { Menubar } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} Radio Groups You can combine the Menubar.RadioGroup and Menubar.RadioItem components to create a radio group within a menu. import { Menubar } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} Nested Menus You can create nested menus using the Menubar.Sub component to create complex menu structures. import { Menubar } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the Menubar.Content component to use Svelte Transitions or another animation library that requires more control. import { Menubar } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Organizes and presents a collection of menu options or actions within a horizontal bar.","href":"/docs/components/menubar"},{"title":"Navigation Menu","content":" import { APISection, ComponentPreviewV2, NavigationMenuDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { NavigationMenu } from \"bits-ui\"; ","description":"A list of links that allow users to navigate between pages of a website.","href":"/docs/components/navigation-menu"},{"title":"Pagination","content":" import { APISection, ComponentPreviewV2, PaginationDemo, Callout } from '$lib/components/index.js' export let schemas {#snippet preview()} {/snippet} Structure import { Pagination } from \"bits-ui\"; {#each pages as page (page.key)} {/each} Managing Page State Bits UI offers several approaches to manage and synchronize the Pagination's page state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:page directive. This method automatically keeps your local state in sync with the component's internal state. import { Pagination } from \"bits-ui\"; let myPage = $state(1); (myPage = 2)}> Go to page 2 Key Benefits Simplifies state management Automatically updates myPage when the internal state changes (e.g., via clicking on a page button) Allows external control (e.g., changing the page via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPageChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Pagination } from \"bits-ui\"; let myPage = $state(1); { myPage = p; // additional logic here. }} Use Cases Implementing custom behaviors on page change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's pressed state, use the controlledPage prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPage prop to true on the Pagination.Root component. Provide a page prop to Pagination.Root, which should be a variable holding the current state. Implement an onPageChange handler to update the state when the internal state changes. import { Pagination } from \"bits-ui\"; let myPage = $state(1); (myPage = p)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Ellipsis The pages snippet prop consists of two types of items: 'page' and 'ellipsis'. The 'page' type represents an actual page number, while the 'ellipsis' type represents a placeholder for rendering an ellipsis between pages. ","description":"Facilitates navigation between pages.","href":"/docs/components/pagination"},{"title":"PIN Input","content":" import { APISection, ComponentPreviewV2, PinInputDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The PIN Input component provides a customizable solution for One-Time Password (OTP), Two-Factor Authentication (2FA), or Multi-Factor Authentication (MFA) input fields. Due to the lack of a native HTML element for these purposes, developers often resort to either basic input fields or custom implementations. This component offers a robust, accessible, and flexible alternative. This component is derived from and would not have been possible without the work done by $2 with $2. Key Features Invisible Input Technique**: Utilizes an invisible input element for seamless integration with form submissions and browser autofill functionality. Customizable Appearance**: Allows for custom designs while maintaining core functionality. Accessibility**: Ensures keyboard navigation and screen reader compatibility. Flexible Configuration**: Supports various PIN lengths and input types (numeric, alphanumeric). Architecture Root Container: A relatively positioned root element that encapsulates the entire component. Invisible Input: A hidden input field that manages the actual value and interacts with the browser's built-in features. Visual Cells: Customizable elements representing each character of the PIN, rendered as siblings to the invisible input. This structure allows for a seamless user experience while providing developers with full control over the visual representation. Structure import { PinInput } from \"bits-ui\"; {#snippet children({ cells })} {#each cells as cell} {/each} {/snippet} ","description":"Allows users to input a sequence of one-character alphanumeric inputs.","href":"/docs/components/pin-input"},{"title":"Popover","content":" import { APISection, ComponentPreviewV2, PopoverDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Popover } from \"bits-ui\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Popover's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { Popover } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Popover Key Benefits Simplifies state management Automatically updates isOpen when the popover closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Popover } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Popover.Root component. Provide an open prop to Popover.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the local state when the internal state changes. import { Popover } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Focus Focus Trap By default, when a Popover is opened, focus will be trapped within that Popover. You can disabled this beahvior by setting the trapFocus prop to false on the Popover.Content component. Open Focus By default, when a Popover is opened, focus will be set to the first focusable element with the Popover.Content. This ensures that users navigating my keyboard end up somewhere within the Popover that they can interact with. You can override this behavior using the onOpenAutoFocus prop on the Popover.Content component. It's highly recommended that you use this prop to focus something within the Popover's content. You'll first need to cancel the default behavior of focusing the first focusable element by cancelling the event passed to the onOpenAutoFocus callback. You can then focus whatever you wish. import { Popover } from \"bits-ui\"; let nameInput = $state(); Open Popover { e.preventDefault(); nameInput?.focus(); }} Close Focus By default, when a Popover is closed, focus will be set to the trigger element of the Popover. You can override this behavior using the onCloseAutoFocus prop on the Popover.Content component. You'll need to cancel the default behavior of focusing the trigger element by cancelling the event passed to the onCloseAutoFocus callback, and then focus whatever you wish. import { Popover } from \"bits-ui\"; let nameInput = $state(); Open Popover { e.preventDefault(); nameInput?.focus(); }} Scroll Lock By default, when a Popover is opened, users can still scroll the body and interact with content outside of the Popover. If you wish to lock the body scroll and prevent users from interacting with content outside of the Popover, you can set the preventScroll prop to true on the Popover.Content component. Escape Keydown By default, when a Popover is open, pressing the Escape key will close the dialog. Bits UI provides a couple ways to override this behavior. escapeKeydownBehavior You can set the escapeKeydownBehavior prop to 'ignore' on the Popover.Content component to prevent the dialog from closing when the Escape key is pressed. onEscapeKeydown You can also override the default behavior by cancelling the event passed to the onEscapeKeydown callback on the Popover.Content component. e.preventDefault()}> Interact Outside By default, when a Popover is open, pointer down events outside the content will close the popover. Bits UI provides a couple ways to override this behavior. interactOutsideBehavior You can set the interactOutsideBehavior prop to 'ignore' on the Popover.Content component to prevent the dialog from closing when the user interacts outside the content. onInteractOutside You can also override the default behavior by cancelling the event passed to the onInteractOutside callback on the Popover.Content component. e.preventDefault()}> ","description":"Display supplementary content or information when users interact with specific elements.","href":"/docs/components/popover"},{"title":"Progress","content":" import { APISection, ComponentPreviewV2, ProgressDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Progress } from \"bits-ui\"; ","description":"Visualizes the progress or completion status of a task or process.","href":"/docs/components/progress"},{"title":"Radio Group","content":" import { APISection, ComponentPreviewV2, RadioGroupDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { RadioGroup } from \"bits-ui\"; {#snippet children({ checked })} {#if checked} ✅ {/if} {/snippet} Reusable Components It's recommended to use the RadioGroup primitives to create your own custom components that can be used throughout your application. In the example below, we're creating a custom MyRadioGroup component that takes in an array of items and renders a radio group with those items along with a $2 component for each item. import { RadioGroup, Label, type WithoutChildrenOrChild, useId } from \"bits-ui\"; type Item = { value: string; label: string; disabled?: boolean; }; type Props = WithoutChildrenOrChild & { items: Item[]; }; let { value = $bindable(\"\"), ref = $bindable(null), items, ...restProps }: Props = $props(); {#each items as item} {@const id = useId()} {#snippet children({ checked })} {#if checked} ✅ {/if} {/snippet} {item.label} {/each} You can then use the MyRadioGroup component in your application like so: import MyRadioGroup from \"$lib/components/MyRadioGroup.svelte\"; const myItems = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"coconut\", label: \"Coconut\", disabled: true }, ]; Managing Value State Bits UI offers several approaches to manage and synchronize the Radio Group's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the RadioGroup.Root component. Provide a value prop to RadioGroup.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. HTML Forms If you set the name prop on the RadioGroup.Root component, a hidden input element will be rendered to submit the value of the radio group to a form. Required To make the hidden input element required you can set the required prop on the RadioGroup.Root component. Disabling Items You can disable a radio group item by setting the disabled prop to true. Apple Orientation The orientation prop is used to determine the orientation of the radio group, which influences how keyboard navigation will work. When the orientation is set to 'vertical', the radio group will navigate through the items using the ArrowUp and ArrowDown keys. When the orientation is set to 'horizontal', the radio group will navigate through the items using the ArrowLeft and ArrowRight keys. ","description":"Allows users to select a single option from a list of mutually exclusive choices.","href":"/docs/components/radio-group"},{"title":"Range Calendar","content":" import { APISection, ComponentPreviewV2, RangeCalendarDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { RangeCalendar } from \"bits-ui\"; {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} ","description":"Presents a calendar view tailored for selecting date ranges.","href":"/docs/components/range-calendar"},{"title":"Scroll Area","content":" import { APISection, ComponentPreviewV2, ScrollAreaDemo, ScrollAreaDemoCustom } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { ScrollArea } from \"bits-ui\"; Reusable Components If you're planning to use the Scroll Area throughout your application, it's recommended to create a reusable component to reduce the amount of code you need to write each time. This example shows you how to create a Scroll Area component that accepts a few custom props that make it more capable. import { ScrollArea, type WithoutChild } from \"bits-ui\"; type Props = WithoutChild & { orientation: \"vertical\" | \"horizontal\" | \"both\"; viewportClasses?: string; }; let { ref = $bindable(null), orientation = \"vertical\", viewportClasses, children, ...restProps }: Props = $props(); {#snippet Scrollbar({ orientation }: { orientation: \"vertical\" | \"horizontal\" })} {/snippet} {@render children?.()} {#if orientation === \"vertical\" || orientation === \"both\"} {@render Scrollbar({ orientation: \"vertical\" })} {/if} {#if orientation === \"horizontal\" || orientation === \"both\"} {@render Scrollbar({ orientation: \"horizontal\" })} {/if} We'll use this custom component in the following examples to demonstrate how to customize the behavior of the Scroll Area. Scroll Area Types Hover The hover type is the default type of the scroll area, demonstrated in the featured example above. It only shows scrollbars when the user hovers over the scroll area and the content is larger than the viewport. Scroll The scroll type displays the scrollbars when the user scrolls the content. This is similar to the behavior of MacOS. Auto The auto type behaves similarly to your typical browser scrollbars. When the content is larger than the viewport, the scrollbars will appear and remain visible at all times. Always The always type behaves as if you set overflow: scroll on the scroll area. Scrollbars will always be visible, even when the content is smaller than the viewport. We've also set the orientation prop on the MyScrollArea to 'both' to ensure both scrollbars are rendered. Customizing the Hide Delay You can customize the hide delay of the scrollbars using the scrollHideDelay prop. ","description":"Consistent scroll area across platforms.","href":"/docs/components/scroll-area"},{"title":"Select","content":" import { APISection, ComponentPreviewV2, SelectDemo, SelectDemoPositioning } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Select component can be used as a replacement for the native `` element in your application. It provides a more flexible and customizable way to select an option from a list of options. The component offers a variety of features, such as typeahead, keyboard navigation, scroll up/down buttons, and more. Structure import { Select } from \"bits-ui\"; Reusable Components As you can see from the structure above, there are a number of pieces that make up the Select component. These pieces are provided to give you maximum flexibility and customization options, but can be a burden to write out everywhere you need to use a Select in your application. To ease this burden, it's recommended to create your own reusable Select component that wraps the primitives and provides a more convenient API for your use cases. Here's an example of how you might create a reusable MySelect component that receives a list of options and renders each of them as an item. import { Select, type WithoutChildren } from \"bits-ui\"; type Props = WithoutChildren & { placeholder?: string; items: { value: string; label: string; disabled?: boolean }[]; contentProps?: WithoutChildren; // any other specific component props if needed }; let { value = $bindable(\"\"), items, contentProps, placeholder, ...restProps }: Props = $props(); const selectedLabel = $derived(items.find((item) => item.value === value)?.label); {#if selectedLabel} {selectedLabel} {:else} {/if} up {#each items as { value, label, disabled } (value)} {#snippet children({ selected })} {selected ? \"✅\" : \"\"} {item.label} {/snippet} {/each} down You can then use the MySelect component throughout your application like so: import MySelect from \"$lib/components/MySelect.svelte\"; const items = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let fruit = $state(\"apple\"); Value State The value represents the currently selected item/option within the select menu. Bits UI provides flexible options for controlling and synchronizing the Select's value state. Two-Way Binding Use the bind:value directive for effortless two-way synchronization between your local state and the Select's internal state. import { Select } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"apple\")}> Apple This setup enables toggling the value via the custom button and ensures the local myValue state updates when the Select's value changes through any internal means (e.g., clicking on an item's button). Change Handler You can also use the onValueChange prop to update local state when the Select's value state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the Select changes. import { Select } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Open State The open state represents whether or not the select content is open. Bits UI provides flexible options for controlling and synchronizing the Select's open state. Two-Way Binding Use the bind:open directive for effortless two-way synchronization between your local state and the Select's internal state. import { Select } from \"bits-ui\"; let isOpen = $state(false); (open = true)}> Open select This setup enables toggling the Select via the custom button and ensures the local isOpen state updates when the Select's open state changes through any internal means e.g. clicking on the trigger or outside the content. Change Handler You can also use the onOpenChange prop to update local state when the Select's open state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the Select changes. import { Select } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Positioning The Select component supports two different positioning strategies for the content. The default positioning strategy is floating, which uses Floating UI to position the content relative to the trigger, similar to other popover-like components. If you prefer a more native-like experience, you can set the position prop to item-aligned, which will position the content relative to the trigger, similar to a native `` element. Here's an example of both strategies in action: NOTE: When using the \"item-aligned\" positioning strategy, the props related to configuring Floating UI on the Select.Content component will be ignored. HTML Forms The Select component is designed to work seamlessly with HTML forms. You can use the name prop to associate the select with a form field. Server-side Rendering To accomplish some of the nice features of the Select component, such as typeahead while the select content is closed and the trigger is focused, we leverage portals to send items into the Select.Value component. Portals only work client-side, so if you are using SvelteKit with SSR, you'll need to handle the case where a default value is provided, otherwise, there will be a flicker of the placeholder value before the default value is portalled into the Select.Value component. We're demonstrating this in the featured demo at the top of this page, but here's an example of how you might handle this: // default value is provided via page data from a load function let { data } = $props(); let options = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let value = $state(data.fruit); const selectedLabel = $derived(options.find((option) => option.value === data.fruit)?.label); (data.fruit = v)}> {#if selectedLabel} {selectedLabel} {:else} {/if} Scroll Lock By default, when a user opens the select, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. What is the Viewport? The Select.Viewport component is used to determine the size of the select content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Select.Viewport component. Scroll Up/Down Buttons The Select.ScrollUpButton and Select.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. Multiple Select The Select component does not support multiple selections. If you're looking for a multi-select component, check out the $2 component. ","description":"Enables users to choose from a list of options presented in a dropdown.","href":"/docs/components/select"},{"title":"Separator","content":" import { APISection, ComponentPreviewV2, SeparatorDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Separator } from \"bits-ui\"; ","description":"Visually separates content or UI elements for clarity and organization.","href":"/docs/components/separator"},{"title":"Slider","content":" import { APISection, ComponentPreviewV2, SliderDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Slider } from \"bits-ui\"; Resuable Components Bits UI provides primitives that enable you to build your own custom slider component that can be reused throughout your application. Here's an example of how you might create a reusable MySlider component. import { Slider } from \"bits-ui\"; type Props = WithoutChildren; let { value = $bindable(), ref = $bindable(null), ...restProps }: Props = $props(); {#snippet children({ thumbs, ticks })} {#each thumbs as index} {/each} {#each ticks as index} {/each} {/snippet} You can then use the MySlider component in your application like so: import MySlider from \"$lib/components/MySlider.svelte\"; let someValue = $state([5, 10]); Managing Value State Bits UI offers several approaches to manage and synchronize the Slider's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Slider } from \"bits-ui\"; let myValue = $state([0]); (myValue = [20])}> Set value to 20 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via dragging the thumb(s)) Allows external control (e.g., updating the value via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Slider } from \"bits-ui\"; let myValue = $state([0]); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Slider.Root component. Provide a value prop to Slider.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Slider } from \"bits-ui\"; let myValue = $state([0]); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Multiple Thumbs and Ticks If the value prop has more than one value, the slider will render multiple thumbs. You can also use the ticks snippet prop to render ticks at specific intervals import { Slider } from \"bits-ui\"; let value = $state([5, 7]); {#snippet children({ ticks, thumbs })} {#each thumbs as index} {/each} {#each ticks as index} {/each} {/snippet} To determine the number of ticks that will be rendered, you can simply divide the max value by the step value. Vertical Orientation You can use the orientation prop to change the orientation of the slider, which defaults to \"horizontal\". RTL Support You can use the dir prop to change the reading direction of the slider, which defaults to \"ltr\". Auto Sort By default, the slider will sort the values from smallest to largest, so if you drag a smaller thumb to a larger value, the value of that thumb will be updated to the larger value. You can disable this behavior by setting the autoSort prop to false. HTML Forms Since there is a near endless number of possible values that a user can select, the slider does not render a hidden input element by default. You'll need to determine how you want to submit the value(s) of the slider with a form. Here's an example of how you might do that: import MySlider from \"$lib/components/MySlider.svelte\"; let expectedIncome = $state([50, 100]); Submit ","description":"Allows users to select a value from a continuous range by sliding a handle.","href":"/docs/components/slider"},{"title":"Switch","content":" import { APISection, ComponentPreviewV2, SwitchDemo, SwitchDemoCustom, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Switch component provides an intuitive and accessible toggle control, allowing users to switch between two states, typically \"on\" and \"off\". This component is commonly used for enabling or disabling features, toggling settings, or representing boolean values in forms. The Switch offers a more visual and interactive alternative to traditional checkboxes for binary choices. Key Features Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. State Management**: Internally manages the on/off state, with options for controlled and uncontrolled usage. Stylable**: Data attributes allow for smooth transitions between states and custom styles. HTML Forms**: Can render a hidden input element for form submissions. Architecture The Switch component is composed of two main parts: Root**: The main container component that manages the state and behavior of the switch. Thumb**: The \"movable\" part of the switch that indicates the current state. Structure Here's an overview of how the Switch component is structured in code: import { Switch } from \"bits-ui\"; Reusable Components It's recommended to use the Switch primitives to create your own custom switch component that can be used throughout your application. In the example below, we're using the Checkbox and $2 components to create a custom switch component. import { Switch, Label, useId, type WithoutChildrenOrChild } from \"bits-ui\"; let { id = useId(), checked = $bindable(false), ref = $bindable(null), ...restProps }: WithoutChildrenOrChild & { labelText: string; } = $props(); {labelText} You can then use the MySwitch component in your application like so: import MySwitch from \"$lib/components/MySwitch.svelte\"; let notifications = $state(true); Managing Checked State Bits UI offers several approaches to manage and synchronize the Switch's checked state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:checked directive. This method automatically keeps your local state in sync with the switch's internal state. import { Switch } from \"bits-ui\"; let myChecked = $state(true); (myChecked = false)}> uncheck Key Benefits Simplifies state management Automatically updates myChecked when the switch changes (e.g., via clicking on the switch) Allows external control (e.g., checking via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onCheckedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Switch } from \"bits-ui\"; let myChecked = $state(false); { myChecked = checked; // additional logic here. }} /> Use Cases Implementing custom behaviors on checked/unchecked Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the switch's checked state, use the controlledChecked prop. This approach requires you to manually manage the checked state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledChecked prop to true on the Switch.Root component. Provide a checked prop to Switch.Root, which should be a variable holding the current state. Implement an onCheckedChange handler to update the state when the internal state changes. import { Switch } from \"bits-ui\"; let myChecked = $state(false); (myChecked = c)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Disabled State You can disable the switch by setting the disabled prop to true. HTML Forms If you pass the name prop to Switch.Root, a hidden input element will be rendered to submit the value of the switch to a form. By default, the input will be submitted with the default checkbox value of 'on' if the switch is checked. Custom Input Value If you'd prefer to submit a different value, you can use the value prop to set the value of the hidden input. For example, if you wanted to submit a string value, you could do the following: Required If you want to make the switch required, you can use the required prop. This will apply the required attribute to the hidden input element, ensuring that proper form submission is enforced. ","description":"A toggle control enabling users to switch between \"on\" and \"off\" states.","href":"/docs/components/switch"},{"title":"Tabs","content":" import { APISection, ComponentPreviewV2, TabsDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Tabs } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"tab-1\")}> Activate tab 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an tab's trigger) Allows external control (e.g., switching tabs via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Tabs.Root component. Provide a value prop to Tabs.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Orientation The orientation prop is used to determine the orientation of the Tabs component, which influences how keyboard navigation will work. When the orientation is set to 'horizontal', the ArrowLeft and ArrowRight keys will move the focus to the previous and next tab, respectively. When the orientation is set to 'vertical', the ArrowUp and ArrowDown keys will move the focus to the previous and next tab, respectively. Activation Mode By default, the Tabs component will automatically activate the tab associated with a trigger when that trigger is focused. This behavior can be disabled by setting the activationMode prop to 'manual'. When set to 'manual', the user will need to activate the tab by pressing the trigger. ","description":"Organizes content into distinct sections, allowing users to switch between them.","href":"/docs/components/tabs"},{"title":"Toggle Group","content":" import { APISection, ComponentPreviewV2, ToggleGroupDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { ToggleGroup } from \"bits-ui\"; bold italic Single & Multiple The ToggleGroup component supports two type props, 'single' and 'multiple'. When the type is set to 'single', the ToggleGroup will only allow a single item to be selected at a time, and the type of the value prop will be a string. When the type is set to 'multiple', the ToggleGroup will allow multiple items to be selected at a time, and the type of the value prop will be an array of strings. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"item-1\")}> Press item 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., toggling an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the ToggleGroup.Root component. Provide a value prop to ToggleGroup.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Groups multiple toggle controls, allowing users to enable one or multiple options.","href":"/docs/components/toggle-group"},{"title":"Toggle","content":" import { APISection, ComponentPreviewV2, ToggleDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Toggle } from \"bits-ui\"; Managing Pressed State Bits UI offers several approaches to manage and synchronize the Toggle's pressed state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:pressed directive. This method automatically keeps your local state in sync with the component's internal state. import { Toggle } from \"bits-ui\"; let myPressed = $state(true); (myPressed = false)}> unpress Key Benefits Simplifies state management Automatically updates myPressed when the switch changes (e.g., via clicking on the toggle) Allows external control (e.g., pressing/toggling via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPressedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Toggle } from \"bits-ui\"; let myPressed = $state(false); { myPressed = p; // additional logic here. }} /> Use Cases Implementing custom behaviors on pressed/unpressed Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's pressed state, use the controlledPressed prop. This approach requires you to manually manage the checked state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPressed prop to true on the Toggle.Root component. Provide a pressed prop to Toggle.Root, which should be a variable holding the current state. Implement an onPressedChange handler to update the state when the internal state changes. import { Toggle } from \"bits-ui\"; let myPressed = $state(false); (myPressed = p)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"A control element that switches between two states, providing a binary choice.","href":"/docs/components/toggle"},{"title":"Toolbar","content":" import { APISection, ComponentPreviewV2, ToolbarDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Toolbar } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"item-1\")}> Press item 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., toggling an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Toolbar.Group component. Provide a value prop to Toolbar.Group, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Displays frequently used actions or tools in a compact, easily accessible bar.","href":"/docs/components/toolbar"},{"title":"Tooltip","content":" import { ComponentPreviewV2, TooltipDemo, TooltipDemoCustom, TooltipDemoDelayDuration, APISection, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { Tooltip } from \"bits-ui\"; Provider Component The Tooltip.Provider component is required to be an ancestor of the Tooltip.Root component. It provides shared state for the tooltip components used within it. You can set a single delayDuration or disableHoverableContent prop on the provider component to apply to all the tooltip components within it. import { Tooltip } from \"bits-ui\"; It also ensures that only a single tooltip within the same provider can be open at a time. It's recommended to wrap your root layout content with the provider component, setting your sensible default props there. import { Tooltip } from \"bits-ui\"; let { children } = $props(); {@render children()} Managing Open State Bits UI offers several approaches to manage and synchronize the Tooltip's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Tooltip } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Tooltip Key Benefits Simplifies state management Automatically updates isOpen when the tooltip closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Tooltip } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the tooltip responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Tooltip.Root component. Provide an open prop to Tooltip.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Tooltip } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Mobile Tooltips Tooltips are not supported on mobile devices. The intent of a tooltip is to provide a \"tip\" about a \"tool\" before the user interacts with that tool (in most cases, a button). This is not possible on mobile devices, because there is no sense of hover on mobile. If a user were to press/touch a button with a tooltip, the action that button triggers would be taken before they were even able to see the tooltip, which renders it useless. If you are using a tooltip on a button without an action, you should consider using a $2 instead. If you'd like to learn more about how we came to this decision, here are some useful resources: The tooltip is not the appropriate role for the more information \"i\" icon, ⓘ. A tooltip is directly associated with the owning element. The ⓘ isn't 'described by' detailed information; the tool or control is. $2 Tooltips should only ever contain non-essential content. The best approach to writing tooltip content is to always assume it may never be read. $2 Reusable Components It's recommended to use the Tooltip primitives to build your own custom tooltip component that can be used throughout your application. Below is an example of how you might create a reusable tooltip component that can be used throughout your application. Of course, this isn't the only way to do it, but it should give you a good idea of how to compose the primitives. import { Tooltip } from \"bits-ui\"; import { type Snippet } from \"svelte\"; type Props = Tooltip.RootProps & { trigger: Snippet; triggerProps?: Tooltip.TriggerProps; }; let { open = $bindable(false), children, buttonText, triggerProps = {}, ...restProps }: Tooltip.RootProps = $props(); {@render trigger()} {@render children?.()} You could then use the MyTooltip component in your application like so: import MyTooltip from \"$lib/components/MyTooltip.svelte\"; import BoldIcon from \"..some-icon-library\"; // not real alert(\"changed to bold!\") }}> {#snippet trigger()} {/snippet} Change font to bold Delay Duration You can change how long a user needs to hover over a trigger before the tooltip appears by setting the delayDuration prop on the Tooltip.Root or Tooltip.Provider component. Close on Trigger Click By default, the tooltip will close when the user clicks the trigger. If you want to disable this behavior, you can set the disableCloseOnTriggerClick prop to true. Hoverable Content By default, the tooltip will remain open when the user hovers over the content. If you instead want the tooltip to close as the user moves their mouse towards the content, you can set the disableHoverableContent prop to true. Non-Keyboard Focus If you want to prevent opening the tooltip when the user focuses the trigger without using the keyboard, you can set the ignoreNonKeyboardFocus prop to true. Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the Tooltip.Content component to use Svelte Transitions or another animation library that requires more control. import { Tooltip } from \"bits-ui\"; import { fly, fade } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content components that handles this logic if you intend to use this approach throughout your app. For more information on using transitions with Bits UI components, see the $2 documentation. Opt-out of Floating UI When you use the Tooltip.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Tooltip.ContentStatic component. This component does not use Floating UI and leaves positioning the content entirely up to you. Hello When using the Tooltip.ContentStatic component, the Tooltip.Arrow component will not be rendered relative to it as it is designed to be used with Tooltip.Content. ","description":"Provides additional information or context when users hover over or interact with an element.","href":"/docs/components/tooltip"},{"title":"mergeProps","content":" The mergeProps function is a utility function that can be used to merge props objects. It takes in two or more props objects and returns a new merged props object, which is useful for composing multiple components with different props. It is used internally by Bits UI components to merge the custom restProps you pass to a component with the props that Bits UI provides to the component. Event Handlers mergeProps handles chaining of event handlers automatically in the order in which they are passed, and if a previous handler calls event.preventDefault(), the next handler in the chain will not be called. import { mergeProps } from \"bits-ui\"; const props1 = { onclick: (event: MouseEvent) => console.log(\"1\") }; const props2 = { onclick: (event: MouseEvent) => console.log(\"2\") }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.onclick(new MouseEvent(\"click\"))); // 1 2 Since props1 didn't call event.preventDefault(), props2 will stll be called as normal. import { mergeProps } from \"bits-ui\"; const props1 = { onclick: (event: MouseEvent) => console.log(\"1\") }; const props2 = { onclick: (event: MouseEvent) => { console.log(\"2\"); event.preventDefault(); }, }; const props3 = { onclick: (event: MouseEvent) => { console.log(\"3\"); }, }; const mergedProps = mergeProps(props1, props2, props3); console.log(mergedProps.onclick(new MouseEvent(\"click\"))); // 1 2 Since props2 called event.preventDefault(), props3's onclick handler will not be called. Non-Event Handler Functions Functions that are't event handlers are also chained together, but one can't cancel out the other since there isn't an event object to cancel. import { mergeProps } from \"bits-ui\"; const props1 = { doSomething: () => console.log(\"1\") }; const props2 = { doSomething: () => console.log(\"2\") }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.onclick(new MouseEvent(\"click\"))); // 1 2 Classes mergeProps also handles the merging of classes using clsx. This means that you can pass in multiple classes as an array or string, and they will be merged together. import { mergeProps } from \"bits-ui\"; const props1 = { class: \"orange blue yellow\" }; const props2 = { class: \"yellow blue green\" }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.class); // \"orange blue yellow green\" Styles mergeProps also handles merging of style objects using style-to-object. You can pass in multiple style objects or style strings and they will be gracefully merged together in the order they are passed. import { mergeProps } from \"bits-ui\"; const props1 = { style: { backgroundColor: \"red\" } }; const props2 = { style: \"background-color: green\" }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.style); // \"background-color: green;\" import { mergeProps } from \"bits-ui\"; const props1 = { style: \"--foo: red\" }; const props2 = { style: { \"--foo\": \"green\", color: \"blue\" } }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.style); // \"--foo: green; color: blue;\" ","description":"A utility function to merge props objects.","href":"/docs/utilities/merge-props"},{"title":"useId","content":" The useId function is a utility function that can be used to generate unique IDs. This function is used internally by all Bits UI components and is exposed for your convenience. Usage import { useId } from \"bits-ui\"; const id = useId(); Label here ","description":"A utility function to generate unique IDs.","href":"/docs/utilities/use-id"},{"title":"WithElementRef","content":" The WithElementRef type helper is a convenience type that enables you to follow the same $2 prop pattern as used by Bits UI components when crafting your own. type WithElementRef = T & { ref?: U | null }; This type helper is used internally by Bits UI components to enable the ref prop on a component. Usage Example import type { WithElementRef } from \"bits-ui\"; type Props = WithElementRef; let { yourPropA, yourPropB, ref = $bindable(null) }: Props = $props(); ","description":"A type helper to enable the `ref` prop on a component.","href":"/docs/type-helpers/with-element-ref"},{"title":"WithoutChild","content":" The WithoutChild type helper is used to exclude the child snippet prop from a component. This is useful when you're building custom component wrappers that populate the children prop of a component and don't provide a way to pass a custom child snippet. To learn more about the child snippet prop, check out the $2 documentation. import { Accordion, type WithoutChild } from \"bits-ui\"; let { children, ...restProps }: WithoutChild = $props(); {@render children?.()} ","description":"A type helper to exclude the child snippet prop from a component.","href":"/docs/type-helpers/without-child"},{"title":"WithoutChildrenOrChild","content":" The WithoutChildrenOrChild type helper is used to exclude the child and children props from a component. This is useful when you're building custom component wrappers that populate the children prop of a component and don't provide a way to pass a custom children or child snippet. To learn more about the child snippet prop, check out the $2 documentation. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; let { title, ...restProps }: WithoutChildrenOrChild = $props(); {title} Now, the CustomAccordionTrigger component won't expose children or child props to the user, but will expose the other root component props. ","description":"A type helper to exclude the child ad children snippet props from a component.","href":"/docs/type-helpers/without-children-or-child"},{"title":"WithoutChildren","content":" The WithoutChildren type helper is used to exclude the children snippet prop from a component. This is useful when you're building custom component wrappers that populate the children prop of a component. import { Accordion, type WithoutChildren } from \"bits-ui\"; let { value, onValueChange, ...restProps }: WithoutChildren = $props(); In the example above, we're using the WithoutChildren type helper to exclude the children snippet prop from the Accordion.Root component. This ensures our exposed props are consistent with what is being used internally. ","description":"A type helper to exclude the children snippet prop from a component.","href":"/docs/type-helpers/without-children"},{"title":"Controlled State","content":" Sometimes, Bits UI doesn't know what's best for your specific use case. In these cases, you can use controlled state to ensure the component remains in a specific state depending on your needs. Uncontrolled State By default, Bits UI components are uncontrolled. This means that the component is responsible for managing its own state. You can bind: to that state for a reference to it, but the component decides when and how to update that state. For example, the Accordion.Root component manages its own value state. When you click or press on any of the triggers, the component will update the value state to the value of the trigger that was clicked. You can update the value state of the Accordion.Root component yourself from the outside, but you can't prevent the component from updating it. Preventing the component from updating the state is where controlled state comes in. Controlled State Controlled state is when you, as the user, are responsible for updating the state of the component. The component will let you know when it thinks it needs to update the state, but you'll be responsible for whether that update happens. This is useful when you have specific conditions that should be met before the component can update, or anything else your requirements dictate. To effectively use controlled state, you'll need to set the controlled prop to true on the component, and you'll also need to pass a local state variable to the component that you'll update yourself. You'll use the onChange callback to update the local state variable. Here's an example of how you might use controlled state with the Accordion component: import { Accordion } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> In the example above, we're using the controlledValue prop to tell the Accordion.Root component that it should be in controlled state. If we were to remove the onValueChange callback, the component wouldn't respond to user interactions and wouldn't update the value state. ","description":"Learn how to use controlled state in Bits UI components.","href":"/docs/controlled-state"},{"title":"Dates and Times","content":" The date and time components in Bits UI are built on top of the $2 package, which provides a unified API for working with dates and times in different locales and time zones. It's heavily inspired by the $2 proposal, and intends to back the objects in this package with the Temporal API once it's available. You can install the package using your favorite package manager: npm install @internationalized/date It's highly recommended to familiarize yourself with the package's documentation before diving into the components. We'll cover the basics of how we use the package in Bits UI in the sections below, but their documentation provides much more detail on the various formats and how to work with them. DateValue We use the DateValue objects provided by @internationalized/date to represent dates and times in a consistent way. These objects are immutable and provide information about the type of date they represent. The DateValue is a union of the following three types: CalendarDate - Represents a date with no time component, such as 2024-07-10 CalendarDateTime - Represents a date and time, such as 2024-07-10T12:30:00 ZonedDateTime - Represents a date and time with a time zone, such as 2023-10-11T21:00:00:00-04:00[America/New_York] The benefit of using these objects is that they allow you to be very specific about the type of date you want, and the component will adapt to that type. For example, if you pass a CalendarDate object to a DateField component, it will only display the date portion of the date, without the time. See the $2 component for more information. CalendarDate The CalendarDate object represents a date with no time component, such as 2024-07-10. You can use the CalendarDate constructor to create a new CalendarDate object: import { CalendarDate } from \"@internationalized/date\"; const date = new CalendarDate(2024, 7, 10); You can also use the parseDate function to parse an $2 string into a CalendarDate object: import { parseDate } from \"@internationalized/date\"; const date = parseDate(\"2024-07-10\"); If you want to create a CalendarDate with the current date, you can use the today function. This function requires a timezone identifier as an argument, which can be passed in as a string, or by using getLocalTimeZone which returns the user's current time zone: import { today, getLocalTimeZone } from \"@internationalized/date\"; const losAngelesToday = today(\"America/Los_Angeles\"); const localToday = today(getLocalTimeZone()); See the $2 for more information. CalendarDateTime The CalendarDateTime object represents a date and time, such as 2024-07-10T12:30:00. You can use the CalendarDateTime constructor to create a new CalendarDateTime object: import { CalendarDateTime } from \"@internationalized/date\"; const dateTime = new CalendarDateTime(2024, 7, 10, 12, 30, 0); You can also use the parseDateTime function to parse an $2 string into a CalendarDateTime object: import { parseDateTime } from \"@internationalized/date\"; const dateTime = parseDateTime(\"2024-07-10T12:30:00\"); See the $2 for more information. ZonedDateTime The ZonedDateTime object represents a date and time with a time zone, which represents an exact date and time in a specific time zone. ZonedDateTimes are often used for things such as in person events (concerts, conferences, etc.), where you want to represent a date and time in a specific time zone, rather than a specific date and time in the user's local time zone. You can use the ZonedDateTime constructor to create a new ZonedDateTime object: import { ZonedDateTime } from \"@internationalized/date\"; const date = new ZonedDateTime( // Date 2022, 2, 3, // Time zone and UTC offset \"America/Los_Angeles\", -28800000, // Time 9, 15, 0 ); You can also use one of the following parsing functions to parse an $2 string into a ZonedDateTime object: import { parseZonedDateTime, parseAbsolute, parseAbsoluteToLocal } from \"@internationalized/date\"; const date = parseZonedDateTime(\"2024-07-12T00:45[America/New_York]\"); // or const date = parseAbsolute(\"2024-07-12T07:45:00Z\", \"America/New_York\"); // or const date = parseAbsoluteToLocal(\"2024-07-12T07:45:00Z\"); See the $2 for more information. Date Ranges Bits UI also provides a DateRange type with the following structure: type DateRange = { start: DateValue; end: DateValue; }; This type is used to represent the value of the various date range components in Bits UI, such as the $2, $2, and $2. Placeholder Each of the date/time components in Bits UI has a bindable placeholder prop, which acts as the starting point for the component when no value is present. The placeholder value is used to determine the type of date/time to display, and the component and its value will adapt to that type. For example, if you pass a CalendarDate object to a DateField component, it will only display the date portion of the date, without the time. If you pass a CalendarDateTime object, it will display the date and time. If you pass a ZonedDateTime object, it will display the date and time with the time zone information. In addition to setting the starting point and type of the date/time, the placeholder is also used to control the view of the calendar. For example, if you wanted to give the user the ability to select a specific month to jump to in the calendar, you could simply update the placeholder to a DateValue representing that month. Here's an example of how you might do that: import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, type DateValue } from \"@internationalized/date\"; let placeholder: DateValue = $state(today(getLocalTimeZone())); let selectedMonth: number = $state(placeholder.month); { placeholder = placeholder.set({ month: selectedMonth }); }} bind:value={selectedMonth} January February In the example above, we're using the placeholder value to control the view of the calendar. The user can select a specific month to jump to in the calendar, and the placeholder will be updated to reflect the selected month. When the placeholder is updated, the calendar view will automatically update to reflect that new month. As the user interacts with the calendar, the placeholder will be updated to reflect the currently focused date in the calendar. If a value is selected in the calendar, the placeholder will be updated to reflect that selected value. Updating the placeholder It's important to note that DateValue objects are immutable, so you can't directly update the placeholder value. Instead, you'll need to reassign the value to the placeholder prop for the changes to reflect. @internationalized/date provides a number of methods for updating the DateValue objects, such as set, add, subtract, and cycle, each of which will return a new DateValue object with the updated value. For example, if you wanted to update the placeholder to the next month, you could use the add method to add one month to the current month in the placeholder value: let placeholder = new CalendarDate(2024, 07, 10); console.log(placeholder.add({ months: 1 })); // 2024-08-10 console.log(placeholder); // 2024-07-10 (unchanged) placeholder = placeholder.add({ months: 1 }); console.log(placeholder); // 2024-08-10 (updated) Formatting Dates @internationalized/date provides a $2 class that is a wrapper around the $2 API that fixes various browser bugs, and polyfills new features. It's highly recommended to use this class to format dates and times in your application, as it will ensure that the formatting is accurate for all locales, time zones, and calendars. Parsing Dates Often, you'll want to parse a string from a database or other source into a DateValue object for use with the date/time components in Bits UI. @internationalized/date provides various parsing functions that can be used to parse strings into each of the supported DateValue objects. parseDate The parseDate function is used to parse a string into a CalendarDate object. ","description":"How to work with the various date and time components in Bits UI.","href":"/docs/dates"},{"title":"Render Delegation","content":" Usage For certain components, we set a default underlying HTML element to wrap the children with. As a high level example, the Accordion.Trigger, looks something like this: {@render children()} While we do allow you to set any attribute that you normally could on a button, let's say you want to apply a $2 or $2 to the button, or use a custom component you've made, that's when render delegation comes into play. Each of the components that support render delegation accept an optional prop called child, which is a $2. When used, the component will pass the attributes as a snippet prop, which you can then apply to the element of your choosing. Note, if you use child any other children that aren't within that child snippet will be ignored. Let's take a look at an example using the Accordion.Trigger component: Let's take a look at an example using the Accordion.Trigger component: {#snippet child({ props })} Open accordion item {/snippet} We're passing all the props/attribute we would normally apply to th ` within the component to whatever element we want. These props include event handlers, aria attributes, and any other attributes you passed into the Accordion.Trigger` component. Custom IDs & Attributes If you wish to use a custom ID, event handlers, or other attributes with a custom element, you must pass them to the component first. A lot of Bits UI internals rely on the ID, and these props are merged via $2 so you'll need to do something like this: console.log(\"clicked\")}> {#snippet child({ props })} Open accordion item {/snippet} Behind the scenes this is what's happening (pseudo): // other imports/props/logic omitted for brevity let { child, children, ...restProps } = $props(); const trigger = makeTrigger(); const mergedProps = $derived(mergeProps(restProps, trigger.props)); {#if child} {@render child({ props: mergedProps })} {:else} {@render children?.()} {/if} ","description":"Learn how to use the `child` snippet to render your own elements.","href":"/docs/delegation"},{"title":"Getting Started","content":" Installation Install bits using your favorite package manager. npm install bits-ui You can then import and start using them in your app. import { Accordion } from \"bits-ui\"; First First accordion content Second Second accordion content Third Third accordion content ","description":"Learn how to get started using Bits in your app.","href":"/docs/getting-started"},{"title":"Introduction","content":" Bits UI is a collection of headless component primitives that enable you to build your own custom components. They are designed to prioritize accessibility and flexibility, enabling you to add your own styles and behaviors to the components. Features Unstyled Most Bits UI components are unstyled by default, it's up to you to style them however you please. You can use the class prop to apply your own styles, or use the applied data attributes to target the components across your entire application. Check out the $2 section for more information. Customizable Each component offers a wide range of props for customizing behavior to fit your needs. Events and callbacks are chainable, allowing you to override the default functionality of the component by simply cancelling the event. Accessible Bits UI components have been designed following the $2 with the goal of making them usable by as many people as possible. Keyboard navigation, screen reader support, and focus management are all built-in. If you notice an accessibility issue, please $2 and we'll address it as soon as possible. Composable Bits UI is built with composability in mind. Each component is designed to be used in isolation, but can be composed together to create more complex UIs. Providing flexibility in the form of $2 and event overrides puts the power of bending the components to your will in your hands. About Bits UI was built and is maintained by $2. The documentation and example components were designed by $2 and $2. Credits $2 - The powerful builder API that inspired a lot of the internals of Bits UI. $2 - The incredible headless component APIs that we've taken heavy inspiration and code references from to build Bits UI. $2 - A world-class library of headless components, hooks, and utilities that we've taken inspiration from to build the various Date and Time components in Bits UI. ","description":"The headless components for Svelte.","href":"/docs/introduction"},{"title":"Ref","content":" Bits UI components that render an underlying HTML element expose a ref prop, which gives you a reference to the underlying element. For example, the Accordion.Trigger component exposes a ref prop, which gives you a reference to the HTMLButtonElement that is rendered by the component. import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } Focus trigger With delegation Bits UI tracks the reference to the underlying element using it's id attribute. This means that even if you use a custom element/component with $2, the ref prop will still work. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } {#snippet child({ props })} {/snippet} One caveat is that if you wish to use a custom id on the element, you must pass it to the component first so it can be registered and associated with the ref prop. The id you pass will be passed down via the props snippet prop on the child snippet. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } const myCustomId = \"my-custom-id\"; {#snippet child({ props })} {/snippet} The following example would not work, as the Accordion.Trigger component has no idea what the id of the CustomButton is. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); // will always be undefined } {#snippet child({ props })} {/snippet} WithElementRef Bits UI exposes a $2 type which enables you to create your own components following the same ref prop pattern. ","description":"Learn about the ref prop.","href":"/docs/ref"},{"title":"Styling","content":" We ship almost zero styles with Bits UI. This is intentional. We want to give you the most flexibility possible when it comes to styling your components. For each component that renders an HTML element, we expose a class prop that you can use to apply styles to the component. This is the recommended and most straightforward way to style them. CSS frameworks If you're using a CSS framework like TailwindCSS or UnoCSS, you can simply pass the classes you need to the component, and they will be applied to the underlying HTML element. import { Button } from \"bits-ui\"; Click me Data attributes A data attribute is applied to each element rendered by Bits UI, which you can use to target the component across your entire application. Check out the API reference of the component to determine what those data attributes are. You can then use those data attributes like so: Define global styles [data-button-root] { height: 3rem; width: 100%; background-color: #3182ce; color: #fff; } Import stylesheet import \"../app.pcss\"; Now every `` component will have the styles applied to it. Global classes If you prefer the class approach, you can simply apply your global classes to the component. Define global styles .button { height: 3rem; width: 100%; background-color: #3182ce; color: #fff; } Apply global styles import \"../app.pcss\"; Use with components import { Button } from \"bits-ui\"; Click me ","description":"Learn how to style Bits UI components.","href":"/docs/styling"},{"title":"Transitions","content":" Svelte Transitions are one of the awesome features of Svelte. Unfortunately, they don't play very nicely with components, due to the fact that they rely on various directives like in:, out:, and transition:, which aren't supported by components. In previous version of Bits UI, we had a workaround for this by exposing a ton of transition* props on the components that we felt were most likely to be used with transitions. However, this was a bit of a hack and limited us to only Svelte Transitions, and users who wanted to use other libraries or just CSS were left out. With Bits UI for Svelte 5, we've completely removed this workaround and instead exposed props and snippets that allow you to use any animation or transitions library you want. The Defaults By default, Bits UI components handle the mounting and unmounting of specific components for you. They are wrapped in a component that ensures the component waits for transitions to finish before unmounting. You can use any CSS transitions or animations you want with this approach, which is what we're doing in the various example components in this documentation, using $2. Force Mounting On each component that we conditionally render, a forceMount prop is exposed. If set to true, the component will be forced to mount in the DOM and become visible to the user. You can use this prop in conjunction with the $2 child snippet to conditionally render the component and apply Svelte Transitions or another animation library. The child snippet exposes a prop that you can use to conditionally render the element and apply your transitions. import { Dialog } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} In the example above, we're using the forceMount prop to tell the component to forcefully mount the Dialog.Content component. We're then using the child snippet to delegate the rendering of the Dialog.Content to a div element which we can apply our props and transitions to. We understand this isn't the prettiest syntax, but it enables us to cover every use case. If you intend to use this approach across your application, it's recommended to create a reusable component that handles this logic, like so: import type { Snippet } from \"svelte\"; import { fly } from \"svelte/transition\"; import { Dialog, type WithoutChildrenOrChild } from \"bits-ui\"; let { ref = $bindable(null), children, ...restProps }: WithoutChildrenOrChild & { children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} Which can then be used alongside the other Dialog.* components: import { Dialog } from \"bits-ui\"; import MyDialogContent from \"$lib/components/MyDialogContent.svelte\"; Open Dialog Dialog Title Dialog Description Close Other dialog content ","description":"Learn how to use transitions with Bits UI components.","href":"/docs/transitions"}] \ No newline at end of file +[{"title":"Accordion","content":" import { APISection, ComponentPreviewV2, AccordionDemo, AccordionDemoTransitions, AccordionDemoCustom, Callout } from '$lib/components/index.js' export let schemas {#snippet preview()} {/snippet} Overview The Accordion component is a versatile UI element that organizes content into collapsible sections, enabling users to focus on specific information while reducing visual clutter. It's particularly useful for presenting large amounts of related content in a compact, navigable format. Key Features Customizable Behavior**: Can be configured for single or multiple open sections. Accessibility**: ARIA attributes for screen reader compatibility and keyboard navigation. Transition Support**: CSS variables and data attributes for smooth transitions between states. Flexible State Management**: Supports controlled and uncontrolled state, take control if needed. Compound Component Structure**: Provides a set of sub-components that work together to create a fully-featured accordion. Architecture The Accordion component is composed of several sub-components, each with a specific role: Root**: The root element that wraps all accordion items and manages the overall state. Item**: Individual sections within the accordion. Trigger**: The button that toggles the visibility of the content. Header**: The title or heading of each item. Content**: The expandable/collapsible body of each item. Structure Here's an overview of how the Accordion component is structured in code: import { Accordion } from \"bits-ui\"; Reusable Components If you're planning to use the Accordion component throughout your application, it's recommended to create reusable wrapper components to reduce the amount of code you need to write each time. For each individual item, you need an Accordion.Item, Accordion.Header, Accordion.Trigger and Accordion.Content component. We can combine these into a single MyAccordionItem component that makes it easier to reuse. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { title: string; content: string; }; let { title, content, ...restProps }: Props = $props(); {item.title} {content} We used the $2 type helper to omit the child and children snippet props from Accordion.ItemProps, since we are opting out of using $2 and are already taking care of rendering the children as text via the content prop. For our MyAccordion component, we'll accept all the props that Accordion.Root accepts, as well as an additional items prop that will be used to render the MyAccordionItem components. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; import MyAccordionItem from \"$lib/components/MyAccordionItem.svelte\"; type Item = { value?: string; title: string; content: string; disabled?: boolean; }; let { value = $bindable(), ref = $bindable(null), ...restProps }: WithoutChildrenOrChild & { items: Item[]; } = $props(); {#each items as item, i (item.title + i)} {/each} import { MyAccordion, MyAccordionItem } from \"$lib/components\"; Content 1 Content 2 Content 3 Managing Value State Bits UI offers several approaches to manage and synchronize the Accordion's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the accordion's internal state. import { Accordion } from \"bits-ui\"; let myValue = $state([]); { myValue = [\"item-1\", \"item-2\"]; }} Open Items 1 and 2 Key Benefits Simplifies state management Automatically updates myValue when the accordion changes (e.g., via clicking on an item's trigger) Allows external control (e.g., opening an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Accordion } from \"bits-ui\"; let myValue = $state([]); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the accordion's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the accordion responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Accordion.Root component. Provide a value prop to Accordion.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Accordion } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Single Type Set the type prop to \"single\" to allow only one accordion item to be open at a time. Multiple Type Set the type prop to \"multiple\" to allow multiple accordion items to be open at the same time. Default Open Items To set default open items, pass them as the value prop, which will be an array if the type is \"multiple\", or a string if the type is \"single\". Disable Items To disable an individual accordion item, set the disabled prop to true. This will prevent users from interacting with the item. Svelte Transitions The Accordion component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Accordion components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of the Accordion.Content. {#snippet child({ props, open })} {#if open} This is the accordion content that will transition in and out. {/if} {/snippet} In this example: The forceMount prop ensures the components are always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directives (transition:fade and transition:fly) apply the animations. {#snippet preview()} {/snippet} Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; import type { Snippet } from \"svelte\"; import { fade } from \"svelte/transition\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyAccordionContent component alongside the other Accordion primitives throughout your application: A ","description":"Organizes content into collapsible sections, allowing users to focus on one or more sections at a time.","href":"/docs/components/accordion"},{"title":"Alert Dialog","content":" import { APISection, ComponentPreviewV2, AlertDialogDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Key Features Compound Component Structure**: Offers a set of sub-components that work together to create a fully-featured alert dialog. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Customizable**: Each sub-component can be styled and configured independently. Portal Support**: Content can be rendered in a portal, ensuring proper stacking context. Managed Focus**: Automatically manages focus, with the option to take control if needed. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the dialog's open state. Architecture The Alert Dialog component is composed of several sub-components, each with a specific role: Root**: The main container component that manages the state of the dialog. Provides context for all child components. Trigger**: A button that toggles the dialog's open state. Portal**: Renders its children in a portal, outside the normal DOM hierarchy. Overlay**: A backdrop that sits behind the dialog content. Content**: The main container for the dialog's content. Title**: Renders the dialog's title. Description**: Renders a description or additional context for the dialog. Cancel**: A button that closes the dialog by cancelling the action. Action**: A button that closes the dialog by taking an action. Structure import { AlertDialog } from \"bits-ui\"; Reusable Components Bits UI provides a decent number of components to construct an Alert Dialog. The idea is to provide a set of building blocks that can be used to create a variety of different components. It's recommended to use these components to build your own reusable Alert Dialog components that can be used throughout your application. The following example shows at a high level how you might create a reusable Alert Dialog component. We've mixed and matched string props and snippets to demonstrate the flexibility of the component API. Use whatever makes sense for you. This example is used in a few places throughout this documentation page to give you a better idea of how it's used. import type { Snippet } from \"svelte\"; import { AlertDialog, type WithoutChild } from \"bits-ui\"; type Props = AlertDialog.RootProps & { buttonText: string; title: Snippet; description: Snippet; contentProps?: WithoutChild; // ...other component props if you wish to pass them }; let { open = $bindable(false), children, buttonText, contentProps, title, description, ...restProps }: Props = $props(); {buttonText} {@render title()} {@render description()} {@render children?.()} Cancel Confirm You can then use the MyAlertDialog component in your application like so: import MyAlertDialog from \"$lib/components/MyAlertDialog.svelte\"; {#snippet title()} Delete your account {/snippet} {#snippet description()} This action cannot be undone. {/snippet} Alternatively, you can define the snippets separately and pass them as props to the component: import MyAlertDialog from \"$lib/components/MyAlertDialog.svelte\"; {#snippet title()} Delete your account {/snippet} {#snippet description()} This action cannot be undone. {/snippet} Managing Open State Bits UI offers several approaches to manage and synchronize the Alert Dialog's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { AlertDialog } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Dialog Key Benefits Simplifies state management Automatically updates isOpen when the dialog closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { AlertDialog } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. import { AlertDialog } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Focus Focus Trap By default, when a dialog is opened, focus will be trapped within the Dialog, preventing the user from interacting with the rest of the page. This follows the $2 for alert dialogs. Although it isn't recommended unless absolutely necessary, you can disabled this behavior by setting the trapFocus prop to false on the AlertDialog.Content component. Open Focus By default, when a dialog is opened, focus will be set to the AlertDialog.Cancel button if it exists, or the first focusable element within the AlertDialog.Content. This ensures that users navigating my keyboard end up somewhere within the Dialog that they can interact with. You can override this behavior using the onOpenAutoFocus prop on the AlertDialog.Content component. It's highly recommended that you use this prop to focus something within the Dialog. You'll first need to cancel the default behavior of focusing the first focusable element by cancelling the event passed to the onOpenAutoFocus callback. You can then focus whatever you wish. import { AlertDialog } from \"bits-ui\"; let nameInput = $state(); Open AlertDialog { e.preventDefault(); nameInput?.focus(); }} Close Focus By default, when a dialog is closed, focus will be set to the trigger element of the dialog. You can override this behavior using the onCloseAutoFocus prop on the AlertDialog.Content component. You'll need to cancel the default behavior of focusing the trigger element by cancelling the event passed to the onCloseAutoFocus callback, and then focus whatever you wish. import { AlertDialog } from \"bits-ui\"; let nameInput = $state(); Open AlertDialog { e.preventDefault(); nameInput?.focus(); }} Advanced Behaviors The Alert Dialog component offers several advanced features to customize its behavior and enhance user experience. This section covers scroll locking, escape key handling, and interaction outside the dialog. Scroll Lock By default, when an Alert Dialog opens, scrolling the body is disabled. This provides a more native-like experience, focusing user attention on the dialog content. Customizing Scroll Behavior To allow body scrolling while the dialog is open, use the preventScroll prop on AlertDialog.Content: Enabling body scroll may affect user focus and accessibility. Use this option judiciously. Escape Key Handling By default, pressing the Escape key closes an open Alert Dialog. Bits UI provides two methods to customize this behavior. Method 1: escapeKeydownBehavior The escapeKeydownBehavior prop allows you to customize the behavior taken by the component when the Escape key is pressed. It accepts one of the following values: 'close' (default): Closes the Alert Dialog immediately. 'ignore': Prevents the Alert Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the key press and not close. To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onEscapeKeydown For more granular control, override the default behavior using the onEscapeKeydown prop: { e.preventDefault(); // do something else instead }} This method allows you to implement custom logic when the Escape key is pressed. Interaction Outside By default, interacting outside the Alert Dialog content area closes the Alert Dialog. Bits UI offers two ways to modify this behavior. Method 1: interactOutsideBehavior The interactOutsideBehavior prop allows you to customize the behavior taken by the component when an interaction (touch, mouse, or pointer event) occurs outside the content. It accepts one of the following values: 'close' (default): Closes the Alert Dialog immediately. 'ignore': Prevents the Alert Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Alert Dialog will ignore the event and not close. To always prevent the Alert Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Alert.Content: Method 2: onInteractOutside For custom handling of outside interactions, you can override the default behavior using the onInteractOutside prop: { e.preventDefault(); // do something else instead }} This approach allows you to implement specific behaviors when users interact outside the Alert Dialog content. Best Practices Scroll Lock**: Consider your use case carefully before disabling scroll lock. It may be necessary for dialogs with scrollable content or for specific UX requirements. Escape Keydown**: Overriding the default escape key behavior should be done thoughtfully. Users often expect the escape key to close modals. Outside Interactions**: Ignoring outside interactions can be useful for important dialogs or multi-step processes, but be cautious not to trap users unintentionally. Accessibility**: Always ensure that any customizations maintain or enhance the dialog's accessibility. User Expectations**: Try to balance custom behaviors with common UX patterns to avoid confusing users. By leveraging these advanced features, you can create highly customized dialog experiences while maintaining usability and accessibility standards. Nested Dialogs Dialogs can be nested within each other to create more complex layouts. See the $2 component for more information on nested dialogs. Svelte Transitions See the $2 component for more information on Svelte Transitions with dialog components. Working with Forms Form Submission When using the AlertDialog component, often you'll want to submit a form or perform an asynchronous action when the user clicks the Action button. This can be done by waiting for the asynchronous action to complete, then programmatically closing the dialog. import { AlertDialog } from \"bits-ui\"; function wait(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } let open = $state(false); Confirm your action Are you sure you want to do this? { wait(1000).then(() => (open = false)); }} No, cancel (close dialog) Yes (submit form) Inside a Form If you're using an AlertDialog within a form, you'll need to ensure that the Portal is disabled or not included in the AlertDialog structure. This is because the Portal will render the dialog content outside of the form, which will prevent the form from being submitted correctly. ","description":"A modal window that alerts users with important information and awaits their acknowledgment or action.","href":"/docs/components/alert-dialog"},{"title":"Aspect Ratio","content":" import { APISection, ComponentPreviewV2, AspectRatioDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Architecture Root**: The root component which contains the aspect ratio logic Structure Here's an overview of how the Aspect Ratio component is structured in code: import { AspectRatio } from \"bits-ui\"; Reusable Component If you plan on using a lot of AspectRatio components throughout your application, you can create a reusable component that combines the AspectRatio.Root and whatever other elements you'd like to render within it. In the following example, we're creating a reusable MyAspectRatio component that takes in a src prop and renders an img element with the src prop. import { AspectRatio, type WithoutChildrenOrChild } from \"bits-ui\"; let { src, alt, ref = $bindable(null), imageRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { src: string; alt: string; imageRef?: HTMLImageElement | null; } = $props(); You can then use the MyAspectRatio component in your application like so: import MyAspectRatio from \"$lib/components/MyAspectRatio.svelte\"; Custom Ratio Use the ratio prop to set a custom aspect ratio for the image. ","description":"Displays content while maintaining a specified aspect ratio, ensuring consistent visual proportions.","href":"/docs/components/aspect-ratio"},{"title":"Avatar","content":" import { APISection, ComponentPreviewV2, AvatarDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Avatar component is designed to represent a user or entity within your application's user interface. It provides a flexible and accessible way to display profile pictures or placeholder images. Key Features Compound Component Structure**: Offers a set of sub-components that work together to create a fully-featured avatar. Fallback Mechanism**: Provides a fallback when the primary image is unavailable or loading. Customizable**: Each sub-component can be styled and configured independently to match your design system. Architecture The Avatar component is composed of several sub-components, each with a specific role: Root**: The main container component that manages the state of the avatar. Image**: The primary image element that displays the user's profile picture or a representative image. Fallback**: The fallback element that displays alternative content when the primary image is unavailable or loading. Structure Here's an overview of how the Avatar component is structured in code: import { Avatar } from \"bits-ui\"; Reusable Components You can create your own reusable components that combine the Avatar primitives and simplify the usage throughout your application. In the following example, we're creating a reusable MyAvatar component that takes in a src and fallback prop and renders an Avatar.Root component with an Avatar.Image and Avatar.Fallback component. import { Avatar, type WithoutChildrenOrChild } from \"bits-ui\"; let { src, alt, fallback, ref = $bindable(null), imageRef = $bindable(null), fallbackRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { src: string; alt: string; fallback: string; imageRef?: HTMLImageElement | null; fallbackRef?: HTMLElement | null; } = $props(); {fallback} You could then use the MyAvatar component in your application like so: import MyAvatar from \"$lib/components/MyAvatar.svelte\"; ","description":"Represents a user or entity with a recognizable image or placeholder in UI elements.","href":"/docs/components/avatar"},{"title":"Button","content":" import { APISection, ComponentPreviewV2, ButtonDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Button } from \"bits-ui\"; ","description":"A component that if passed a `href` prop will render an anchor element instead of a button element.","href":"/docs/components/button"},{"title":"Calendar","content":" import { APISection, ComponentPreviewV2, CalendarDemo, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { Calendar } from \"bits-ui\"; {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} Placeholder The placeholder prop for the Calendar.Root component determines what date our calendar should start with when the user hasn't selected a date yet. It also determines the current \"view\" of the calendar. As the user navigates through the calendar, the placeholder will be updated to reflect the currently focused date in that view. By default, the placeholder will be set to the current date, and be of type CalendarDate. Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the Calendar.Root component. Provide a placeholder prop to Calendar.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { Calendar } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Calendar } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the Calendar.Root component. Provide a value prop to Calendar.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Calendar } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Default Value Often, you'll want to start the Calendar.Root component with a default value. Likely this value will come from a database in the format of an ISO 8601 string. You can use the parseDate function from the @internationalized/date package to parse the string into a CalendarDate object. import { Calendar } from \"bits-ui\"; import { parseDate } from \"@internationalized/date\"; // this came from a database/API call const date = \"2024-08-03\"; let value = $state(parseDate(date)); Validation Minimum Value You can set a minimum value for the calendar by using the minValue prop on Calendar.Root. If a user selects a date that is less than the minimum value, the calendar will be marked as invalid. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const yesterday = todayDate.subtract({ days: 1 }); Maximum Value You can set a maximum value for the calendar by using the maxValue prop on Calendar.Root. If a user selects a date that is greater than the maximum value, the calendar will be marked as invalid. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); Unavailable Dates You can specify specific dates that are unavailable for selection by using the isDateUnavailable prop. This prop accepts a function that returns a boolean value indicating whether a date is unavailable or not. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, isNotNull } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); function isDateUnavailable(date: DateValue) { return date.day === 1; } Disabled Dates You can specify specific dates that are disabled for selection by using the isDateDisabled prop. import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, isNotNull } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); function isDateDisabled(date: DateValue) { return date.day === 1; } ","description":"Displays dates and days of the week, facilitating date-related interactions.","href":"/docs/components/calendar"},{"title":"Checkbox","content":" import { APISection, ComponentPreviewV2, CheckboxDemo, CheckboxDemoCustom, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Checkbox component provides a flexible and accessible way to create checkbox inputs in your Svelte applications. It supports three states: checked, unchecked, and indeterminate, allowing for complex form interactions and data representations. Key Features Tri-State Support**: Handles checked, unchecked, and indeterminate states, providing versatility in form design. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the checkbox's checked state. Architecture The Checkbox component is composed of the following parts: Root**: The main component that manages the state and behavior of the checkbox. Structure Here's an overview of how the Checkbox component is structured in code: import { Checkbox } from \"bits-ui\"; {#snippet children({ checked })} {#if checked === \"indeterminate\"} {:else if checked} ✅ {:else} ❌ {/if} {/snippet} Reusable Components It's recommended to use the Checkbox primitive to create your own custom checkbox component that can be used throughout your application. In the example below, we're using the Checkbox and $2 components to create a custom checkbox component. import { Checkbox, Label, useId, type WithoutChildrenOrChild } from \"bits-ui\"; let { id = useId(), checked = $bindable(false), ref = $bindable(null), labelRef = $bindable(null), ...restProps }: WithoutChildrenOrChild & { labelText: string; labelRef?: HTMLLabelElement | null; } = $props(); {#snippet children({ checked })} {#if checked === \"indeterminate\"} {:else if checked} ✅ {:else} ❌ {/if} {/snippet} {labelText} You can then use the MyCheckbox component in your application like so: import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; Managing Checked State Bits UI offers several approaches to manage and synchronize the Checkbox's checked state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:checked directive. This method automatically keeps your local state in sync with the checkbox's internal state. import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; let myChecked = $state(false); (myChecked = false)}> uncheck Key Benefits Simplifies state management Automatically updates myChecked when the checkbox changes (e.g., via clicking on the checkbox) Allows external control (e.g., checking via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onCheckedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import MyCheckbox from \"$lib/components/MyCheckbox.svelte\"; let myChecked = $state(false); { myChecked = checked; if (checked === \"indeterminate\") { // do something different } // additional logic here. }} /> Use Cases Implementing custom behaviors on checked/unchecked Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the checkbox's checked state, use the controlledChecked prop. This approach requires you to manually manage the checked state, giving you full control over when and how the checkbox responds to change events. To implement controlled state: Set the controlledChecked prop to true on the Checkbox.Root component. Provide a checked prop to Checkbox.Root, which should be a variable holding the current state. Implement an onCheckedChange handler to update the state when the internal state changes. import { Checkbox } from \"bits-ui\"; let myChecked = $state(false); (myChecked = c)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Disabled State You can disable the checkbox by setting the disabled prop to true. HTML Forms If you set the name prop, a hidden checkbox input will be rendered to submit the value of the checkbox with a form. By default, the checkbox will be submitted with default checkbox value of 'on' if the checked prop is true. Custom Input Value If you'd prefer to submit a different value, you can use the value prop to set the value of the hidden input. For example, if you wanted to submit a string value, you could do the following: Required If you want to make the checkbox required, you can use the required prop. This will apply the required attribute to the hidden input element, ensuring that proper form submission is enforced. ","description":"Allow users to switch between checked, unchecked, and indeterminate states.","href":"/docs/components/checkbox"},{"title":"Collapsible","content":" import { APISection, ComponentPreviewV2, CollapsibleDemo, CollapsibleDemoTransitions, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Collapsible component enables you to create expandable and collapsible content sections. It provides an efficient way to manage space and organize information in user interfaces, enabling users to show or hide content as needed. Key Features Accessibility**: ARIA attributes for screen reader compatibility and keyboard navigation. Transition Support**: CSS variables and data attributes for smooth transitions between states. Flexible State Management**: Supports controlled and uncontrolled state, take control if needed. Compound Component Structure**: Provides a set of sub-components that work together to create a fully-featured collapsible. Architecture The Accordion component is composed of a few sub-components, each with a specific role: Root**: The parent container that manages the state and context for the collapsible functionality. Trigger**: The interactive element (e.g., button) that toggles the expanded/collapsed state of the content. Content**: The container for the content that will be shown or hidden based on the collapsible state. Structure Here's an overview of how the Collapsible component is structured in code: import { Collapsible } from \"bits-ui\"; Reusable Components It's recommended to use the Collapsible primitives to create your own custom collapsible component that can be used throughout your application. import { Collapsible, type WithoutChild } from \"bits-ui\"; type Props = WithoutChild & { buttonText: string; }; let { open = $bindable(false), ref = $bindable(null), buttonText, children, ...restProps }: Props = $props(); {buttonText} {@render children?.()} You can then use the MyCollapsible component in your application like so: import MyCollapsible from \"$lib/components/MyCollapsible.svelte\"; Here is my collapsible content. Managing Open State Bits UI offers several approaches to manage and synchronize the Collapsible's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the Collapsible's internal state. import { Collapsible } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Collapsible Key Benefits Simplifies state management Automatically updates isOpen when the collapsible closes (e.g., via trigger press) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Collapsible } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the Collapsible's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the collapsible responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Collapsible.Root component. Provide an open prop to Collapsible.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Collapsible } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Svelte Transitions The Collapsible component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Collapsible components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of the Collapsible.Content. import { Collapsible } from \"bits-ui\"; import { fade } from \"svelte/transition\"; Open {#snippet child({ props, open })} {#if open} {/if} {/snippet} In this example: The forceMount prop ensures the content is always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directive (transition:fade) apply the animations. Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Collapsible, type WithoutChildrenOrChild } from \"bits-ui\"; import { fade } from \"svelte/transition\"; import type { Snippet } from \"svelte\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyCollapsibleContent component alongside the other Collapsible primitives throughout your application: import { Collapsible } from \"bits-ui\"; import { MyCollapsibleContent } from \"$lib/components\"; Open ","description":"Conceals or reveals content sections, enhancing space utilization and organization.","href":"/docs/components/collapsible"},{"title":"Combobox","content":" import { APISection, ComponentPreviewV2, ComboboxDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Combobox component combines the functionality of an input field with a dropdown list of selectable options. It provides users with the ability to search, filter, and select from a predefined set of choices. Key Features Keyboard Navigation**: Full support for keyboard interactions, allowing users to navigate and select options without using a mouse. Customizable Rendering**: Flexible architecture for rendering options, including support for grouped items. Accessibility**: Built with ARIA attributes and keyboard interactions to ensure screen reader compatibility and accessibility standards. Portal Support**: Ability to render the dropdown content in a portal, preventing layout issues in complex UI structures. Architecture The Combobox component is composed of several sub-components, each with a specific role: Root**: The main container component that manages the state and context for the combobox. Input**: The input field that allows users to enter search queries. Trigger**: The button or element that opens the dropdown list. Portal**: Responsible for portalling the dropdown content to the body or a custom target. Group**: A container for grouped items, used to group related items. GroupHeading**: A heading for a group of items, providing a descriptive label for the group. Item**: An individual item within the list. Separator**: A visual separator between items. Content**: The dropdown container that displays the items. It uses $2 to position the content relative to the trigger. ContentStatic**: An alternative to the Content component, that enables you to opt-out of Floating UI and position the content yourself. Arrow**: An arrow element that points to the trigger when using the Combobox.Content component. Structure Here's an overview of how the Combobox component is structured in code: import { Combobox } from \"bits-ui\"; Reusable Components It's recommended to use the Combobox primitives to build your own custom combobox component that can be reused throughout your application. import { Combobox, type WithoutChildrenOrChild, mergeProps } from \"bits-ui\"; type Item = { value: string; label: string }; type Props = Combobox.RootProps & { items: Item[]; inputProps?: WithoutChildrenOrChild; contentProps?: WithoutChildrenOrChild; }; let { items, value = $bindable(), open = $bindable(false), inputProps, contentProps, ...restProps }: Props = $props(); let searchValue = $state(\"\"); const filteredItems = $derived.by(() => { if (searchValue === \"\") return items; return items.filter((item) => item.label.toLowerCase().includes(searchValue.toLowerCase())); }); function handleInput(e: Event & { currentTarget: HTMLInputElement }) { searchValue = e.currentTarget.value; } function handleOpenChange(newOpen: boolean) { if (!newOpen) searchValue = \"\"; } const mergedRootProps = $derived(mergeProps(restProps, { onOpenChange: handleOpenChange })); const mergedInputProps = $derived(mergeProps(inputProps, { oninput: handleInput })); Open {#each filteredItems as item, i (i + item.value)} {#snippet children({ selected })} {item.label} {selected ? \"✅\" : \"\"} {/snippet} {:else} No results found {/each} import { CustomCombobox } from \"$lib/components\"; const items = [ { value: \"mango\", label: \"Mango\" }, { value: \"watermelon\", label: \"Watermelon\" }, { value: \"apple\", label: \"Apple\" }, // ... ]; Managing Value State Bits UI offers several approaches to manage and synchronize the Combobox's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Combobox.Root component. Provide a value prop to Combobox.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Combobox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the Combobox's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = true)}> Open Key Benefits Simplifies state management Automatically updates myOpen when the internal state changes (e.g., via clicking on the trigger/input) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); { myOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledOpen prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledOpen prop to true on the Combobox.Root component. Provide an open prop to Combobox.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Combobox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Opt-out of Floating UI When you use the Combobox.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Combobox.ContentStatic component. When using this component, you'll need to handle the positioning of the content yourself. Keep in mind that using Combobox.Portal alongside Combobox.ContentStatic may result in some unexpected positioning behavior, feel free to not use the portal or work around it. Custom Anchor By default, the Combobox.Content is anchored to the Combobox.Trigger component, which determines where the content is positioned. If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the Combobox.Content component. import { Combobox } from \"bits-ui\"; let customAnchor = $state(null!); What is the Viewport? The Combobox.Viewport component is used to determine the size of the content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Combobox.Viewport component. Scroll Up/Down Buttons The Combobox.ScrollUpButton and Combobox.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. You must use the Combobox.Viewport component when using the scroll buttons. Native Scrolling/Overflow If you don't want to use the scroll buttons and prefer to use the standard scrollbar/overflow behavior, you can omit the Combobox.Scroll[Up|Down]Button components and the Combobox.Viewport component. You'll need to set a height on the Combobox.Content component and appropriate overflow styles to enable scrolling. Scroll Lock By default, when a user opens the Combobox, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. Highlighted Items The Combobox component follows the $2 for highlighting items. This means that the Combobox.Input retains focus the entire time, even when navigating with the keyboard, and items are highlighted as the user navigates them. Styling Highlighted Items You can use the data-highlighted attribute on the Combobox.Item component to style the item differently when it is highlighted. onHighlight / onUnhighlight To trigger side effects when an item is highlighted or unhighlighted, you can use the onHighlight and onUnhighlight props. console.log('I am highlighted!')} onUnhighlight={() => console.log('I am unhighlighted!')} /> ","description":"Enables users to pick from a list of options displayed in a dropdown.","href":"/docs/components/combobox"},{"title":"Command","content":" import { APISection, ComponentPreviewV2, CommandDemo, CommandDemoDialog, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Command component, also known as a command menu, is designed to provide users with a quick and efficient way to search, filter, and select items within an application. It combines the functionality of a search input with a dynamic, filterable list of commands or options, making it ideal for applications that require fast navigation or action execution. Key Features Dynamic Filtering**: As users type in the input field, the list of commands or items is instantly filtered and sorted based on an (overridable) scoring algorithm. Keyboard Navigation**: Full support for keyboard interactions, allowing users to quickly navigate and select items without using a mouse. Grouped Commands**: Ability to organize commands into logical groups, enhancing readability and organization. Empty and Loading States**: Built-in components to handle scenarios where no results are found or when results are being loaded. Accessibility**: Designed with ARIA attributes and keyboard interactions to ensure screen reader compatibility and accessibility standards. Architecture The Command component is composed of several sub-components, each with a specific role: Root**: The main container that manages the overall state and context of the command menu. Input**: The text input field where users can type to search or filter commands. List**: The container for the list of commands or items. Viewport**: The visible area of the command list, which applies CSS variables to handle dynamic resizing/animations based on the height of the list. Empty**: A component to display when no results are found. Loading**: A component to display while results are being fetched or processed. Group**: A container for a group of items within the command menu. GroupHeading**: A header element to provide an accessible label for a group of items. GroupItems**: A container for the items within a group. Item**: Individual selectable command or item. LinkItem**: A variant of Command.Item specifically for link-based actions. Separator**: A visual separator to divide different sections of the command list. Structure Here's an overview of how the Command component is structured in code: import { Combobox } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the Command's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Command.Root component. Provide a value prop to Command.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Command } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex value change logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. In a Modal You can combine the Command component with the Dialog component to display the command menu within a modal. {#snippet preview()} {/snippet} Filtering Custom Filter By default, the Command component uses a scoring algorithm to determine how the items should be sorted/filtered. You can provide a custom filter function to override this behavior. The function should return a number between 0 and 1, with 1 being a perfect match, and 0 being no match, resulting in the item being hidden entirely. The following example shows how you might implement a strict substring match filter: import { Command } from \"bits-ui\"; function customFilter(value: string, search: string, keywords?: string[]): number { return value.includes(search) ? 1 : 0; } Disable Filtering You can disable filtering by setting the shouldFilter prop to false. This is useful when you have a lot of custom logic, need to fetch items asynchronously, or just want to handle filtering yourself. You'll be responsible for iterating over the items and determining which ones should be shown. Item Selection You can use the onSelect prop to handle the selection of items. console.log(\"selected something!\")} /> Links If you want one of the items to get all the benefits of a link (prefetching, etc.), you should use the Command.LinkItem component instead of the Command.Item component. The only difference is that the Command.LinkItem component will render an a element instead of a div element. ","description":"A command menu component that can be used to search, filter, and select items.","href":"/docs/components/command"},{"title":"Context Menu","content":" import { APISection, ComponentPreviewV2, ContextMenuDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { ContextMenu } from \"bits-ui\"; {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} Reusable Components If you're planning to use Context Menu in multiple places, you can create a reusable component that wraps the Context Menu component. This example shows you how to create a Context Menu component that accepts a few custom props that make it more capable. import type { Snippet } from \"svelte\"; import { ContextMenu, type WithoutChild } from \"bits-ui\"; type Props = ContextMenu.Props & { trigger: Snippet; items: string[]; contentProps?: WithoutChild; // other component props if needed }; let { open = $bindable(false), children, trigger, items, contentProps, ...restProps }: Props = $props(); {@render trigger()} Select an Office {#each items as item} {item} {/each} You can then use the CustomContextMenu component like this: import CustomContextMenu from \"./CustomContextMenu.svelte\"; {#snippet triggerArea()} Right-click me {/snippet} Alternatively, you can define the snippet(s) separately and pass them as props to the component: import CustomContextMenu from \"./CustomContextMenu.svelte\"; {#snippet triggerArea()} Right-click me {/snippet} Managing Open State Bits UI offers several approaches to manage and synchronize the Context Menu's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { ContextMenu } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Context Menu Key Benefits Simplifies state management Automatically updates isOpen when the menu closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { ContextMenu } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the ContextMenu.Root component. Provide an open prop to ContextMenu.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { ContextMenu } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Checkbox Items You can use the ContextMenu.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { ContextMenu } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} See the $2 for more information. Radio Groups You can combine the ContextMenu.RadioGroup and ContextMenu.RadioItem components to create a radio group within a menu. import { ContextMenu } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} See the $2 and $2 APIs for more information. Nested Menus You can create nested menus using the ContextMenu.Sub component to create complex menu structures. import { ContextMenu } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the ContextMenu.Content component to use Svelte Transitions or another animation library that requires more control. import { ContextMenu } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Displays options or actions relevant to a specific context or selected item, triggered by a right-click.","href":"/docs/components/context-menu"},{"title":"Date Field","content":" import { CalendarDateTime, CalendarDate, now, getLocalTimeZone, parseDate, today } from \"@internationalized/date\"; import { APISection, ComponentPreviewV2, DateFieldDemo, DateFieldDemoCustom, DemoContainer, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Overview The DateField component is an alternative to the native `` element. It provides a more flexible and customizable way to select dates within a designated field. Before jumping into the DateField component, it's important to understand how dates and times are handled in Bits UI. You can learn more about this on the $2 page. Structure import { DateField } from \"$lib\"; Check-in date {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} Reusable Components It's recommended to use the DateField primitives to build your own custom date field component that can be used throughout your application. The following example shows how you might create a reusable MyDateField component that can be used throughout your application. For style inspiration, reference the featured demo at the top of this page. import { DateField, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { labelText: string; }; let { value, placeholder, name, ...restProps }: Props = $props(); {labelText} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {#snippet preview()} {/snippet} We'll be using this newly created MyDateField component in the following demos and examples to prevent repeating the same code, so be sure to reference it as you go through the documentation. Segments A segment of the DateField represents a not only a specific part of the date, such as the day, month, year, hour, but can also reference a \"literal\" which is typically a separator between the different parts of the date, and varies based on the locale. Notice that in the MyDateField component we created, we're styling the DateField.Segment components differently based on whether they are a \"literal\" or not. Placeholder The placeholder prop for the DateField.Root component isn't what is displayed when the field is empty, but rather what date our field should start with when the user attempts to cycle through the segments. The placeholder can also be used to set a granularity for the date field, which will determine which type of DateValue object is used for the value. By default, the placeholder will be set to the current date, and be of type CalendarDate. However, if we wanted this date field to also allow for selecting a time, we could set the placeholder to a CalendarDateTime object. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDateTime } from \"@internationalized/date\"; If we're collecting a date from the user where we want the timezone as well, we can use a ZonedDateTime object instead. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { now, getLocalTimeZone } from \"@internationalized/date\"; If you're creating a date field for something like a birthday, ensure your placeholder is set in a leap year to ensure users born on a leap year will be able to select the correct date. Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateField.Root component. Provide a placeholder prop to DateField.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateField } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateField.Root component. Provide a value prop to DateField.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateField } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Default Value Often, you'll want to start the DateField.Root component with a default value. Likely this value will come from a database in the format of an ISO 8601 string. You can use the parseDate function from the @internationalized/date package to parse the string into a CalendarDate object. import { DateField } from \"bits-ui\"; import { parseDate } from \"@internationalized/date\"; // this came from a database/API call const date = \"2024-08-03\"; let value = $state(parseDate(date)); Now our input is populated with the default value. In addition to the parseDate function, you can also use parseDateTime or parseZonedDateTime to parse the string into a CalendarDateTime or ZonedDateTime object respectively. Validation Minimum Value You can set a minimum value for the DateField.Root component by using the minValue prop. If a user selects a date that is less than the minimum value, the date field will be marked as invalid. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const yesterday = todayDate.subtract({ days: 1 }); In the example above, we're setting the minimum value to today, and the default value to yesterday. This causes the date field to be marked as invalid, and we can style it accordingly. If you adjust the date to be greater than the minimum value, the invalid state will be cleared. Maximum Value You can set a maximum value for the DateField.Root component by using the maxValue prop. If a user selects a date that is greater than the maximum value, the date field will be marked as invalid. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { today, getLocalTimeZone } from \"@internationalized/date\"; const todayDate = today(getLocalTimeZone()); const tomorrow = todayDate.add({ days: 1 }); In the example above, we're setting the maximum value to today, and the default value to tomorrow. This causes the date field to be marked as invalid, and we can style it accordingly. If you adjust the date to be less than the maximum value, the invalid state will be cleared. Custom Validation You can use the validate prop to provide a custom validation function for the date field. This function should return a string or array of strings as validation errors if the date is invalid, or undefined/nothing if the date is valid. The strings are then passed to the onInvalid callback, which you can use to display an error message to the user. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDate, type DateValue } from \"@internationalized/date\"; const value = new CalendarDate(2024, 8, 2); function validate(date: DateValue) { return date.day === 1 ? \"Date cannot be the first day of the month\" : undefined; } function onInvalid(reason: \"min\" | \"max\" | \"custom\", msg?: string | string[]) { if (reason === \"custom\") { if (typeof msg === \"string\") { // do something with the error message console.log(msg); return; } else if (Array.isArray(msg)) { // do something with the error messages console.log(msg); return; } console.log(\"The date is invalid\"); } else if (reason === \"min\") { // let the user know that the date is too early. console.log(\"The date is too early.\"); } else if (reason === \"max\") { // let the user know that the date is too late. console.log(\"The date is too late.\"); } } date.day === 1 ? \"Date cannot be the first day of the month\" : undefined} value={new CalendarDate(2024, 8, 2)} onInvalid={(reason, msg) => { if (reason === \"custom\") { if (typeof msg === \"string\") { // do something with the error message console.log(msg); return; } else if (Array.isArray(msg)) { // do something with the error messages console.log(msg); return; } console.log(\"The date is invalid\"); } else if (reason === \"min\") { // let the user know that the date is too early. console.log(\"The date is too early.\"); } else if (reason === \"max\") { // let the user know that the date is too late. console.log(\"The date is too late.\"); } }} /> In the example above, we're setting the isDateUnavailable prop to a function that returns true for the first day of the month. Try selecting a date that is the first day of the month to see the date field marked as invalid. Granularity The granularity prop sets the granularity of the date field, which determines which segments are rendered in the date field. The granularity can be set to either 'day', 'hour', 'minute', or 'second'. import MyDateField from \"$lib/components/MyDateField.svelte\"; import { CalendarDateTime } from \"@internationalized/date\"; const value = new CalendarDateTime(2024, 8, 2, 12, 30); In the example above, we're setting the granularity to 'second', which means that the date field will include an additional segment for the seconds. ","description":"Enables users to input specific dates within a designated field.","href":"/docs/components/date-field"},{"title":"Date Picker","content":" import { APISection, ComponentPreviewV2, DatePickerDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DatePicker } from \"bits-ui\"; {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myPlaceholder = new CalendarDate(2024, 8, 3))}> Set placeholder to August 3rd, 2024 Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { placeholder = p; }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DatePicker.Root component. Provide a placeholder prop to DatePicker.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); (myValue = myValue.add({ days: 1 }))}> Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { value = v.set({ hour: v.hour + 1 }); }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DatePicker.Root component. Provide a value prop to DatePicker.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the component's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DatePicker } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open DatePicker Key Benefits Simplifies state management Automatically updates isOpen when the picker closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DatePicker } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DatePicker.Root component. Provide an open prop to DatePicker.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DatePicker } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Facilitates the selection of dates through an input and calendar-based interface.","href":"/docs/components/date-picker"},{"title":"Date Range Field","content":" import { APISection, ComponentPreviewV2, DateRangeFieldDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DateRangeField } from \"$lib\"; Check-in date {#each [\"start\", \"end\"] as const as type} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {/each} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangeField } from \"bits-ui\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { myPlaceholder = p.set({ year: 2025 }); }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateRangeField.Root component. Provide a placeholder prop to DateRangeField.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateRangeField } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: value.start.add({ days: 1 }), end: value.end.add({ days: 1 }), }; }} Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangeField } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: v.start?.set({ hour: v.start.hour + 1 }), end: v.end?.set({ hour: v.end.hour + 1 }), }; }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateRangeField.Root component. Provide a value prop to DateRangeField.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateRangeField } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Allows users to input a range of dates within a designated field.","href":"/docs/components/date-range-field"},{"title":"Date Range Picker","content":" import { APISection, ComponentPreviewV2, DateRangePickerDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { DateRangePicker } from \"bits-ui\"; {#each [\"start\", \"end\"] as const as type} {#snippet children({ segments })} {#each segments as { part, value }} {value} {/each} {/snippet} {/each} {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {date.day} {/each} {/each} {/each} {/snippet} Managing Placeholder State Bits UI offers several approaches to manage and synchronize the component's placeholder state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:placeholder directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); Key Benefits Simplifies state management Automatically updates myPlaceholder when the internal state changes Allows external control (e.g., changing the placeholder via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPlaceholderChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; let myPlaceholder = $state(new CalendarDateTime(2024, 8, 3, 12, 30)); { myPlaceholder = p.set({ year: 2025 }); }} Use Cases Implementing custom behaviors on placeholder change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's placeholder state, use the controlledPlaceholder prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPlaceholder prop to true on the DateRangePicker.Root component. Provide a placeholder prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onPlaceholderChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myPlaceholder = $state(); (myPlaceholder = p)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: value.start.add({ days: 1 }), end: value.end.add({ days: 1 }), }; }} Add 1 day Key Benefits Simplifies state management Automatically updates myValue when the internal state changes Allows external control (e.g., changing the value via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; import { CalendarDateTime } from \"@internationalized/date\"; let myValue = $state({ start: new CalendarDateTime(2024, 8, 3, 12, 30), end: new CalendarDateTime(2024, 8, 4, 12, 30), }); { value = { start: v.start?.set({ hour: v.start.hour + 1 }), end: v.end?.set({ hour: v.end.hour + 1 }), }; }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledValue prop to true on the DateRangePicker.Root component. Provide a value prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myValue = $state(); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the component's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DateRangePicker } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open DateRangePicker Key Benefits Simplifies state management Automatically updates isOpen when the picker closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DateRangePicker } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DateRangePicker.Root component. Provide an open prop to DateRangePicker.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DateRangePicker } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Facilitates the selection of date ranges through an input and calendar-based interface.","href":"/docs/components/date-range-picker"},{"title":"Dialog","content":" import { APISection, ComponentPreviewV2, DialogDemo, DialogDemoCustom, DialogDemoNested, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Dialog component in Bits UI provides a flexible and accessible way to create modal dialogs in your Svelte applications. It follows a compound component pattern, allowing for fine-grained control over the dialog's structure and behavior while maintaining accessibility and ease of use. Key Features Compound Component Structure**: Offers a set of sub-components that work together to create a fully-featured dialog. Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. Customizable**: Each sub-component can be styled and configured independently. Portal Support**: Content can be rendered in a portal, ensuring proper stacking context. Managed Focus**: Automatically manages focus, with the option to take control if needed. Flexible State Management**: Supports both controlled and uncontrolled state, allowing for full control over the dialog's open state. Architecture The Dialog component is composed of several sub-components, each with a specific role: Root**: The main container component that manages the state of the dialog. Provides context for all child components. Trigger**: A button that toggles the dialog's open state. Portal**: Renders its children in a portal, outside the normal DOM hierarchy. Overlay**: A backdrop that sits behind the dialog content. Content**: The main container for the dialog's content. Title**: Renders the dialog's title. Description**: Renders a description or additional context for the dialog. Close**: A button that closes the dialog. Structure Here's an overview of how the Dialog component is structured in code: import { Dialog } from \"bits-ui\"; Reusable Components Bits UI provides a comprehensive set of Dialog components that serve as building blocks for creating customized, reusable Dialog implementations. This approach offers flexibility in design while maintaining consistency and accessibility across your application. Building a Reusable Dialog The following example demonstrates how to create a versatile, reusable Dialog component using Bits UI building blocks. This implementation showcases the flexibility of the component API by combining props and snippets. import type { Snippet } from \"svelte\"; import { Dialog, type WithoutChild } from \"bits-ui\"; type Props = Dialog.RootProps & { buttonText: string; title: Snippet; description: Snippet; contentProps?: WithoutChild; // ...other component props if you wish to pass them }; let { open = $bindable(false), children, buttonText, contentProps, title, description, ...restProps }: Props = $props(); {buttonText} {@render title()} {@render description()} {@render children?.()} Close Dialog Usage with Inline Snippets import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} Account settings {/snippet} {#snippet description()} Manage your account settings and preferences. {/snippet} Usage with Separate Snippets import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} Account settings {/snippet} {#snippet description()} Manage your account settings and preferences. {/snippet} Best Practices Prop Flexibility**: Design your component to accept props for any nested components for maximum flexibility Styling Options**: Use tools like clsx to merge class overrides Binding Props**: Use bind: and expose $bindable props to provide consumers with full control Type Safety**: Use the exported types from Bits UI to type your component props Managing Open State Bits UI offers several approaches to manage and synchronize the Alert Dialog's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { Dialog } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Dialog Key Benefits Simplifies state management Automatically updates isOpen when the dialog closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Dialog } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Dialog.Root component. Provide an open prop to Dialog.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Dialog } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Focus Management Proper focus management is crucial for accessibility and user experience in modal dialogs. Bits UI's Dialog component provides several features to help you manage focus effectively. Focus Trap By default, the Dialog implements a focus trap, adhering to the WAI-ARIA design pattern for modal dialogs. This ensures that keyboard focus remains within the Dialog while it's open, preventing users from interacting with the rest of the page. Disabling the Focus Trap While not recommended, you can disable the focus trap if absolutely necessary: Disabling the focus trap may compromise accessibility. Only do this if you have a specific reason and implement an alternative focus management strategy. Open Focus When a Dialog opens, focus is automatically set to the first focusable element within Dialog.Content. This ensures keyboard users can immediately interact with the Dialog contents. Customizing Initial Focus To specify which element receives focus when the Dialog opens, use the onOpenAutoFocus prop on Dialog.Content: import { Dialog } from \"bits-ui\"; let nameInput = $state(); Open Dialog { e.preventDefault(); nameInput?.focus(); }} Always ensure that something within the Dialog receives focus when it opens. This is crucial for maintaining keyboard navigation context and makes your users happy. Close Focus When a Dialog closes, focus returns to the element that triggered its opening (typically the Dialog.Trigger). Customizing Close Focus To change which element receives focus when the Dialog closes, use the onCloseAutoFocus prop on Dialog.Content: import { Dialog } from \"bits-ui\"; let nameInput = $state(); Open Dialog { e.preventDefault(); nameInput?.focus(); }} Best Practices Always maintain a clear focus management strategy for your Dialogs. Ensure that focus is predictable and logical for keyboard users. Test your focus management with keyboard navigation to verify its effectiveness. Advanced Behaviors Bits UI's Dialog component offers several advanced features to customize its behavior and enhance user experience. This section covers scroll locking, escape key handling, and interaction outside the dialog. Scroll Lock By default, when a Dialog opens, scrolling the body is disabled. This provides a more native-like experience, focusing user attention on the dialog content. Customizing Scroll Behavior To allow body scrolling while the dialog is open, use the preventScroll prop on Dialog.Content: Enabling body scroll may affect user focus and accessibility. Use this option judiciously. Escape Key Handling By default, pressing the Escape key closes an open Dialog. Bits UI provides two methods to customize this behavior. Method 1: escapeKeydownBehavior The escapeKeydownBehavior prop allows you to customize the behavior taken by the component when the Escape key is pressed. It accepts one of the following values: 'close' (default): Closes the Dialog immediately. 'ignore': Prevents the Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will ignore the key press and not close. To always prevent the Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onEscapeKeydown For more granular control, override the default behavior using the onEscapeKeydown prop: { e.preventDefault(); // do something else instead }} This method allows you to implement custom logic when the Escape key is pressed. Interaction Outside By default, interacting outside the Dialog content area closes the Dialog. Bits UI offers two ways to modify this behavior. Method 1: interactOutsideBehavior The interactOutsideBehavior prop allows you to customize the behavior taken by the component when an interaction (touch, mouse, or pointer event) occurs outside the content. It accepts one of the following values: 'close' (default): Closes the Dialog immediately. 'ignore': Prevents the Dialog from closing. 'defer-otherwise-close': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will close immediately. 'defer-otherwise-ignore': If an ancestor Bits UI component also implements this prop, it will defer the closing decision to that component. Otherwise, the Dialog will ignore the event and not close. To always prevent the Dialog from closing on Escape key press, set the escapeKeydownBehavior prop to 'ignore' on Dialog.Content: Method 2: onInteractOutside For custom handling of outside interactions, you can override the default behavior using the onInteractOutside prop: { e.preventDefault(); // do something else instead }} This approach allows you to implement specific behaviors when users interact outside the Dialog content. Best Practices Scroll Lock**: Consider your use case carefully before disabling scroll lock. It may be necessary for dialogs with scrollable content or for specific UX requirements. Escape Keydown**: Overriding the default escape key behavior should be done thoughtfully. Users often expect the escape key to close modals. Outside Interactions**: Ignoring outside interactions can be useful for important dialogs or multi-step processes, but be cautious not to trap users unintentionally. Accessibility**: Always ensure that any customizations maintain or enhance the dialog's accessibility. User Expectations**: Try to balance custom behaviors with common UX patterns to avoid confusing users. By leveraging these advanced features, you can create highly customized dialog experiences while maintaining usability and accessibility standards. Nested Dialogs Dialogs can be nested within each other to create more complex user interfaces: import MyDialog from \"$lib/components/MyDialog.svelte\"; {#snippet title()} First Dialog {/snippet} {#snippet description()} This is the first dialog. {/snippet} {#snippet title()} Second Dialog {/snippet} {#snippet description()} This is the second dialog. {/snippet} Svelte Transitions The Dialog component can be enhanced with Svelte's built-in transition effects or other animation libraries. Using forceMount and child Snippets To apply Svelte transitions to Dialog components, use the forceMount prop in combination with the child snippet. This approach gives you full control over the mounting behavior and animation of Dialog.Content and Dialog.Overlay. import { Dialog } from \"bits-ui\"; import { fly, fade } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} {#snippet child({ props, open })} {#if open} {/if} {/snippet} In this example: The forceMount prop ensures the components are always in the DOM. The child snippet provides access to the open state and component props. Svelte's #if block controls when the content is visible. Transition directives (transition:fade and transition:fly) apply the animations. Best Practices For cleaner code and better maintainability, consider creating custom reusable components that encapsulate this transition logic. import { Dialog, type WithoutChildrenOrChild } from \"bits-ui\"; import { fade } from \"svelte/transition\"; import type { Snippet } from \"svelte\"; let { ref = $bindable(null), duration = 200, children, ...restProps }: WithoutChildrenOrChild & { duration?: number; children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} You can then use the MyDialogOverlay component alongside the other Dialog primitives throughout your application: import { Dialog } from \"bits-ui\"; import { MyDialogOverlay } from \"$lib/components\"; Open Working with Forms Form Submission When using the Dialog component, often you'll want to submit a form or perform an asynchronous action and then close the dialog. This can be done by waiting for the asynchronous action to complete, then programmatically closing the dialog. import { Dialog } from \"bits-ui\"; function wait(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } let open = $state(false); Confirm your action Are you sure you want to do this? { wait(1000).then(() => (open = false)); }} Submit form Inside a Form If you're using a Dialog within a form, you'll need to ensure that the Portal is disabled or not included in the Dialog structure. This is because the Portal will render the dialog content outside of the form, which will prevent the form from being submitted correctly. ","description":"A modal window presenting content or seeking user input without navigating away from the current context.","href":"/docs/components/dialog"},{"title":"Dropdown Menu","content":" import { APISection, ComponentPreviewV2, DropdownMenuDemo, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { DropdownMenu } from \"bits-ui\"; Reusable Components If you're planning to use Dropdown Menu in multiple places, you can create a reusable component that wraps the Dropdown Menu component. This example shows you how to create a Dropdown Menu component that accepts a few custom props that make it more capable. import type { Snippet } from \"svelte\"; import { DropdownMenu, type WithoutChild } from \"bits-ui\"; type Props = DropdownMenu.Props & { buttonText: string; items: string[]; contentProps?: WithoutChild; // other component props if needed }; let { open = $bindable(false), children, buttonText, items, contentProps, ...restProps }: Props = $props(); {buttonText} {#each items as item} {item} {/each} You can then use the MyDropdownMenu component like this: import MyDropdownMenu from \"./MyDropdownMenu.svelte\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Dropdown Menu's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { DropdownMenu } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Context Menu Key Benefits Simplifies state management Automatically updates isOpen when the menu closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { DropdownMenu } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the DropdownMenu.Root component. Provide an open prop to DropdownMenu.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { DropdownMenu } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Groups To group related menu items, you can use the DropdownMenu.Group component along with either a DropdownMenu.GroupHeading or an aria-label attribute on the DropdownMenu.Group component. File New Open Save Save As New Open Save Save As Group Heading The DropdownMenu.GroupHeading component must be a child of either a DropdownMenu.Group or DropdownMenu.RadioGroup component. If used on its own, an error will be thrown during development. File Favorite color Checkbox Items You can use the DropdownMenu.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { DropdownMenu } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} The checked state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the checked prop. Radio Groups You can combine the DropdownMenu.RadioGroup and DropdownMenu.RadioItem components to create a radio group within a menu. import { DropdownMenu } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); Favorite number {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} The value state does not persist between menu open/close cycles. To persist the state, you must store it in a $state variable and pass it to the value prop. Nested Menus You can create nested menus using the DropdownMenu.Sub component to create complex menu structures. import { DropdownMenu } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the DropdownMenu.Content component to use Svelte Transitions or another animation library that requires more control. import { DropdownMenu } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Displays a menu of items that users can select from when triggered.","href":"/docs/components/dropdown-menu"},{"title":"Label","content":" import { APISection, ComponentPreviewV2, LabelDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Label } from \"bits-ui\"; ","description":"Identifies or describes associated UI elements.","href":"/docs/components/label"},{"title":"Link Preview","content":" import { APISection, ComponentPreviewV2, LinkPreviewDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview A component that lets users preview a link before they decide to follow it. This is useful for providing non-essential context or additional information about a link without having to navigate away from the current page. This component is only intended to be used with a mouse or other pointing device. It doesn't respond to touch events, and the preview content cannot be accessed via the keyboard. On touch devices, the link will be followed immediately. As it is not accessible to all users, the preview should not contain vital information. Structure import { LinkPreview } from \"bits-ui\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Link Preview's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { LinkPreview } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Link Preview Key Benefits Simplifies state management Automatically updates isOpen when the preview closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { LinkPreview } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the LinkPreview.Root component. Provide an open prop to LinkPreview.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { LinkPreview } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Opt-out of Floating UI When you use the LinkPreview.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the LinkPreview.ContentStatic component. This component does not use Floating UI and leaves positioning the content entirely up to you. The LinkPreview.Arrow component is designed to be used with Floating UI and LinkPreview.Content, so you may experience unexpected behavior if you attempt to use it with LinkPreview.ContentStatic. ","description":"Displays a summarized preview of a linked content's details or information.","href":"/docs/components/link-preview"},{"title":"Listbox","content":" import { APISection, ComponentPreviewV2, ListboxDemo, ListboxDemoCustomAnchor, ListboxDemoMultiple, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Overview The Listbox component provides users with a selectable list of options. It's designed to offer an enhanced selection experience with features like typeahead search, keyboard navigation, and customizable grouping. This component is particularly useful for scenarios where users need to choose from a predefined set of options, offering more functionality than a standard select element. Key Features Typeahead Search**: Users can quickly find options by typing Keyboard Navigation**: Full support for keyboard interactions, allowing users to navigate through options using arrow keys, enter to select, and more. Grouped Options**: Ability to organize options into logical groups, enhancing readability and organization of large option sets. Scroll Management**: Includes scroll up/down buttons for easy navigation in long lists. Accessibility**: Built-in ARIA attributes and keyboard support ensure compatibility with screen readers and adherence to accessibility standards. Portal Support**: Option to render the listbox content in a portal, preventing layout issues in complex UI structures. Architecture The Listbox component is composed of several sub-components, each with a specific role: Root**: The main container component that manages the state and context for the combobox. Trigger**: The button or element that opens the dropdown list. Portal**: Responsible for portalling the dropdown content to the body or a custom target. Group**: A container for grouped items, used to group related items. GroupHeading**: A heading for a group of items, providing a descriptive label for the group. Item**: An individual item within the list. Separator**: A visual separator between items. Content**: The dropdown container that displays the items. It uses $2 to position the content relative to the trigger. ContentStatic** (Optional): An alternative to the Content component, that enables you to opt-out of Floating UI and position the content yourself. Arrow**: An arrow element that points to the trigger when using the Combobox.Content component. Structure Here's an overview of how the Listbox component is structured in code: import { Listbox } from \"bits-ui\"; Reusable Components As you can see from the structure above, there are a number of pieces that make up the Listbox component. These pieces are provided to give you maximum flexibility and customization options, but can be a burden to write out everywhere you need to use a listbox in your application. To ease this burden, it's recommended to create your own reusable listbox component that wraps the primitives and provides a more convenient API for your use cases. Here's an example of how you might create a reusable MyListbox component that receives a list of options and renders each of them as an item. import { Listbox, type WithoutChildren } from \"bits-ui\"; type Props = WithoutChildren & { placeholder?: string; items: { value: string; label: string; disabled?: boolean }[]; contentProps?: WithoutChildren; // any other specific component props if needed }; let { value = $bindable(\"\"), items, contentProps, placeholder, ...restProps }: Props = $props(); const selectedLabel = $derived(items.find((item) => item.value === value)?.label); {#if selectedLabel} {selectedLabel} {:else} {/if} up {#each items as { value, label, disabled } (value)} {#snippet children({ selected })} {selected ? \"✅\" : \"\"} {item.label} {/snippet} {/each} down You can then use the MyListbox component throughout your application like so: import MyListbox from \"$lib/components/MyListbox.svelte\"; const items = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let fruit = $state(\"apple\"); Managing Value State Bits UI offers several approaches to manage and synchronize the Listbox's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Listbox.Root component. Provide a value prop to Listbox.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Listbox } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Open State Bits UI offers several approaches to manage and synchronize the Listbox's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = true)}> Open Key Benefits Simplifies state management Automatically updates myOpen when the internal state changes (e.g., via clicking on the trigger/input) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); { myOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledOpen prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledOpen prop to true on the Listbox.Root component. Provide an open prop to Listbox.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Listbox } from \"bits-ui\"; let myOpen = $state(false); (myOpen = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Multiple Selection The type prop can be set to 'multiple' to allow multiple items to be selected at a time. import { Listbox } from \"bits-ui\"; let value = $state([]); {#snippet preview()} {/snippet} Opt-out of Floating UI When you use the Listbox.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Listbox.ContentStatic component. When using this component, you'll need to handle the positioning of the content yourself. Keep in mind that using Listbox.Portal alongside Listbox.ContentStatic may result in some unexpected positioning behavior, feel free to not use the portal or work around it. Custom Anchor By default, the Listbox.Content is anchored to the Listbox.Trigger component, which determines where the content is positioned. If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the Listbox.Content component. import { Listbox } from \"bits-ui\"; let customAnchor = $state(null!); What is the Viewport? The Listbox.Viewport component is used to determine the size of the content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Listbox.Viewport component. Scroll Up/Down Buttons The Listbox.ScrollUpButton and Listbox.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. You must use the Listbox.Viewport component when using the scroll buttons. Native Scrolling/Overflow If you don't want to use the scroll buttons and prefer to use the standard scrollbar/overflow behavior, you can omit the Listbox.Scroll[Up|Down]Button components and the Listbox.Viewport component. You'll need to set a height on the Listbox.Content component and appropriate overflow styles to enable scrolling. Scroll Lock By default, when a user opens the listbox, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. Highlighted Items The Listbox component follows the $2 for highlighting items. This means that the Listbox.Trigger retains focus the entire time, even when navigating with the keyboard, and items are highlighted as the user navigates them. Styling Highlighted Items You can use the data-highlighted attribute on the Listbox.Item component to style the item differently when it is highlighted. onHighlight / onUnhighlight To trigger side effects when an item is highlighted or unhighlighted, you can use the onHighlight and onUnhighlight props. console.log('I am highlighted!')} onUnhighlight={() => console.log('I am unhighlighted!')} /> Select vs. Listbox Use Select as a drop-in replacement for `, supporting form auto-fill. Use Listbox for multi-select or custom single-select needs outside forms. For single-select within forms, prefer Select`. ","description":"A list of options that can be selected by the user.","href":"/docs/components/listbox"},{"title":"Menubar","content":" import { APISection, ComponentPreviewV2, MenubarDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Menubar } from \"bits-ui\"; {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} {#snippet children({ checked })} {checked ? \"✅\" : \"\"} {/snippet} Reusable Components If you're planning to use Menubar in multiple places, you can create reusable components that wrap the different parts of the Menubar. In the following example, we're creating a reusable MyMenubarMenu component that contains the trigger, content, and items of a menu. import { Menubar, type WithoutChildrenOrChild } from \"bits-ui\"; type Props = WithoutChildrenOrChild & { triggerText: string; items: { label: string; value: string; onSelect?: () => void }[]; contentProps?: WithoutChildrenOrChild; // other component props if needed }; let { triggerText, items, contentProps, ...restProps }: Props = $props(); {triggerText} {#each items as item} {item.label} {/each} Now, we can use the MyMenubarMenu component within a Menubar.Root component to render out the various menus. import { Menubar } from \"bits-ui\"; import MyMenubarMenu from \"./MyMenubarMenu.svelte\"; const sales = [ { label: \"Michael Scott\", value: \"michael\" }, { label: \"Dwight Schrute\", value: \"dwight\" }, { label: \"Jim Halpert\", value: \"jim\" }, { label: \"Stanley Hudson\", value: \"stanley\" }, { label: \"Phyllis Vance\", value: \"phyllis\" }, { label: \"Pam Beesly\", value: \"pam\" }, { label: \"Andy Bernard\", value: \"andy\" }, ]; const hr = [ { label: \"Toby Flenderson\", value: \"toby\" }, { label: \"Holly Flax\", value: \"holly\" }, { label: \"Jan Levinson\", value: \"jan\" }, ]; const accounting = [ { label: \"Angela Martin\", value: \"angela\" }, { label: \"Kevin Malone\", value: \"kevin\" }, { label: \"Oscar Martinez\", value: \"oscar\" }, ]; const menubarMenus = [ { title: \"Sales\", items: sales }, { title: \"HR\", items: hr }, { title: \"Accounting\", items: accounting }, ]; {#each menubarMenus as { title, items }} {/each} Value State Bits UI provides flexible options for controlling and synchronizing the menubar's active value state. The value represents the currently opened menu within the menubar. Two-Way Binding Use the bind:value directive for effortless two-way synchronization between your local state and the menubar's internal state. import { Menubar } from \"bits-ui\"; let activeValue = $state(\"\"); (activeValue = \"menu-1\")}>Open Menubar Menu Change Handler You can also use the onValueCHange prop to update local state when the menubar's active menu changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the menus open or close. import { Menubar } from \"bits-ui\"; let activeValue = $state(\"\"); { activeValue = value; // additional logic here. }} Checkbox Items You can use the Menubar.CheckboxItem component to create a menuitemcheckbox element to add checkbox functionality to menu items. import { Menubar } from \"bits-ui\"; let notifications = $state(true); {#snippet children({ checked })} {#if checked} ✅ {/if} Notifications {/snippet} Radio Groups You can combine the Menubar.RadioGroup and Menubar.RadioItem components to create a radio group within a menu. import { Menubar } from \"bits-ui\"; const values = [\"one\", \"two\", \"three\"]; let value = $state(\"one\"); {#each values as value} {#snippet children({ checked })} {#if checked} ✅ {/if} {value} {/snippet} {/each} Nested Menus You can create nested menus using the Menubar.Sub component to create complex menu structures. import { Menubar } from \"bits-ui\"; Item 1 Item 2 Open Sub Menu Sub Item 1 Sub Item 2 --> Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the Menubar.Content component to use Svelte Transitions or another animation library that requires more control. import { Menubar } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} Item 1 Item 2 {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the $2 documentation. ","description":"Organizes and presents a collection of menu options or actions within a horizontal bar.","href":"/docs/components/menubar"},{"title":"Navigation Menu","content":" import { APISection, ComponentPreviewV2, NavigationMenuDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { NavigationMenu } from \"bits-ui\"; ","description":"A list of links that allow users to navigate between pages of a website.","href":"/docs/components/navigation-menu"},{"title":"Pagination","content":" import { APISection, ComponentPreviewV2, PaginationDemo, Callout } from '$lib/components/index.js' export let schemas {#snippet preview()} {/snippet} Structure import { Pagination } from \"bits-ui\"; {#each pages as page (page.key)} {/each} Managing Page State Bits UI offers several approaches to manage and synchronize the Pagination's page state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:page directive. This method automatically keeps your local state in sync with the component's internal state. import { Pagination } from \"bits-ui\"; let myPage = $state(1); (myPage = 2)}> Go to page 2 Key Benefits Simplifies state management Automatically updates myPage when the internal state changes (e.g., via clicking on a page button) Allows external control (e.g., changing the page via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPageChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Pagination } from \"bits-ui\"; let myPage = $state(1); { myPage = p; // additional logic here. }} Use Cases Implementing custom behaviors on page change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's pressed state, use the controlledPage prop. This approach requires you to manually manage the state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPage prop to true on the Pagination.Root component. Provide a page prop to Pagination.Root, which should be a variable holding the current state. Implement an onPageChange handler to update the state when the internal state changes. import { Pagination } from \"bits-ui\"; let myPage = $state(1); (myPage = p)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Ellipsis The pages snippet prop consists of two types of items: 'page' and 'ellipsis'. The 'page' type represents an actual page number, while the 'ellipsis' type represents a placeholder for rendering an ellipsis between pages. ","description":"Facilitates navigation between pages.","href":"/docs/components/pagination"},{"title":"PIN Input","content":" import { APISection, ComponentPreviewV2, PinInputDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The PIN Input component provides a customizable solution for One-Time Password (OTP), Two-Factor Authentication (2FA), or Multi-Factor Authentication (MFA) input fields. Due to the lack of a native HTML element for these purposes, developers often resort to either basic input fields or custom implementations. This component offers a robust, accessible, and flexible alternative. This component is derived from and would not have been possible without the work done by $2 with $2. Key Features Invisible Input Technique**: Utilizes an invisible input element for seamless integration with form submissions and browser autofill functionality. Customizable Appearance**: Allows for custom designs while maintaining core functionality. Accessibility**: Ensures keyboard navigation and screen reader compatibility. Flexible Configuration**: Supports various PIN lengths and input types (numeric, alphanumeric). Architecture Root Container: A relatively positioned root element that encapsulates the entire component. Invisible Input: A hidden input field that manages the actual value and interacts with the browser's built-in features. Visual Cells: Customizable elements representing each character of the PIN, rendered as siblings to the invisible input. This structure allows for a seamless user experience while providing developers with full control over the visual representation. Structure import { PinInput } from \"bits-ui\"; {#snippet children({ cells })} {#each cells as cell} {/each} {/snippet} Paste Handling The onPaste prop allows you to sanitize pasted text. This can be useful for cleaning up pasted text, like removing hyphens or other characters that should not make it into the input. This function should return the sanitized text. import { PinInput } from \"bits-ui\"; text.replace(/-/g, \"\")}> ","description":"Allows users to input a sequence of one-character alphanumeric inputs.","href":"/docs/components/pin-input"},{"title":"Popover","content":" import { APISection, ComponentPreviewV2, PopoverDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Popover } from \"bits-ui\"; Managing Open State Bits UI offers several approaches to manage and synchronize the Popover's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the dialog's internal state. import { Popover } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Popover Key Benefits Simplifies state management Automatically updates isOpen when the popover closes/opens (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Popover } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the dialog responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Popover.Root component. Provide an open prop to Popover.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the local state when the internal state changes. import { Popover } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Managing Focus Focus Trap By default, when a Popover is opened, focus will be trapped within that Popover. You can disable this behavior by setting the trapFocus prop to false on the Popover.Content component. Open Focus By default, when a Popover is opened, focus will be set to the first focusable element with the Popover.Content. This ensures that users navigating my keyboard end up somewhere within the Popover that they can interact with. You can override this behavior using the onOpenAutoFocus prop on the Popover.Content component. It's highly recommended that you use this prop to focus something within the Popover's content. You'll first need to cancel the default behavior of focusing the first focusable element by cancelling the event passed to the onOpenAutoFocus callback. You can then focus whatever you wish. import { Popover } from \"bits-ui\"; let nameInput = $state(); Open Popover { e.preventDefault(); nameInput?.focus(); }} Close Focus By default, when a Popover is closed, focus will be set to the trigger element of the Popover. You can override this behavior using the onCloseAutoFocus prop on the Popover.Content component. You'll need to cancel the default behavior of focusing the trigger element by cancelling the event passed to the onCloseAutoFocus callback, and then focus whatever you wish. import { Popover } from \"bits-ui\"; let nameInput = $state(); Open Popover { e.preventDefault(); nameInput?.focus(); }} Scroll Lock By default, when a Popover is opened, users can still scroll the body and interact with content outside of the Popover. If you wish to lock the body scroll and prevent users from interacting with content outside of the Popover, you can set the preventScroll prop to true on the Popover.Content component. Escape Keydown By default, when a Popover is open, pressing the Escape key will close the dialog. Bits UI provides a couple ways to override this behavior. escapeKeydownBehavior You can set the escapeKeydownBehavior prop to 'ignore' on the Popover.Content component to prevent the dialog from closing when the Escape key is pressed. onEscapeKeydown You can also override the default behavior by cancelling the event passed to the onEscapeKeydown callback on the Popover.Content component. e.preventDefault()}> Interact Outside By default, when a Popover is open, pointer down events outside the content will close the popover. Bits UI provides a couple ways to override this behavior. interactOutsideBehavior You can set the interactOutsideBehavior prop to 'ignore' on the Popover.Content component to prevent the dialog from closing when the user interacts outside the content. onInteractOutside You can also override the default behavior by cancelling the event passed to the onInteractOutside callback on the Popover.Content component. e.preventDefault()}> ","description":"Display supplementary content or information when users interact with specific elements.","href":"/docs/components/popover"},{"title":"Progress","content":" import { APISection, ComponentPreviewV2, ProgressDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Progress } from \"bits-ui\"; ","description":"Visualizes the progress or completion status of a task or process.","href":"/docs/components/progress"},{"title":"Radio Group","content":" import { APISection, ComponentPreviewV2, RadioGroupDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { RadioGroup } from \"bits-ui\"; {#snippet children({ checked })} {#if checked} ✅ {/if} {/snippet} Reusable Components It's recommended to use the RadioGroup primitives to create your own custom components that can be used throughout your application. In the example below, we're creating a custom MyRadioGroup component that takes in an array of items and renders a radio group with those items along with a $2 component for each item. import { RadioGroup, Label, type WithoutChildrenOrChild, useId } from \"bits-ui\"; type Item = { value: string; label: string; disabled?: boolean; }; type Props = WithoutChildrenOrChild & { items: Item[]; }; let { value = $bindable(\"\"), ref = $bindable(null), items, ...restProps }: Props = $props(); {#each items as item} {@const id = useId()} {#snippet children({ checked })} {#if checked} ✅ {/if} {/snippet} {item.label} {/each} You can then use the MyRadioGroup component in your application like so: import MyRadioGroup from \"$lib/components/MyRadioGroup.svelte\"; const myItems = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"coconut\", label: \"Coconut\", disabled: true }, ]; Managing Value State Bits UI offers several approaches to manage and synchronize the Radio Group's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"A\")}> Select A Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., selecting an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the RadioGroup.Root component. Provide a value prop to RadioGroup.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { RadioGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. HTML Forms If you set the name prop on the RadioGroup.Root component, a hidden input element will be rendered to submit the value of the radio group to a form. Required To make the hidden input element required you can set the required prop on the RadioGroup.Root component. Disabling Items You can disable a radio group item by setting the disabled prop to true. Apple Orientation The orientation prop is used to determine the orientation of the radio group, which influences how keyboard navigation will work. When the orientation is set to 'vertical', the radio group will navigate through the items using the ArrowUp and ArrowDown keys. When the orientation is set to 'horizontal', the radio group will navigate through the items using the ArrowLeft and ArrowRight keys. ","description":"Allows users to select a single option from a list of mutually exclusive choices.","href":"/docs/components/radio-group"},{"title":"Range Calendar","content":" import { APISection, ComponentPreviewV2, RangeCalendarDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Before diving into this component, it's important to understand how dates/times work in Bits UI. Please read the $2 documentation to learn more! Structure import { RangeCalendar } from \"bits-ui\"; {#snippet children({ months, weekdays })} {#each months as month} {#each weekdays as day} {day} {/each} {#each month.weeks as weekDates} {#each weekDates as date} {/each} {/each} {/each} {/snippet} ","description":"Presents a calendar view tailored for selecting date ranges.","href":"/docs/components/range-calendar"},{"title":"Scroll Area","content":" import { APISection, ComponentPreviewV2, ScrollAreaDemo, ScrollAreaDemoCustom } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { ScrollArea } from \"bits-ui\"; Reusable Components If you're planning to use the Scroll Area throughout your application, it's recommended to create a reusable component to reduce the amount of code you need to write each time. This example shows you how to create a Scroll Area component that accepts a few custom props that make it more capable. import { ScrollArea, type WithoutChild } from \"bits-ui\"; type Props = WithoutChild & { orientation: \"vertical\" | \"horizontal\" | \"both\"; viewportClasses?: string; }; let { ref = $bindable(null), orientation = \"vertical\", viewportClasses, children, ...restProps }: Props = $props(); {#snippet Scrollbar({ orientation }: { orientation: \"vertical\" | \"horizontal\" })} {/snippet} {@render children?.()} {#if orientation === \"vertical\" || orientation === \"both\"} {@render Scrollbar({ orientation: \"vertical\" })} {/if} {#if orientation === \"horizontal\" || orientation === \"both\"} {@render Scrollbar({ orientation: \"horizontal\" })} {/if} We'll use this custom component in the following examples to demonstrate how to customize the behavior of the Scroll Area. Scroll Area Types Hover The hover type is the default type of the scroll area, demonstrated in the featured example above. It only shows scrollbars when the user hovers over the scroll area and the content is larger than the viewport. Scroll The scroll type displays the scrollbars when the user scrolls the content. This is similar to the behavior of MacOS. Auto The auto type behaves similarly to your typical browser scrollbars. When the content is larger than the viewport, the scrollbars will appear and remain visible at all times. Always The always type behaves as if you set overflow: scroll on the scroll area. Scrollbars will always be visible, even when the content is smaller than the viewport. We've also set the orientation prop on the MyScrollArea to 'both' to ensure both scrollbars are rendered. Customizing the Hide Delay You can customize the hide delay of the scrollbars using the scrollHideDelay prop. ","description":"Consistent scroll area across platforms.","href":"/docs/components/scroll-area"},{"title":"Select","content":" import { APISection, ComponentPreviewV2, SelectDemo, SelectDemoPositioning } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Select component can be used as a replacement for the native `` element in your application. It provides a more flexible and customizable way to select an option from a list of options. The component offers a variety of features, such as typeahead, keyboard navigation, scroll up/down buttons, and more. Structure import { Select } from \"bits-ui\"; Reusable Components As you can see from the structure above, there are a number of pieces that make up the Select component. These pieces are provided to give you maximum flexibility and customization options, but can be a burden to write out everywhere you need to use a Select in your application. To ease this burden, it's recommended to create your own reusable Select component that wraps the primitives and provides a more convenient API for your use cases. Here's an example of how you might create a reusable MySelect component that receives a list of options and renders each of them as an item. import { Select, type WithoutChildren } from \"bits-ui\"; type Props = WithoutChildren & { placeholder?: string; items: { value: string; label: string; disabled?: boolean }[]; contentProps?: WithoutChildren; // any other specific component props if needed }; let { value = $bindable(\"\"), items, contentProps, placeholder, ...restProps }: Props = $props(); const selectedLabel = $derived(items.find((item) => item.value === value)?.label); {#if selectedLabel} {selectedLabel} {:else} {/if} up {#each items as { value, label, disabled } (value)} {#snippet children({ selected })} {selected ? \"✅\" : \"\"} {item.label} {/snippet} {/each} down You can then use the MySelect component throughout your application like so: import MySelect from \"$lib/components/MySelect.svelte\"; const items = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let fruit = $state(\"apple\"); Value State The value represents the currently selected item/option within the select menu. Bits UI provides flexible options for controlling and synchronizing the Select's value state. Two-Way Binding Use the bind:value directive for effortless two-way synchronization between your local state and the Select's internal state. import { Select } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"apple\")}> Apple This setup enables toggling the value via the custom button and ensures the local myValue state updates when the Select's value changes through any internal means (e.g., clicking on an item's button). Change Handler You can also use the onValueChange prop to update local state when the Select's value state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the Select changes. import { Select } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = value; // additional logic here. }} Open State The open state represents whether or not the select content is open. Bits UI provides flexible options for controlling and synchronizing the Select's open state. Two-Way Binding Use the bind:open directive for effortless two-way synchronization between your local state and the Select's internal state. import { Select } from \"bits-ui\"; let isOpen = $state(false); (open = true)}> Open select This setup enables toggling the Select via the custom button and ensures the local isOpen state updates when the Select's open state changes through any internal means e.g. clicking on the trigger or outside the content. Change Handler You can also use the onOpenChange prop to update local state when the Select's open state changes. This is useful when you don't want two-way binding for one reason or another, or you want to perform additional logic when the Select changes. import { Select } from \"bits-ui\"; let isOpen = $state(false); { isOpen = open; // additional logic here. }} Positioning The Select component supports two different positioning strategies for the content. The default positioning strategy is floating, which uses Floating UI to position the content relative to the trigger, similar to other popover-like components. If you prefer a more native-like experience, you can set the position prop to item-aligned, which will position the content relative to the trigger, similar to a native `` element. Here's an example of both strategies in action: NOTE: When using the \"item-aligned\" positioning strategy, the props related to configuring Floating UI on the Select.Content component will be ignored. HTML Forms The Select component is designed to work seamlessly with HTML forms. You can use the name prop to associate the select with a form field. Server-side Rendering To accomplish some of the nice features of the Select component, such as typeahead while the select content is closed and the trigger is focused, we leverage portals to send items into the Select.Value component. Portals only work client-side, so if you are using SvelteKit with SSR, you'll need to handle the case where a default value is provided, otherwise, there will be a flicker of the placeholder value before the default value is portalled into the Select.Value component. We're demonstrating this in the featured demo at the top of this page, but here's an example of how you might handle this: // default value is provided via page data from a load function let { data } = $props(); let options = [ { value: \"apple\", label: \"Apple\" }, { value: \"banana\", label: \"Banana\" }, { value: \"cherry\", label: \"Cherry\" }, ]; let value = $state(data.fruit); const selectedLabel = $derived(options.find((option) => option.value === data.fruit)?.label); (data.fruit = v)}> {#if selectedLabel} {selectedLabel} {:else} {/if} Scroll Lock By default, when a user opens the select, scrolling outside the content will be disabled. You can override this behavior by setting the preventScroll prop to false. What is the Viewport? The Select.Viewport component is used to determine the size of the select content in order to determine whether or not the scroll up and down buttons should be rendered. If you wish to set a minimum/maximum height for the select content, you should apply it to the Select.Viewport component. Scroll Up/Down Buttons The Select.ScrollUpButton and Select.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport. Multiple Select The Select component does not support multiple selections. If you're looking for a multi-select component, check out the $2 component. Select vs. Listbox Use Select as a drop-in replacement for `, supporting form auto-fill. Use Listbox for multi-select or custom single-select needs outside forms. For single-select within forms, prefer Select`. ","description":"Enables users to choose from a list of options presented in a dropdown.","href":"/docs/components/select"},{"title":"Separator","content":" import { APISection, ComponentPreviewV2, SeparatorDemo } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Separator } from \"bits-ui\"; ","description":"Visually separates content or UI elements for clarity and organization.","href":"/docs/components/separator"},{"title":"Slider","content":" import { APISection, ComponentPreviewV2, SliderDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Slider } from \"bits-ui\"; Reusable Components Bits UI provides primitives that enable you to build your own custom slider component that can be reused throughout your application. Here's an example of how you might create a reusable MySlider component. import { Slider } from \"bits-ui\"; type Props = WithoutChildren; let { value = $bindable(), ref = $bindable(null), ...restProps }: Props = $props(); {#snippet children({ thumbs, ticks })} {#each thumbs as index} {/each} {#each ticks as index} {/each} {/snippet} You can then use the MySlider component in your application like so: import MySlider from \"$lib/components/MySlider.svelte\"; let someValue = $state([5, 10]); Managing Value State Bits UI offers several approaches to manage and synchronize the Slider's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Slider } from \"bits-ui\"; let myValue = $state([0]); (myValue = [20])}> Set value to 20 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via dragging the thumb(s)) Allows external control (e.g., updating the value via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Slider } from \"bits-ui\"; let myValue = $state([0]); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Slider.Root component. Provide a value prop to Slider.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Slider } from \"bits-ui\"; let myValue = $state([0]); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Multiple Thumbs and Ticks If the value prop has more than one value, the slider will render multiple thumbs. You can also use the ticks snippet prop to render ticks at specific intervals import { Slider } from \"bits-ui\"; let value = $state([5, 7]); {#snippet children({ ticks, thumbs })} {#each thumbs as index} {/each} {#each ticks as index} {/each} {/snippet} To determine the number of ticks that will be rendered, you can simply divide the max value by the step value. Vertical Orientation You can use the orientation prop to change the orientation of the slider, which defaults to \"horizontal\". RTL Support You can use the dir prop to change the reading direction of the slider, which defaults to \"ltr\". Auto Sort By default, the slider will sort the values from smallest to largest, so if you drag a smaller thumb to a larger value, the value of that thumb will be updated to the larger value. You can disable this behavior by setting the autoSort prop to false. HTML Forms Since there is a near endless number of possible values that a user can select, the slider does not render a hidden input element by default. You'll need to determine how you want to submit the value(s) of the slider with a form. Here's an example of how you might do that: import MySlider from \"$lib/components/MySlider.svelte\"; let expectedIncome = $state([50, 100]); Submit ","description":"Allows users to select a value from a continuous range by sliding a handle.","href":"/docs/components/slider"},{"title":"Switch","content":" import { APISection, ComponentPreviewV2, SwitchDemo, SwitchDemoCustom, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Overview The Switch component provides an intuitive and accessible toggle control, allowing users to switch between two states, typically \"on\" and \"off\". This component is commonly used for enabling or disabling features, toggling settings, or representing boolean values in forms. The Switch offers a more visual and interactive alternative to traditional checkboxes for binary choices. Key Features Accessibility**: Built with WAI-ARIA guidelines in mind, ensuring keyboard navigation and screen reader support. State Management**: Internally manages the on/off state, with options for controlled and uncontrolled usage. Style-able**: Data attributes allow for smooth transitions between states and custom styles. HTML Forms**: Can render a hidden input element for form submissions. Architecture The Switch component is composed of two main parts: Root**: The main container component that manages the state and behavior of the switch. Thumb**: The \"movable\" part of the switch that indicates the current state. Structure Here's an overview of how the Switch component is structured in code: import { Switch } from \"bits-ui\"; Reusable Components It's recommended to use the Switch primitives to create your own custom switch component that can be used throughout your application. In the example below, we're using the Checkbox and $2 components to create a custom switch component. import { Switch, Label, useId, type WithoutChildrenOrChild } from \"bits-ui\"; let { id = useId(), checked = $bindable(false), ref = $bindable(null), ...restProps }: WithoutChildrenOrChild & { labelText: string; } = $props(); {labelText} You can then use the MySwitch component in your application like so: import MySwitch from \"$lib/components/MySwitch.svelte\"; let notifications = $state(true); Managing Checked State Bits UI offers several approaches to manage and synchronize the Switch's checked state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:checked directive. This method automatically keeps your local state in sync with the switch's internal state. import { Switch } from \"bits-ui\"; let myChecked = $state(true); (myChecked = false)}> uncheck Key Benefits Simplifies state management Automatically updates myChecked when the switch changes (e.g., via clicking on the switch) Allows external control (e.g., checking via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onCheckedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Switch } from \"bits-ui\"; let myChecked = $state(false); { myChecked = checked; // additional logic here. }} /> Use Cases Implementing custom behaviors on checked/unchecked Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the switch's checked state, use the controlledChecked prop. This approach requires you to manually manage the checked state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledChecked prop to true on the Switch.Root component. Provide a checked prop to Switch.Root, which should be a variable holding the current state. Implement an onCheckedChange handler to update the state when the internal state changes. import { Switch } from \"bits-ui\"; let myChecked = $state(false); (myChecked = c)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Disabled State You can disable the switch by setting the disabled prop to true. HTML Forms If you pass the name prop to Switch.Root, a hidden input element will be rendered to submit the value of the switch to a form. By default, the input will be submitted with the default checkbox value of 'on' if the switch is checked. Custom Input Value If you'd prefer to submit a different value, you can use the value prop to set the value of the hidden input. For example, if you wanted to submit a string value, you could do the following: Required If you want to make the switch required, you can use the required prop. This will apply the required attribute to the hidden input element, ensuring that proper form submission is enforced. ","description":"A toggle control enabling users to switch between \"on\" and \"off\" states.","href":"/docs/components/switch"},{"title":"Tabs","content":" import { APISection, ComponentPreviewV2, TabsDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Tabs } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"tab-1\")}> Activate tab 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an tab's trigger) Allows external control (e.g., switching tabs via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Tabs.Root component. Provide a value prop to Tabs.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Tabs } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Orientation The orientation prop is used to determine the orientation of the Tabs component, which influences how keyboard navigation will work. When the orientation is set to 'horizontal', the ArrowLeft and ArrowRight keys will move the focus to the previous and next tab, respectively. When the orientation is set to 'vertical', the ArrowUp and ArrowDown keys will move the focus to the previous and next tab, respectively. Activation Mode By default, the Tabs component will automatically activate the tab associated with a trigger when that trigger is focused. This behavior can be disabled by setting the activationMode prop to 'manual'. When set to 'manual', the user will need to activate the tab by pressing the trigger. ","description":"Organizes content into distinct sections, allowing users to switch between them.","href":"/docs/components/tabs"},{"title":"Toggle Group","content":" import { APISection, ComponentPreviewV2, ToggleGroupDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { ToggleGroup } from \"bits-ui\"; bold italic Single & Multiple The ToggleGroup component supports two type props, 'single' and 'multiple'. When the type is set to 'single', the ToggleGroup will only allow a single item to be selected at a time, and the type of the value prop will be a string. When the type is set to 'multiple', the ToggleGroup will allow multiple items to be selected at a time, and the type of the value prop will be an array of strings. Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"item-1\")}> Press item 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., toggling an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the ToggleGroup.Root component. Provide a value prop to ToggleGroup.Root, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { ToggleGroup } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Groups multiple toggle controls, allowing users to enable one or multiple options.","href":"/docs/components/toggle-group"},{"title":"Toggle","content":" import { APISection, ComponentPreviewV2, ToggleDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Toggle } from \"bits-ui\"; Managing Pressed State Bits UI offers several approaches to manage and synchronize the Toggle's pressed state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:pressed directive. This method automatically keeps your local state in sync with the component's internal state. import { Toggle } from \"bits-ui\"; let myPressed = $state(true); (myPressed = false)}> un-press Key Benefits Simplifies state management Automatically updates myPressed when the switch changes (e.g., via clicking on the toggle) Allows external control (e.g., pressing/toggling via a separate button/programmatically) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onPressedChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Toggle } from \"bits-ui\"; let myPressed = $state(false); { myPressed = p; // additional logic here. }} /> Use Cases Implementing custom behaviors on pressed/unpressed Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's pressed state, use the controlledPressed prop. This approach requires you to manually manage the checked state, giving you full control over when and how the component responds to change events. To implement controlled state: Set the controlledPressed prop to true on the Toggle.Root component. Provide a pressed prop to Toggle.Root, which should be a variable holding the current state. Implement an onPressedChange handler to update the state when the internal state changes. import { Toggle } from \"bits-ui\"; let myPressed = $state(false); (myPressed = p)}> When to Use Implementing complex checked/unchecked logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"A control element that switches between two states, providing a binary choice.","href":"/docs/components/toggle"},{"title":"Toolbar","content":" import { APISection, ComponentPreviewV2, ToolbarDemo, Callout } from '$lib/components/index.js' export let schemas; {#snippet preview()} {/snippet} Structure import { Toolbar } from \"bits-ui\"; Managing Value State Bits UI offers several approaches to manage and synchronize the component's value state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:value directive. This method automatically keeps your local state in sync with the component's internal state. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = \"item-1\")}> Press item 1 Key Benefits Simplifies state management Automatically updates myValue when the internal state changes (e.g., via clicking on an item) Allows external control (e.g., toggling an item via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onValueChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} Use Cases Implementing custom behaviors on value change Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the component's value state, use the controlledValue prop. This approach requires you to manually manage the value state, giving you full control over when and how the component responds to value change events. To implement controlled state: Set the controlledValue prop to true on the Toolbar.Group component. Provide a value prop to Toolbar.Group, which should be a variable holding the current state. Implement an onValueChange handler to update the state when the internal state changes. import { Toolbar } from \"bits-ui\"; let myValue = $state(\"\"); { myValue = v; // additional logic here. }} When to Use Implementing complex logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. ","description":"Displays frequently used actions or tools in a compact, easily accessible bar.","href":"/docs/components/toolbar"},{"title":"Tooltip","content":" import { ComponentPreviewV2, TooltipDemo, TooltipDemoCustom, TooltipDemoDelayDuration, APISection, Callout } from '$lib/components' export let schemas; {#snippet preview()} {/snippet} Structure import { Tooltip } from \"bits-ui\"; Provider Component The Tooltip.Provider component is required to be an ancestor of the Tooltip.Root component. It provides shared state for the tooltip components used within it. You can set a single delayDuration or disableHoverableContent prop on the provider component to apply to all the tooltip components within it. import { Tooltip } from \"bits-ui\"; It also ensures that only a single tooltip within the same provider can be open at a time. It's recommended to wrap your root layout content with the provider component, setting your sensible default props there. import { Tooltip } from \"bits-ui\"; let { children } = $props(); {@render children()} Managing Open State Bits UI offers several approaches to manage and synchronize the Tooltip's open state, catering to different levels of control and integration needs. 1. Two-Way Binding For seamless state synchronization, use Svelte's bind:open directive. This method automatically keeps your local state in sync with the component's internal state. import { Tooltip } from \"bits-ui\"; let isOpen = $state(false); (isOpen = true)}>Open Tooltip Key Benefits Simplifies state management Automatically updates isOpen when the tooltip closes (e.g., via escape key) Allows external control (e.g., opening via a separate button) 2. Change Handler For more granular control or to perform additional logic on state changes, use the onOpenChange prop. This approach is useful when you need to execute custom logic alongside state updates. import { Tooltip } from \"bits-ui\"; let isOpen = $state(false); { isOpen = o; // additional logic here. }} Use Cases Implementing custom behaviors on open/close Integrating with external state management solutions Triggering side effects (e.g., logging, data fetching) 3. Fully Controlled For complete control over the dialog's open state, use the controlledOpen prop. This approach requires you to manually manage the open state, giving you full control over when and how the tooltip responds to open/close events. To implement controlled state: Set the controlledOpen prop to true on the Tooltip.Root component. Provide an open prop to Tooltip.Root, which should be a variable holding the current state. Implement an onOpenChange handler to update the state when the internal state changes. import { Tooltip } from \"bits-ui\"; let myOpen = $state(false); (myOpen = o)}> When to Use Implementing complex open/close logic Coordinating multiple UI elements Debugging state-related issues While powerful, fully controlled state should be used judiciously as it increases complexity and can cause unexpected behaviors if not handled carefully. For more in-depth information on controlled components and advanced state management techniques, refer to our $2 documentation. Mobile Tooltips Tooltips are not supported on mobile devices. The intent of a tooltip is to provide a \"tip\" about a \"tool\" before the user interacts with that tool (in most cases, a button). This is not possible on mobile devices, because there is no sense of hover on mobile. If a user were to press/touch a button with a tooltip, the action that button triggers would be taken before they were even able to see the tooltip, which renders it useless. If you are using a tooltip on a button without an action, you should consider using a $2 instead. If you'd like to learn more about how we came to this decision, here are some useful resources: The tooltip is not the appropriate role for the more information \"i\" icon, ⓘ. A tooltip is directly associated with the owning element. The ⓘ isn't 'described by' detailed information; the tool or control is. $2 Tooltips should only ever contain non-essential content. The best approach to writing tooltip content is to always assume it may never be read. $2 Reusable Components It's recommended to use the Tooltip primitives to build your own custom tooltip component that can be used throughout your application. Below is an example of how you might create a reusable tooltip component that can be used throughout your application. Of course, this isn't the only way to do it, but it should give you a good idea of how to compose the primitives. import { Tooltip } from \"bits-ui\"; import { type Snippet } from \"svelte\"; type Props = Tooltip.RootProps & { trigger: Snippet; triggerProps?: Tooltip.TriggerProps; }; let { open = $bindable(false), children, buttonText, triggerProps = {}, ...restProps }: Tooltip.RootProps = $props(); {@render trigger()} {@render children?.()} You could then use the MyTooltip component in your application like so: import MyTooltip from \"$lib/components/MyTooltip.svelte\"; import BoldIcon from \"..some-icon-library\"; // not real alert(\"changed to bold!\") }}> {#snippet trigger()} {/snippet} Change font to bold Delay Duration You can change how long a user needs to hover over a trigger before the tooltip appears by setting the delayDuration prop on the Tooltip.Root or Tooltip.Provider component. Close on Trigger Click By default, the tooltip will close when the user clicks the trigger. If you want to disable this behavior, you can set the disableCloseOnTriggerClick prop to true. Hoverable Content By default, the tooltip will remain open when the user hovers over the content. If you instead want the tooltip to close as the user moves their mouse towards the content, you can set the disableHoverableContent prop to true. Non-Keyboard Focus If you want to prevent opening the tooltip when the user focuses the trigger without using the keyboard, you can set the ignoreNonKeyboardFocus prop to true. Svelte Transitions You can use the forceMount prop along with the child snippet to forcefully mount the Tooltip.Content component to use Svelte Transitions or another animation library that requires more control. import { Tooltip } from \"bits-ui\"; import { fly, fade } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content components that handles this logic if you intend to use this approach throughout your app. For more information on using transitions with Bits UI components, see the $2 documentation. Opt-out of Floating UI When you use the Tooltip.Content component, Bits UI uses $2 to position the content relative to the trigger, similar to other popover-like components. You can opt-out of this behavior by instead using the Tooltip.ContentStatic component. This component does not use Floating UI and leaves positioning the content entirely up to you. Hello When using the Tooltip.ContentStatic component, the Tooltip.Arrow component will not be rendered relative to it as it is designed to be used with Tooltip.Content. ","description":"Provides additional information or context when users hover over or interact with an element.","href":"/docs/components/tooltip"},{"title":"mergeProps","content":" Overview mergeProps is a utility function designed to merge multiple props objects. It's particularly useful for composing components with different prop sets or extending the functionality of existing components. It is used internally by Bits UI components to merge the custom restProps you pass to a component with the props that Bits UI provides to the component. Key Features Merges multiple props objects Chains event handlers with cancellation support Combines class names Merges style objects and strings Chains non-event handler functions Detailed Behavior Event Handlers Event handlers are chained in the order they're passed. If a handler calls event.preventDefault(), subsequent handlers in the chain are not executed. const props1 = { onclick: (e: MouseEvent) => console.log(\"First click\") }; const props2 = { onclick: (e: MouseEvent) => console.log(\"Second click\") }; const mergedProps = mergeProps(props1, props2); mergedProps.onclick(new MouseEvent(\"click\")); // Logs: \"First click\" then \"Second click\" If preventDefault() is called: const props1 = { onclick: (e: MouseEvent) => console.log(\"First click\") }; const props2 = { onclick: (e: MouseEvent) => { console.log(\"Second click\"); e.preventDefault(); }, }; const props3 = { onclick: (e: MouseEvent) => console.log(\"Third click\") }; const mergedProps = mergeProps(props1, props2, props3); mergedProps.onclick(new MouseEvent(\"click\")); // Logs: \"First click\" then \"Second click\" only Since props2 called event.preventDefault(), props3's onclick handler will not be called. Non-Event Handler Functions Non-event handler functions are also chained, but without the ability to prevent subsequent functions from executing: const props1 = { doSomething: () => console.log(\"Action 1\") }; const props2 = { doSomething: () => console.log(\"Action 2\") }; const mergedProps = mergeProps(props1, props2); mergedProps.doSomething(); // Logs: \"Action 1\" then \"Action 2\" Classes Class names are merged using $2: const props1 = { class: \"text-lg font-bold\" }; const props2 = { class: [\"bg-blue-500\", \"hover:bg-blue-600\"] }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.class); // \"text-lg font-bold bg-blue-500 hover:bg-blue-600\" Styles Style objects and strings are merged, with later properties overriding earlier ones: const props1 = { style: { color: \"red\", fontSize: \"16px\" } }; const props2 = { style: \"background-color: blue; font-weight: bold;\" }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.style); // \"color: red; font-size: 16px; background-color: blue; font-weight: bold;\" import { mergeProps } from \"bits-ui\"; const props1 = { style: \"--foo: red\" }; const props2 = { style: { \"--foo\": \"green\", color: \"blue\" } }; const mergedProps = mergeProps(props1, props2); console.log(mergedProps.style); // \"--foo: green; color: blue;\" ","description":"A utility function to merge props objects.","href":"/docs/utilities/merge-props"},{"title":"Portal","content":" Overview The Portal component is a utility component that renders its children in a portal, preventing layout issues in complex UI structures. This component is used for the various Bits UI component that have a Portal sub-component. Usage Default behavior By default, the Portal component will render its children in the body element. import { Portal } from \"bits-ui\"; This content will be portalled to the body Custom target You can use the to prop to specify a custom target element or selector to render the content to. import { Portal } from \"bits-ui\"; This content will be portalled to the #custom-target element Disable You can use the disabled prop to disable the portal behavior. import { Portal } from \"bits-ui\"; This content will not be portalled ","description":"A component that renders its children in a portal, preventing layout issues in complex UI structures.","href":"/docs/utilities/portal"},{"title":"useId","content":" The useId function is a utility function that can be used to generate unique IDs. This function is used internally by all Bits UI components and is exposed for your convenience. Usage import { useId } from \"bits-ui\"; const id = useId(); Label here ","description":"A utility function to generate unique IDs.","href":"/docs/utilities/use-id"},{"title":"WithElementRef","content":" The WithElementRef type helper is a convenience type that enables you to follow the same $2 prop pattern as used by Bits UI components when crafting your own. type WithElementRef = T & { ref?: U | null }; This type helper is used internally by Bits UI components to enable the ref prop on a component. Usage Example import type { WithElementRef } from \"bits-ui\"; type Props = WithElementRef; let { yourPropA, yourPropB, ref = $bindable(null) }: Props = $props(); ","description":"A type helper to enable the `ref` prop on a component.","href":"/docs/type-helpers/with-element-ref"},{"title":"WithoutChild","content":" The WithoutChild type helper is used to exclude the child snippet prop from a component. This is useful when you're building custom component wrappers that populate the children prop of a component and don't provide a way to pass a custom child snippet. To learn more about the child snippet prop, check out the $2 documentation. import { Accordion, type WithoutChild } from \"bits-ui\"; let { children, ...restProps }: WithoutChild = $props(); {@render children?.()} ","description":"A type helper to exclude the child snippet prop from a component.","href":"/docs/type-helpers/without-child"},{"title":"WithoutChildrenOrChild","content":" The WithoutChildrenOrChild type helper is used to exclude the child and children props from a component. This is useful when you're building custom component wrappers that populate the children prop of a component and don't provide a way to pass a custom children or child snippet. To learn more about the child snippet prop, check out the $2 documentation. import { Accordion, type WithoutChildrenOrChild } from \"bits-ui\"; let { title, ...restProps }: WithoutChildrenOrChild = $props(); {title} Now, the CustomAccordionTrigger component won't expose children or child props to the user, but will expose the other root component props. ","description":"A type helper to exclude the child ad children snippet props from a component.","href":"/docs/type-helpers/without-children-or-child"},{"title":"WithoutChildren","content":" The WithoutChildren type helper is used to exclude the children snippet prop from a component. This is useful when you're building custom component wrappers that populate the children prop of a component. import { Accordion, type WithoutChildren } from \"bits-ui\"; let { value, onValueChange, ...restProps }: WithoutChildren = $props(); In the example above, we're using the WithoutChildren type helper to exclude the children snippet prop from the Accordion.Root component. This ensures our exposed props are consistent with what is being used internally. ","description":"A type helper to exclude the children snippet prop from a component.","href":"/docs/type-helpers/without-children"},{"title":"Child Snippet","content":" Usage Many Bits UI components have a default HTML element that wraps their children. For example, Accordion.Trigger typically renders as: {@render children()} While you can set standard button attributes, you might need more control for: Applying Svelte transitions or actions Using custom components Scoped CSS This is where the child snippet comes in. Components supporting render delegation accept an optional child prop, which is a Svelte snippet. When used, the component passes its attributes to this snippet, allowing you to apply them to any element. Let's take a look at an example using the Accordion.Trigger component: {#snippet child({ props })} Open accordion item {/snippet} The props object includes event handlers, ARIA attributes, and any other attributes passed to Accordion.Trigger. Note that when using child, other children outside this snippet are ignored. Custom IDs & Attributes To use custom IDs, event handlers, or other attributes with a custom element, you must pass them to the component first. This is crucial because: Many Bits UI internals rely on specific IDs Props are merged using a $2 function to handle cancelling internal handlers, etc. Correct usage: console.log(\"clicked\")}> {#snippet child({ props })} Open accordion item {/snippet} In this example, my-custom-id, the click event handler, and my-custom-class are properly merged into the props object, ensuring they work alongside Bits UI's internal logic. Behind the scenes, components using the child prop typically implement logic similar to this: // other imports/props/logic omitted for brevity let { child, children, ...restProps } = $props(); const trigger = makeTrigger(); const mergedProps = $derived(mergeProps(restProps, trigger.props)); {#if child} {@render child({ props: mergedProps })} {:else} {@render children?.()} {/if} ","description":"Learn how to use the `child` snippet to render your own elements.","href":"/docs/child-snippet"},{"title":"Controlled State","content":" Bits UI components offer flexibility in state management, allowing you to choose between uncontrolled and controlled states. This guide will help you understand when and how to use controlled state effectively. Understanding State Management Uncontrolled State (Default) By default, Bits UI components operate in an uncontrolled state. In this mode: The component internally manages its own state. You can bind: to the state for reference. The component decides when and how to update its state. You can update the state of the component yourself from the outside, but you can't prevent the component from updating it. Here's an example of an uncontrolled Accordion: import { Accordion } from \"bits-ui\"; let myValue = $state(\"\"); In this example, the Accordion.Root component manages its value state internally. When a user interacts with the accordion, the component updates the value automatically. The local myValue is synced with the component's internal value state in both directions. Controlled State Controlled state puts you in charge of the component's state management. Use this approach when: You need to meet specific conditions before state updates. You want to synchronize the component's state with other parts of your application. You require custom logic for state updates. To implement controlled state: Set the controlled prop to true (e.g., controlledValue). Pass a local state variable to the component. Use the onChange callback to update the local state (e.g., onValueChange). Here's an example of how you might use controlled state with the Accordion component: import { Accordion } from \"bits-ui\"; let myValue = $state(\"\"); (myValue = v)}> In this controlled state example: We set controlledValue to true. We pass our local myValue state to the value prop. We use onValueChange to handle state updates Best Practices Choose wisely**: Use controlled state only when necessary. Uncontrolled state is simpler and sufficient for most use cases. Consistent control**: If you opt for controlled state, ensure you handle all related state updates to maintain consistency. Performance consideration**: Be mindful of potential performance impacts when using controlled state, especially with frequently updating components. Common Controlled State Scenarios Form validation before state updates Syncing component state with external data sources Implementing undo/redo functionality Creating interdependent component behaviors ","description":"Learn how to use controlled state in Bits UI components.","href":"/docs/controlled-state"},{"title":"Dates and Times","content":" The date and time components in Bits UI are built on top of the $2 package, which provides a unified API for working with dates and times in different locales and time zones. It's heavily inspired by the $2 proposal, and intends to back the objects in this package with the Temporal API once it's available. You can install the package using your favorite package manager: npm install @internationalized/date It's highly recommended to familiarize yourself with the package's documentation before diving into the components. We'll cover the basics of how we use the package in Bits UI in the sections below, but their documentation provides much more detail on the various formats and how to work with them. DateValue We use the DateValue objects provided by @internationalized/date to represent dates and times in a consistent way. These objects are immutable and provide information about the type of date they represent. The DateValue is a union of the following three types: CalendarDate - Represents a date with no time component, such as 2024-07-10 CalendarDateTime - Represents a date and time, such as 2024-07-10T12:30:00 ZonedDateTime - Represents a date and time with a time zone, such as 2023-10-11T21:00:00:00-04:00[America/New_York] The benefit of using these objects is that they allow you to be very specific about the type of date you want, and the component will adapt to that type. For example, if you pass a CalendarDate object to a DateField component, it will only display the date portion of the date, without the time. See the $2 component for more information. CalendarDate The CalendarDate object represents a date with no time component, such as 2024-07-10. You can use the CalendarDate constructor to create a new CalendarDate object: import { CalendarDate } from \"@internationalized/date\"; const date = new CalendarDate(2024, 7, 10); You can also use the parseDate function to parse an $2 string into a CalendarDate object: import { parseDate } from \"@internationalized/date\"; const date = parseDate(\"2024-07-10\"); If you want to create a CalendarDate with the current date, you can use the today function. This function requires a timezone identifier as an argument, which can be passed in as a string, or by using getLocalTimeZone which returns the user's current time zone: import { today, getLocalTimeZone } from \"@internationalized/date\"; const losAngelesToday = today(\"America/Los_Angeles\"); const localToday = today(getLocalTimeZone()); See the $2 for more information. CalendarDateTime The CalendarDateTime object represents a date and time, such as 2024-07-10T12:30:00. You can use the CalendarDateTime constructor to create a new CalendarDateTime object: import { CalendarDateTime } from \"@internationalized/date\"; const dateTime = new CalendarDateTime(2024, 7, 10, 12, 30, 0); You can also use the parseDateTime function to parse an $2 string into a CalendarDateTime object: import { parseDateTime } from \"@internationalized/date\"; const dateTime = parseDateTime(\"2024-07-10T12:30:00\"); See the $2 for more information. ZonedDateTime The ZonedDateTime object represents a date and time with a time zone, which represents an exact date and time in a specific time zone. ZonedDateTimes are often used for things such as in person events (concerts, conferences, etc.), where you want to represent a date and time in a specific time zone, rather than a specific date and time in the user's local time zone. You can use the ZonedDateTime constructor to create a new ZonedDateTime object: import { ZonedDateTime } from \"@internationalized/date\"; const date = new ZonedDateTime( // Date 2022, 2, 3, // Time zone and UTC offset \"America/Los_Angeles\", -28800000, // Time 9, 15, 0 ); You can also use one of the following parsing functions to parse an $2 string into a ZonedDateTime object: import { parseZonedDateTime, parseAbsolute, parseAbsoluteToLocal } from \"@internationalized/date\"; const date = parseZonedDateTime(\"2024-07-12T00:45[America/New_York]\"); // or const date = parseAbsolute(\"2024-07-12T07:45:00Z\", \"America/New_York\"); // or const date = parseAbsoluteToLocal(\"2024-07-12T07:45:00Z\"); See the $2 for more information. Date Ranges Bits UI also provides a DateRange type with the following structure: type DateRange = { start: DateValue; end: DateValue; }; This type is used to represent the value of the various date range components in Bits UI, such as the $2, $2, and $2. Placeholder Each of the date/time components in Bits UI has a bindable placeholder prop, which acts as the starting point for the component when no value is present. The placeholder value is used to determine the type of date/time to display, and the component and its value will adapt to that type. For example, if you pass a CalendarDate object to a DateField component, it will only display the date portion of the date, without the time. If you pass a CalendarDateTime object, it will display the date and time. If you pass a ZonedDateTime object, it will display the date and time with the time zone information. In addition to setting the starting point and type of the date/time, the placeholder is also used to control the view of the calendar. For example, if you wanted to give the user the ability to select a specific month to jump to in the calendar, you could simply update the placeholder to a DateValue representing that month. Here's an example of how you might do that: import { Calendar } from \"bits-ui\"; import { today, getLocalTimeZone, type DateValue } from \"@internationalized/date\"; let placeholder: DateValue = $state(today(getLocalTimeZone())); let selectedMonth: number = $state(placeholder.month); { placeholder = placeholder.set({ month: selectedMonth }); }} bind:value={selectedMonth} January February In the example above, we're using the placeholder value to control the view of the calendar. The user can select a specific month to jump to in the calendar, and the placeholder will be updated to reflect the selected month. When the placeholder is updated, the calendar view will automatically update to reflect that new month. As the user interacts with the calendar, the placeholder will be updated to reflect the currently focused date in the calendar. If a value is selected in the calendar, the placeholder will be updated to reflect that selected value. Updating the placeholder It's important to note that DateValue objects are immutable, so you can't directly update the placeholder value. Instead, you'll need to reassign the value to the placeholder prop for the changes to reflect. @internationalized/date provides a number of methods for updating the DateValue objects, such as set, add, subtract, and cycle, each of which will return a new DateValue object with the updated value. For example, if you wanted to update the placeholder to the next month, you could use the add method to add one month to the current month in the placeholder value: let placeholder = new CalendarDate(2024, 07, 10); console.log(placeholder.add({ months: 1 })); // 2024-08-10 console.log(placeholder); // 2024-07-10 (unchanged) placeholder = placeholder.add({ months: 1 }); console.log(placeholder); // 2024-08-10 (updated) Formatting Dates @internationalized/date provides a $2 class that is a wrapper around the $2 API that fixes various browser bugs, and polyfills new features. It's highly recommended to use this class to format dates and times in your application, as it will ensure that the formatting is accurate for all locales, time zones, and calendars. Parsing Dates Often, you'll want to parse a string from a database or other source into a DateValue object for use with the date/time components in Bits UI. @internationalized/date provides various parsing functions that can be used to parse strings into each of the supported DateValue objects. parseDate The parseDate function is used to parse a string into a CalendarDate object. ","description":"How to work with the various date and time components in Bits UI.","href":"/docs/dates"},{"title":"Getting Started","content":" Installation Install bits using your favorite package manager. npm install bits-ui You can then import and start using them in your app. import { Accordion } from \"bits-ui\"; First First accordion content Second Second accordion content Third Third accordion content ","description":"Learn how to get started using Bits in your app.","href":"/docs/getting-started"},{"title":"Introduction","content":" Bits UI is a collection of headless component primitives that enable you to build your own custom components. They are designed to prioritize accessibility and flexibility, enabling you to add your own styles and behaviors to the components. Features Unstyled Most Bits UI components are unstyled by default, it's up to you to style them however you please. You can use the class prop to apply your own styles, or use the applied data attributes to target the components across your entire application. Check out the $2 section for more information. Customizable Each component offers a wide range of props for customizing behavior to fit your needs. Events and callbacks are chainable, allowing you to override the default functionality of the component by simply cancelling the event. Accessible Bits UI components have been designed following the $2 with the goal of making them usable by as many people as possible. Keyboard navigation, screen reader support, and focus management are all built-in. If you notice an accessibility issue, please $2 and we'll address it as soon as possible. Composable Bits UI is built with composability in mind. Each component is designed to be used in isolation, but can be composed together to create more complex UIs. Providing flexibility in the form of $2 and event overrides puts the power of bending the components to your will in your hands. About Bits UI was built and is maintained by $2. The documentation and example components were designed by $2 and $2. Credits $2 - The powerful builder API that inspired a lot of the internals of Bits UI. $2 - The incredible headless component APIs that we've taken heavy inspiration and code references from to build Bits UI. $2 - A world-class library of headless components, hooks, and utilities that we've taken inspiration from to build the various Date and Time components in Bits UI. ","description":"The headless components for Svelte.","href":"/docs/introduction"},{"title":"Ref","content":" Bits UI components with underlying HTML elements provide a ref prop for direct element access. For example, Accordion.Trigger's ref gives access to its rendered HTMLButtonElement: import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } Focus trigger With delegation Bits UI tracks the reference to the underlying element using its id attribute. This means that even if you use a custom element/component with $2, the ref prop will still work. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } {#snippet child({ props })} {/snippet} One caveat is that if you wish to use a custom id on the element, you must pass it to the component first, so it can be registered and associated with the ref prop. The id you pass will be passed down via the props snippet prop on the child snippet. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); } const myCustomId = \"my-custom-id\"; {#snippet child({ props })} {/snippet} The following example would not work, as the Accordion.Trigger component has no idea what the id of the CustomButton is. import CustomButton from \"./CustomButton.svelte\"; import { Accordion } from \"bits-ui\"; let triggerRef = $state(); function focusTrigger() { triggerRef?.focus(); // will always be undefined } {#snippet child({ props })} {/snippet} Why Possibly null? The ref prop may be null until the element has mounted, especially with the many components that use conditional rendering. This HTMLElement | null type mimics browser DOM methods like getElementById. WithElementRef Bits UI exposes a $2 type which enables you to create your own components following the same ref prop pattern. ","description":"Learn about the $bindable ref prop.","href":"/docs/ref"},{"title":"Styling","content":" We ship almost zero styles with Bits UI. This is intentional. We want to give you the most flexibility possible when it comes to styling your components. For each component that renders an HTML element, we expose a class prop that you can use to apply styles to the component. This is the recommended and most straightforward way to style them. CSS frameworks If you're using a CSS framework like TailwindCSS or UnoCSS, you can simply pass the classes you need to the component, and they will be applied to the underlying HTML element. import { Button } from \"bits-ui\"; Click me Data attributes A data attribute is applied to each element rendered by Bits UI, which you can use to target the component across your entire application. Check out the API reference of the component to determine what those data attributes are. You can then use those data attributes like so: Define global styles [data-button-root] { height: 3rem; width: 100%; background-color: #3182ce; color: #fff; } Import stylesheet import \"../app.pcss\"; let { children } = $props(); {@render children()} Now every `` component will have the styles applied to it. Global classes If you prefer the class approach, you can simply apply your global classes to the component. 1. Define global styles .button { height: 3rem; width: 100%; background-color: #3182ce; color: #fff; } 2. Apply global styles import \"../app.pcss\"; let { children } = $props(); {@render children()} 3. Use with components import { Button } from \"bits-ui\"; Click me Scoped Styles If you wish to use Svelte's scoped styles, you must use the child snippet for the various components that support it. This moves the underlying HTML element out of the Bits UI component scope and into the scope of your component. See the $2 documentation for more information. Style Prop Bits UI components accept a style prop, which can either be a string or an object of CSS properties and values. These are gracefully merged with the component's internal styles to create a single style object using the $2 function. ","description":"Learn how to style Bits UI components.","href":"/docs/styling"},{"title":"Transitions","content":" Svelte Transitions are one of the awesome features of Svelte. Unfortunately, they don't play very nicely with components, due to the fact that they rely on various directives like in:, out:, and transition:, which aren't supported by components. In previous version of Bits UI, we had a workaround for this by exposing a ton of transition* props on the components that we felt were most likely to be used with transitions. However, this was a bit of a hack and limited us to only Svelte Transitions, and users who wanted to use other libraries or just CSS were left out. With Bits UI for Svelte 5, we've completely removed this workaround and instead exposed props and snippets that allow you to use any animation or transitions library you want. The Defaults By default, Bits UI components handle the mounting and unmounting of specific components for you. They are wrapped in a component that ensures the component waits for transitions to finish before unmounting. You can use any CSS transitions or animations you want with this approach, which is what we're doing in the various example components in this documentation, using $2. Force Mounting On each component that we conditionally render, a forceMount prop is exposed. If set to true, the component will be forced to mount in the DOM and become visible to the user. You can use this prop in conjunction with the $2 child snippet to conditionally render the component and apply Svelte Transitions or another animation library. The child snippet exposes a prop that you can use to conditionally render the element and apply your transitions. import { Dialog } from \"bits-ui\"; import { fly } from \"svelte/transition\"; {#snippet child({ props, open })} {#if open} {/if} {/snippet} In the example above, we're using the forceMount prop to tell the component to forcefully mount the Dialog.Content component. We're then using the child snippet to delegate the rendering of the Dialog.Content to a div element which we can apply our props and transitions to. We understand this isn't the prettiest syntax, but it enables us to cover every use case. If you intend to use this approach across your application, it's recommended to create a reusable component that handles this logic, like so: import type { Snippet } from \"svelte\"; import { fly } from \"svelte/transition\"; import { Dialog, type WithoutChildrenOrChild } from \"bits-ui\"; let { ref = $bindable(null), children, ...restProps }: WithoutChildrenOrChild & { children?: Snippet; } = $props(); {#snippet child({ props, open })} {#if open} {@render children?.()} {/if} {/snippet} Which can then be used alongside the other Dialog.* components: import { Dialog } from \"bits-ui\"; import MyDialogContent from \"$lib/components/MyDialogContent.svelte\"; Open Dialog Dialog Title Dialog Description Close Other dialog content ","description":"Learn how to use transitions with Bits UI components.","href":"/docs/transitions"}] \ No newline at end of file diff --git a/sites/docs/svelte.config.js b/sites/docs/svelte.config.js index dbdb69d82..e65ab0a20 100644 --- a/sites/docs/svelte.config.js +++ b/sites/docs/svelte.config.js @@ -27,8 +27,7 @@ const config = { adapter: adapter(), alias: { "$icons/*": "src/lib/components/icons/*", - "contentlayer/generated": ".contentlayer/generated", - "$contentlayer/*": "../.contentlayer/*", + "$content/*": ".velite/*", }, }, }; diff --git a/sites/docs/tsconfig.json b/sites/docs/tsconfig.json index b7d620c84..c7d59b8a6 100644 --- a/sites/docs/tsconfig.json +++ b/sites/docs/tsconfig.json @@ -24,7 +24,7 @@ "./tests/**/*.js", "./tests/**/*.ts", "./tests/**/*.svelte", - ".contentlayer/generated", + ".velite/**/*", "./mdsx.config.js", "./svelte.config.js", "./other/**/*.js", diff --git a/sites/docs/velite.config.js b/sites/docs/velite.config.js new file mode 100644 index 000000000..b9f9718e2 --- /dev/null +++ b/sites/docs/velite.config.js @@ -0,0 +1,43 @@ +import { defineConfig, s } from "velite"; + +const sharedSchema = s + .object({ + title: s.string(), + description: s.string(), + path: s.path(), + content: s.markdown(), + navLabel: s.string().optional(), + raw: s.raw(), + }) + .transform((data) => { + return { + ...data, + slug: data.path.split("/").slice(1).join("/"), + slugFull: `/${data.path}`, + }; + }); + +export default defineConfig({ + collections: { + docs: { + name: "Doc", + pattern: "./*.md", + schema: sharedSchema, + }, + componentDocs: { + name: "ComponentDoc", + pattern: "./components/**/*.md", + schema: sharedSchema, + }, + utilityDocs: { + name: "UtilityDoc", + pattern: "./utilities/**/*.md", + schema: sharedSchema, + }, + typeHelperDocs: { + name: "TypeHelperDoc", + pattern: "./type-helpers/**/*.md", + schema: sharedSchema, + }, + }, +});